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:
authorAntony Riakiotakis <kalast@gmail.com>2014-09-08 20:15:42 +0400
committerAntony Riakiotakis <kalast@gmail.com>2014-09-08 20:15:42 +0400
commitd9ffc99e66d659ac887d801b9cc071b4c3f9b8ab (patch)
treed88e83b5a9edab115081641d26c811b6aa22296a
parent551ebaa3dd758bc1975548c28766bfa3159d3846 (diff)
parentb1490e39dd1017e51984d8a34d226e869bbb25df (diff)
Merge branch 'master' into soc-2014-viewport_fxsoc-2014-viewport_fx
I have resolved some differences, for instance selection code which was more or less a stub, to be the same as master. This will have to be fixed later. Conflicts: CMakeLists.txt intern/ghost/CMakeLists.txt intern/ghost/intern/GHOST_SystemWin32.cpp intern/ghost/intern/GHOST_Window.cpp intern/ghost/intern/GHOST_WindowWin32.cpp intern/ghost/intern/GHOST_WindowX11.cpp source/blender/blenlib/BLI_math_matrix.h source/blender/blenlib/intern/math_matrix.c source/blender/gpu/CMakeLists.txt source/blender/gpu/GPU_select.h source/blender/gpu/intern/gpu_buffers.c source/blender/gpu/intern/gpu_draw.c source/blender/gpu/intern/gpu_extensions.c source/blender/gpu/intern/gpu_select.c source/blender/gpu/shaders/gpu_shader_simple_vert.glsl source/blender/nodes/CMakeLists.txt
-rw-r--r--.gitignore6
-rw-r--r--CMakeLists.txt134
-rw-r--r--GNUmakefile59
-rw-r--r--SConstruct53
-rwxr-xr-xbuild_files/build_environment/install_deps.sh110
-rw-r--r--build_files/buildbot/config/user-config-glibc211-i686.py6
-rw-r--r--build_files/buildbot/config/user-config-glibc211-x86_64.py6
-rw-r--r--build_files/buildbot/config/user-config-mac-i386.py2
-rw-r--r--build_files/buildbot/master.cfg213
-rw-r--r--build_files/buildbot/slave_compile.py12
-rw-r--r--build_files/buildbot/slave_pack.py14
-rw-r--r--build_files/cmake/Modules/FindGLEW.cmake132
-rw-r--r--build_files/cmake/Modules/FindOpenEXR.cmake13
-rw-r--r--build_files/cmake/buildinfo.cmake2
-rw-r--r--build_files/cmake/cmake_consistency_check_config.py1
-rwxr-xr-xbuild_files/cmake/cmake_netbeans_project.py4
-rwxr-xr-xbuild_files/cmake/cmake_qtcreator_project.py4
-rw-r--r--build_files/cmake/macros.cmake59
-rw-r--r--build_files/scons/config/darwin-config.py8
-rw-r--r--build_files/scons/config/linux-config.py4
-rw-r--r--build_files/scons/config/win32-mingw-config.py4
-rw-r--r--build_files/scons/config/win32-vc-config.py33
-rw-r--r--build_files/scons/config/win64-mingw-config.py4
-rw-r--r--build_files/scons/config/win64-vc-config.py34
-rwxr-xr-xbuild_files/scons/tools/Blender.py53
-rw-r--r--build_files/scons/tools/btools.py3
-rwxr-xr-xdoc/manpage/blender.1.py1
-rw-r--r--doc/python_api/rst/bge.constraints.rst10
-rw-r--r--doc/python_api/rst/bge.logic.rst17
-rw-r--r--doc/python_api/rst/bge.render.rst28
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst127
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst20
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_MouseFocusSensor.rst17
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_Scene.rst2
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_TrackToActuator.rst22
-rw-r--r--doc/python_api/rst/info_gotcha.rst10
-rw-r--r--extern/CMakeLists.txt5
-rw-r--r--extern/SConscript4
-rw-r--r--extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp11
-rw-r--r--extern/carve/carve-capi.cc24
-rw-r--r--extern/carve/carve-capi.h16
-rw-r--r--extern/carve/carve-util.cc27
-rw-r--r--extern/carve/carve-util.h10
-rw-r--r--extern/clew/CMakeLists.txt42
-rw-r--r--extern/clew/SConscript35
-rw-r--r--extern/clew/include/clew.h2759
-rw-r--r--extern/clew/src/clew.c382
-rw-r--r--extern/cuew/CMakeLists.txt (renamed from intern/opencl/CMakeLists.txt)10
-rw-r--r--extern/cuew/LICENSE174
-rw-r--r--extern/cuew/README12
-rw-r--r--extern/cuew/SConscript (renamed from intern/opencl/SConscript)7
-rw-r--r--extern/cuew/auto/cuda_errors.py35
-rw-r--r--extern/cuew/auto/cuda_extra.py125
-rw-r--r--extern/cuew/auto/cuew_gen.py591
-rwxr-xr-xextern/cuew/auto/cuew_gen.sh10
-rw-r--r--extern/cuew/auto/stdlib.h3
-rw-r--r--extern/cuew/include/cuew.h1138
-rw-r--r--extern/cuew/src/cuew.c710
-rw-r--r--extern/gtest/CMakeLists.txt1
-rw-r--r--extern/libmv/libmv/simple_pipeline/bundle.cc3
-rw-r--r--intern/CMakeLists.txt4
-rw-r--r--intern/SConscript3
-rw-r--r--intern/atomic/atomic_ops.h5
-rw-r--r--intern/audaspace/FX/AUD_PitchReader.cpp2
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.cpp2
-rw-r--r--intern/cycles/SConscript2
-rw-r--r--intern/cycles/app/CMakeLists.txt2
-rw-r--r--intern/cycles/app/cycles_xml.cpp4
-rw-r--r--intern/cycles/blender/CMakeLists.txt1
-rw-r--r--intern/cycles/blender/addon/__init__.py6
-rw-r--r--intern/cycles/blender/addon/engine.py1
-rw-r--r--intern/cycles/blender/addon/presets.py17
-rw-r--r--intern/cycles/blender/addon/properties.py27
-rw-r--r--intern/cycles/blender/addon/ui.py25
-rw-r--r--intern/cycles/blender/addon/version_update.py44
-rw-r--r--intern/cycles/blender/blender_camera.cpp6
-rw-r--r--intern/cycles/blender/blender_curves.cpp49
-rw-r--r--intern/cycles/blender/blender_mesh.cpp88
-rw-r--r--intern/cycles/blender/blender_object.cpp2
-rw-r--r--intern/cycles/blender/blender_python.cpp11
-rw-r--r--intern/cycles/blender/blender_session.cpp53
-rw-r--r--intern/cycles/blender/blender_session.h3
-rw-r--r--intern/cycles/blender/blender_shader.cpp15
-rw-r--r--intern/cycles/blender/blender_sync.cpp8
-rw-r--r--intern/cycles/bvh/bvh.cpp36
-rw-r--r--intern/cycles/bvh/bvh_params.h2
-rw-r--r--intern/cycles/device/CMakeLists.txt2
-rw-r--r--intern/cycles/device/device.cpp19
-rw-r--r--intern/cycles/device/device.h1
-rw-r--r--intern/cycles/device/device_cpu.cpp98
-rw-r--r--intern/cycles/device/device_cuda.cpp305
-rw-r--r--intern/cycles/device/device_intern.h2
-rw-r--r--intern/cycles/device/device_memory.h2
-rw-r--r--intern/cycles/device/device_multi.cpp16
-rw-r--r--intern/cycles/device/device_network.cpp5
-rw-r--r--intern/cycles/device/device_opencl.cpp105
-rw-r--r--intern/cycles/device/device_task.cpp25
-rw-r--r--intern/cycles/device/device_task.h3
-rw-r--r--intern/cycles/kernel/CMakeLists.txt71
-rw-r--r--intern/cycles/kernel/SConscript53
-rw-r--r--intern/cycles/kernel/closure/bsdf.h10
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h2
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h12
-rw-r--r--intern/cycles/kernel/closure/bsdf_util.h18
-rw-r--r--intern/cycles/kernel/geom/geom_curve.h6
-rw-r--r--intern/cycles/kernel/geom/geom_motion_triangle.h6
-rw-r--r--intern/cycles/kernel/geom/geom_triangle.h21
-rw-r--r--intern/cycles/kernel/kernel.cl6
-rw-r--r--intern/cycles/kernel/kernel.cpp4
-rw-r--r--intern/cycles/kernel/kernel.cu6
-rw-r--r--intern/cycles/kernel/kernel.h12
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h49
-rw-r--r--intern/cycles/kernel/kernel_avx.cpp4
-rw-r--r--intern/cycles/kernel/kernel_avx2.cpp4
-rw-r--r--intern/cycles/kernel/kernel_bake.h7
-rw-r--r--intern/cycles/kernel/kernel_camera.h13
-rw-r--r--intern/cycles/kernel/kernel_emission.h8
-rw-r--r--intern/cycles/kernel/kernel_jitter.h24
-rw-r--r--intern/cycles/kernel/kernel_light.h31
-rw-r--r--intern/cycles/kernel/kernel_path.h75
-rw-r--r--intern/cycles/kernel/kernel_path_surface.h8
-rw-r--r--intern/cycles/kernel/kernel_path_volume.h87
-rw-r--r--intern/cycles/kernel/kernel_shader.h6
-rw-r--r--intern/cycles/kernel/kernel_sse2.cpp4
-rw-r--r--intern/cycles/kernel/kernel_sse3.cpp4
-rw-r--r--intern/cycles/kernel/kernel_sse41.cpp4
-rw-r--r--intern/cycles/kernel/kernel_types.h70
-rw-r--r--intern/cycles/kernel/kernel_volume.h76
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.cpp24
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp20
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h2
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp38
-rw-r--r--intern/cycles/kernel/osl/osl_services.h92
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp9
-rw-r--r--intern/cycles/kernel/shaders/node_fresnel.h13
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h6
-rw-r--r--intern/cycles/kernel/svm/svm.h12
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h33
-rw-r--r--intern/cycles/kernel/svm/svm_convert.h4
-rw-r--r--intern/cycles/render/background.cpp2
-rw-r--r--intern/cycles/render/bake.cpp128
-rw-r--r--intern/cycles/render/bake.h16
-rw-r--r--intern/cycles/render/camera.cpp6
-rw-r--r--intern/cycles/render/camera.h3
-rw-r--r--intern/cycles/render/film.cpp12
-rw-r--r--intern/cycles/render/image.cpp27
-rw-r--r--intern/cycles/render/image.h1
-rw-r--r--intern/cycles/render/integrator.cpp15
-rw-r--r--intern/cycles/render/integrator.h3
-rw-r--r--intern/cycles/render/light.cpp17
-rw-r--r--intern/cycles/render/light.h1
-rw-r--r--intern/cycles/render/mesh.cpp1
-rw-r--r--intern/cycles/render/mesh.h3
-rw-r--r--intern/cycles/render/object.cpp2
-rw-r--r--intern/cycles/render/osl.cpp13
-rw-r--r--intern/cycles/render/scene.cpp2
-rw-r--r--intern/cycles/render/svm.cpp67
-rw-r--r--intern/cycles/render/svm.h12
-rw-r--r--intern/cycles/util/CMakeLists.txt4
-rw-r--r--intern/cycles/util/util_cache.h44
-rw-r--r--intern/cycles/util/util_cuda.cpp501
-rw-r--r--intern/cycles/util/util_cuda.h634
-rw-r--r--intern/cycles/util/util_math.h29
-rw-r--r--intern/cycles/util/util_opencl.cpp337
-rw-r--r--intern/cycles/util/util_opencl.h1313
-rw-r--r--intern/cycles/util/util_optimization.h7
-rw-r--r--intern/cycles/util/util_progress.h6
-rw-r--r--intern/cycles/util/util_stats.h1
-rw-r--r--intern/cycles/util/util_types.h6
-rw-r--r--intern/ghost/GHOST_C-api.h8
-rw-r--r--intern/ghost/GHOST_ISystem.h68
-rw-r--r--intern/ghost/GHOST_IWindow.h13
-rw-r--r--intern/ghost/GHOST_Rect.h2
-rw-r--r--intern/ghost/intern/GHOST_Context.cpp8
-rw-r--r--intern/ghost/intern/GHOST_DisplayManager.cpp5
-rw-r--r--intern/ghost/intern/GHOST_DisplayManager.h2
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerSDL.cpp3
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.cpp8
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerX11.cpp11
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.cpp70
-rw-r--r--intern/ghost/intern/GHOST_DropTargetX11.h6
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.cpp24
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.h2
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c4
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerCocoa.mm2
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerWin32.cpp2
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerX11.cpp5
-rw-r--r--intern/ghost/intern/GHOST_System.cpp12
-rw-r--r--intern/ghost/intern/GHOST_System.h8
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm4
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsWin32.cpp2
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp177
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h4
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp24
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h4
-rw-r--r--intern/ghost/intern/GHOST_TaskbarWin32.h55
-rw-r--r--intern/ghost/intern/GHOST_TimerManager.h2
-rw-r--r--intern/ghost/intern/GHOST_TimerTask.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.h4
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp289
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h4
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp2
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h2
-rw-r--r--intern/ghost/test/gears/GHOST_Test.cpp3
-rw-r--r--intern/glew-mx/glew-mx.h2
-rw-r--r--intern/guardedalloc/MEM_guardedalloc.h2
-rw-r--r--intern/guardedalloc/intern/mallocn_guarded_impl.c20
-rw-r--r--intern/itasc/Armature.cpp2
-rw-r--r--intern/moto/include/MT_Matrix3x3.h7
-rw-r--r--intern/moto/include/MT_Vector3.h2
-rw-r--r--intern/moto/include/MT_Vector3.inl7
-rw-r--r--intern/opencl/intern/clew.c316
-rw-r--r--intern/opencl/intern/clew.h1317
-rw-r--r--intern/rigidbody/rb_bullet_api.cpp2
-rw-r--r--intern/smoke/intern/tnt/tnt_math_utils.h4
-rw-r--r--release/darwin/README_codesigning.txt5
-rw-r--r--release/darwin/codesigning_rules_blender.plist14
-rw-r--r--release/darwin/codesigning_rules_player.plist15
-rw-r--r--release/datafiles/blender_icons.svg215
-rw-r--r--release/datafiles/blender_icons16/icon16_ipo_bounce.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_ipo_elastic.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_loopsel.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_loopsel.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_nla_pushdown.datbin4120 -> 4120 bytes
-rwxr-xr-xrelease/datafiles/prvicons_update.py11
-rw-r--r--release/scripts/freestyle/modules/freestyle/chainingiterators.py2
-rw-r--r--release/scripts/freestyle/modules/freestyle/functions.py37
-rw-r--r--release/scripts/freestyle/modules/freestyle/predicates.py68
-rw-r--r--release/scripts/freestyle/modules/freestyle/shaders.py64
-rw-r--r--release/scripts/freestyle/modules/freestyle/types.py2
-rw-r--r--release/scripts/freestyle/modules/freestyle/utils.py317
-rw-r--r--release/scripts/freestyle/modules/parameter_editor.py1017
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils_spell_check.py4
-rw-r--r--release/scripts/modules/bpy/path.py5
-rw-r--r--release/scripts/modules/bpy/utils.py8
-rw-r--r--release/scripts/modules/bpy_extras/mesh_utils.py1
-rw-r--r--release/scripts/modules/bpy_extras/object_utils.py1
-rw-r--r--release/scripts/modules/bpy_types.py9
-rw-r--r--release/scripts/modules/rna_prop_ui.py3
-rw-r--r--release/scripts/modules/sys_info.py26
-rw-r--r--release/scripts/presets/camera/1__colon__2.3_inch.py6
-rw-r--r--release/scripts/presets/camera/1__colon__2.5_inch.py6
-rw-r--r--release/scripts/presets/camera/2__colon__3_inch.py6
-rw-r--r--release/scripts/presets/camera/4__colon__3_inch.py6
-rw-r--r--release/scripts/presets/camera/Arri_Alexa.py6
-rw-r--r--release/scripts/presets/camera/Blackmagic_Cinema_Camera.py6
-rw-r--r--release/scripts/presets/camera/Blackmagic_Pocket_Cinema_Camera.py4
-rw-r--r--release/scripts/presets/camera/Blackmagic_Production_Camera_4K.py4
-rw-r--r--release/scripts/presets/camera/Blender.py6
-rw-r--r--release/scripts/presets/camera/Canon_1100D.py6
-rw-r--r--release/scripts/presets/camera/Canon_APS-C.py6
-rw-r--r--release/scripts/presets/camera/Canon_APS-H.py6
-rw-r--r--release/scripts/presets/camera/Canon_C300.py6
-rw-r--r--release/scripts/presets/camera/Full_Frame_35mm_Camera.py6
-rw-r--r--release/scripts/presets/camera/GoPro_Hero3_Black.py8
-rw-r--r--release/scripts/presets/camera/GoPro_Hero3_Silver.py8
-rw-r--r--release/scripts/presets/camera/GoPro_Hero3_White.py8
-rw-r--r--release/scripts/presets/camera/Nexus_5.py8
-rw-r--r--release/scripts/presets/camera/Nikon_D3100.py6
-rw-r--r--release/scripts/presets/camera/Nikon_DX.py6
-rw-r--r--release/scripts/presets/camera/Panasonic_AG-HVX200.py6
-rw-r--r--release/scripts/presets/camera/Panasonic_LX2.py6
-rw-r--r--release/scripts/presets/camera/Red_Epic.py6
-rw-r--r--release/scripts/presets/camera/Red_One_2K.py6
-rw-r--r--release/scripts/presets/camera/Red_One_3K.py6
-rw-r--r--release/scripts/presets/camera/Red_One_4K.py6
-rw-r--r--release/scripts/presets/camera/Samsung_Galaxy_S3.py8
-rw-r--r--release/scripts/presets/camera/Samsung_Galaxy_S4.py8
-rw-r--r--release/scripts/presets/camera/Sony_A55.py6
-rw-r--r--release/scripts/presets/camera/Sony_EX1.py6
-rw-r--r--release/scripts/presets/camera/Sony_F65.py6
-rw-r--r--release/scripts/presets/camera/Super_16_Film.py6
-rw-r--r--release/scripts/presets/camera/Super_35_Film.py6
-rw-r--r--release/scripts/presets/camera/iPhone_4.py8
-rw-r--r--release/scripts/presets/camera/iPhone_4S.py8
-rw-r--r--release/scripts/presets/camera/iPhone_5.py8
-rw-r--r--release/scripts/presets/cycles/integrator/direct_light.py4
-rw-r--r--release/scripts/presets/cycles/integrator/full_global_illumination.py4
-rw-r--r--release/scripts/presets/cycles/integrator/limited_global_illumination.py4
-rw-r--r--release/scripts/presets/interface_theme/back_to_black.xml117
-rw-r--r--release/scripts/presets/interface_theme/blender_24x.xml85
-rw-r--r--release/scripts/presets/interface_theme/elsyiun.xml85
-rw-r--r--release/scripts/presets/interface_theme/hexagon.xml85
-rw-r--r--release/scripts/presets/interface_theme/ubuntu_ambiance.xml85
-rw-r--r--release/scripts/presets/keyconfig/3dsmax.py38
-rw-r--r--release/scripts/presets/keyconfig/maya.py19
-rw-r--r--release/scripts/presets/sunsky/classic.py26
-rw-r--r--release/scripts/presets/sunsky/desert.py26
-rw-r--r--release/scripts/presets/sunsky/mountain.py26
-rw-r--r--release/scripts/presets/tracking_camera/Blackmagic_Pocket_Cinema_Camera.py9
-rw-r--r--release/scripts/presets/tracking_camera/Blackmagic_Production_Camera_4K.py9
-rw-r--r--release/scripts/startup/bl_operators/object.py17
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py229
-rw-r--r--release/scripts/startup/bl_operators/presets.py4
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_lightmap.py4
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py2
-rw-r--r--release/scripts/startup/bl_operators/vertexpaint_dirt.py2
-rw-r--r--release/scripts/startup/bl_operators/view3d.py7
-rw-r--r--release/scripts/startup/bl_operators/wm.py79
-rw-r--r--release/scripts/startup/bl_ui/properties_constraint.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_data_empty.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_freestyle.py19
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py28
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py155
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py1
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py2
-rw-r--r--release/scripts/startup/bl_ui/space_image.py134
-rw-r--r--release/scripts/startup/bl_ui/space_info.py10
-rw-r--r--release/scripts/startup/bl_ui/space_node.py10
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py34
-rw-r--r--release/scripts/startup/bl_ui/space_time.py5
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py16
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py10
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py288
-rw-r--r--release/scripts/startup/nodeitems_builtins.py10
-rw-r--r--release/scripts/templates_osl/fresnel_conductive.osl38
-rw-r--r--release/scripts/templates_py/ui_pie_menu.py32
-rw-r--r--release/text/readme.html10
-rw-r--r--source/blender/blenfont/intern/blf_font.c36
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c3
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h2
-rw-r--r--source/blender/blenfont/intern/blf_lang.c10
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h16
-rw-r--r--source/blender/blenkernel/BKE_blender.h12
-rw-r--r--source/blender/blenkernel/BKE_brush.h6
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h8
-rw-r--r--source/blender/blenkernel/BKE_context.h1
-rw-r--r--source/blender/blenkernel/BKE_curve.h4
-rw-r--r--source/blender/blenkernel/BKE_editmesh_bvh.h13
-rw-r--r--source/blender/blenkernel/BKE_idprop.h26
-rw-r--r--source/blender/blenkernel/BKE_lattice.h1
-rw-r--r--source/blender/blenkernel/BKE_library.h3
-rw-r--r--source/blender/blenkernel/BKE_linestyle.h59
-rw-r--r--source/blender/blenkernel/BKE_main.h2
-rw-r--r--source/blender/blenkernel/BKE_material.h3
-rw-r--r--source/blender/blenkernel/BKE_mball.h1
-rw-r--r--source/blender/blenkernel/BKE_mesh.h6
-rw-r--r--source/blender/blenkernel/BKE_node.h8
-rw-r--r--source/blender/blenkernel/BKE_object.h12
-rw-r--r--source/blender/blenkernel/BKE_paint.h26
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h3
-rw-r--r--source/blender/blenkernel/BKE_scene.h5
-rw-r--r--source/blender/blenkernel/BKE_screen.h7
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h2
-rw-r--r--source/blender/blenkernel/BKE_shrinkwrap.h51
-rw-r--r--source/blender/blenkernel/BKE_text.h1
-rw-r--r--source/blender/blenkernel/BKE_unit.h4
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c4
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c103
-rw-r--r--source/blender/blenkernel/intern/action.c6
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c17
-rw-r--r--source/blender/blenkernel/intern/armature.c9
-rw-r--r--source/blender/blenkernel/intern/blender.c12
-rw-r--r--source/blender/blenkernel/intern/bpath.c12
-rw-r--r--source/blender/blenkernel/intern/brush.c98
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c294
-rw-r--r--source/blender/blenkernel/intern/camera.c4
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c381
-rw-r--r--source/blender/blenkernel/intern/constraint.c28
-rw-r--r--source/blender/blenkernel/intern/context.c14
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c33
-rw-r--r--source/blender/blenkernel/intern/curve.c296
-rw-r--r--source/blender/blenkernel/intern/deform.c55
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c92
-rw-r--r--source/blender/blenkernel/intern/displist.c211
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c7
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c4
-rw-r--r--source/blender/blenkernel/intern/editmesh_bvh.c86
-rw-r--r--source/blender/blenkernel/intern/effect.c2
-rw-r--r--source/blender/blenkernel/intern/fcurve.c31
-rw-r--r--source/blender/blenkernel/intern/freestyle.c2
-rw-r--r--source/blender/blenkernel/intern/gpencil.c2
-rw-r--r--source/blender/blenkernel/intern/idcode.c2
-rw-r--r--source/blender/blenkernel/intern/idprop.c6
-rw-r--r--source/blender/blenkernel/intern/image.c4
-rw-r--r--source/blender/blenkernel/intern/implicit.c7
-rw-r--r--source/blender/blenkernel/intern/ipo.c8
-rw-r--r--source/blender/blenkernel/intern/lattice.c135
-rw-r--r--source/blender/blenkernel/intern/library.c34
-rw-r--r--source/blender/blenkernel/intern/linestyle.c149
-rw-r--r--source/blender/blenkernel/intern/mask.c2
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c2
-rw-r--r--source/blender/blenkernel/intern/material.c135
-rw-r--r--source/blender/blenkernel/intern/mball.c50
-rw-r--r--source/blender/blenkernel/intern/mesh.c43
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c136
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c57
-rw-r--r--source/blender/blenkernel/intern/modifier.c30
-rw-r--r--source/blender/blenkernel/intern/multires.c2
-rw-r--r--source/blender/blenkernel/intern/nla.c8
-rw-r--r--source/blender/blenkernel/intern/node.c9
-rw-r--r--source/blender/blenkernel/intern/object.c131
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c4
-rw-r--r--source/blender/blenkernel/intern/paint.c105
-rw-r--r--source/blender/blenkernel/intern/particle.c7
-rw-r--r--source/blender/blenkernel/intern/particle_system.c17
-rw-r--r--source/blender/blenkernel/intern/pbvh.c15
-rw-r--r--source/blender/blenkernel/intern/report.c2
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c193
-rw-r--r--source/blender/blenkernel/intern/sca.c4
-rw-r--r--source/blender/blenkernel/intern/scene.c142
-rw-r--r--source/blender/blenkernel/intern/screen.c26
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c303
-rw-r--r--source/blender/blenkernel/intern/sequencer.c77
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c80
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c50
-rw-r--r--source/blender/blenkernel/intern/text.c17
-rw-r--r--source/blender/blenkernel/intern/texture.c273
-rw-r--r--source/blender/blenkernel/intern/tracking_region_tracker.c2
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c6
-rw-r--r--source/blender/blenkernel/intern/treehash.c2
-rw-r--r--source/blender/blenkernel/intern/unit.c145
-rw-r--r--source/blender/blenkernel/intern/world.c3
-rw-r--r--source/blender/blenkernel/intern/writeavi.c2
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c9
-rw-r--r--source/blender/blenlib/BLI_array.h8
-rw-r--r--source/blender/blenlib/BLI_callbacks.h9
-rw-r--r--source/blender/blenlib/BLI_dial.h59
-rw-r--r--source/blender/blenlib/BLI_dynstr.h2
-rw-r--r--source/blender/blenlib/BLI_edgehash.h6
-rw-r--r--source/blender/blenlib/BLI_fileops.h4
-rw-r--r--source/blender/blenlib/BLI_fileops_types.h2
-rw-r--r--source/blender/blenlib/BLI_ghash.h10
-rw-r--r--source/blender/blenlib/BLI_gsqueue.h3
-rw-r--r--source/blender/blenlib/BLI_heap.h22
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h2
-rw-r--r--source/blender/blenlib/BLI_linklist_stack.h12
-rw-r--r--source/blender/blenlib/BLI_listbase.h16
-rw-r--r--source/blender/blenlib/BLI_math_base.h18
-rw-r--r--source/blender/blenlib/BLI_math_color_blend.h36
-rw-r--r--source/blender/blenlib/BLI_math_geom.h32
-rw-r--r--source/blender/blenlib/BLI_math_interp.h20
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h50
-rw-r--r--source/blender/blenlib/BLI_math_vector.h2
-rw-r--r--source/blender/blenlib/BLI_path_util.h4
-rw-r--r--source/blender/blenlib/BLI_rand.h32
-rw-r--r--source/blender/blenlib/BLI_smallhash.h4
-rw-r--r--source/blender/blenlib/BLI_stack.h14
-rw-r--r--source/blender/blenlib/BLI_stackdefines.h11
-rw-r--r--source/blender/blenlib/BLI_string.h2
-rw-r--r--source/blender/blenlib/BLI_sys_types.h124
-rw-r--r--source/blender/blenlib/BLI_utildefines.h108
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/BLI_array.c15
-rw-r--r--source/blender/blenlib/intern/BLI_dial.c100
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c60
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c100
-rw-r--r--source/blender/blenlib/intern/BLI_linklist.c15
-rw-r--r--source/blender/blenlib/intern/callbacks.c6
-rw-r--r--source/blender/blenlib/intern/edgehash.c53
-rw-r--r--source/blender/blenlib/intern/fileops.c3
-rw-r--r--source/blender/blenlib/intern/gsqueue.c6
-rw-r--r--source/blender/blenlib/intern/listbase.c10
-rw-r--r--source/blender/blenlib/intern/math_color.c221
-rw-r--r--source/blender/blenlib/intern/math_color_blend_inline.c860
-rw-r--r--source/blender/blenlib/intern/math_color_inline.c16
-rw-r--r--source/blender/blenlib/intern/math_geom.c330
-rw-r--r--source/blender/blenlib/intern/math_interp.c195
-rw-r--r--source/blender/blenlib/intern/math_matrix.c348
-rw-r--r--source/blender/blenlib/intern/math_rotation.c18
-rw-r--r--source/blender/blenlib/intern/math_vector.c21
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c52
-rw-r--r--source/blender/blenlib/intern/path_util.c41
-rw-r--r--source/blender/blenlib/intern/polyfill2d.c2
-rw-r--r--source/blender/blenlib/intern/rand.c16
-rw-r--r--source/blender/blenlib/intern/scanfill.c3
-rw-r--r--source/blender/blenlib/intern/smallhash.c52
-rw-r--r--source/blender/blenlib/intern/stack.c69
-rw-r--r--source/blender/blenlib/intern/storage.c2
-rw-r--r--source/blender/blenlib/intern/string.c39
-rw-r--r--source/blender/blenlib/intern/winstuff.c7
-rw-r--r--source/blender/blenloader/BLO_readfile.h3
-rw-r--r--source/blender/blenloader/intern/readfile.c102
-rw-r--r--source/blender/blenloader/intern/versioning_260.c6
-rw-r--r--source/blender/blenloader/intern/versioning_270.c58
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c68
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c4
-rw-r--r--source/blender/blenloader/intern/writefile.c227
-rw-r--r--source/blender/bmesh/CMakeLists.txt2
-rw-r--r--source/blender/bmesh/bmesh_class.h8
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c144
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators_inline.h10
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c28
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.h9
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c55
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h8
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c592
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c276
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h8
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c51
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c20
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h168
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h42
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.c2
-rw-r--r--source/blender/bmesh/operators/bmo_bevel.c3
-rw-r--r--source/blender/bmesh/operators/bmo_bridge.c4
-rw-r--r--source/blender/bmesh/operators/bmo_connect.c93
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c72
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c46
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c11
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c4
-rw-r--r--source/blender/bmesh/operators/bmo_extrude.c64
-rw-r--r--source/blender/bmesh/operators/bmo_fill_attribute.c2
-rw-r--r--source/blender/bmesh/operators/bmo_fill_grid.c4
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c6
-rw-r--r--source/blender/bmesh/operators/bmo_poke.c2
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c34
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c5
-rw-r--r--source/blender/bmesh/operators/bmo_smooth_laplacian.c2
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide_edgering.c8
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c158
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c13
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c61
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.h3
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c8
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.c5
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c1302
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.h (renamed from intern/opencl/intern/OCL_opencl.c)30
-rw-r--r--source/blender/bmesh/tools/bmesh_wireframe.c8
-rw-r--r--source/blender/collada/AnimationImporter.cpp6
-rw-r--r--source/blender/collada/ControllerExporter.cpp2
-rw-r--r--source/blender/collada/DocumentImporter.cpp52
-rw-r--r--source/blender/collada/DocumentImporter.h2
-rw-r--r--source/blender/collada/MeshImporter.cpp2
-rw-r--r--source/blender/collada/SkinInfo.cpp6
-rw-r--r--source/blender/collada/TransformWriter.cpp2
-rw-r--r--source/blender/compositor/CMakeLists.txt9
-rw-r--r--source/blender/compositor/COM_compositor.h2
-rw-r--r--source/blender/compositor/SConscript4
-rw-r--r--source/blender/compositor/intern/COM_ChunkOrder.cpp2
-rw-r--r--source/blender/compositor/intern/COM_Converter.cpp4
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cpp198
-rw-r--r--source/blender/compositor/intern/COM_NodeConverter.cpp8
-rw-r--r--source/blender/compositor/intern/COM_NodeConverter.h4
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.cpp10
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h4
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.cpp7
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.cpp8
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.h2
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cpp6
-rw-r--r--source/blender/compositor/intern/COM_compositor.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_SocketProxyNode.cpp6
-rw-r--r--source/blender/compositor/nodes/COM_SocketProxyNode.h9
-rw-r--r--source/blender/compositor/nodes/COM_SunBeamsNode.cpp42
-rw-r--r--source/blender/compositor/nodes/COM_SunBeamsNode.h (renamed from intern/opencl/OCL_opencl.h)30
-rw-r--r--source/blender/compositor/nodes/COM_SwitchNode.cpp4
-rw-r--r--source/blender/compositor/operations/COM_BokehImageOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_DilateErodeOperation.cpp12
-rw-r--r--source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_MathBaseOperation.cpp9
-rw-r--r--source/blender/compositor/operations/COM_MathBaseOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_SocketProxyOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_SocketProxyOperation.h9
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.cpp308
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.h48
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c2
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c14
-rw-r--r--source/blender/editors/animation/anim_deps.c2
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c2
-rw-r--r--source/blender/editors/animation/anim_markers.c280
-rw-r--r--source/blender/editors/animation/anim_ops.c3
-rw-r--r--source/blender/editors/animation/keyframes_edit.c8
-rw-r--r--source/blender/editors/animation/keyframes_general.c8
-rw-r--r--source/blender/editors/animation/keyframing.c37
-rw-r--r--source/blender/editors/armature/CMakeLists.txt2
-rw-r--r--source/blender/editors/armature/SConscript1
-rw-r--r--source/blender/editors/armature/armature_add.c9
-rw-r--r--source/blender/editors/armature/armature_edit.c4
-rw-r--r--source/blender/editors/armature/armature_select.c6
-rw-r--r--source/blender/editors/armature/armature_skinning.c27
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c8
-rw-r--r--source/blender/editors/armature/meshlaplacian.c9
-rw-r--r--source/blender/editors/armature/pose_edit.c4
-rw-r--r--source/blender/editors/armature/pose_lib.c8
-rw-r--r--source/blender/editors/armature/pose_select.c88
-rw-r--r--source/blender/editors/armature/pose_slide.c2
-rw-r--r--source/blender/editors/curve/editcurve.c52
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt2
-rw-r--r--source/blender/editors/datafiles/SConscript2
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c12
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c6
-rw-r--r--source/blender/editors/include/BIF_gl.h20
-rw-r--r--source/blender/editors/include/ED_armature.h6
-rw-r--r--source/blender/editors/include/ED_curve.h1
-rw-r--r--source/blender/editors/include/ED_datafiles.h6
-rw-r--r--source/blender/editors/include/ED_gpencil.h2
-rw-r--r--source/blender/editors/include/ED_image.h3
-rw-r--r--source/blender/editors/include/ED_lattice.h1
-rw-r--r--source/blender/editors/include/ED_mball.h2
-rw-r--r--source/blender/editors/include/ED_mesh.h3
-rw-r--r--source/blender/editors/include/ED_numinput.h4
-rw-r--r--source/blender/editors/include/ED_object.h5
-rw-r--r--source/blender/editors/include/ED_paint.h6
-rw-r--r--source/blender/editors/include/ED_space_api.h1
-rw-r--r--source/blender/editors/include/ED_transform.h1
-rw-r--r--source/blender/editors/include/ED_uvedit.h2
-rw-r--r--source/blender/editors/include/ED_view3d.h10
-rw-r--r--source/blender/editors/include/UI_icons.h4
-rw-r--r--source/blender/editors/include/UI_interface.h38
-rw-r--r--source/blender/editors/include/UI_resources.h4
-rw-r--r--source/blender/editors/interface/interface.c148
-rw-r--r--source/blender/editors/interface/interface_draw.c18
-rw-r--r--source/blender/editors/interface/interface_handlers.c802
-rw-r--r--source/blender/editors/interface/interface_icons.c2
-rw-r--r--source/blender/editors/interface/interface_intern.h54
-rw-r--r--source/blender/editors/interface/interface_layout.c235
-rw-r--r--source/blender/editors/interface/interface_ops.c213
-rw-r--r--source/blender/editors/interface/interface_panel.c103
-rw-r--r--source/blender/editors/interface/interface_regions.c293
-rw-r--r--source/blender/editors/interface/interface_templates.c192
-rw-r--r--source/blender/editors/interface/interface_utils.c2
-rw-r--r--source/blender/editors/interface/interface_widgets.c347
-rw-r--r--source/blender/editors/interface/resources.c84
-rw-r--r--source/blender/editors/interface/view2d.c2
-rw-r--r--source/blender/editors/interface/view2d_ops.c45
-rw-r--r--source/blender/editors/io/io_collada.c2
-rw-r--r--source/blender/editors/mask/mask_draw.c44
-rw-r--r--source/blender/editors/mask/mask_ops.c148
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt1
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c116
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c182
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c75
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c400
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c213
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c2
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c96
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c6
-rw-r--r--source/blender/editors/mesh/editmesh_select.c46
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c51
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c9
-rw-r--r--source/blender/editors/mesh/mesh_data.c11
-rw-r--r--source/blender/editors/mesh/mesh_intern.h4
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c2
-rw-r--r--source/blender/editors/mesh/mesh_ops.c2
-rw-r--r--source/blender/editors/metaball/mball_edit.c27
-rw-r--r--source/blender/editors/object/object_add.c61
-rw-r--r--source/blender/editors/object/object_bake.c2
-rw-r--r--source/blender/editors/object/object_bake_api.c211
-rw-r--r--source/blender/editors/object/object_constraint.c2
-rw-r--r--source/blender/editors/object/object_edit.c23
-rw-r--r--source/blender/editors/object/object_group.c64
-rw-r--r--source/blender/editors/object/object_hook.c3
-rw-r--r--source/blender/editors/object/object_intern.h3
-rw-r--r--source/blender/editors/object/object_lattice.c15
-rw-r--r--source/blender/editors/object/object_lod.c7
-rw-r--r--source/blender/editors/object/object_modifier.c4
-rw-r--r--source/blender/editors/object/object_ops.c3
-rw-r--r--source/blender/editors/object/object_relations.c105
-rw-r--r--source/blender/editors/object/object_select.c4
-rw-r--r--source/blender/editors/object/object_shapekey.c75
-rw-r--r--source/blender/editors/object/object_transform.c57
-rw-r--r--source/blender/editors/object/object_vgroup.c59
-rw-r--r--source/blender/editors/physics/rigidbody_object.c74
-rw-r--r--source/blender/editors/render/render_intern.h1
-rw-r--r--source/blender/editors/render/render_internal.c23
-rw-r--r--source/blender/editors/render/render_ops.c1
-rw-r--r--source/blender/editors/render/render_shading.c66
-rw-r--r--source/blender/editors/render/render_update.c9
-rw-r--r--source/blender/editors/screen/area.c75
-rw-r--r--source/blender/editors/screen/screen_edit.c2
-rw-r--r--source/blender/editors/screen/screen_ops.c15
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt1
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c164
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c787
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c643
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c876
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c1239
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h68
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c177
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c522
-rw-r--r--source/blender/editors/sculpt_paint/paint_undo.c54
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c322
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c174
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c305
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h7
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c12
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c10
-rw-r--r--source/blender/editors/space_action/action_draw.c2
-rw-r--r--source/blender/editors/space_action/action_select.c15
-rw-r--r--source/blender/editors/space_api/spacetypes.c18
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c11
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c6
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c2
-rw-r--r--source/blender/editors/space_clip/clip_draw.c28
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c18
-rw-r--r--source/blender/editors/space_clip/clip_ops.c21
-rw-r--r--source/blender/editors/space_clip/space_clip.c2
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c4
-rw-r--r--source/blender/editors/space_file/file_draw.c33
-rw-r--r--source/blender/editors/space_file/file_ops.c5
-rw-r--r--source/blender/editors/space_file/file_panels.c5
-rw-r--r--source/blender/editors/space_file/filesel.c22
-rw-r--r--source/blender/editors/space_file/space_file.c2
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c10
-rw-r--r--source/blender/editors/space_graph/graph_edit.c4
-rw-r--r--source/blender/editors/space_graph/graph_ops.c1
-rw-r--r--source/blender/editors/space_image/image_buttons.c16
-rw-r--r--source/blender/editors/space_image/image_edit.c39
-rw-r--r--source/blender/editors/space_image/image_intern.h1
-rw-r--r--source/blender/editors/space_image/image_ops.c42
-rw-r--r--source/blender/editors/space_image/space_image.c17
-rw-r--r--source/blender/editors/space_info/info_stats.c73
-rw-r--r--source/blender/editors/space_info/textview.c2
-rw-r--r--source/blender/editors/space_logic/logic_window.c32
-rw-r--r--source/blender/editors/space_node/drawnode.c59
-rw-r--r--source/blender/editors/space_node/node_draw.c4
-rw-r--r--source/blender/editors/space_node/node_edit.c6
-rw-r--r--source/blender/editors/space_node/node_group.c2
-rw-r--r--source/blender/editors/space_node/space_node.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c10
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c10
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c22
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c14
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h7
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c12
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c38
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c157
-rw-r--r--source/blender/editors/space_text/space_text.c11
-rw-r--r--source/blender/editors/space_text/text_draw.c5
-rw-r--r--source/blender/editors/space_text/text_ops.c6
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c69
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c154
-rw-r--r--source/blender/editors/space_view3d/drawobject.c103
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c55
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c11
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c155
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h4
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c66
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c187
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c64
-rw-r--r--source/blender/editors/transform/SConscript1
-rw-r--r--source/blender/editors/transform/transform.c172
-rw-r--r--source/blender/editors/transform/transform.h11
-rw-r--r--source/blender/editors/transform/transform_constraints.c5
-rw-r--r--source/blender/editors/transform/transform_conversions.c222
-rw-r--r--source/blender/editors/transform/transform_generics.c54
-rw-r--r--source/blender/editors/transform/transform_manipulator.c96
-rw-r--r--source/blender/editors/transform/transform_ops.c28
-rw-r--r--source/blender/editors/transform/transform_orientations.c2
-rw-r--r--source/blender/editors/transform/transform_snap.c80
-rw-r--r--source/blender/editors/util/ed_transverts.c2
-rw-r--r--source/blender/editors/util/ed_util.c2
-rw-r--r--source/blender/editors/util/numinput.c30
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c53
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c22
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c4
-rw-r--r--source/blender/freestyle/FRS_freestyle.h6
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp6
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp378
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h19
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h8
-rw-r--r--source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp13
-rw-r--r--source/blender/freestyle/intern/geometry/Grid.h2
-rw-r--r--source/blender/freestyle/intern/python/BPy_Convert.cpp9
-rw-r--r--source/blender/freestyle/intern/python/BPy_Freestyle.cpp3
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp15
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp4
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp22
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp34
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp2
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp36
-rw-r--r--source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp8
-rw-r--r--source/blender/freestyle/intern/stroke/BasicStrokeShaders.h15
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.cpp35
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.h18
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeIterators.h12
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeRep.cpp8
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeRep.h15
-rw-r--r--source/blender/freestyle/intern/system/PointerSequence.h2
-rw-r--r--source/blender/freestyle/intern/view_map/Interface0D.h12
-rw-r--r--source/blender/freestyle/intern/view_map/SteerableViewMap.h4
-rw-r--r--source/blender/gpu/CMakeLists.txt2
-rw-r--r--source/blender/gpu/GPU_buffers.h9
-rw-r--r--source/blender/gpu/GPU_draw.h2
-rw-r--r--source/blender/gpu/GPU_immediate.h11
-rw-r--r--source/blender/gpu/GPU_select.h50
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c156
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c8
-rw-r--r--source/blender/gpu/intern/gpu_draw.c32
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c58
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c2
-rw-r--r--source/blender/gpu/intern/gpu_material.c6
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c2
-rw-r--r--source/blender/gpu/intern/gpu_raster.c2
-rw-r--r--source/blender/gpu/intern/gpu_select.c330
-rw-r--r--source/blender/gpu/intern/gpu_utility.c4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl54
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_vert.glsl54
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex.glsl12
-rw-r--r--source/blender/ikplugin/intern/iksolver_plugin.c4
-rw-r--r--source/blender/ikplugin/intern/itasc_plugin.cpp2
-rw-r--r--source/blender/imbuf/IMB_imbuf.h20
-rw-r--r--source/blender/imbuf/intern/cineon/cineonlib.c4
-rw-r--r--source/blender/imbuf/intern/cineon/dpxlib.c4
-rw-r--r--source/blender/imbuf/intern/colormanagement.c2
-rw-r--r--source/blender/imbuf/intern/divers.c1
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp10
-rw-r--r--source/blender/imbuf/intern/rectop.c270
-rw-r--r--source/blender/imbuf/intern/scaling.c99
-rw-r--r--source/blender/imbuf/intern/util.c4
-rw-r--r--source/blender/makesdna/DNA_ID.h12
-rw-r--r--source/blender/makesdna/DNA_actuator_types.h16
-rw-r--r--source/blender/makesdna/DNA_anim_types.h3
-rw-r--r--source/blender/makesdna/DNA_brush_types.h94
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h3
-rw-r--r--source/blender/makesdna/DNA_curve_types.h6
-rw-r--r--source/blender/makesdna/DNA_linestyle_types.h2
-rw-r--r--source/blender/makesdna/DNA_material_types.h17
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h4
-rw-r--r--source/blender/makesdna/DNA_node_types.h6
-rw-r--r--source/blender/makesdna/DNA_object_types.h9
-rw-r--r--source/blender/makesdna/DNA_scene_types.h43
-rw-r--r--source/blender/makesdna/DNA_screen_types.h15
-rw-r--r--source/blender/makesdna/DNA_sensor_types.h4
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h10
-rw-r--r--source/blender/makesdna/DNA_space_types.h3
-rw-r--r--source/blender/makesdna/DNA_texture_types.h36
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h28
-rw-r--r--source/blender/makesdna/DNA_vfont_types.h2
-rw-r--r--source/blender/makesrna/RNA_access.h21
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt4
-rw-r--r--source/blender/makesrna/intern/SConscript3
-rw-r--r--source/blender/makesrna/intern/makesrna.c37
-rw-r--r--source/blender/makesrna/intern/rna_ID.c9
-rw-r--r--source/blender/makesrna/intern/rna_access.c229
-rw-r--r--source/blender/makesrna/intern/rna_action.c2
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c32
-rw-r--r--source/blender/makesrna/intern/rna_armature.c2
-rw-r--r--source/blender/makesrna/intern/rna_brush.c400
-rw-r--r--source/blender/makesrna/intern/rna_color.c56
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c8
-rw-r--r--source/blender/makesrna/intern/rna_curve_api.c15
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c2
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c3
-rw-r--r--source/blender/makesrna/intern/rna_internal.h21
-rw-r--r--source/blender/makesrna/intern/rna_lattice_api.c9
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c38
-rw-r--r--source/blender/makesrna/intern/rna_main.c14
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c6
-rw-r--r--source/blender/makesrna/intern/rna_material.c103
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c2
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c15
-rw-r--r--source/blender/makesrna/intern/rna_meta_api.c8
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c21
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c37
-rw-r--r--source/blender/makesrna/intern/rna_object.c21
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c17
-rw-r--r--source/blender/makesrna/intern/rna_packedfile.c4
-rw-r--r--source/blender/makesrna/intern/rna_particle.c248
-rw-r--r--source/blender/makesrna/intern/rna_scene.c25
-rw-r--r--source/blender/makesrna/intern/rna_screen.c9
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c146
-rw-r--r--source/blender/makesrna/intern/rna_sensor.c27
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c22
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c1
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c6
-rw-r--r--source/blender/makesrna/intern/rna_space.c90
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c1
-rw-r--r--source/blender/makesrna/intern/rna_ui.c8
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c12
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c146
-rw-r--r--source/blender/makesrna/intern/rna_wm.c67
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c40
-rw-r--r--source/blender/modifiers/intern/MOD_array.c756
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c5
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c8
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c3
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c2
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_mdd.c4
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_pc2.c3
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c2
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c6
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c1
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c11
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c271
-rw-r--r--source/blender/modifiers/intern/MOD_util.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvg_util.c6
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c19
-rw-r--r--source/blender/nodes/CMakeLists.txt7
-rw-r--r--source/blender/nodes/NOD_composite.h2
-rw-r--r--source/blender/nodes/NOD_shader.h2
-rw-r--r--source/blender/nodes/NOD_static_types.h3
-rw-r--r--source/blender/nodes/SConscript3
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c24
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sunbeams.c63
-rw-r--r--source/blender/nodes/intern/node_common.c34
-rw-r--r--source/blender/nodes/intern/node_exec.c6
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_linestyle.c54
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c50
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_uvmap.c9
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c12
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c128
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.h23
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.c2
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_select.c4
-rw-r--r--source/blender/python/bmesh/bmesh_py_utils.c137
-rw-r--r--source/blender/python/generic/bgl.c13
-rw-r--r--source/blender/python/generic/idprop_py_api.c2
-rw-r--r--source/blender/python/intern/bpy.c13
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c2
-rw-r--r--source/blender/python/intern/bpy_operator.c2
-rw-r--r--source/blender/python/intern/bpy_rna.c34
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.c23
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c228
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.h1
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c9
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c81
-rw-r--r--source/blender/render/extern/include/RE_bake.h18
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h2
-rw-r--r--source/blender/render/intern/include/render_types.h4
-rw-r--r--source/blender/render/intern/source/bake.c4
-rw-r--r--source/blender/render/intern/source/bake_api.c51
-rw-r--r--source/blender/render/intern/source/convertblender.c35
-rw-r--r--source/blender/render/intern/source/envmap.c4
-rw-r--r--source/blender/render/intern/source/external_engine.c11
-rw-r--r--source/blender/render/intern/source/imagetexture.c181
-rw-r--r--source/blender/render/intern/source/occlusion.c18
-rw-r--r--source/blender/render/intern/source/pipeline.c55
-rw-r--r--source/blender/render/intern/source/render_texture.c4
-rw-r--r--source/blender/render/intern/source/shadbuf.c2
-rw-r--r--source/blender/render/intern/source/shadeoutput.c14
-rw-r--r--source/blender/render/intern/source/volumetric.c2
-rw-r--r--source/blender/windowmanager/WM_api.h12
-rw-r--r--source/blender/windowmanager/WM_keymap.h2
-rw-r--r--source/blender/windowmanager/WM_types.h9
-rw-r--r--source/blender/windowmanager/intern/wm.c3
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c19
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c6
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c87
-rw-r--r--source/blender/windowmanager/intern/wm_files.c8
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c2
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c3
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c137
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c262
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c2
-rw-r--r--source/blender/windowmanager/intern/wm_window.c9
-rw-r--r--source/blender/windowmanager/wm_event_system.h5
-rw-r--r--source/blender/windowmanager/wm_event_types.h584
-rw-r--r--source/blenderplayer/CMakeLists.txt6
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c17
-rw-r--r--source/creator/CMakeLists.txt116
-rw-r--r--source/creator/creator.c11
-rw-r--r--source/creator/creator_launch_win.c85
-rw-r--r--source/creator/osx_locals.map2
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp4
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp2
-rw-r--r--source/gameengine/Converter/BL_ShapeActionActuator.h2
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp4
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.cpp7
-rw-r--r--source/gameengine/Expressions/Expression.cpp4
-rw-r--r--source/gameengine/Expressions/Expression.h4
-rw-r--r--source/gameengine/Expressions/IntValue.cpp2
-rw-r--r--source/gameengine/Expressions/Value.cpp8
-rw-r--r--source/gameengine/Expressions/Value.h6
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h2
-rw-r--r--source/gameengine/GameLogic/SCA_IScene.cpp44
-rw-r--r--source/gameengine/GameLogic/SCA_IScene.h6
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyActuator.cpp30
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyActuator.h1
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.cpp7
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.h1
-rw-r--r--source/gameengine/Ketsji/KX_Dome.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp136
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h16
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp116
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.h48
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_MouseActuator.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.cpp88
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.h20
-rw-r--r--source/gameengine/Ketsji/KX_NavMeshObject.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp101
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp37
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h2
-rw-r--r--source/gameengine/Ketsji/KX_SteeringActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.cpp223
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.h15
-rw-r--r--source/gameengine/Physics/Bullet/CMakeLists.txt1
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp25
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h1
-rw-r--r--source/gameengine/Physics/Bullet/SConscript1
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp6
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h2
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp2
-rw-r--r--source/gameengine/VideoTexture/ImageBuff.cpp4
-rw-r--r--source/gameengine/VideoTexture/ImageRender.cpp2
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.cpp11
-rw-r--r--tests/gtests/blenlib/BLI_listbase_test.cc39
-rw-r--r--tests/gtests/blenlib/BLI_math_color_test.cc14
-rw-r--r--tests/gtests/blenlib/BLI_math_geom_test.cc4
-rw-r--r--tests/gtests/blenlib/BLI_path_util_test.cc6
-rw-r--r--tests/gtests/blenlib/BLI_stack_test.cc13
-rw-r--r--tests/gtests/blenlib/BLI_string_test.cc34
-rw-r--r--tests/gtests/blenlib/CMakeLists.txt2
-rw-r--r--tests/python/bl_mesh_modifiers.py5
-rw-r--r--tests/python/bl_pyapi_mathutils.py44
-rw-r--r--tests/python/bl_pyapi_units.py23
1027 files changed, 37807 insertions, 16411 deletions
diff --git a/.gitignore b/.gitignore
index 6bc7b3394e4..b172c446553 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,9 @@ Desktop.ini
# local patches
/*.patch
/*.diff
+
+# in-source doc-gen
+/doc/doxygen/html/
+/doc/python_api/sphinx-in-tmp/
+/doc/python_api/sphinx-in/
+/doc/python_api/sphinx-out/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 432e5eb71e0..1e079d9d18c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -136,6 +136,11 @@ if(APPLE)
endif()
option(WITH_BUILDINFO "Include extra build details (only disable for development & faster builds)" ON)
+if(${CMAKE_VERSION} VERSION_LESS 2.8.8)
+ # add_library OBJECT arg unsupported
+ set(WITH_BUILDINFO OFF)
+endif()
+
option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON)
option(WITH_IK_SOLVER "Enable Legacy IK solver (only disable for development)" ON)
option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effects)" ON)
@@ -281,11 +286,13 @@ if(UNIX AND NOT APPLE)
endif()
option(WITH_PYTHON_INSTALL "Copy system python into the blender install folder" ON)
option(WITH_PYTHON_INSTALL_NUMPY "Copy system numpy into the blender install folder" ON)
-set(PYTHON_NUMPY_PATH "" CACHE PATH "Python to python site-packages or dist-packages containing 'numpy' module")
+set(PYTHON_NUMPY_PATH "" CACHE PATH "Path to python site-packages or dist-packages containing 'numpy' module")
mark_as_advanced(PYTHON_NUMPY_PATH)
if(UNIX AND NOT APPLE)
option(WITH_PYTHON_INSTALL_REQUESTS "Copy system requests into the blender install folder" ON)
+ set(PYTHON_REQUESTS_PATH "" CACHE PATH "Path to python site-packages or dist-packages containing 'requests' module")
+ mark_as_advanced(PYTHON_REQUESTS_PATH)
endif()
# Cycles
@@ -300,7 +307,11 @@ unset(PLATFORM_DEFAULT)
# LLVM
option(WITH_LLVM "Use LLVM" OFF)
-option(LLVM_STATIC "Link with LLVM static libraries" ON)
+if(APPLE)
+ option(LLVM_STATIC "Link with LLVM static libraries" ON) # we prefer static llvm build on Apple, dyn build possible though
+else()
+ option(LLVM_STATIC "Link with LLVM static libraries" OFF)
+endif()
mark_as_advanced(LLVM_STATIC)
# disable for now, but plan to support on all platforms eventually
@@ -368,7 +379,9 @@ if(APPLE)
endif()
execute_process(COMMAND uname -r OUTPUT_VARIABLE MAC_SYS) # check for actual system-version
- if(${MAC_SYS} MATCHES 13)
+ if(${MAC_SYS} MATCHES 14)
+ set(OSX_SYSTEM 10.10)
+ elseif(${MAC_SYS} MATCHES 13)
set(OSX_SYSTEM 10.9)
elseif(${MAC_SYS} MATCHES 12)
set(OSX_SYSTEM 10.8)
@@ -1025,6 +1038,10 @@ elseif(WIN32)
add_definitions(-DWIN32)
if(MSVC)
+ # needed for some MSVC installations
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
list(APPEND PLATFORM_LINKLIBS ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid psapi)
@@ -1048,6 +1065,8 @@ elseif(WIN32)
endif()
endif()
+ add_definitions(-DOIIO_STATIC_BUILD)
+
set(CMAKE_CXX_FLAGS "/nologo /J /Gd /EHsc /MP" CACHE STRING "MSVC MT C++ flags " FORCE)
set(CMAKE_C_FLAGS "/nologo /J /Gd /MP" CACHE STRING "MSVC MT C++ flags " FORCE)
@@ -1197,8 +1216,12 @@ elseif(WIN32)
${OPENCOLLADA}/lib/opencollada/xml.lib
${OPENCOLLADA}/lib/opencollada/buffer.lib
${OPENCOLLADA}/lib/opencollada/ftoa.lib
- ${OPENCOLLADA}/lib/opencollada/UTF.lib
)
+
+ if(NOT WITH_LLVM)
+ list(APPEND OPENCOLLADA_LIBRARIES ${OPENCOLLADA}/lib/opencollada/UTF.lib)
+ endif()
+
set(PCRE_LIBRARIES
${OPENCOLLADA}/lib/opencollada/pcre.lib
)
@@ -1234,15 +1257,23 @@ elseif(WIN32)
set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include)
set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR)
set(OPENEXR_LIBPATH ${OPENEXR}/lib)
- set(_openexr_suffix "-2_1")
- set(OPENEXR_LIBRARIES
- ${OPENEXR_LIBPATH}/Iex${_openexr_suffix}.lib
- ${OPENEXR_LIBPATH}/Half.lib # Half doesn't have a suffix?
- ${OPENEXR_LIBPATH}/IlmImf${_openexr_suffix}.lib
- ${OPENEXR_LIBPATH}/Imath${_openexr_suffix}.lib
- ${OPENEXR_LIBPATH}/IlmThread${_openexr_suffix}.lib
- )
- unset(_openexr_suffix)
+ if(MSVC12)
+ set(OPENEXR_LIBRARIES
+ ${OPENEXR_LIBPATH}/Iex-2_1.lib
+ ${OPENEXR_LIBPATH}/Half.lib
+ ${OPENEXR_LIBPATH}/IlmImf-2_1.lib
+ ${OPENEXR_LIBPATH}/Imath-2_1.lib
+ ${OPENEXR_LIBPATH}/IlmThread-2_1.lib
+ )
+ else()
+ set(OPENEXR_LIBRARIES
+ ${OPENEXR_LIBPATH}/Iex.lib
+ ${OPENEXR_LIBPATH}/Half.lib
+ ${OPENEXR_LIBPATH}/IlmImf.lib
+ ${OPENEXR_LIBPATH}/Imath.lib
+ ${OPENEXR_LIBPATH}/IlmThread.lib
+ )
+ endif()
endif(NOT OPENEXR_FOUND)
endif()
@@ -1288,8 +1319,8 @@ elseif(WIN32)
list(APPEND boost_extra_libs locale)
endif(WITH_INTERNATIONAL)
set(Boost_USE_STATIC_RUNTIME ON) # prefix lib
- set(Boost_USE_MULTITHREADED ON) # suffix -mt
- set(Boost_USE_STATIC_LIBS ON) # suffix -s
+ set(Boost_USE_MULTITHREADED ON) # suffix -mt
+ set(Boost_USE_STATIC_LIBS ON) # suffix -s
find_package(Boost COMPONENTS date_time filesystem thread regex system ${boost_extra_libs})
IF(NOT Boost_FOUND)
message(WARNING "USING HARDCODED boost locations")
@@ -1333,7 +1364,9 @@ elseif(WIN32)
find_package(OpenImageIO)
set(OPENIMAGEIO ${LIBDIR}/openimageio)
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
- set(OPENIMAGEIO_LIBRARIES optimized OpenImageIO debug OpenImageIO_d)
+ set(OIIO_OPTIMIZED optimized OpenImageIO optimized OpenImageIO_Util)
+ set(OIIO_DEBUG debug OpenImageIO_d debug OpenImageIO_Util_d)
+ set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0")
endif()
@@ -1415,7 +1448,7 @@ elseif(WIN32)
if(WITH_MINGW64)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
- set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} -lpthread")
+ list(APPEND PLATFORM_LINKLIBS -lpthread)
add_definitions(-DFREE_WINDOWS64 -DMS_WIN64)
endif()
@@ -1590,7 +1623,7 @@ elseif(WIN32)
LLVMX86Utils LLVMipa
LLVMipo LLVMCore)
# imagehelp is needed by LLVM 3.1 on MinGW, check lib\Support\Windows\Signals.inc
- set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} -limagehlp")
+ list(APPEND PLATFORM_LINKLIBS -limagehlp)
endif()
if(WITH_OPENCOLORIO)
@@ -1826,7 +1859,11 @@ elseif(APPLE)
)
set(OPENCOLLADA_LIBPATH ${OPENCOLLADA}/lib)
- set(OPENCOLLADA_LIBRARIES "OpenCOLLADASaxFrameworkLoader -lOpenCOLLADAFramework -lOpenCOLLADABaseUtils -lOpenCOLLADAStreamWriter -lMathMLSolver -lGeneratedSaxParser -lUTF -lxml2 -lbuffer -lftoa")
+ set(OPENCOLLADA_LIBRARIES "OpenCOLLADASaxFrameworkLoader -lOpenCOLLADAFramework -lOpenCOLLADABaseUtils -lOpenCOLLADAStreamWriter -lMathMLSolver -lGeneratedSaxParser -lxml2 -lbuffer -lftoa")
+ # Use UTF functions from collada if LLVM is not enabled
+ if(NOT WITH_LLVM)
+ set(OPENCOLLADA_LIBRARIES "${OPENCOLLADA_LIBRARIES} -lUTF")
+ endif()
# pcre is bundled with openCollada
#set(PCRE ${LIBDIR}/pcre)
#set(PCRE_LIBPATH ${PCRE}/lib)
@@ -1899,7 +1936,7 @@ elseif(APPLE)
if(WITH_LLVM)
set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
- set(LLVM_VERSION "3.1" CACHE STRING "Version of LLVM to use")
+ set(LLVM_VERSION "3.4" CACHE STRING "Version of LLVM to use")
if(EXISTS "${LLVM_DIRECTORY}/bin/llvm-config")
set(LLVM_CONFIG "${LLVM_DIRECTORY}/bin/llvm-config")
else()
@@ -1927,6 +1964,8 @@ elseif(APPLE)
OUTPUT_VARIABLE LLVM_LIBRARY
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE " " ";" LLVM_LIBRARY ${LLVM_LIBRARY})
+ else()
+ set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -lLLVM-3.4")
endif()
else()
message(FATAL_ERROR "LLVM not found.")
@@ -1991,6 +2030,8 @@ elseif(APPLE)
# Xcode 5 is always using CLANG, which has too low template depth of 128 for libmv
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth=1024")
endif()
+ # Get rid of eventually clashes, we export some symbols explicite as local
+ set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Xlinker -unexported_symbols_list -Xlinker ${CMAKE_SOURCE_DIR}/source/creator/osx_locals.map")
endif()
#-----------------------------------------------------------------------------
@@ -2469,62 +2510,13 @@ if(WITH_PYTHON)
if(WIN32)
# pass, we have this in an archive to extract
elseif(WITH_PYTHON_INSTALL AND WITH_PYTHON_INSTALL_NUMPY)
- # set but invalid
- # -- disabled until we make numpy bundled with blender - campbell
- if((NOT ${PYTHON_NUMPY_PATH} STREQUAL "") AND (NOT ${PYTHON_NUMPY_PATH} MATCHES NOTFOUND))
-# if(NOT EXISTS "${PYTHON_NUMPY_PATH}/numpy")
-# message(WARNING "PYTHON_NUMPY_PATH is invalid, numpy not found in '${PYTHON_NUMPY_PATH}' "
-# "WITH_PYTHON_INSTALL_NUMPY option will be ignored when installing python")
-# set(WITH_PYTHON_INSTALL_NUMPY OFF)
-# endif()
- # not set, so initialize
- else()
- string(REPLACE "." ";" _PY_VER_SPLIT "${PYTHON_VERSION}")
- list(GET _PY_VER_SPLIT 0 _PY_VER_MAJOR)
-
- # re-cache
- unset(PYTHON_NUMPY_PATH CACHE)
- find_path(PYTHON_NUMPY_PATH
- NAMES
- numpy
- HINTS
- "${PYTHON_LIBPATH}/python${PYTHON_VERSION}/"
- "${PYTHON_LIBPATH}/python${_PY_VER_MAJOR}/"
- PATH_SUFFIXES
- site-packages
- dist-packages
- NO_DEFAULT_PATH
- )
-
- if(NOT EXISTS "${PYTHON_NUMPY_PATH}")
- message(WARNING "'numpy' path could not be found in:\n"
- "'${PYTHON_LIBPATH}/python${PYTHON_VERSION}/site-packages/numpy', "
- "'${PYTHON_LIBPATH}/python${_PY_VER_MAJOR}/site-packages/numpy', "
- "'${PYTHON_LIBPATH}/python${PYTHON_VERSION}/dist-packages/numpy', "
- "'${PYTHON_LIBPATH}/python${_PY_VER_MAJOR}/dist-packages/numpy', "
- "WITH_PYTHON_INSTALL_NUMPY option will be ignored when installing python")
- set(WITH_PYTHON_INSTALL_NUMPY OFF)
- else()
- message(STATUS "numpy found at '${PYTHON_NUMPY_PATH}'")
- endif()
-
- unset(_PY_VER_SPLIT)
- unset(_PY_VER_MAJOR)
- endif()
+ find_python_package(numpy)
endif()
if(WIN32 OR APPLE)
# pass, we have this in lib/python/site-packages
elseif(WITH_PYTHON_INSTALL_REQUESTS)
- if(NOT EXISTS ${PYTHON_LIBPATH}/python${PYTHON_VERSION}/site-packages/requests)
- # gets annoying otherwise...
- if(FIRST_RUN)
- message(WARNING "'requests' path could not be found in:\n"
- "'${PYTHON_LIBPATH}/python${PYTHON_VERSION}/site-packages/requests'\n"
- "WITH_PYTHON_INSTALL_REQUESTS option will be ignored when installing python")
- endif()
- set(WITH_PYTHON_INSTALL_REQUESTS OFF)
- endif()
+ find_python_package(requests)
endif()
endif()
diff --git a/GNUmakefile b/GNUmakefile
index c7807720cb9..6e3e3cde5e8 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -237,26 +237,42 @@ test_deprecated:
test_style_c:
# run our own checks on C/C++ style
- PYTHONIOENCODING=utf_8 python3 "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" "$(BLENDER_DIR)/source/blender" "$(BLENDER_DIR)/source/creator" --no-length-check
+ PYTHONIOENCODING=utf_8 python3 \
+ "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
+ "$(BLENDER_DIR)/source/blender" \
+ "$(BLENDER_DIR)/source/creator" \
+ --no-length-check
test_style_c_qtc:
# run our own checks on C/C++ style
USE_QTC_TASK=1 \
- PYTHONIOENCODING=utf_8 python3 "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" "$(BLENDER_DIR)/source/blender" "$(BLENDER_DIR)/source/creator" --no-length-check > \
- test_style.tasks
+ PYTHONIOENCODING=utf_8 python3 \
+ "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
+ "$(BLENDER_DIR)/source/blender" \
+ "$(BLENDER_DIR)/source/creator" \
+ --no-length-check \
+ > \
+ "$(BLENDER_DIR)/test_style.tasks"
@echo "written: test_style.tasks"
test_style_osl:
# run our own checks on C/C++ style
- PYTHONIOENCODING=utf_8 python3 "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" "$(BLENDER_DIR)/intern/cycles/kernel/shaders" "$(BLENDER_DIR)/release/scripts/templates_osl"
+ PYTHONIOENCODING=utf_8 python3 \
+ "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
+ "$(BLENDER_DIR)/intern/cycles/kernel/shaders" \
+ "$(BLENDER_DIR)/release/scripts/templates_osl"
test_style_osl_qtc:
# run our own checks on C/C++ style
USE_QTC_TASK=1 \
- PYTHONIOENCODING=utf_8 python3 "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" "$(BLENDER_DIR)/intern/cycles/kernel/shaders" "$(BLENDER_DIR)/release/scripts/templates_osl" > \
- test_style.tasks
+ PYTHONIOENCODING=utf_8 python3 \
+ "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
+ "$(BLENDER_DIR)/intern/cycles/kernel/shaders" \
+ "$(BLENDER_DIR)/release/scripts/templates_osl" \
+ > \
+ "$(BLENDER_DIR)/test_style.tasks"
@echo "written: test_style.tasks"
# -----------------------------------------------------------------------------
@@ -281,7 +297,7 @@ check_cppcheck:
$(CMAKE_CONFIG)
cd "$(BUILD_DIR)" ; \
python3 "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py" 2> \
- "$(BLENDER_DIR)/check_cppcheck.txt"
+ "$(BLENDER_DIR)/check_cppcheck.txt"
@echo "written: check_cppcheck.txt"
check_clang_array:
@@ -306,22 +322,39 @@ check_smatch:
check_spelling_py:
cd "$(BUILD_DIR)" ; \
- PYTHONIOENCODING=utf_8 python3 "$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" "$(BLENDER_DIR)/release/scripts"
+ PYTHONIOENCODING=utf_8 python3 \
+ "$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
+ "$(BLENDER_DIR)/release/scripts"
check_spelling_c:
cd "$(BUILD_DIR)" ; \
- PYTHONIOENCODING=utf_8 python3 "$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" "$(BLENDER_DIR)/source"
+ PYTHONIOENCODING=utf_8 python3 \
+ "$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
+ "$(BLENDER_DIR)/source" \
+ "$(BLENDER_DIR)/intern/cycles" \
+ "$(BLENDER_DIR)/intern/guardedalloc" \
+ "$(BLENDER_DIR)/intern/ghost" \
check_spelling_c_qtc:
cd "$(BUILD_DIR)" ; USE_QTC_TASK=1 \
- PYTHONIOENCODING=utf_8 python3 "$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" "$(BLENDER_DIR)/source" > \
- "$(BLENDER_DIR)/check_spelling_c.tasks"
+ PYTHONIOENCODING=utf_8 python3 \
+ "$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
+ "$(BLENDER_DIR)/source" \
+ "$(BLENDER_DIR)/intern/cycles" \
+ "$(BLENDER_DIR)/intern/guardedalloc" \
+ "$(BLENDER_DIR)/intern/ghost" \
+ > \
+ "$(BLENDER_DIR)/check_spelling_c.tasks"
check_spelling_osl:
- cd "$(BUILD_DIR)" ; PYTHONIOENCODING=utf_8 python3 "$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" "$(BLENDER_DIR)/intern/cycles/kernel/shaders"
+ cd "$(BUILD_DIR)" ;\
+ PYTHONIOENCODING=utf_8 python3 \
+ "$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
+ "$(BLENDER_DIR)/intern/cycles/kernel/shaders"
check_descriptions:
- "$(BUILD_DIR)/bin/blender" --background -noaudio --factory-startup --python "$(BLENDER_DIR)/source/tools/check_source/check_descriptions.py"
+ "$(BUILD_DIR)/bin/blender" --background -noaudio --factory-startup --python \
+ "$(BLENDER_DIR)/source/tools/check_source/check_descriptions.py"
# -----------------------------------------------------------------------------
# Utilities
diff --git a/SConstruct b/SConstruct
index 6abf91c3c13..d1d0db909ad 100644
--- a/SConstruct
+++ b/SConstruct
@@ -70,7 +70,7 @@ quickdebug = None
##### BEGIN SETUP #####
-B.possible_types = ['core', 'player', 'player2', 'intern', 'extern']
+B.possible_types = ['core', 'player', 'player2', 'intern', 'extern', 'system']
B.binarykind = ['blender' , 'blenderplayer']
##################################
@@ -125,7 +125,7 @@ else:
B.quickie=[]
toolset = B.arguments.get('BF_TOOLSET', None)
-vcver = B.arguments.get('MSVS_VERSION', '9.0')
+vcver = B.arguments.get('MSVS_VERSION', '12.0')
if toolset:
print "Using " + toolset
@@ -210,6 +210,11 @@ if sys.platform=='win32':
if B.bitness==64:
env.Append(CPPFLAGS=['-DWIN64']) # -DWIN32 needed too, as it's used all over to target Windows generally
+if env['BF_DEBUG']:
+ env.Append(CPPDEFINES=['_DEBUG', 'DEBUG'])
+else:
+ env.Append(CPPDEFINES=['NDEBUG'])
+
if not env['BF_FANCY']:
B.bc.disable()
@@ -323,7 +328,10 @@ if env['OURPLATFORM']=='darwin':
print B.bc.OKGREEN + "Available SDK's: \n" + B.bc.ENDC + MACOSX_SDK_CHECK.replace('\t', '')
if env['MACOSX_SDK'] == '': # no set sdk, choosing best one found
- if 'OS X 10.9' in MACOSX_SDK_CHECK:
+ if 'OS X 10.10' in MACOSX_SDK_CHECK:
+ env['MACOSX_DEPLOYMENT_TARGET'] = '10.6'
+ env['MACOSX_SDK']='/Developer/SDKs/MacOSX10.10.sdk'
+ elif 'OS X 10.9' in MACOSX_SDK_CHECK:
env['MACOSX_DEPLOYMENT_TARGET'] = '10.6'
env['MACOSX_SDK']='/Developer/SDKs/MacOSX10.9.sdk'
elif 'OS X 10.8' in MACOSX_SDK_CHECK:
@@ -430,6 +438,7 @@ if env['OURPLATFORM']=='darwin':
print B.bc.OKGREEN + "Disabled OpenMP, not supported by compiler"
if env['WITH_BF_CYCLES_OSL'] == 1:
+ env['WITH_BF_LLVM'] = 1
OSX_OSL_LIBPATH = Dir(env.subst(env['BF_OSL_LIBPATH'])).abspath
# we need 2 variants of passing the oslexec with the force_load option, string and list type atm
if env['C_COMPILER_ID'] == 'gcc' and env['CCVERSION'] >= '4.8' or env['C_COMPILER_ID'] == 'clang' and env['CCVERSION'] >= '3.4':
@@ -437,6 +446,12 @@ if env['OURPLATFORM']=='darwin':
else:
env.Append(LINKFLAGS=['-L'+OSX_OSL_LIBPATH,'-loslcomp','-force_load '+ OSX_OSL_LIBPATH +'/liboslexec.a','-loslquery'])
env.Append(BF_PROGRAM_LINKFLAGS=['-Xlinker','-force_load','-Xlinker',OSX_OSL_LIBPATH +'/liboslexec.a'])
+ else:
+ env['WITH_BF_LLVM'] = 0
+
+ if env['WITH_BF_LLVM'] == 0:
+ # Due duplicated generic UTF functions, we pull them either from LLVMSupport or COLLADA
+ env.Append(BF_OPENCOLLADA_LIB=' UTF')
# Trying to get rid of eventually clashes, we export some symbols explicite as local
env.Append(LINKFLAGS=['-Xlinker','-unexported_symbols_list','-Xlinker','./source/creator/osx_locals.map'])
@@ -730,6 +745,8 @@ if B.targets != ['cudakernels']:
data_to_c_simple("release/datafiles/brushicons/soften.png")
data_to_c_simple("release/datafiles/brushicons/subtract.png")
data_to_c_simple("release/datafiles/brushicons/texdraw.png")
+ data_to_c_simple("release/datafiles/brushicons/texfill.png")
+ data_to_c_simple("release/datafiles/brushicons/texmask.png")
data_to_c_simple("release/datafiles/brushicons/thumb.png")
data_to_c_simple("release/datafiles/brushicons/twist.png")
data_to_c_simple("release/datafiles/brushicons/vertexdraw.png")
@@ -806,7 +823,7 @@ SConscript(B.root_build_dir+'/extern/SConscript')
# libraries to give as objects to linking phase
mainlist = []
for tp in B.possible_types:
- if (not tp == 'player') and (not tp == 'player2'):
+ if (not tp == 'player') and (not tp == 'player2') and (not tp == 'system'):
mainlist += B.create_blender_liblist(env, tp)
if B.arguments.get('BF_PRIORITYLIST', '0')=='1':
@@ -818,7 +835,17 @@ thestatlibs, thelibincs = B.setup_staticlibs(env)
thesyslibs = B.setup_syslibs(env)
if 'blender' in B.targets or not env['WITH_BF_NOBLENDER']:
- env.BlenderProg(B.root_build_dir, "blender", creob + mainlist + thestatlibs + dobj, thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blender')
+ blender_progname = "blender"
+ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
+ blender_progname = "blender-app"
+
+ lenv = env.Clone()
+ lenv.Append(LINKFLAGS = env['PLATFORM_LINKFLAGS'])
+ targetpath = B.root_build_dir + '/blender'
+ launcher_obj = [env.Object(B.root_build_dir + 'source/creator/creator/creator_launch_win', ['#source/creator/creator_launch_win.c'])]
+ env.BlenderProg(B.root_build_dir, 'blender', [launcher_obj] + B.resources, ['bf_utfconv'] + thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blender')
+
+ env.BlenderProg(B.root_build_dir, blender_progname, creob + mainlist + thestatlibs + dobj, thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blender')
if env['WITH_BF_PLAYER']:
playerlist = B.create_blender_liblist(env, 'player')
playerlist += B.create_blender_liblist(env, 'player2')
@@ -868,6 +895,10 @@ if env['OURPLATFORM']!='darwin':
td, tf = os.path.split(targetdir)
dotblenderinstall.append(env.Install(dir=td, source=srcfile))
+ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
+ scriptinstall.append(env.InstallAs(env['BF_INSTALLDIR'] + '/blender-app.exe.manifest',
+ 'source/icons/blender.exe.manifest'))
+
if env['WITH_BF_PYTHON']:
#-- local/VERSION/scripts
scriptpaths=['release/scripts']
@@ -953,8 +984,9 @@ if env['OURPLATFORM']!='darwin':
dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'lib')
for arch in env['BF_CYCLES_CUDA_BINARIES_ARCH']:
kernel_build_dir = os.path.join(B.root_build_dir, 'intern/cycles/kernel')
- cubin_file = os.path.join(kernel_build_dir, "kernel_%s.cubin" % arch)
- cubininstall.append(env.Install(dir=dir,source=cubin_file))
+ for suffix in ('', '_experimental'):
+ cubin_file = os.path.join(kernel_build_dir, "kernel%s_%s.cubin" % (suffix, arch))
+ cubininstall.append(env.Install(dir=dir,source=cubin_file))
# osl shaders
if env['WITH_BF_CYCLES_OSL']:
@@ -1095,16 +1127,15 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
dllsources += ['${BF_PTHREADS_LIBPATH}/${BF_PTHREADS_LIB}.dll']
if env['WITH_BF_SDL']:
- if env['OURPLATFORM'] == 'win64-vc':
- pass # we link statically already to SDL on win64
- else:
- dllsources.append('${BF_SDL_LIBPATH}/SDL.dll')
+ dllsources.append('${BF_SDL_LIBPATH}/SDL.dll')
if env['WITH_BF_PYTHON']:
if env['BF_DEBUG']:
dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_DLL}_d.dll')
+ dllsources.append('${BF_PYTHON_LIBPATH}/sqlite3_d.dll')
else:
dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_DLL}.dll')
+ dllsources.append('${BF_PYTHON_LIBPATH}/sqlite3.dll')
if env['WITH_BF_ICONV']:
if env['OURPLATFORM'] == 'win64-vc':
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index c5228512091..c1b2fd96c97 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -28,7 +28,7 @@ getopt \
--long source:,install:,tmp:,threads:,help,no-sudo,with-all,with-opencollada,ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,\
force-all,force-python,force-numpy,force-boost,force-ocio,force-oiio,force-llvm,force-osl,force-opencollada,\
force-ffmpeg,skip-python,skip-numpy,skip-boost,skip-ocio,skip-oiio,skip-llvm,skip-osl,skip-ffmpeg,\
-skip-opencollada,required-numpy,libyaml-cpp-ver: \
+skip-opencollada,required-numpy: \
-- "$@" \
)
@@ -176,11 +176,7 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--required-numpy
Use this in case your distro features a valid python package, but no matching Numpy one.
- It will force compilation of both python and numpy
-
- --libyaml-cpp-ver=<ver>
- Ubuntu hack: you may have to force installation of a non-defaut version of libyaml-cpp
- (e.g. ocio in trusty uses 0.3, while default version is 0.5... *sigh*)\""
+ It will force compilation of both python and numpy\""
##### Main Vars #####
@@ -202,12 +198,10 @@ BOOST_VERSION_MIN="1.49"
BOOST_FORCE_REBUILD=false
BOOST_SKIP=false
-OCIO_VERSION="1.0.7"
+OCIO_VERSION="1.0.9"
OCIO_VERSION_MIN="1.0"
OCIO_FORCE_REBUILD=false
OCIO_SKIP=false
-LIBYAML_CPP_VER_DEFINED=false
-LIBYAML_CPP_VER="0.0"
OPENEXR_VERSION="2.1.0"
OPENEXR_VERSION_MIN="2.0.1"
@@ -216,19 +210,19 @@ OPENEXR_FORCE_REBUILD=false
OPENEXR_SKIP=false
_with_built_openexr=false
-OIIO_VERSION="1.4.0"
+OIIO_VERSION="1.4.11"
OIIO_VERSION_MIN="1.4.0"
OIIO_FORCE_REBUILD=false
OIIO_SKIP=false
-LLVM_VERSION="3.3"
-LLVM_VERSION_MIN="3.3"
+LLVM_VERSION="3.4"
+LLVM_VERSION_MIN="3.4"
LLVM_VERSION_FOUND=""
LLVM_FORCE_REBUILD=false
LLVM_SKIP=false
# OSL needs to be compiled for now!
-OSL_VERSION="1.4.0"
+OSL_VERSION="1.5.0"
OSL_VERSION_MIN=$OSL_VERSION
OSL_FORCE_REBUILD=false
OSL_SKIP=false
@@ -238,8 +232,8 @@ OPENCOLLADA_VERSION="1.3"
OPENCOLLADA_FORCE_REBUILD=false
OPENCOLLADA_SKIP=false
-FFMPEG_VERSION="2.1.4"
-FFMPEG_VERSION_MIN="0.7.6"
+FFMPEG_VERSION="2.1.5"
+FFMPEG_VERSION_MIN="2.1.5"
FFMPEG_FORCE_REBUILD=false
FFMPEG_SKIP=false
_ffmpeg_list_sep=";"
@@ -453,9 +447,6 @@ while true; do
--required-numpy)
NUMPY_REQUIRED=true; shift; continue
;;
- --libyaml-cpp-ver)
- LIBYAML_CPP_VER_DEFINED=true; LIBYAML_CPP_VER="$2"; shift; shift; continue
- ;;
--)
# no more arguments to parse
break
@@ -483,21 +474,22 @@ _boost_version_nodots=`echo "$BOOST_VERSION" | sed -r 's/\./_/g'`
BOOST_SOURCE=( "http://sourceforge.net/projects/boost/files/boost/$BOOST_VERSION/boost_$_boost_version_nodots.tar.bz2/download" )
OCIO_SOURCE=( "https://github.com/imageworks/OpenColorIO/tarball/v$OCIO_VERSION" )
+
#OPENEXR_SOURCE=( "http://download.savannah.nongnu.org/releases/openexr/openexr-$OPENEXR_VERSION.tar.gz" )
OPENEXR_SOURCE=( "https://github.com/mont29/openexr.git" )
OPENEXR_REPO_UID="2787aa1cf652d244ed45ae124eb1553f6cff11ee"
ILMBASE_SOURCE=( "http://download.savannah.nongnu.org/releases/openexr/ilmbase-$ILMBASE_VERSION.tar.gz" )
#OIIO_SOURCE=( "https://github.com/OpenImageIO/oiio/archive/Release-$OIIO_VERSION.tar.gz" )
-OIIO_SOURCE=( "https://github.com/mont29/oiio.git" )
-OIIO_REPO_UID="99113d12619c90cf44721195a759674ea61f02b1"
+OIIO_SOURCE=( "https://github.com/OpenImageIO/oiio.git" )
+OIIO_REPO_UID="c9e67275a0b248ead96152f6d2221cc0c0f278a4"
LLVM_SOURCE=( "http://llvm.org/releases/$LLVM_VERSION/llvm-$LLVM_VERSION.src.tar.gz" )
LLVM_CLANG_SOURCE=( "http://llvm.org/releases/$LLVM_VERSION/clang-$LLVM_VERSION.src.tar.gz" "http://llvm.org/releases/$LLVM_VERSION/cfe-$LLVM_VERSION.src.tar.gz" )
#OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage/archive/Release-$OSL_VERSION.tar.gz" )
-#OSL_SOURCE=( "https://github.com/mont29/OpenShadingLanguage.git" )
-OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage.git" )
-OSL_REPO_UID="4abd672ed3979e5e965323201a5ba5ab802a76a9"
+#OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage.git" )
+OSL_SOURCE=( "https://github.com/mont29/OpenShadingLanguage.git" )
+OSL_REPO_UID="85179714e1bc69cd25ecb6bb711c1a156685d395"
OPENCOLLADA_SOURCE=( "https://github.com/KhronosGroup/OpenCOLLADA.git" )
OPENCOLLADA_REPO_UID="18da7f4109a8eafaa290a33f5550501cc4c8bae8"
@@ -973,12 +965,11 @@ clean_ILMBASE() {
compile_ILMBASE() {
# To be changed each time we make edits that would modify the compiled result!
- ilmbase_magic=8
+ ilmbase_magic=9
_init_ilmbase
# Clean install if needed!
magic_compile_check ilmbase-$ILMBASE_VERSION $ilmbase_magic
-
if [ $? -eq 1 -o $OPENEXR_FORCE_REBUILD == true ]; then
clean_ILMBASE
rm -rf $_openexr_inst
@@ -1060,7 +1051,7 @@ clean_OPENEXR() {
compile_OPENEXR() {
# To be changed each time we make edits that would modify the compiled result!
- openexr_magic=12
+ openexr_magic=13
# Clean install if needed!
magic_compile_check openexr-$OPENEXR_VERSION $openexr_magic
@@ -1189,11 +1180,11 @@ compile_OIIO() {
if [ ! -d $_src ]; then
mkdir -p $SRC
-# download OIIO_SOURCE[@] "$_src.tar.gz"
-
-# INFO "Unpacking OpenImageIO-$OIIO_VERSION"
-# tar -C $SRC --transform "s,(.*/?)oiio-Release-[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" \
-# -xf $_src.tar.gz
+ #download OIIO_SOURCE[@] "$_src.tar.gz"
+#
+ #INFO "Unpacking OpenImageIO-$OIIO_VERSION"
+ #tar -C $SRC --transform "s,(.*/?)oiio-Release-[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" \
+ #-xf $_src.tar.gz
git clone ${OIIO_SOURCE[0]} $_src
@@ -1421,11 +1412,11 @@ compile_OSL() {
if [ ! -d $_src ]; then
mkdir -p $SRC
-# download OSL_SOURCE[@] "$_src.tar.gz"
+ #download OSL_SOURCE[@] "$_src.tar.gz"
-# INFO "Unpacking OpenShadingLanguage-$OSL_VERSION"
-# tar -C $SRC --transform "s,(.*/?)OpenShadingLanguage-[^/]*(.*),\1OpenShadingLanguage-$OSL_VERSION\2,x" \
-# -xf $_src.tar.gz
+ #INFO "Unpacking OpenShadingLanguage-$OSL_VERSION"
+ #tar -C $SRC --transform "s,(.*/?)OpenShadingLanguage-[^/]*(.*),\1OpenShadingLanguage-$OSL_VERSION\2,x" \
+ #-xf $_src.tar.gz
git clone ${OSL_SOURCE[0]} $_src
@@ -1458,6 +1449,7 @@ compile_OSL() {
cmake_d="$cmake_d -D ILMBASE_VERSION=$ILMBASE_VERSION"
if [ $_with_built_openexr == true ]; then
+ INFO "ILMBASE_HOME=$INST/openexr"
cmake_d="$cmake_d -D ILMBASE_HOME=$INST/openexr"
fi
@@ -1702,7 +1694,7 @@ check_package_DEB() {
}
check_package_installed_DEB() {
- r=`dpkg -s $1 | grep -c '$1'`
+ r=`dpkg-query -W -f='${Status}' $1 | grep -c "install ok"`
if [ $r -ge 1 ]; then
return 0
@@ -1749,11 +1741,6 @@ install_DEB() {
PRINT ""
INFO "Installing dependencies for DEB-based distribution"
PRINT ""
- WARNING "Beware of recent Ubuntu/Debian!!!"
- PRINT "Ubuntu 14.4 and Debian Jessie come with a default libyaml-cpp in 0.5 version, while their ocio package still"
- PRINT "uses the 0.3 version. You have to use '--libyaml-cpp-ver=0.3' option (else Blender will builds with 0.5,"
- PRINT "and break when using packaged ocio)..."
- PRINT ""
PRINT "`eval _echo "$COMMON_INFO"`"
PRINT ""
@@ -1867,7 +1854,7 @@ install_DEB() {
# Only install jack if jack2 is not already installed!
JACK="libjack-dev"
JACK2="libjack-jackd2-dev"
- check_package_installed_DEB JACK2
+ check_package_installed_DEB $JACK2
if [ $? -eq 0 ]; then
_packages="$_packages $JACK2"
else
@@ -1990,13 +1977,14 @@ install_DEB() {
if $OCIO_SKIP; then
WARNING "Skipping OpenColorIO installation, as requested..."
else
- check_package_version_ge_DEB libopencolorio-dev $OCIO_VERSION_MIN
- if [ $? -eq 0 ]; then
- install_packages_DEB libopencolorio-dev
- clean_OCIO
- else
+ # XXX Always force build of own OCIO, until linux distro guys update their package to default libyaml-cpp ver (0.5)!
+ #check_package_version_ge_DEB libopencolorio-dev $OCIO_VERSION_MIN
+ #if [ $? -eq 0 ]; then
+ #install_packages_DEB libopencolorio-dev
+ #clean_OCIO
+ #else
compile_OCIO
- fi
+ #fi
fi
PRINT ""
@@ -2424,13 +2412,14 @@ install_RPM() {
if $OCIO_SKIP; then
WARNING "Skipping OpenColorIO installation, as requested..."
else
- check_package_version_ge_RPM OpenColorIO-devel $OCIO_VERSION_MIN
- if [ $? -eq 0 ]; then
- install_packages_RPM OpenColorIO-devel
- clean_OCIO
- else
+ # XXX Always force build of own OCIO, until linux distro guys update their package to default libyaml-cpp ver (0.5)!
+ #check_package_version_ge_RPM OpenColorIO-devel $OCIO_VERSION_MIN
+ #if [ $? -eq 0 ]; then
+ #install_packages_RPM OpenColorIO-devel
+ #clean_OCIO
+ #else
compile_OCIO
- fi
+ #fi
fi
PRINT ""
@@ -2733,14 +2722,15 @@ install_ARCH() {
if $OCIO_SKIP; then
WARNING "Skipping OpenColorIO installation, as requested..."
else
- check_package_version_ge_ARCH opencolorio $OCIO_VERSION_MIN
- if [ $? -eq 0 ]; then
- install_packages_ARCH opencolorio yaml-cpp tinyxml
- clean_OCIO
- else
+ # XXX Always force build of own OCIO, until linux distro guys update their package to default libyaml-cpp ver (0.5)!
+ #check_package_version_ge_ARCH opencolorio $OCIO_VERSION_MIN
+ #if [ $? -eq 0 ]; then
+ #install_packages_ARCH opencolorio yaml-cpp tinyxml
+ #clean_OCIO
+ #else
install_packages_ARCH yaml-cpp tinyxml
compile_OCIO
- fi
+ #fi
fi
PRINT ""
diff --git a/build_files/buildbot/config/user-config-glibc211-i686.py b/build_files/buildbot/config/user-config-glibc211-i686.py
index 41d6a4a78dc..d7a1439e003 100644
--- a/build_files/buildbot/config/user-config-glibc211-i686.py
+++ b/build_files/buildbot/config/user-config-glibc211-i686.py
@@ -22,7 +22,7 @@ BF_OPENCOLLADA_LIB_STATIC = '${BF_OPENCOLLADA}/lib/libOpenCOLLADAStreamWriter.a
'${BF_OPENCOLLADA}/lib/libOpenCOLLADAFramework.a ' + \
'${BF_OPENCOLLADA}/lib/libOpenCOLLADABaseUtils.a ' + \
'${BF_OPENCOLLADA}/lib/libGeneratedSaxParser.a ' + \
- '${BF_OPENCOLLADA}/lib/libUTF.a ${BF_OPENCOLLADA}/lib/libMathMLSolver.a ' + \
+ '${BF_OPENCOLLADA}/lib/libMathMLSolver.a ' + \
'${BF_OPENCOLLADA}/lib/libbuffer.a ${BF_OPENCOLLADA}/lib/libftoa.a ' + \
'/usr/lib/libxml2.a /usr/lib/libexpat.a /usr/lib/libpcre.a'
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib /home/sources/staticlibs/lib64'
@@ -134,8 +134,8 @@ BF_OSL_COMPILER = '${BF_OSL}/bin/oslc'
WITH_BF_LLVM = True
WITH_BF_STATICLLVM = False
-BF_LLVM = '/opt/lib/llvm-3.1'
-BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \
+BF_LLVM = '/opt/lib/llvm-3.4.2'
+BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMObject LLVMX86Info LLVMX86AsmPrinter ' + \
'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \
'LLVMTarget LLVMMC LLVMCore LLVMSupport'
BF_LLVM_LIBPATH = '${BF_LLVM}/lib'
diff --git a/build_files/buildbot/config/user-config-glibc211-x86_64.py b/build_files/buildbot/config/user-config-glibc211-x86_64.py
index d94923cc39d..f07c447bf29 100644
--- a/build_files/buildbot/config/user-config-glibc211-x86_64.py
+++ b/build_files/buildbot/config/user-config-glibc211-x86_64.py
@@ -22,7 +22,7 @@ BF_OPENCOLLADA_LIB_STATIC = '${BF_OPENCOLLADA}/lib/libOpenCOLLADAStreamWriter.a
'${BF_OPENCOLLADA}/lib/libOpenCOLLADAFramework.a ' + \
'${BF_OPENCOLLADA}/lib/libOpenCOLLADABaseUtils.a ' + \
'${BF_OPENCOLLADA}/lib/libGeneratedSaxParser.a ' + \
- '${BF_OPENCOLLADA}/lib/libUTF.a ${BF_OPENCOLLADA}/lib/libMathMLSolver.a ' + \
+ '${BF_OPENCOLLADA}/lib/libMathMLSolver.a ' + \
'${BF_OPENCOLLADA}/lib/libbuffer.a ${BF_OPENCOLLADA}/lib/libftoa.a ' + \
'/usr/lib/libxml2.a /usr/lib/libexpat.a /usr/lib/libpcre.a'
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib /home/sources/staticlibs/lib64'
@@ -134,8 +134,8 @@ BF_OSL_COMPILER = '${BF_OSL}/bin/oslc'
WITH_BF_LLVM = True
WITH_BF_STATICLLVM = False
-BF_LLVM = '/opt/lib/llvm-3.1'
-BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \
+BF_LLVM = '/opt/lib/llvm-3.4.2'
+BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMObject LLVMX86Info LLVMX86AsmPrinter ' + \
'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \
'LLVMTarget LLVMMC LLVMCore LLVMSupport'
BF_LLVM_LIBPATH = '${BF_LLVM}/lib'
diff --git a/build_files/buildbot/config/user-config-mac-i386.py b/build_files/buildbot/config/user-config-mac-i386.py
index 296b752649d..ab93628c78d 100644
--- a/build_files/buildbot/config/user-config-mac-i386.py
+++ b/build_files/buildbot/config/user-config-mac-i386.py
@@ -3,3 +3,5 @@ MACOSX_ARCHITECTURE = 'i386' # valid archs: ppc, i386, ppc64, x86_64
WITH_BF_CYCLES_CUDA_BINARIES = True
+WITH_BF_CYCLES_OSL = False # OSL never worked on OSX 32bit !
+
diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg
index 6b3efb469b3..5f315337d3a 100644
--- a/build_files/buildbot/master.cfg
+++ b/build_files/buildbot/master.cfg
@@ -3,6 +3,52 @@
# <pep8 compliant>
+"""
+Stock Twisted directory lister doesn't provide any information about last file
+modification time, we hack the class a bit in order to have such functionaliity
+:)
+"""
+
+from buildbot.status.web.base import DirectoryLister
+
+
+def get_files_and_directories(self, directory):
+ from twisted.web.static import (getTypeAndEncoding,
+ formatFileSize)
+ import urllib
+ import cgi
+ import time
+ import os
+ files = []
+ dirs = []
+ for path in directory:
+ url = urllib.quote(path, "/")
+ escapedPath = cgi.escape(path)
+ lastmodified = time.ctime(os.path.getmtime(
+ os.path.join(self.path, path)))
+ if os.path.isdir(os.path.join(self.path, path)):
+ url = url + '/'
+ dirs.append({'text': escapedPath + "/", 'href': url,
+ 'size': '', 'type': '[Directory]',
+ 'encoding': '',
+ 'lastmodified': lastmodified})
+ else:
+ mimetype, encoding = getTypeAndEncoding(path, self.contentTypes,
+ self.contentEncodings,
+ self.defaultType)
+ try:
+ size = os.stat(os.path.join(self.path, path)).st_size
+ except OSError:
+ continue
+ files.append({
+ 'text': escapedPath, "href": url,
+ 'type': '[%s]' % mimetype,
+ 'encoding': (encoding and '[%s]' % encoding or ''),
+ 'size': formatFileSize(size),
+ 'lastmodified': lastmodified})
+ return dirs, files
+DirectoryLister._getFilesAndDirectories = get_files_and_directories
+
# Dictionary that the buildmaster pays attention to.
c = BuildmasterConfig = {}
@@ -32,51 +78,83 @@ c['change_source'] = GitPoller(
'git://git.blender.org/blender.git',
pollinterval=1200)
+
+# CODEBASES
+#
+# Allow to controll separately things like branches for each repo and submodules.
+
+all_repositories = {
+ r'git://git.blender.org/blender.git': 'blender',
+ r'git://git.blender.org/blender-translations.git': 'blender-translations',
+ r'git://git.blender.org/blender-addons.git': 'blender-addons',
+ r'git://git.blender.org/blender-addons-contrib.git': 'blender-addons-contrib',
+ r'git://git.blender.org/scons.git': 'scons',
+ r'https://svn.blender.org/svnroot/bf-blender/': 'lib svn',
+}
+
+def codebaseGenerator(chdict):
+ return all_repositories[chdict['repository']]
+
+c['codebaseGenerator'] = codebaseGenerator
+
+
# SCHEDULERS
#
# Decide how to react to incoming changes.
# from buildbot.scheduler import Scheduler
-from buildbot.schedulers import timed
+from buildbot.schedulers import timed, forcesched
c['schedulers'] = []
+def schedule_force_build(name):
+ c['schedulers'].append(forcesched.ForceScheduler(name='force ' + name,
+ builderNames=[name],
+ codebases=[forcesched.CodebaseParameter(
+ codebase="blender",
+ branch=forcesched.ChoiceStringParameter(
+ name="branch", choices=["master", "testbuild"], default="master"),
+ # Do not hide revision, can be handy!
+ repository=forcesched.FixedParameter(name="repository", default="", hide=True),
+ project=forcesched.FixedParameter(name="project", default="", hide=True)),
+ # For now, hide other codebases.
+ forcesched.CodebaseParameter(hide=True, codebase="blender-translations"),
+ forcesched.CodebaseParameter(hide=True, codebase="blender-addons"),
+ forcesched.CodebaseParameter(hide=True, codebase="blender-addons-contrib"),
+ forcesched.CodebaseParameter(hide=True, codebase="scons"),
+ forcesched.CodebaseParameter(hide=True, codebase="lib svn")],
+ properties=[]))
+
+
def schedule_build(name, hour, minute=0):
c['schedulers'].append(timed.Nightly(name='nightly ' + name,
+ codebases={
+ "blender": {"repository": ""},
+ "blender-translations": {"repository": ""},
+ "blender-addons": {"repository": ""},
+ "blender-addons-contrib": {"repository": ""},
+ "scons": {"repository": ""},
+ "lib svn": {"repository": ""}},
+ branch=None,
builderNames=[name],
hour=hour,
minute=minute))
-"""
-schedule_cycle = 4
-
-for i in range(0, schedule_cycle):
- names = []
- for j in range(0, len(buildernames)):
- if j % schedule_cycle == i:
- names += [buildernames[j]]
-
- print(names)
- c['schedulers'].append(timed.Nightly(name='nightly' + str(i),
- builderNames=names,
- hour=3+i,
- minute=0))
-"""
# BUILDERS
#
-# The 'builders' list defines the Builders, which tell Buildbot how to perform a build:
-# what steps, and which slaves can execute them. Note that any particular build will
-# only take place on one slave.
+# The 'builders' list defines the Builders, which tell Buildbot how to
+# perform a build: what steps, and which slaves can execute them.
+# Note that any particular build will only take place on one slave.
from buildbot.process.factory import BuildFactory
+from buildbot.process.properties import Interpolate
from buildbot.steps.source import SVN
from buildbot.steps.source import Git
from buildbot.steps.shell import ShellCommand
from buildbot.steps.shell import Compile
from buildbot.steps.shell import Test
from buildbot.steps.transfer import FileUpload
-# from buildbot.steps.transfer import FileDownload
from buildbot.steps.master import MasterShellCommand
from buildbot.config import BuilderConfig
@@ -86,7 +164,8 @@ c['builders'] = []
buildernames = []
-def add_builder(c, name, libdir, factory, branch='', rsync=False, hour=3, minute=0):
+def add_builder(c, name, libdir, factory, branch='',
+ rsync=False, hour=3, minute=0):
slavenames = []
for slave in master_private.slaves:
@@ -95,31 +174,69 @@ def add_builder(c, name, libdir, factory, branch='', rsync=False, hour=3, minute
if len(slavenames) > 0:
f = factory(name, libdir, branch, rsync)
- c['builders'].append(BuilderConfig(name=name, slavenames=slavenames, factory=f, category='blender'))
+ c['builders'].append(BuilderConfig(name=name,
+ slavenames=slavenames,
+ factory=f,
+ category='blender'))
buildernames.append(name)
schedule_build(name, hour, minute)
+ schedule_force_build(name)
# common steps
+
def git_submodule_step(submodule):
- return Git(name=submodule+'.git', repourl='git://git.blender.org/' + submodule + '.git', mode='update', workdir=submodule + '.git')
+ return Git(name=submodule + '.git',
+ repourl='git://git.blender.org/' + submodule + '.git',
+ mode='update',
+ codebase=submodule,
+ workdir=submodule + '.git')
+
def git_step(branch=''):
if branch:
- return Git(name='blender.git', repourl='git://git.blender.org/blender.git', mode='update', branch=branch, workdir='blender.git', submodules=True)
+ return Git(name='blender.git',
+ repourl='git://git.blender.org/blender.git',
+ mode='update',
+ branch=branch,
+ codebase='blender',
+ workdir='blender.git',
+ submodules=True)
else:
- return Git(name='blender.git', repourl='git://git.blender.org/blender.git', mode='update', workdir='blender.git', submodules=True)
+ return Git(name='blender.git',
+ repourl='git://git.blender.org/blender.git',
+ mode='update',
+ codebase='blender',
+ workdir='blender.git',
+ submodules=True)
+
def git_submodules_update():
- command = ['git', 'submodule', 'foreach', '--recursive', 'git', 'pull', 'origin', 'master']
- return ShellCommand(name='Submodules Update', command=command, description='updating', descriptionDone='up to date', workdir='blender.git')
+ command = ['git', 'submodule', 'foreach', '--recursive',
+ 'git', 'pull', 'origin', 'master']
+ return ShellCommand(name='Submodules Update',
+ command=command,
+ description='updating',
+ descriptionDone='up to date',
+ workdir='blender.git')
+
def lib_svn_step(dir):
- return SVN(name='lib svn', baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/lib/' + dir, mode='update', defaultBranch='trunk', workdir='lib/' + dir)
+ return SVN(name='lib svn',
+ baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/lib/' + dir,
+ codebase='lib svn',
+ mode='update',
+ defaultBranch='trunk',
+ workdir='lib/' + dir)
+
def rsync_step(id, branch, rsync_script):
- return ShellCommand(name='rsync', command=['python', rsync_script, id, branch], description='uploading', descriptionDone='uploaded', workdir='install')
+ return ShellCommand(name='rsync',
+ command=['python', rsync_script, id, branch],
+ description='uploading',
+ descriptionDone='uploaded',
+ workdir='install')
# generic builder
@@ -136,21 +253,38 @@ def generic_builder(id, libdir='', branch='', rsync=False):
if libdir != '':
f.addStep(lib_svn_step(libdir))
- for submodule in ('blender-translations', 'blender-addons', 'blender-addons-contrib', 'scons'):
+ for submodule in ('blender-translations',
+ 'blender-addons',
+ 'blender-addons-contrib',
+ 'scons'):
f.addStep(git_submodule_step(submodule))
+
f.addStep(git_step(branch))
f.addStep(git_submodules_update())
f.addStep(Compile(command=['python', compile_script, id], timeout=3600))
f.addStep(Test(command=['python', test_script, id]))
- f.addStep(ShellCommand(name='package', command=['python', pack_script, id, branch], description='packaging', descriptionDone='packaged'))
+ f.addStep(ShellCommand(name='package',
+ command=['python', pack_script, id, branch or Interpolate('%(src:blender:branch)s')],
+ description='packaging',
+ descriptionDone='packaged'))
if rsync:
f.addStep(rsync_step(id, branch, rsync_script))
elif id.find('cmake') != -1:
- f.addStep(FileUpload(name='upload', slavesrc='buildbot_upload.zip', masterdest=filename, maxsize=150 * 1024 * 1024))
+ f.addStep(FileUpload(name='upload',
+ slavesrc='buildbot_upload.zip',
+ masterdest=filename,
+ maxsize=150 * 1024 * 1024))
else:
- f.addStep(FileUpload(name='upload', slavesrc='buildbot_upload.zip', masterdest=filename, maxsize=150 * 1024 * 1024, workdir='install'))
- f.addStep(MasterShellCommand(name='unpack', command=['python', unpack_script, filename], description='unpacking', descriptionDone='unpacked'))
+ f.addStep(FileUpload(name='upload',
+ slavesrc='buildbot_upload.zip',
+ masterdest=filename,
+ maxsize=150 * 1024 * 1024,
+ workdir='install'))
+ f.addStep(MasterShellCommand(name='unpack',
+ command=['python', unpack_script, filename],
+ description='unpacking',
+ descriptionDone='unpacked'))
return f
# builders
@@ -159,10 +293,6 @@ add_builder(c, 'mac_x86_64_10_6_scons', 'darwin-9.x.universal', generic_builder,
add_builder(c, 'mac_i386_10_6_scons', 'darwin-9.x.universal', generic_builder, hour=11)
add_builder(c, 'linux_glibc211_i386_scons', '', generic_builder, hour=1)
add_builder(c, 'linux_glibc211_x86_64_scons', '', generic_builder, hour=2)
-add_builder(c, 'win32_scons', 'windows', generic_builder, hour=1)
-add_builder(c, 'win64_scons', 'win64', generic_builder, hour=2)
-#add_builder(c, 'win32_scons_vc2012', 'windows_vc11', generic_builder, hour=1)
-#add_builder(c, 'win64_scons_vc2012', 'win64_vc11', generic_builder, hour=2)
add_builder(c, 'win32_scons_vc2013', 'windows_vc12', generic_builder, hour=1)
add_builder(c, 'win64_scons_vc2013', 'win64_vc12', generic_builder, hour=2)
#add_builder(c, 'mingw_win32_scons', 'mingw32', generic_builder, hour=4)
@@ -195,15 +325,16 @@ authz_cfg = authz.Authz(
# change any of these to True to enable; see the manual for more
# options
gracefulShutdown=False,
- forceBuild='auth', # use this to test your slave once it is set up
+ forceBuild=True, # use this to test your slave once it is set up
forceAllBuilds=False,
pingBuilder=False,
- stopBuild='auth',
+ stopBuild=True,
stopAllBuilds=False,
- cancelPendingBuild='auth',
+ cancelPendingBuild=True,
)
c['status'].append(html.WebStatus(http_port=8010, authz=authz_cfg))
+#c['status'].append(html.WebStatus(http_port=8010))
# PROJECT IDENTITY
diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py
index 67fae89a22a..a5dadbde05c 100644
--- a/build_files/buildbot/slave_compile.py
+++ b/build_files/buildbot/slave_compile.py
@@ -53,9 +53,13 @@ if builder.find('cmake') != -1:
retcode = subprocess.call(['make', '-s', '-j4', 'install'])
sys.exit(retcode)
else:
+ python_bin = 'python'
+ if builder.find('linux') != -1:
+ python_bin = '/opt/lib/python-2.7/bin/python2.7'
+
# scons
os.chdir(blender_dir)
- scons_cmd = ['python', 'scons/scons.py']
+ scons_cmd = [python_bin, 'scons/scons.py']
scons_options = ['BF_FANCY=False']
# We're using the same rules as release builder, so tweak
@@ -148,7 +152,7 @@ else:
scons_options.append('MSVS_VERSION=12.0')
scons_options.append('MSVC_VERSION=12.0')
scons_options.append('WITH_BF_CYCLES_CUDA_BINARIES=1')
- scons_options.append('BF_CYCLES_CUDA_NVCC=nvcc')
+ scons_options.append('BF_CYCLES_CUDA_NVCC=nvcc.exe')
scons_options.append('BF_NUMJOBS=1')
elif builder.find('mac') != -1:
@@ -164,8 +168,6 @@ else:
os.makedirs(install_dir)
if builder.endswith('vc2013'):
dlls = ('msvcp120.dll', 'msvcr120.dll', 'vcomp120.dll')
- else:
- dlls = ('msvcm90.dll', 'msvcp90.dll', 'msvcr90.dll', 'vcomp90.dll', 'Microsoft.VC90.CRT.manifest', 'Microsoft.VC90.OpenMP.manifest')
if builder.find('win64') == -1:
dlls_path = '..\\..\\..\\redist\\x86'
else:
@@ -173,6 +175,6 @@ else:
for dll in dlls:
shutil.copyfile(os.path.join(dlls_path, dll), os.path.join(install_dir, dll))
- retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options)
+ retcode = subprocess.call([python_bin, 'scons/scons.py'] + scons_options)
sys.exit(retcode)
diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py
index 2a940f97628..c989cd8e31a 100644
--- a/build_files/buildbot/slave_pack.py
+++ b/build_files/buildbot/slave_pack.py
@@ -33,13 +33,15 @@ if len(sys.argv) < 2:
sys.exit(1)
builder = sys.argv[1]
-branch = ''
-
-if len(sys.argv) >= 3:
- branch = sys.argv[2]
+# Never write branch if it is master.
+branch = sys.argv[2] if (len(sys.argv) >= 3 and sys.argv[2] != 'master') else ''
# scons does own packaging
if builder.find('scons') != -1:
+ python_bin = 'python'
+ if builder.find('linux') != -1:
+ python_bin = '/opt/lib/python-2.7/bin/python2.7'
+
os.chdir('../blender.git')
scons_options = ['BF_QUICK=slnt', 'BUILDBOT_BRANCH=' + branch, 'buildslave', 'BF_FANCY=False']
@@ -82,7 +84,7 @@ if builder.find('scons') != -1:
os.system('cp %s %s' % (software_gl, install_dir))
os.system('chmod 755 %s' % (os.path.join(install_dir, 'blender-softwaregl')))
- retcode = subprocess.call(['schroot', '-c', chroot_name, '--', 'python', 'scons/scons.py'] + scons_options)
+ retcode = subprocess.call(['schroot', '-c', chroot_name, '--', python_bin, 'scons/scons.py'] + scons_options)
sys.exit(retcode)
else:
@@ -111,7 +113,7 @@ if builder.find('scons') != -1:
scons_options.append('BF_CONFIG=' + os.path.join(config_dir, config))
- retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options)
+ retcode = subprocess.call([python_bin, 'scons/scons.py'] + scons_options)
sys.exit(retcode)
# clean release directory if it already exists
diff --git a/build_files/cmake/Modules/FindGLEW.cmake b/build_files/cmake/Modules/FindGLEW.cmake
index 3f7cca333cc..8589e143ada 100644
--- a/build_files/cmake/Modules/FindGLEW.cmake
+++ b/build_files/cmake/Modules/FindGLEW.cmake
@@ -1,59 +1,77 @@
+# - Find GLEW library
+# Find the native Glew includes and library
+# This module defines
+# GLEW_INCLUDE_DIRS, where to find glew.h, Set when
+# GLEW_INCLUDE_DIR is found.
+# GLEW_ROOT_DIR, The base directory to search for Glew.
+# This can also be an environment variable.
+# GLEW_FOUND, If false, do not try to use Glew.
#
-# Try to find GLEW library and include path.
-# Once done this will define
+# also defined,
+# GLEW_LIBRARY, where to find the Glew library.
+# GLEW_MX_LIBRARY, where to find the GlewMX library.
+
+#=============================================================================
+# Copyright 2014 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
#
-# GLEW_FOUND
-# GLEW_INCLUDE_PATH
-# GLEW_LIBRARY
-#
-
-IF (WIN32)
- FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
- $ENV{PROGRAMFILES}/GLEW/include
- ${PROJECT_SOURCE_DIR}/src/nvgl/glew/include
- DOC "The directory where GL/glew.h resides")
- IF (NV_SYSTEM_PROCESSOR STREQUAL "AMD64")
- FIND_LIBRARY( GLEW_LIBRARY
- NAMES glew64 glew64s
- PATHS
- $ENV{PROGRAMFILES}/GLEW/lib
- ${PROJECT_SOURCE_DIR}/src/nvgl/glew/bin
- ${PROJECT_SOURCE_DIR}/src/nvgl/glew/lib
- DOC "The GLEW library (64-bit)"
- )
- ELSE(NV_SYSTEM_PROCESSOR STREQUAL "AMD64")
- FIND_LIBRARY( GLEW_LIBRARY
- NAMES glew GLEW glew32 glew32s
- PATHS
- $ENV{PROGRAMFILES}/GLEW/lib
- ${PROJECT_SOURCE_DIR}/src/nvgl/glew/bin
- ${PROJECT_SOURCE_DIR}/src/nvgl/glew/lib
- DOC "The GLEW library"
- )
- ENDIF(NV_SYSTEM_PROCESSOR STREQUAL "AMD64")
-ELSE (WIN32)
- FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
- /usr/include
- /usr/local/include
- /sw/include
- /opt/local/include
- DOC "The directory where GL/glew.h resides")
- FIND_LIBRARY( GLEW_LIBRARY
- NAMES GLEW glew
- PATHS
- /usr/lib64
- /usr/lib
- /usr/local/lib64
- /usr/local/lib
- /sw/lib
- /opt/local/lib
- DOC "The GLEW library")
-ENDIF (WIN32)
-
-IF (GLEW_INCLUDE_PATH)
- SET(GLEW_FOUND TRUE)
-ELSE (GLEW_INCLUDE_PATH)
- SET(GLEW_FOUND FALSE)
-ENDIF (GLEW_INCLUDE_PATH)
-
-MARK_AS_ADVANCED( GLEW_FOUND )
+# 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 GLEW_ROOT_DIR was defined in the environment, use it.
+IF(NOT GLEW_ROOT_DIR AND NOT $ENV{GLEW_ROOT_DIR} STREQUAL "")
+ SET(GLEW_ROOT_DIR $ENV{GLEW_ROOT_DIR})
+ENDIF()
+
+SET(_glew_SEARCH_DIRS
+ ${GLEW_ROOT_DIR}
+ /usr/local
+)
+
+FIND_PATH(GLEW_INCLUDE_DIR
+ NAMES
+ GL/glew.h
+ HINTS
+ ${_glew_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include
+)
+
+FIND_LIBRARY(GLEW_LIBRARY
+ NAMES
+ GLEW
+ HINTS
+ ${_glew_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+ )
+
+
+FIND_LIBRARY(GLEW_MX_LIBRARY
+ NAMES
+ GLEWmx
+ HINTS
+ ${_glew_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+ )
+
+# handle the QUIETLY and REQUIRED arguments and set GLEW_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Glew DEFAULT_MSG
+ GLEW_LIBRARY GLEW_INCLUDE_DIR)
+
+IF(GLEW_FOUND)
+ SET(GLEW_INCLUDE_DIRS ${GLEW_INCLUDE_DIR})
+ENDIF(GLEW_FOUND)
+
+MARK_AS_ADVANCED(
+ GLEW_INCLUDE_DIR
+ GLEW_LIBRARY
+ GLEW_MX_LIBRARY
+)
diff --git a/build_files/cmake/Modules/FindOpenEXR.cmake b/build_files/cmake/Modules/FindOpenEXR.cmake
index 7190cfc5a88..1c59ef49e59 100644
--- a/build_files/cmake/Modules/FindOpenEXR.cmake
+++ b/build_files/cmake/Modules/FindOpenEXR.cmake
@@ -34,6 +34,9 @@ IF(NOT OPENEXR_ROOT_DIR AND NOT $ENV{OPENEXR_ROOT_DIR} STREQUAL "")
SET(OPENEXR_ROOT_DIR $ENV{OPENEXR_ROOT_DIR})
ENDIF()
+# Old versions (before 2.0?) do not have any version string, just assuming this should be fine though.
+SET(_openexr_libs_ver_init "2.0")
+
SET(_openexr_FIND_COMPONENTS
Half
Iex
@@ -82,12 +85,9 @@ IF(OPENEXR_INCLUDE_DIR)
IF(OPENEXR_BUILD_SPECIFICATION)
MESSAGE(STATUS "${OPENEXR_BUILD_SPECIFICATION}")
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")
+ "\\1" _openexr_libs_ver_init ${OPENEXR_BUILD_SPECIFICATION})
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")
+ MESSAGE(WARNING "Could not determine ILMBase library version, assuming ${_openexr_libs_ver_init}.")
ENDIF()
UNSET(_openexr_CONFIG CACHE)
@@ -95,6 +95,9 @@ IF(OPENEXR_INCLUDE_DIR)
ENDIF()
ENDIF()
+SET("OPENEXR_VERSION" ${_openexr_libs_ver_init} CACHE STRING "Version of OpenEXR lib")
+UNSET(_openexr_libs_ver_init)
+
STRING(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _openexr_libs_ver ${OPENEXR_VERSION})
SET(_openexr_LIBRARIES)
diff --git a/build_files/cmake/buildinfo.cmake b/build_files/cmake/buildinfo.cmake
index ead2474fd8a..d2392682c42 100644
--- a/build_files/cmake/buildinfo.cmake
+++ b/build_files/cmake/buildinfo.cmake
@@ -138,7 +138,7 @@ if(WIN32)
execute_process(COMMAND cmd /c time /t OUTPUT_VARIABLE BUILD_TIME OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
-# Write a file with the SVNVERSION define
+# Write a file with the BUILD_HASH define
file(WRITE buildinfo.h.txt
"#define BUILD_HASH \"${MY_WC_HASH}\"\n"
"#define BUILD_COMMIT_TIMESTAMP ${MY_WC_COMMIT_TIMESTAMP}\n"
diff --git a/build_files/cmake/cmake_consistency_check_config.py b/build_files/cmake/cmake_consistency_check_config.py
index 55bad251a53..729eecce233 100644
--- a/build_files/cmake/cmake_consistency_check_config.py
+++ b/build_files/cmake/cmake_consistency_check_config.py
@@ -2,6 +2,7 @@ import os
IGNORE = (
"/test/",
+ "/tests/gtests/",
"/BSP_GhostTest/",
"/release/",
"/xembed/",
diff --git a/build_files/cmake/cmake_netbeans_project.py b/build_files/cmake/cmake_netbeans_project.py
index b2b1f062509..fc6c64db1cd 100755
--- a/build_files/cmake/cmake_netbeans_project.py
+++ b/build_files/cmake/cmake_netbeans_project.py
@@ -24,7 +24,7 @@
"""
Example linux usage
- python3 ~/blenderSVN/blender/build_files/cmake/cmake_netbeans_project.py ~/blenderSVN/cmake
+ python3 ~/blender-git/blender/build_files/cmake/cmake_netbeans_project.py ~/blender-git/cmake
Windows not supported so far
"""
@@ -67,7 +67,7 @@ def create_nb_project_main():
if 0:
PROJECT_NAME = "Blender"
else:
- # be tricky, get the project name from SVN if we can!
+ # be tricky, get the project name from git if we can!
PROJECT_NAME = project_name_get()
# --------------- NB spesific
diff --git a/build_files/cmake/cmake_qtcreator_project.py b/build_files/cmake/cmake_qtcreator_project.py
index 76f1efa6ccb..346f5ea6a8e 100755
--- a/build_files/cmake/cmake_qtcreator_project.py
+++ b/build_files/cmake/cmake_qtcreator_project.py
@@ -27,7 +27,7 @@ Example Win32 usage:
c:\Python32\python.exe c:\blender_dev\blender\build_files\cmake\cmake_qtcreator_project.py c:\blender_dev\cmake_build
example linux usage
- python .~/blenderSVN/blender/build_files/cmake/cmake_qtcreator_project.py ~/blenderSVN/cmake
+ python .~/blender-git/blender/build_files/cmake/cmake_qtcreator_project.py ~/blender-git/cmake
"""
from project_info import (SIMPLE_PROJECTFILE,
@@ -133,7 +133,7 @@ def create_qtc_project_python():
if 0:
PROJECT_NAME = "Blender_Python"
else:
- # be tricky, get the project name from SVN if we can!
+ # be tricky, get the project name from git if we can!
PROJECT_NAME = project_name_get() + "_Python"
FILE_NAME = PROJECT_NAME.lower()
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 9ba5864c5c4..e22c2d20dda 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -413,6 +413,12 @@ macro(setup_liblinks
endif()
target_link_libraries(${target} ${PLATFORM_LINKLIBS} ${CMAKE_DL_LIBS})
+
+ # We put CLEW and CUEW here because OPENSUBDIV_LIBRARIES dpeends on them..
+ if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV)
+ target_link_libraries(${target} "extern_clew")
+ target_link_libraries(${target} "extern_cuew")
+ endif()
endmacro()
macro(SETUP_BLENDER_SORTED_LIBS)
@@ -495,6 +501,7 @@ macro(SETUP_BLENDER_SORTED_LIBS)
bf_bmesh
bf_blenkernel
bf_nodes
+ bf_rna
bf_gpu
bf_blenloader
bf_imbuf
@@ -534,7 +541,6 @@ macro(SETUP_BLENDER_SORTED_LIBS)
extern_openjpeg
extern_redcode
ge_videotex
- bf_rna
bf_dna
bf_blenfont
bf_intern_audaspace
@@ -1326,3 +1332,54 @@ macro(msgfmt_simple
unset(_file_to)
unset(_file_to_path)
endmacro()
+
+macro(find_python_package
+ package)
+
+ string(TOUPPER ${package} _upper_package)
+
+ # set but invalid
+ if((NOT ${PYTHON_${_upper_package}_PATH} STREQUAL "") AND
+ (NOT ${PYTHON_${_upper_package}_PATH} MATCHES NOTFOUND))
+# if(NOT EXISTS "${PYTHON_${_upper_package}_PATH}/${package}")
+# message(WARNING "PYTHON_${_upper_package}_PATH is invalid, ${package} not found in '${PYTHON_${_upper_package}_PATH}' "
+# "WITH_PYTHON_INSTALL_${_upper_package} option will be ignored when installing python")
+# set(WITH_PYTHON_INSTALL${_upper_package} OFF)
+# endif()
+ # not set, so initialize
+ else()
+ string(REPLACE "." ";" _PY_VER_SPLIT "${PYTHON_VERSION}")
+ list(GET _PY_VER_SPLIT 0 _PY_VER_MAJOR)
+
+ # re-cache
+ unset(PYTHON_${_upper_package}_PATH CACHE)
+ find_path(PYTHON_${_upper_package}_PATH
+ NAMES
+ ${package}
+ HINTS
+ "${PYTHON_LIBPATH}/python${PYTHON_VERSION}/"
+ "${PYTHON_LIBPATH}/python${_PY_VER_MAJOR}/"
+ PATH_SUFFIXES
+ site-packages
+ dist-packages
+ NO_DEFAULT_PATH
+ )
+
+ if(NOT EXISTS "${PYTHON_${_upper_package}_PATH}")
+ message(WARNING "'${package}' path could not be found in:\n"
+ "'${PYTHON_LIBPATH}/python${PYTHON_VERSION}/site-packages/${package}', "
+ "'${PYTHON_LIBPATH}/python${_PY_VER_MAJOR}/site-packages/${package}', "
+ "'${PYTHON_LIBPATH}/python${PYTHON_VERSION}/dist-packages/${package}', "
+ "'${PYTHON_LIBPATH}/python${_PY_VER_MAJOR}/dist-packages/${package}', "
+ "WITH_PYTHON_INSTALL_${_upper_package} option will be ignored when installing python")
+ set(WITH_PYTHON_INSTALL_${_upper_package} OFF)
+ else()
+ message(STATUS "${package} found at '${PYTHON_${_upper_package}_PATH}'")
+ endif()
+
+ unset(_PY_VER_SPLIT)
+ unset(_PY_VER_MAJOR)
+ endif()
+
+ unset(_upper_package)
+endmacro()
diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py
index 6f49960d624..338065e5e88 100644
--- a/build_files/scons/config/darwin-config.py
+++ b/build_files/scons/config/darwin-config.py
@@ -154,7 +154,7 @@ BF_COLLADA_INC = '${BF_COLLADA}'
BF_COLLADA_LIB = 'bf_collada'
BF_OPENCOLLADA = LIBDIR + '/opencollada'
BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
-BF_OPENCOLLADA_LIB = 'OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils OpenCOLLADAStreamWriter MathMLSolver GeneratedSaxParser UTF xml2 buffer ftoa'
+BF_OPENCOLLADA_LIB = 'OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils OpenCOLLADAStreamWriter MathMLSolver GeneratedSaxParser xml2 buffer ftoa'
BF_OPENCOLLADA_LIBPATH = LIBDIR + '/opencollada'
BF_PCRE = LIBDIR + '/opencollada'
BF_PCRE_LIB = 'pcre'
@@ -181,7 +181,7 @@ WITH_BF_LLVM = True
BF_LLVM = LIBDIR + '/llvm'
BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \
'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \
- 'LLVMTarget LLVMMC LLVMCore LLVMSupport'
+ 'LLVMTarget LLVMMC LLVMCore LLVMSupport LLVMObject'
BF_LLVM_LIBPATH = '${BF_LLVM}/lib'
WITH_BF_OIIO = True
@@ -237,7 +237,7 @@ LLIBS = ['stdc++']
REL_CFLAGS = []
REL_CXXFLAGS = []
-REL_CCFLAGS = ['-DNDEBUG', '-O2']
+REL_CCFLAGS = ['-O2']
CC_WARN = ['-Wall']
C_WARN = ['-Wno-char-subscripts', '-Wpointer-arith', '-Wcast-align', '-Wdeclaration-after-statement', '-Wno-unknown-pragmas', '-Wstrict-prototypes']
@@ -253,7 +253,7 @@ BF_PROFILE_LINKFLAGS = ['-pg']
BF_PROFILE = False
BF_DEBUG = False
-BF_DEBUG_CCFLAGS = ['-g', '-D_DEBUG']
+BF_DEBUG_CCFLAGS = ['-g']
#############################################################################
################### Output directories ##################
diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py
index 0c76aecfc4b..05f09c2f2da 100644
--- a/build_files/scons/config/linux-config.py
+++ b/build_files/scons/config/linux-config.py
@@ -241,7 +241,7 @@ if WITH_BF_FFMPEG:
CXXFLAGS += ['-D__STDC_CONSTANT_MACROS', ]
REL_CFLAGS = []
REL_CXXFLAGS = []
-REL_CCFLAGS = ['-DNDEBUG', '-O2']
+REL_CCFLAGS = ['-O2']
C_WARN = ['-Wno-char-subscripts', '-Wdeclaration-after-statement', '-Wunused-parameter', '-Wstrict-prototypes', '-Werror=declaration-after-statement', '-Werror=implicit-function-declaration', '-Werror=return-type']
CC_WARN = ['-Wall']
@@ -254,7 +254,7 @@ BF_PROFILE_CCFLAGS = ['-pg','-g']
BF_PROFILE_LINKFLAGS = ['-pg']
BF_DEBUG = False
-BF_DEBUG_CCFLAGS = ['-g', '-D_DEBUG']
+BF_DEBUG_CCFLAGS = ['-g']
BF_BUILDDIR = '../build/linux'
BF_INSTALLDIR='../install/linux'
diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py
index a6d1a7d7996..85aa72af19c 100644
--- a/build_files/scons/config/win32-mingw-config.py
+++ b/build_files/scons/config/win32-mingw-config.py
@@ -190,7 +190,7 @@ CXXFLAGS = []
CPPFLAGS = ['-DWIN32', '-DFREE_WINDOWS', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64', '-D_LARGEFILE64_SOURCE', '-DBOOST_ALL_NO_LIB', '-DBOOST_THREAD_USE_LIB', '-DGLEW_STATIC', '-DOPJ_STATIC']
REL_CFLAGS = []
REL_CXXFLAGS = []
-REL_CCFLAGS = ['-DNDEBUG', '-O2']
+REL_CCFLAGS = ['-O2']
C_WARN = ['-Wno-char-subscripts', '-Wdeclaration-after-statement', '-Wstrict-prototypes']
@@ -205,7 +205,7 @@ PLATFORM_LINKFLAGS = ['-Xlinker', '--stack=2097152']
# PLATFORM_LINKFLAGS += ["-static-libgcc", "-static-libstdc++"]
BF_DEBUG = False
-BF_DEBUG_CCFLAGS= ['-g', '-D_DEBUG']
+BF_DEBUG_CCFLAGS= ['-g']
BF_PROFILE_CCFLAGS = ['-pg', '-g']
BF_PROFILE_LINKFLAGS = ['-pg']
diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py
index ebe24bf0644..6dd853b7da4 100644
--- a/build_files/scons/config/win32-vc-config.py
+++ b/build_files/scons/config/win32-vc-config.py
@@ -6,9 +6,6 @@ CL_STDOUT, CL_STDERR = CL_OUT.communicate()
if "18.00." in CL_STDERR:
VC_VERSION = '12.0'
LCGDIR = '#../lib/windows_vc12'
-elif "15.00." in CL_STDERR:
- VC_VERSION = '9.0'
- LCGDIR = '#../lib/windows'
else:
import sys
print("Visual C version not supported {}\n".format(CL_STDERR))
@@ -72,10 +69,7 @@ WITH_BF_OPENEXR = True
WITH_BF_STATICOPENEXR = False
BF_OPENEXR = LIBDIR + '/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR '
-if VC_VERSION == '12.0':
- BF_OPENEXR_LIB = ' Iex-2_1 Half IlmImf-2_1 Imath-2_1 IlmThread-2_1 '
-else:
- BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread '
+BF_OPENEXR_LIB = ' Iex-2_1 Half IlmImf-2_1 Imath-2_1 IlmThread-2_1 '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
@@ -154,7 +148,7 @@ BF_COLLADA_LIB = 'bf_collada'
BF_OPENCOLLADA = LIBDIR + '/opencollada'
BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include/opencollada'
-BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml pcre buffer ftoa UTF'
+BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml pcre buffer ftoa'
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib/opencollada'
WITH_BF_3DMOUSE = True
@@ -196,12 +190,8 @@ WITH_BF_STATICOCIO = True
WITH_BF_BOOST = True
BF_BOOST = '${LIBDIR}/boost'
BF_BOOST_INC = '${BF_BOOST}/include'
-if VC_VERSION == '12.0':
- BF_BOOST_LIB = 'libboost_date_time-vc120-mt-s-1_55 libboost_filesystem-vc120-mt-s-1_55 libboost_regex-vc120-mt-s-1_55 libboost_system-vc120-mt-s-1_55 libboost_thread-vc120-mt-s-1_55 libboost_wave-vc120-mt-s-1_55'
- BF_BOOST_LIB_INTERNATIONAL = ' libboost_locale-vc120-mt-s-1_55'
-else:
- BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49 libboost_wave-vc90-mt-s-1_49'
- BF_BOOST_LIB_INTERNATIONAL = 'libboost_locale-vc90-mt-s-1_49'
+BF_BOOST_LIB = 'libboost_date_time-vc120-mt-s-1_55 libboost_filesystem-vc120-mt-s-1_55 libboost_regex-vc120-mt-s-1_55 libboost_system-vc120-mt-s-1_55 libboost_thread-vc120-mt-s-1_55 libboost_wave-vc120-mt-s-1_55'
+BF_BOOST_LIB_INTERNATIONAL = ' libboost_locale-vc120-mt-s-1_55'
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
#CUDA
@@ -231,12 +221,15 @@ CCFLAGS = ['/nologo', '/J', '/W3', '/Gd', '/w34062', '/wd4018', '/wd4065', '/wd4
CXXFLAGS = ['/EHsc']
BGE_CXXFLAGS = ['/O2', '/Ob2', '/EHsc', '/GR', '/fp:fast', '/arch:SSE']
+if VC_VERSION == '12.0':
+ CCFLAGS.append('/DOIIO_STATIC_BUILD') # OIIO api changed with 1.4 making this needed
+
BF_DEBUG_CCFLAGS = ['/Zi', '/Ob0', '/Od', '/FR${TARGET}.sbr']
CPPFLAGS = ['-DWIN32','-D_CONSOLE', '-D_LIB', '-D_CRT_SECURE_NO_DEPRECATE', '-DOPJ_STATIC']
REL_CFLAGS = []
REL_CXXFLAGS = []
-REL_CCFLAGS = ['-O2', '/Ob2', '-DNDEBUG']
+REL_CCFLAGS = ['-O2', '/Ob2']
C_WARN = []
CC_WARN = []
@@ -253,10 +246,6 @@ PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:IX86','/STACK:2097152','/IN
BF_BSC=False
-if VC_VERSION == '12.0':
- BF_CYCLES_CUDA_ENV="C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd"
- BF_BUILDDIR = '..\\build\\win32-vc'
- BF_INSTALLDIR='..\\install\\win32-vc'
-else:
- BF_BUILDDIR = '..\\build\\win32-vc9'
- BF_INSTALLDIR='..\\install\\win32-vc9'
+BF_CYCLES_CUDA_ENV="C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd"
+BF_BUILDDIR = '..\\build\\win32-vc'
+BF_INSTALLDIR='..\\install\\win32-vc'
diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py
index dcdea6583d7..92dcd6db455 100644
--- a/build_files/scons/config/win64-mingw-config.py
+++ b/build_files/scons/config/win64-mingw-config.py
@@ -184,7 +184,7 @@ CXXFLAGS = [ '-fpermissive' ]
CPPFLAGS = ['-DWIN32', '-DMS_WIN64', '-DFREE_WINDOWS', '-DFREE_WINDOWS64', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64', '-D_LARGEFILE64_SOURCE', '-DBOOST_ALL_NO_LIB', '-DBOOST_THREAD_USE_LIB', '-DGLEW_STATIC', '-DOPJ_STATIC']
REL_CFLAGS = []
REL_CXXFLAGS = []
-REL_CCFLAGS = ['-DNDEBUG', '-O2', '-ftree-vectorize']
+REL_CCFLAGS = ['-O2', '-ftree-vectorize']
C_WARN = ['-Wno-char-subscripts', '-Wdeclaration-after-statement', '-Wstrict-prototypes']
@@ -199,7 +199,7 @@ PLATFORM_LINKFLAGS = ['-Xlinker', '--stack=2097152']
# PLATFORM_LINKFLAGS += ["-static-libgcc", "-static-libstdc++"]
BF_DEBUG = False
-BF_DEBUG_CCFLAGS= ['-g', '-D_DEBUG']
+BF_DEBUG_CCFLAGS= ['-g']
BF_PROFILE_CCFLAGS = ['-pg', '-g']
BF_PROFILE_LINKFLAGS = ['-pg']
diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py
index d94de3b54e4..f928f166ba7 100644
--- a/build_files/scons/config/win64-vc-config.py
+++ b/build_files/scons/config/win64-vc-config.py
@@ -6,9 +6,6 @@ CL_STDOUT, CL_STDERR = CL_OUT.communicate()
if "18.00." in CL_STDERR:
VC_VERSION = '12.0'
LCGDIR = '#../lib/win64_vc12'
-elif "15.00." in CL_STDERR:
- VC_VERSION = '9.0'
- LCGDIR = '#../lib/win64'
else:
import sys
print("Visual C version not supported {}\n".format(CL_STDERR))
@@ -69,10 +66,7 @@ WITH_BF_OPENEXR = True
WITH_BF_STATICOPENEXR = False
BF_OPENEXR = LIBDIR + '/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR '
-if VC_VERSION == '12.0':
- BF_OPENEXR_LIB = ' Iex-2_1 Half IlmImf-2_1 Imath-2_1 IlmThread-2_1 '
-else:
- BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread '
+BF_OPENEXR_LIB = ' Iex-2_1 Half IlmImf-2_1 Imath-2_1 IlmThread-2_1 '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
@@ -157,7 +151,7 @@ BF_COLLADA_LIB = 'bf_collada'
BF_OPENCOLLADA = LIBDIR + '/opencollada'
BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include/opencollada'
-BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml pcre buffer ftoa UTF'
+BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml pcre buffer ftoa'
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib/opencollada'
WITH_BF_3DMOUSE = True
@@ -186,7 +180,7 @@ WITH_BF_OIIO = True
BF_OIIO = '${LIBDIR}/openimageio'
BF_OIIO_INC = '${BF_OIIO}/include'
BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
-BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/OpenImageIO.lib'
+BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/OpenImageIO.lib ${BF_OIIO_LIBPATH}/OpenImageIO_Util.lib'
WITH_BF_STATICOIIO = True
WITH_BF_OCIO = True
@@ -199,12 +193,8 @@ WITH_BF_STATICOCIO = True
WITH_BF_BOOST = True
BF_BOOST = '${LIBDIR}/boost'
BF_BOOST_INC = '${BF_BOOST}/include'
-if VC_VERSION == '12.0':
- BF_BOOST_LIB = 'libboost_date_time-vc120-mt-s-1_55 libboost_filesystem-vc120-mt-s-1_55 libboost_regex-vc120-mt-s-1_55 libboost_system-vc120-mt-s-1_55 libboost_thread-vc120-mt-s-1_55 libboost_wave-vc120-mt-s-1_55'
- BF_BOOST_LIB_INTERNATIONAL = ' libboost_locale-vc120-mt-s-1_55'
-else:
- BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49 libboost_wave-vc90-mt-s-1_49'
- BF_BOOST_LIB_INTERNATIONAL = ' libboost_locale-vc90-mt-s-1_49'
+BF_BOOST_LIB = 'libboost_date_time-vc120-mt-s-1_55 libboost_filesystem-vc120-mt-s-1_55 libboost_regex-vc120-mt-s-1_55 libboost_system-vc120-mt-s-1_55 libboost_thread-vc120-mt-s-1_55 libboost_wave-vc120-mt-s-1_55'
+BF_BOOST_LIB_INTERNATIONAL = ' libboost_locale-vc120-mt-s-1_55'
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
#CUDA
@@ -236,6 +226,7 @@ CCFLAGS = ['/nologo', '/J', '/W3', '/Gd', '/w34062', '/wd4018', '/wd4065', '/wd4
# We want to support Vista level ABI for x64
if VC_VERSION == '12.0':
CCFLAGS.append('/D_WIN32_WINNT=0x600')
+ CCFLAGS.append('/DOIIO_STATIC_BUILD') # OIIO api changed with 1.4 making this needed
CXXFLAGS = ['/EHsc']
BGE_CXXFLAGS = ['/O2', '/Ob2', '/EHsc', '/GR', '/fp:fast']
@@ -245,7 +236,7 @@ BF_DEBUG_CCFLAGS = ['/Zi', '/FR${TARGET}.sbr', '/Od', '/Ob0']
CPPFLAGS = ['-DWIN32', '-D_CONSOLE', '-D_LIB', '-D_CRT_SECURE_NO_DEPRECATE', '-DOPJ_STATIC']
REL_CFLAGS = []
REL_CXXFLAGS = []
-REL_CCFLAGS = ['-O2', '/Ob2', '-DNDEBUG']
+REL_CCFLAGS = ['-O2', '/Ob2']
C_WARN = []
CC_WARN = []
@@ -254,10 +245,7 @@ CXX_WARN = []
LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi']
PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:X64','/STACK:2097152','/OPT:NOREF','/INCREMENTAL:NO', '/NODEFAULTLIB:msvcrt.lib', '/NODEFAULTLIB:msvcmrt.lib', '/NODEFAULTLIB:msvcurt.lib', '/NODEFAULTLIB:msvcrtd.lib']
-if VC_VERSION == '12.0':
- BF_CYCLES_CUDA_ENV="C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd"
- BF_BUILDDIR = '..\\build\\win64-vc'
- BF_INSTALLDIR='..\\install\\win64-vc'
-else:
- BF_BUILDDIR = '..\\build\\win64-vc9'
- BF_INSTALLDIR='..\\install\\win64-vc9'
+
+BF_CYCLES_CUDA_ENV="C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd"
+BF_BUILDDIR = '..\\build\\win64-vc'
+BF_INSTALLDIR='..\\install\\win64-vc'
diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py
index c3ac92c77b2..b5853b22455 100755
--- a/build_files/scons/tools/Blender.py
+++ b/build_files/scons/tools/Blender.py
@@ -248,6 +248,11 @@ def setup_staticlibs(lenv):
libincs = [e for e in libincs if SCons.Subst.scons_subst(e, lenv, gvars=lenv.Dictionary()) != "/usr/lib"]
libincs.append('/usr/lib')
+ # Hack to pass OSD libraries to linker before extern_{clew,cuew}
+ # Here we only store library path, actual library name will be added in setup_syslibs()
+ for syslib in create_blender_liblist(lenv, 'system'):
+ libincs.append(os.path.dirname(syslib))
+
return statlibs, libincs
def setup_syslibs(lenv):
@@ -339,6 +344,10 @@ def setup_syslibs(lenv):
if not lenv['WITH_BF_STATICPNG']:
syslibs += Split(lenv['BF_PNG_LIB'])
+ # Hack to pass OSD libraries to linker before extern_{clew,cuew}
+ for syslib in create_blender_liblist(lenv, 'system'):
+ syslibs.append(os.path.basename(syslib))
+
syslibs += lenv['LLIBS']
return syslibs
@@ -702,37 +711,37 @@ def AppIt(target=None, source=None, env=None):
commands.getoutput(cmd)
cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,installdir, binary, binary)
commands.getoutput(cmd)
- cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/'%(installdir, binary, VERSION)
+ cmd = 'mkdir %s/%s.app/Contents/Resources/%s/'%(installdir, binary, VERSION)
commands.getoutput(cmd)
cmd = installdir + '/%s.app/Contents/MacOS/%s'%(binary,VERSION)
# blenderplayer doesn't need all the files
if binary == 'blender':
- cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/datafiles'%(installdir, binary, VERSION)
+ cmd = 'mkdir %s/%s.app/Contents/Resources/%s/datafiles'%(installdir, binary, VERSION)
commands.getoutput(cmd)
- cmd = 'cp -R %s/release/datafiles/fonts %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
+ cmd = 'cp -R %s/release/datafiles/fonts %s/%s.app/Contents/Resources/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
commands.getoutput(cmd)
mo_dir = os.path.join(builddir[:-4], "locale")
for f in os.listdir(mo_dir):
- cmd = 'ditto %s/%s %s/%s.app/Contents/MacOS/%s/datafiles/locale/%s/LC_MESSAGES/blender.mo'%(mo_dir, f, installdir, binary, VERSION, f[:-3])
+ cmd = 'ditto %s/%s %s/%s.app/Contents/Resources/%s/datafiles/locale/%s/LC_MESSAGES/blender.mo'%(mo_dir, f, installdir, binary, VERSION, f[:-3])
commands.getoutput(cmd)
- cmd = 'cp %s/release/datafiles/locale/languages %s/%s.app/Contents/MacOS/%s/datafiles/locale/'%(bldroot, installdir, binary, VERSION)
+ cmd = 'cp %s/release/datafiles/locale/languages %s/%s.app/Contents/Resources/%s/datafiles/locale/'%(bldroot, installdir, binary, VERSION)
commands.getoutput(cmd)
if env['WITH_BF_OCIO']:
- cmd = 'cp -R %s/release/datafiles/colormanagement %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
+ cmd = 'cp -R %s/release/datafiles/colormanagement %s/%s.app/Contents/Resources/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
commands.getoutput(cmd)
- cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
+ cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/Resources/%s/'%(bldroot,installdir,binary,VERSION)
commands.getoutput(cmd)
if VERSION_RELEASE_CYCLE == "release":
- cmd = 'rm -rf %s/%s.app/Contents/MacOS/%s/scripts/addons_contrib'%(installdir,binary,VERSION)
+ cmd = 'rm -rf %s/%s.app/Contents/Resources/%s/scripts/addons_contrib'%(installdir,binary,VERSION)
commands.getoutput(cmd)
if env['WITH_BF_CYCLES']:
croot = '%s/intern/cycles' % (bldroot)
- cinstalldir = '%s/%s.app/Contents/MacOS/%s/scripts/addons/cycles' % (installdir,binary,VERSION)
+ cinstalldir = '%s/%s.app/Contents/Resources/%s/scripts/addons/cycles' % (installdir,binary,VERSION)
cmd = 'mkdir %s' % (cinstalldir)
commands.getoutput(cmd)
@@ -760,11 +769,11 @@ def AppIt(target=None, source=None, env=None):
commands.getoutput(cmd)
if env['WITH_OSX_STATICPYTHON']:
- cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION)
+ cmd = 'mkdir %s/%s.app/Contents/Resources/%s/python/'%(installdir,binary, VERSION)
commands.getoutput(cmd)
- cmd = 'unzip -q %s/release/%s -d %s/%s.app/Contents/MacOS/%s/python/'%(libdir,python_zip,installdir,binary,VERSION)
+ cmd = 'unzip -q %s/release/%s -d %s/%s.app/Contents/Resources/%s/python/'%(libdir,python_zip,installdir,binary,VERSION)
commands.getoutput(cmd)
- cmd = 'cp -R %s/release/site-packages/ %s/%s.app/Contents/MacOS/%s/python/lib/python%s/site-packages/'%(libdir,installdir,binary,VERSION,env['BF_PYTHON_VERSION'])
+ cmd = 'cp -R %s/release/site-packages/ %s/%s.app/Contents/Resources/%s/python/lib/python%s/site-packages/'%(libdir,installdir,binary,VERSION,env['BF_PYTHON_VERSION'])
commands.getoutput(cmd)
cmd = 'chmod +x %s/%s.app/Contents/MacOS/%s'%(installdir,binary, binary)
@@ -781,28 +790,28 @@ def AppIt(target=None, source=None, env=None):
if env['C_COMPILER_ID'] == 'gcc' and env['CCVERSION'] >= '4.6.1': # for correct errorhandling with gcc >= 4.6.1 we need the gcc.dylib and gomp.dylib to link, thus distribute in app-bundle
print "Bundling libgcc and libgomp"
instname = env['BF_CXX']
- cmd = 'ditto --arch %s %s/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/'%(osxarch, instname, installdir, binary) # copy libgcc
+ cmd = 'ditto --arch %s %s/lib/libgcc_s.1.dylib %s/%s.app/Contents/Resources/lib/'%(osxarch, instname, installdir, binary) # copy libgcc
commands.getoutput(cmd)
- cmd = 'install_name_tool -id @executable_path/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/libgcc_s.1.dylib'%(installdir, binary) # change id of libgcc
+ cmd = 'install_name_tool -id @executable_path/../Resources/lib/libgcc_s.1.dylib %s/%s.app/Contents/Resources/lib/libgcc_s.1.dylib'%(installdir, binary) # change id of libgcc
commands.getoutput(cmd)
- cmd = 'ditto --arch %s %s/lib/libgomp.1.dylib %s/%s.app/Contents/MacOS/lib/'%(osxarch, instname, installdir, binary) # copy libgomp
+ cmd = 'ditto --arch %s %s/lib/libgomp.1.dylib %s/%s.app/Contents/Resources/lib/'%(osxarch, instname, installdir, binary) # copy libgomp
commands.getoutput(cmd)
- cmd = 'install_name_tool -id @executable_path/lib/libgomp.1.dylib %s/%s.app/Contents/MacOS/lib/libgomp.1.dylib'%(installdir, binary) # change id of libgomp
+ cmd = 'install_name_tool -id @executable_path/../Resources/lib/libgomp.1.dylib %s/%s.app/Contents/Resources/lib/libgomp.1.dylib'%(installdir, binary) # change id of libgomp
commands.getoutput(cmd)
- cmd = 'install_name_tool -change %s/lib/libgcc_s.1.dylib @executable_path/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/libgomp.1.dylib'%(instname, installdir, binary) # change ref to libgcc
+ cmd = 'install_name_tool -change %s/lib/libgcc_s.1.dylib @executable_path/../Resources/lib/libgcc_s.1.dylib %s/%s.app/Contents/Resources/lib/libgomp.1.dylib'%(instname, installdir, binary) # change ref to libgcc
commands.getoutput(cmd)
- cmd = 'install_name_tool -change %s/lib/libgcc_s.1.dylib @executable_path/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/%s'%(instname, installdir, binary, binary) # change ref to libgcc ( blender )
+ cmd = 'install_name_tool -change %s/lib/libgcc_s.1.dylib @executable_path/../Resources/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/%s'%(instname, installdir, binary, binary) # change ref to libgcc ( blender )
commands.getoutput(cmd)
- cmd = 'install_name_tool -change %s/lib/libgomp.1.dylib @executable_path/lib/libgomp.1.dylib %s/%s.app/Contents/MacOS/%s'%(instname, installdir, binary, binary) # change ref to libgomp ( blender )
+ cmd = 'install_name_tool -change %s/lib/libgomp.1.dylib @executable_path/../Resources/lib/libgomp.1.dylib %s/%s.app/Contents/MacOS/%s'%(instname, installdir, binary, binary) # change ref to libgomp ( blender )
commands.getoutput(cmd)
if env['C_COMPILER_ID'] == 'clang' and env['CCVERSION'] >= '3.4':
print "Bundling libiomp5"
instname = env['LCGDIR'][1:] # made libiomp5 part of blender libs
- cmd = 'ditto --arch %s %s/openmp/lib/libiomp5.dylib %s/%s.app/Contents/MacOS/lib/'%(osxarch, instname, installdir, binary) # copy libiomp5
+ cmd = 'ditto --arch %s %s/openmp/lib/libiomp5.dylib %s/%s.app/Contents/Resources/lib/'%(osxarch, instname, installdir, binary) # copy libiomp5
commands.getoutput(cmd)
- cmd = 'install_name_tool -id @loader_path/lib/libiomp5.dylib %s/%s.app/Contents/MacOS/lib/libiomp5.dylib'%(installdir, binary) # change id of libiomp5
+ cmd = 'install_name_tool -id @loader_path/../Resources/lib/libiomp5.dylib %s/%s.app/Contents/Resources/lib/libiomp5.dylib'%(installdir, binary) # change id of libiomp5
commands.getoutput(cmd)
- cmd = 'install_name_tool -change @loader_path/libiomp5.dylib @loader_path/lib/libiomp5.dylib %s/%s.app/Contents/MacOS/%s'%(installdir, binary, binary) # change ref to libiomp5 ( blender )
+ cmd = 'install_name_tool -change @loader_path/libiomp5.dylib @loader_path/../Resources/lib/libiomp5.dylib %s/%s.app/Contents/MacOS/%s'%(installdir, binary, binary) # change ref to libiomp5 ( blender )
commands.getoutput(cmd)
# extract copy system python, be sure to update other build systems
diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py
index 214827b6668..5a09e07b3b3 100644
--- a/build_files/scons/tools/btools.py
+++ b/build_files/scons/tools/btools.py
@@ -686,9 +686,6 @@ def buildslave(target=None, source=None, env=None):
else:
platform = env['OURPLATFORM'].split('-')[0]
- if env['OURPLATFORM'] in ('win32-vc', 'win64-vc') and env['MSVC_VERSION'] == '9.0':
- platform = platform + '-vc9'
-
if platform == 'linux':
import platform
diff --git a/doc/manpage/blender.1.py b/doc/manpage/blender.1.py
index 32e8cc06857..77f5c5e4f16 100755
--- a/doc/manpage/blender.1.py
+++ b/doc/manpage/blender.1.py
@@ -31,7 +31,6 @@ and <output-filename> is where to write the generated man page.
# <pep8 compliant>
import subprocess
-import os
import sys
import time
diff --git a/doc/python_api/rst/bge.constraints.rst b/doc/python_api/rst/bge.constraints.rst
index 4d3e4ce880f..018be96fd14 100644
--- a/doc/python_api/rst/bge.constraints.rst
+++ b/doc/python_api/rst/bge.constraints.rst
@@ -28,6 +28,7 @@ Physics Constraints (bge.constraints)
- :class:`ANGULAR_CONSTRAINT`
- :class:`CONETWIST_CONSTRAINT`
- :class:`VEHICLE_CONSTRAINT`
+ - :class:`GENERIC_6DOF_CONSTRAINT`
:type constrainttype: int
@@ -49,7 +50,7 @@ Physics Constraints (bge.constraints)
:arg axisZ: Z axis
:type axisZ: float
- :arg flag: .. to do
+ :arg flag: 128 to disable collision between linked bodies
:type flag: int
.. attribute:: error
@@ -368,3 +369,10 @@ Physics Constraints (bge.constraints)
Constraint type to be used with function :class:`createConstraint`
.. to do
+
+.. data:: GENERIC_6DOF_CONSTRAINT
+
+ .. note::
+ Constraint type to be used with function :class:`createConstraint`
+
+ .. to do
diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst
index 4e0d317e4bf..d901a4e4207 100644
--- a/doc/python_api/rst/bge.logic.rst
+++ b/doc/python_api/rst/bge.logic.rst
@@ -868,6 +868,23 @@ See :class:`bge.types.KX_SteeringActuator.behavior`
:value: 3
+.. _logic-trackto-actuator:
+
+-----------------
+TrackTo Actuator
+-----------------
+
+See :class:`bge.types.KX_TrackToActuator`
+
+.. data:: KX_TRACK_UPAXIS_POS_X
+.. data:: KX_TRACK_UPAXIS_POS_Y
+.. data:: KX_TRACK_UPAXIS_POS_Z
+.. data:: KX_TRACK_TRAXIS_POS_X
+.. data:: KX_TRACK_TRAXIS_POS_Y
+.. data:: KX_TRACK_TRAXIS_POS_Z
+.. data:: KX_TRACK_TRAXIS_NEG_X
+.. data:: KX_TRACK_TRAXIS_NEG_Y
+.. data:: KX_TRACK_TRAXIS_NEG_Z
=======
Various
diff --git a/doc/python_api/rst/bge.render.rst b/doc/python_api/rst/bge.render.rst
index 5a80b7fa5c1..9dd4057c82f 100644
--- a/doc/python_api/rst/bge.render.rst
+++ b/doc/python_api/rst/bge.render.rst
@@ -301,6 +301,34 @@ Functions
Disable the motion blur effect.
+.. function:: showFramerate(enable)
+
+ Show or hide the framerate.
+
+ :type enable: boolean
+
+.. function:: showProfile(enable)
+
+ Show or hide the profile.
+
+ :type enable: boolean
+
+.. function:: showProperties(enable)
+
+ Show or hide the debug properties.
+
+ :type enable: boolean
+
+.. function:: autoDebugList(enable)
+
+ Enable or disable auto adding debug properties to the debug list.
+
+ :type enable: boolean
+
+.. function:: clearDebugList()
+
+ Clears the debug property list.
+
.. function:: setVsync(value)
Set the vsync value
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst b/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst
index c26675147ac..53bef120f7a 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst
@@ -11,8 +11,131 @@ base class --- :class:`PyObjectPlus`
.. method:: getConstraintId(val)
- Returns the contraint's ID
+ Returns the contraint ID
- :return: the constraint's ID
+ :return: the constraint ID
:rtype: integer
+ .. method:: setParam(axis, value0, value1)
+
+ Set the contraint limits
+
+ :arg axis:
+ :type axis: integer
+
+ .. note::
+ For each axis:
+ * Lowerlimit == Upperlimit -> axis is locked
+ * Lowerlimit > Upperlimit -> axis is free
+ * Lowerlimit < Upperlimit -> axis it limited in that range
+
+ PHY_LINEHINGE_CONSTRAINT = 2 or PHY_ANGULAR_CONSTRAINT = 3:
+ axis = 3 is a constraint limit, with low/high limit value
+
+ * 3: X axis angle
+
+ :arg value0 (min): Set the minimum limit of the axis
+ :type value0: float
+ :arg value1 (max): Set the maximum limit of the axis
+ :type value1: float
+
+ PHY_CONE_TWIST_CONSTRAINT = 3:
+ axis = 3..5 are constraint limits, high limit values
+ * 3: X axis angle
+ * 4: Y axis angle
+ * 5: Z axis angle
+
+ :arg value0 (min): Set the minimum limit of the axis
+ :type value0: float
+ :arg value1 (max): Set the maximum limit of the axis
+ :type value1: float
+
+ PHY_GENERIC_6DOF_CONSTRAINT = 12:
+ axis = 0..2 are constraint limits, with low/high limit value
+ * 0: X axis position
+ * 1: Y axis position
+ * 2: Z axis position
+
+ axis = 3..5 are relative constraint (Euler) angles in radians
+ * 3: X axis angle
+ * 4: Y axis angle
+ * 5: Z axis angle
+
+ :arg value0 (min): Set the minimum limit of the axis
+ :type value0: float
+ :arg value1 (max): Set the maximum limit of the axis
+ :type value1: float
+
+ axis = 6..8 are translational motors, with value0=target velocity, value1 = max motor force
+ * 6: X axis position
+ * 7: Y axis position
+ * 8: Z axis position
+
+ axis = 9..11 are rotational motors, with value0=target velocity, value1 = max motor force
+ * 9: X axis angle
+ * 10: Y axis angle
+ * 11: Z axis angle
+
+ :arg value0 (speed): Set the linear velocity of the axis
+ :type value0: float Range: -10,000.00 to 10,000.00
+ :arg value1 (force): Set the maximum force limit of the axis
+ :type value1: float Range: -10,000.00 to 10,000.00
+
+ axis = 12..14 are for linear springs on each of the position of freedom
+ * 12: X axis position
+ * 13: Y axis position
+ * 14: Z axis position
+
+ axis = 15..17 are for angular springs on each of the angle of freedom in radians
+ * 15: X axis angle
+ * 16: Y axis angle
+ * 17: Z axis angle
+
+ :arg value0 (stiffness): Set the stiffness of the spring
+ :type value0: float
+ :arg value1 (damping): Tendency of the spring to return to it's original position
+ :type value1: float
+ 1.0 = springs back to original position (no damping)
+ 0.0 = don't springs back
+
+ .. method:: getParam(axis)
+
+ Get the contraint position or euler angle of a generic 6DOF constraint
+
+ :arg axis:
+ :type axis: integer
+
+ axis = 0..2 are linear constraint values
+ * 0: X axis position
+ * 1: Y axis position
+ * 2: Z axis position
+
+ :return: position
+ :rtype: float
+
+ axis = 3..5 are relative constraint (Euler) angles in radians
+ * 3: X axis angle
+ * 4: Y axis angle
+ * 5: Z axis angle
+
+ :return: angle
+ :rtype: float
+
+ .. attribute:: constraint_id
+
+ Returns the contraint ID (read only)
+
+ :type: integer
+
+ .. attribute:: constraint_type
+
+ Returns the contraint type (read only)
+
+ :type: integer
+
+ * 1 = POINTTOPOINT_CONSTRAINT
+ * 2 = LINEHINGE_CONSTRAINT
+ * 3 = ANGULAR_CONSTRAINT (aka LINEHINGE_CONSTRAINT)
+ * 4 = CONETWIST_CONSTRAINT
+ * 11 = VEHICLE_CONSTRAINT
+ * 12 = GENERIC_6DOF_CONSTRAINT
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
index 215ff40577c..a6d03dee1a1 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
@@ -363,6 +363,18 @@ base class --- :class:`SCA_IObject`
:type: float
+ .. attribute:: debug
+
+ If true, the object's debug properties will be displayed on screen.
+
+ :type: boolean
+
+ .. attribute:: debugRecursive
+
+ If true, the object's and children's debug properties will be displayed on screen.
+
+ :type: boolean
+
.. method:: endObject()
Delete this object, can be used in place of the EndObject Actuator.
@@ -857,3 +869,11 @@ base class --- :class:`SCA_IObject`
:return: Whether or not the action is playing
:rtype: boolean
+ .. method:: addDebugProperty (name, debug = True)
+
+ Adds a single debug property to the debug list.
+
+ :arg name: name of the property that added to the debug list.
+ :type name: string
+ :arg debug: the debug state.
+ :type debug: boolean \ No newline at end of file
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_MouseFocusSensor.rst b/doc/python_api/rst/bge_types/bge.types.KX_MouseFocusSensor.rst
index dda73eadb52..0600a4b5aae 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_MouseFocusSensor.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_MouseFocusSensor.rst
@@ -64,3 +64,20 @@ base class --- :class:`SCA_MouseSensor`
:type: boolean
+ .. attribute:: useXRay
+
+ If enabled it allows the sensor to see through game objects that don't have the selected property or material.
+
+ :type: boolean
+
+ .. attribute:: propName
+
+ The property or material the sensor is looking for.
+
+ :type: string
+
+ .. attribute:: useMaterial
+
+ Determines if the sensor is looking for a property or material. KX_True = Find material; KX_False = Find property.
+
+ :type: boolean
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst
index 75630ae4d26..f2dad58731c 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst
@@ -152,6 +152,8 @@ base class --- :class:`PyObjectPlus`
:arg scene: The name of the scene to replace this scene with.
:type scene: string
+ :return: True if the scene exists and was scheduled for addition, False otherwise.
+ :rtype: boolean
.. method:: suspend()
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_TrackToActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_TrackToActuator.rst
index 070243c6a05..5b5c5d0c0db 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_TrackToActuator.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_TrackToActuator.rst
@@ -37,3 +37,25 @@ base class --- :class:`SCA_IActuator`
:type: boolean
+ .. attribute:: upAxis
+
+ The axis that points upward.
+
+ :type: integer from 0 to 2
+
+ * KX_TRACK_UPAXIS_POS_X
+ * KX_TRACK_UPAXIS_POS_Y
+ * KX_TRACK_UPAXIS_POS_Z
+
+ .. attribute:: trackAxis
+
+ The axis that points to the target object.
+
+ :type: integer from 0 to 5
+
+ * KX_TRACK_TRAXIS_POS_X
+ * KX_TRACK_TRAXIS_POS_Y
+ * KX_TRACK_TRAXIS_POS_Z
+ * KX_TRACK_TRAXIS_NEG_X
+ * KX_TRACK_TRAXIS_NEG_Y
+ * KX_TRACK_TRAXIS_NEG_Z
diff --git a/doc/python_api/rst/info_gotcha.rst b/doc/python_api/rst/info_gotcha.rst
index 5817f0f0d67..35f9c1bda9f 100644
--- a/doc/python_api/rst/info_gotcha.rst
+++ b/doc/python_api/rst/info_gotcha.rst
@@ -408,17 +408,19 @@ These returns the absolute path which can be used with native python modules.
Unicode Problems
================
-Python supports many different encodings so there is nothing stopping you from writing a script in latin1 or iso-8859-15.
+Python supports many different encodings so there is nothing stopping you from
+writing a script in ``latin1`` or ``iso-8859-15``.
See `pep-0263 <http://www.python.org/dev/peps/pep-0263/>`_
-However this complicates things for the python api because blend files themselves don't have an encoding.
+However this complicates matters for Blender's Python API because ``.blend`` files don't have an explicit encoding.
-To simplify the problem for python integration and script authors we have decided all strings in blend files **must** be UTF-8 or ASCII compatible.
+To avoid the problem for Python integration and script authors we have decided all strings in blend files
+**must** be ``UTF-8``, ``ASCII`` compatible.
This means assigning strings with different encodings to an object names for instance will raise an error.
-Paths are an exception to this rule since we cannot ignore the existane of non-utf-8 paths on peoples filesystems.
+Paths are an exception to this rule since we cannot ignore the existence of non ``UTF-8`` paths on users file-system.
This means seemingly harmless expressions can raise errors, eg.
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 8c6c0ae2c21..bfcc1cdde2c 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -77,6 +77,11 @@ if(WITH_LZMA)
add_subdirectory(lzma)
endif()
+if(WITH_CYCLES OR WITH_COMPOSITOR)
+ add_subdirectory(clew)
+ add_subdirectory(cuew)
+endif()
+
if(WITH_MOD_BOOLEAN)
add_subdirectory(carve)
endif()
diff --git a/extern/SConscript b/extern/SConscript
index 041aa345d79..714dfd2d537 100644
--- a/extern/SConscript
+++ b/extern/SConscript
@@ -20,6 +20,10 @@ if env['WITH_BF_ELTOPO']:
if env['WITH_BF_BULLET']:
SConscript(['bullet2/src/SConscript'])
+if env['WITH_BF_COMPOSITOR'] or env['WITH_BF_CYCLES']:
+ SConscript (['clew/SConscript'])
+ SConscript (['cuew/SConscript'])
+
if env['WITH_BF_OPENJPEG'] and env['BF_OPENJPEG_LIB'] == '':
SConscript(['libopenjpeg/SConscript'])
diff --git a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
index 8f1cd20bf45..8d940e63cd3 100644
--- a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
+++ b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
@@ -29,10 +29,13 @@ subject to the following restrictions:
static btVector3
getNormalizedVector(const btVector3& v)
{
- btVector3 n = v.normalized();
- if (n.length() < SIMD_EPSILON) {
- n.setValue(0, 0, 0);
- }
+ btScalar l = v.length();
+ btVector3 n = v;
+ if (l < SIMD_EPSILON) {
+ n.setValue(0,0,0);
+ } else {
+ n /= l;
+ }
return n;
}
diff --git a/extern/carve/carve-capi.cc b/extern/carve/carve-capi.cc
index d8c7727605c..5648977ad27 100644
--- a/extern/carve/carve-capi.cc
+++ b/extern/carve/carve-capi.cc
@@ -555,6 +555,19 @@ void cleanupFaceEdgeAttrs(const MeshSet<3> *left,
interpolator->swapAttributes(&new_interpolator);
}
+void cleanupFaceEdgeAttrsCallback(const MeshSet<3> *left,
+ const MeshSet<3> *right,
+ void *descr_v)
+{
+ CarveMeshDescr *descr = (CarveMeshDescr *) descr_v;
+ cleanupFaceEdgeAttrs(left,
+ right,
+ &descr->face_edge_triangulated_flag);
+ cleanupFaceEdgeAttrs(left,
+ right,
+ &descr->orig_face_edge_mapping);
+}
+
} // namespace
CarveMeshDescr *carve_addMesh(struct ImportMeshData *import_data,
@@ -737,14 +750,9 @@ bool carve_performBooleanOperation(CarveMeshDescr *left_mesh,
// intersecting that meshes tessellation of operation result can't be
// done properly. The only way to make such situations working is to
// union intersecting meshes of the same operand.
- if (carve_unionIntersections(&csg, &left, &right)) {
- cleanupFaceEdgeAttrs(left,
- right,
- &output_descr->face_edge_triangulated_flag);
- cleanupFaceEdgeAttrs(left,
- right,
- &output_descr->orig_face_edge_mapping);
- }
+ carve_unionIntersections(&csg, &left, &right,
+ cleanupFaceEdgeAttrsCallback,
+ (void *) output_descr);
left_mesh->poly = left;
right_mesh->poly = right;
diff --git a/extern/carve/carve-capi.h b/extern/carve/carve-capi.h
index 25704dfeb48..f08ce418762 100644
--- a/extern/carve/carve-capi.h
+++ b/extern/carve/carve-capi.h
@@ -54,13 +54,13 @@ typedef int (*CarveImporter_GetNumPolys) (struct ImportMeshData *import_data);
// Get 3D coordinate of vertex with given index.
typedef void (*CarveImporter_GetVertCoord) (struct ImportMeshData *import_data, int vert_index, float coord[3]);
-// Get index of vertices which are adjucent to edge specified by it's index.
+// Get index of vertices which are adjacent to edge specified by its index.
typedef void (*CarveImporter_GetEdgeVerts) (struct ImportMeshData *import_data, int edge_index, int *v1, int *v2);
-// Get number of adjucent vertices to the poly specified by it's index.
+// Get number of adjacent vertices to the poly specified by its index.
typedef int (*CarveImporter_GetPolyNumVerts) (struct ImportMeshData *import_data, int poly_index);
-// Get list of adjucent vertices to the poly specified by it's index.
+// Get list of adjacent vertices to the poly specified by its index.
typedef void (*CarveImporter_GetPolyVerts) (struct ImportMeshData *import_data, int poly_index, int *verts);
// Triangulate 2D polygon.
@@ -89,24 +89,24 @@ struct ExportMeshData;
// Initialize arrays for geometry.
typedef void (*CarveExporter_InitGeomArrays) (struct ExportMeshData *export_data,
int num_verts, int num_edges,
- int num_polys, int num_loops);
+ int num_loops, int num_polys);
// Set coordinate of vertex with given index.
typedef void (*CarveExporter_SetVert) (struct ExportMeshData *export_data,
int vert_index, float coord[3],
- int which_orig_mesh, int orig_edge_index);
+ int which_orig_mesh, int orig_vert_index);
-// Set vertices which are adjucent to the edge specified by it's index.
+// Set vertices which are adjacent to the edge specified by its index.
typedef void (*CarveExporter_SetEdge) (struct ExportMeshData *export_data,
int edge_index, int v1, int v2,
int which_orig_mesh, int orig_edge_index);
-// Set adjucent loops to the poly specified by it's index.
+// Set adjacent loops to the poly specified by its index.
typedef void (*CarveExporter_SetPoly) (struct ExportMeshData *export_data,
int poly_index, int start_loop, int num_loops,
int which_orig_mesh, int orig_poly_index);
-// Set list vertex and edge which are adjucent to loop with given index.
+// Set list vertex and edge which are adjacent to loop with given index.
typedef void (*CarveExporter_SetLoop) (struct ExportMeshData *export_data,
int loop_index, int vertex, int edge,
int which_orig_mesh, int orig_loop_index);
diff --git a/extern/carve/carve-util.cc b/extern/carve/carve-util.cc
index 1106fa16a21..0dff1deb750 100644
--- a/extern/carve/carve-util.cc
+++ b/extern/carve/carve-util.cc
@@ -365,7 +365,10 @@ MeshSet<3> *getIntersectedOperand(std::vector<MeshSet<3>::mesh_t*> *meshes,
MeshSet<3> *unionIntersectingMeshes(carve::csg::CSG *csg,
MeshSet<3> *poly,
- const MeshSet<3>::aabb_t &otherAABB)
+ const MeshSet<3> *other_poly,
+ const MeshSet<3>::aabb_t &otherAABB,
+ UnionIntersectionsCallback callback,
+ void *user_data)
{
if (poly->meshes.size() <= 1) {
return poly;
@@ -409,6 +412,7 @@ MeshSet<3> *unionIntersectingMeshes(carve::csg::CSG *csg,
carve::csg::CSG::UNION,
NULL, carve::csg::CSG::CLASSIFY_EDGE);
+ callback(result, other_poly, user_data);
delete left;
delete right;
@@ -420,6 +424,8 @@ MeshSet<3> *unionIntersectingMeshes(carve::csg::CSG *csg,
MeshSet<3> *result = meshSetFromTwoMeshes(left->meshes, right->meshes);
+ callback(result, other_poly, user_data);
+
delete left;
delete right;
@@ -455,37 +461,36 @@ MeshSet<3> *unionIntersectingMeshes(carve::csg::CSG *csg,
// TODO(sergey): This function is to be totally re-implemented to make it
// more clear what's going on and hopefully optimize it as well.
-bool carve_unionIntersections(carve::csg::CSG *csg,
+void carve_unionIntersections(carve::csg::CSG *csg,
MeshSet<3> **left_r,
- MeshSet<3> **right_r)
+ MeshSet<3> **right_r,
+ UnionIntersectionsCallback callback,
+ void *user_data)
{
MeshSet<3> *left = *left_r, *right = *right_r;
- bool changed = false;
if (left->meshes.size() == 1 && right->meshes.size() == 0) {
- return false;
+ return;
}
MeshSet<3>::aabb_t leftAABB = left->getAABB();
MeshSet<3>::aabb_t rightAABB = right->getAABB();;
- left = unionIntersectingMeshes(csg, left, rightAABB);
- right = unionIntersectingMeshes(csg, right, leftAABB);
+ left = unionIntersectingMeshes(csg, left, right, rightAABB,
+ callback, user_data);
+ right = unionIntersectingMeshes(csg, right, left, leftAABB,
+ callback, user_data);
if (left != *left_r) {
- changed = true;
delete *left_r;
}
if (right != *right_r) {
- changed = true;
delete *right_r;
}
*left_r = left;
*right_r = right;
-
- return changed;
}
static inline void add_newell_cross_v3_v3v3(const Vector &v_prev,
diff --git a/extern/carve/carve-util.h b/extern/carve/carve-util.h
index 0b509aa3cab..3edf1bb1c02 100644
--- a/extern/carve/carve-util.h
+++ b/extern/carve/carve-util.h
@@ -70,9 +70,15 @@ void carve_getRescaleMinMax(const carve::mesh::MeshSet<3> *left,
carve::geom3d::Vector *min,
carve::geom3d::Vector *max);
-bool carve_unionIntersections(carve::csg::CSG *csg,
+typedef void (*UnionIntersectionsCallback) (const carve::mesh::MeshSet<3> *left,
+ const carve::mesh::MeshSet<3> *right,
+ void *userdata);
+
+void carve_unionIntersections(carve::csg::CSG *csg,
carve::mesh::MeshSet<3> **left_r,
- carve::mesh::MeshSet<3> **right_r);
+ carve::mesh::MeshSet<3> **right_r,
+ UnionIntersectionsCallback callback,
+ void *user_data);
bool carve_checkPolyPlanarAndGetNormal(const std::vector<carve::mesh::MeshSet<3>::vertex_t> &vertex_storage,
const int verts_per_poly,
diff --git a/extern/clew/CMakeLists.txt b/extern/clew/CMakeLists.txt
new file mode 100644
index 00000000000..f75e933034f
--- /dev/null
+++ b/extern/clew/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 *****
+
+set(INC
+ .
+ include
+)
+
+set(INC_SYS
+
+)
+
+set(SRC
+ include/clew.h
+ src/clew.c
+)
+
+add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_1_APIS)
+
+blender_add_lib(extern_clew "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/extern/clew/SConscript b/extern/clew/SConscript
new file mode 100644
index 00000000000..14a03c7298e
--- /dev/null
+++ b/extern/clew/SConscript
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+#
+# ***** 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): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+Import ('env')
+
+sources = env.Glob('src/clew.c')
+
+incs = 'include'
+defs = ['CL_USE_DEPRECATED_OPENCL_1_1_APIS']
+
+env.BlenderLib ('extern_clew', sources, Split(incs), defines=defs, libtype=['system'], priority = [999])
diff --git a/extern/clew/include/clew.h b/extern/clew/include/clew.h
new file mode 100644
index 00000000000..624fdb299fe
--- /dev/null
+++ b/extern/clew/include/clew.h
@@ -0,0 +1,2759 @@
+#ifndef CLEW_HPP_INCLUDED
+#define CLEW_HPP_INCLUDED
+
+//////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2009-2011 Organic Vectory B.V., KindDragon
+// Written by George van Venrooij
+//
+// Distributed under the MIT License.
+//////////////////////////////////////////////////////////////////////////
+
+//! \file clew.h
+//! \brief OpenCL run-time loader header
+//!
+//! This file contains a copy of the contents of CL.H and CL_PLATFORM.H from the
+//! official OpenCL spec. The purpose of this code is to load the OpenCL dynamic
+//! library at run-time and thus allow the executable to function on many
+//! platforms regardless of the vendor of the OpenCL driver actually installed.
+//! Some of the techniques used here were inspired by work done in the GLEW
+//! library (http://glew.sourceforge.net/)
+
+// Run-time dynamic linking functionality based on concepts used in GLEW
+#ifdef __OPENCL_CL_H
+#error cl.h included before clew.h
+#endif
+
+#ifdef __OPENCL_CL_PLATFORM_H
+#error cl_platform.h included before clew.h
+#endif
+
+// Prevent cl.h inclusion
+#define __OPENCL_CL_H
+// Prevent cl_platform.h inclusion
+#define __CL_PLATFORM_H
+
+/*******************************************************************************
+* Copyright (c) 2008-2010 The Khronos Group Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and/or associated documentation files (the
+* "Materials"), to deal in the Materials without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Materials, and to
+* permit persons to whom the Materials are furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Materials.
+*
+* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+******************************************************************************/
+#ifdef __APPLE__
+ /* Contains #defines for AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER below */
+ #include <AvailabilityMacros.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_WIN32)
+ #define CL_API_ENTRY
+ #define CL_API_CALL __stdcall
+ #define CL_CALLBACK __stdcall
+#else
+ #define CL_API_ENTRY
+ #define CL_API_CALL
+ #define CL_CALLBACK
+#endif
+
+#ifdef __APPLE__
+ #define CL_EXTENSION_WEAK_LINK __attribute__((weak_import))
+ #define CL_API_SUFFIX__VERSION_1_0 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+ #define CL_EXT_SUFFIX__VERSION_1_0 CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+ #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+ #define CL_EXT_PREFIX__VERSION_1_0_DEPRECATED CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+ #define CL_API_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK
+ #define CL_EXT_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK
+ #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
+ #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
+ #define CL_API_SUFFIX__VERSION_1_2 CL_EXTENSION_WEAK_LINK
+ #define CL_EXT_SUFFIX__VERSION_1_2 CL_EXTENSION_WEAK_LINK
+#else
+ #define CL_EXTENSION_WEAK_LINK
+ #define CL_API_SUFFIX__VERSION_1_0
+ #define CL_EXT_SUFFIX__VERSION_1_0
+ #define CL_API_SUFFIX__VERSION_1_1
+ #define CL_EXT_SUFFIX__VERSION_1_1
+ #define CL_API_SUFFIX__VERSION_1_2
+ #define CL_EXT_SUFFIX__VERSION_1_2
+
+ #if defined(__GNUC__)
+ #ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+ #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED
+ #define CL_EXT_PREFIX__VERSION_1_0_DEPRECATED
+ #else
+ #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED __attribute__((deprecated))
+ #define CL_EXT_PREFIX__VERSION_1_0_DEPRECATED
+ #endif
+
+ #ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS
+ #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
+ #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
+ #else
+ #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED __attribute__((deprecated))
+ #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
+ #endif
+ #elif defined(_WIN32)
+ #ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+ #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED
+ #define CL_EXT_PREFIX__VERSION_1_0_DEPRECATED
+ #else
+ #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED
+ #define CL_EXT_PREFIX__VERSION_1_0_DEPRECATED __declspec(deprecated)
+ #endif
+
+ #ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS
+ #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
+ #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
+ #else
+ #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
+ #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED __declspec(deprecated)
+ #endif
+ #else
+ #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED
+ #define CL_EXT_PREFIX__VERSION_1_0_DEPRECATED
+
+ #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
+ #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
+ #endif
+#endif
+
+#if (defined (_WIN32) && defined(_MSC_VER))
+
+/* scalar types */
+typedef signed __int8 cl_char;
+typedef unsigned __int8 cl_uchar;
+typedef signed __int16 cl_short;
+typedef unsigned __int16 cl_ushort;
+typedef signed __int32 cl_int;
+typedef unsigned __int32 cl_uint;
+typedef signed __int64 cl_long;
+typedef unsigned __int64 cl_ulong;
+
+typedef unsigned __int16 cl_half;
+typedef float cl_float;
+typedef double cl_double;
+
+/* Macro names and corresponding values defined by OpenCL */
+#define CL_CHAR_BIT 8
+#define CL_SCHAR_MAX 127
+#define CL_SCHAR_MIN (-127-1)
+#define CL_CHAR_MAX CL_SCHAR_MAX
+#define CL_CHAR_MIN CL_SCHAR_MIN
+#define CL_UCHAR_MAX 255
+#define CL_SHRT_MAX 32767
+#define CL_SHRT_MIN (-32767-1)
+#define CL_USHRT_MAX 65535
+#define CL_INT_MAX 2147483647
+#define CL_INT_MIN (-2147483647-1)
+#define CL_UINT_MAX 0xffffffffU
+#define CL_LONG_MAX ((cl_long) 0x7FFFFFFFFFFFFFFFLL)
+#define CL_LONG_MIN ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL)
+#define CL_ULONG_MAX ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL)
+
+#define CL_FLT_DIG 6
+#define CL_FLT_MANT_DIG 24
+#define CL_FLT_MAX_10_EXP +38
+#define CL_FLT_MAX_EXP +128
+#define CL_FLT_MIN_10_EXP -37
+#define CL_FLT_MIN_EXP -125
+#define CL_FLT_RADIX 2
+#define CL_FLT_MAX 340282346638528859811704183484516925440.0f
+#define CL_FLT_MIN 1.175494350822287507969e-38f
+#define CL_FLT_EPSILON 0x1.0p-23f
+
+#define CL_DBL_DIG 15
+#define CL_DBL_MANT_DIG 53
+#define CL_DBL_MAX_10_EXP +308
+#define CL_DBL_MAX_EXP +1024
+#define CL_DBL_MIN_10_EXP -307
+#define CL_DBL_MIN_EXP -1021
+#define CL_DBL_RADIX 2
+#define CL_DBL_MAX 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0
+#define CL_DBL_MIN 2.225073858507201383090e-308
+#define CL_DBL_EPSILON 2.220446049250313080847e-16
+
+#define CL_M_E 2.718281828459045090796
+#define CL_M_LOG2E 1.442695040888963387005
+#define CL_M_LOG10E 0.434294481903251816668
+#define CL_M_LN2 0.693147180559945286227
+#define CL_M_LN10 2.302585092994045901094
+#define CL_M_PI 3.141592653589793115998
+#define CL_M_PI_2 1.570796326794896557999
+#define CL_M_PI_4 0.785398163397448278999
+#define CL_M_1_PI 0.318309886183790691216
+#define CL_M_2_PI 0.636619772367581382433
+#define CL_M_2_SQRTPI 1.128379167095512558561
+#define CL_M_SQRT2 1.414213562373095145475
+#define CL_M_SQRT1_2 0.707106781186547572737
+
+#define CL_M_E_F 2.71828174591064f
+#define CL_M_LOG2E_F 1.44269502162933f
+#define CL_M_LOG10E_F 0.43429449200630f
+#define CL_M_LN2_F 0.69314718246460f
+#define CL_M_LN10_F 2.30258512496948f
+#define CL_M_PI_F 3.14159274101257f
+#define CL_M_PI_2_F 1.57079637050629f
+#define CL_M_PI_4_F 0.78539818525314f
+#define CL_M_1_PI_F 0.31830987334251f
+#define CL_M_2_PI_F 0.63661974668503f
+#define CL_M_2_SQRTPI_F 1.12837922573090f
+#define CL_M_SQRT2_F 1.41421353816986f
+#define CL_M_SQRT1_2_F 0.70710676908493f
+
+#define CL_NAN (CL_INFINITY - CL_INFINITY)
+#define CL_HUGE_VALF ((cl_float) 1e50)
+#define CL_HUGE_VAL ((cl_double) 1e500)
+#define CL_MAXFLOAT CL_FLT_MAX
+#define CL_INFINITY CL_HUGE_VALF
+
+#else
+
+#include <stdint.h>
+
+/* scalar types */
+typedef int8_t cl_char;
+typedef uint8_t cl_uchar;
+typedef int16_t cl_short __attribute__((aligned(2)));
+typedef uint16_t cl_ushort __attribute__((aligned(2)));
+typedef int32_t cl_int __attribute__((aligned(4)));
+typedef uint32_t cl_uint __attribute__((aligned(4)));
+typedef int64_t cl_long __attribute__((aligned(8)));
+typedef uint64_t cl_ulong __attribute__((aligned(8)));
+
+typedef uint16_t cl_half __attribute__((aligned(2)));
+typedef float cl_float __attribute__((aligned(4)));
+typedef double cl_double __attribute__((aligned(8)));
+
+/* Macro names and corresponding values defined by OpenCL */
+#define CL_CHAR_BIT 8
+#define CL_SCHAR_MAX 127
+#define CL_SCHAR_MIN (-127-1)
+#define CL_CHAR_MAX CL_SCHAR_MAX
+#define CL_CHAR_MIN CL_SCHAR_MIN
+#define CL_UCHAR_MAX 255
+#define CL_SHRT_MAX 32767
+#define CL_SHRT_MIN (-32767-1)
+#define CL_USHRT_MAX 65535
+#define CL_INT_MAX 2147483647
+#define CL_INT_MIN (-2147483647-1)
+#define CL_UINT_MAX 0xffffffffU
+#define CL_LONG_MAX ((cl_long) 0x7FFFFFFFFFFFFFFFLL)
+#define CL_LONG_MIN ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL)
+#define CL_ULONG_MAX ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL)
+
+#define CL_FLT_DIG 6
+#define CL_FLT_MANT_DIG 24
+#define CL_FLT_MAX_10_EXP +38
+#define CL_FLT_MAX_EXP +128
+#define CL_FLT_MIN_10_EXP -37
+#define CL_FLT_MIN_EXP -125
+#define CL_FLT_RADIX 2
+#define CL_FLT_MAX 0x1.fffffep127f
+#define CL_FLT_MIN 0x1.0p-126f
+#define CL_FLT_EPSILON 0x1.0p-23f
+
+#define CL_DBL_DIG 15
+#define CL_DBL_MANT_DIG 53
+#define CL_DBL_MAX_10_EXP +308
+#define CL_DBL_MAX_EXP +1024
+#define CL_DBL_MIN_10_EXP -307
+#define CL_DBL_MIN_EXP -1021
+#define CL_DBL_RADIX 2
+#define CL_DBL_MAX 0x1.fffffffffffffp1023
+#define CL_DBL_MIN 0x1.0p-1022
+#define CL_DBL_EPSILON 0x1.0p-52
+
+#define CL_M_E 2.718281828459045090796
+#define CL_M_LOG2E 1.442695040888963387005
+#define CL_M_LOG10E 0.434294481903251816668
+#define CL_M_LN2 0.693147180559945286227
+#define CL_M_LN10 2.302585092994045901094
+#define CL_M_PI 3.141592653589793115998
+#define CL_M_PI_2 1.570796326794896557999
+#define CL_M_PI_4 0.785398163397448278999
+#define CL_M_1_PI 0.318309886183790691216
+#define CL_M_2_PI 0.636619772367581382433
+#define CL_M_2_SQRTPI 1.128379167095512558561
+#define CL_M_SQRT2 1.414213562373095145475
+#define CL_M_SQRT1_2 0.707106781186547572737
+
+#define CL_M_E_F 2.71828174591064f
+#define CL_M_LOG2E_F 1.44269502162933f
+#define CL_M_LOG10E_F 0.43429449200630f
+#define CL_M_LN2_F 0.69314718246460f
+#define CL_M_LN10_F 2.30258512496948f
+#define CL_M_PI_F 3.14159274101257f
+#define CL_M_PI_2_F 1.57079637050629f
+#define CL_M_PI_4_F 0.78539818525314f
+#define CL_M_1_PI_F 0.31830987334251f
+#define CL_M_2_PI_F 0.63661974668503f
+#define CL_M_2_SQRTPI_F 1.12837922573090f
+#define CL_M_SQRT2_F 1.41421353816986f
+#define CL_M_SQRT1_2_F 0.70710676908493f
+
+#if defined( __GNUC__ )
+ #define CL_HUGE_VALF __builtin_huge_valf()
+ #define CL_HUGE_VAL __builtin_huge_val()
+ #define CL_NAN __builtin_nanf( "" )
+#else
+ #define CL_HUGE_VALF ((cl_float) 1e50)
+ #define CL_HUGE_VAL ((cl_double) 1e500)
+ float nanf( const char * );
+ #define CL_NAN nanf( "" )
+#endif
+#define CL_MAXFLOAT CL_FLT_MAX
+#define CL_INFINITY CL_HUGE_VALF
+
+#endif
+
+#include <stddef.h>
+
+/* Mirror types to GL types. Mirror types allow us to avoid deciding which headers to load based on whether we are using GL or GLES here. */
+typedef unsigned int cl_GLuint;
+typedef int cl_GLint;
+typedef unsigned int cl_GLenum;
+
+/*
+ * Vector types
+ *
+ * Note: OpenCL requires that all types be naturally aligned.
+ * This means that vector types must be naturally aligned.
+ * For example, a vector of four floats must be aligned to
+ * a 16 byte boundary (calculated as 4 * the natural 4-byte
+ * alignment of the float). The alignment qualifiers here
+ * will only function properly if your compiler supports them
+ * and if you don't actively work to defeat them. For example,
+ * in order for a cl_float4 to be 16 byte aligned in a struct,
+ * the start of the struct must itself be 16-byte aligned.
+ *
+ * Maintaining proper alignment is the user's responsibility.
+ */
+
+
+#ifdef _MSC_VER
+#if defined(_M_IX86)
+#if _M_IX86_FP >= 0
+#define __SSE__
+#endif
+#if _M_IX86_FP >= 1
+# ifndef __SSE2__
+# define __SSE2__
+# endif
+#endif
+#elif defined(_M_X64)
+# ifndef __SSE__
+# define __SSE__
+# endif
+# ifndef __SSE2__
+# define __SSE2__
+# endif
+#endif
+#endif
+
+/* Define basic vector types */
+#if defined( __VEC__ )
+ #include <altivec.h> /* may be omitted depending on compiler. AltiVec spec provides no way to detect whether the header is required. */
+ typedef vector unsigned char __cl_uchar16;
+ typedef vector signed char __cl_char16;
+ typedef vector unsigned short __cl_ushort8;
+ typedef vector signed short __cl_short8;
+ typedef vector unsigned int __cl_uint4;
+ typedef vector signed int __cl_int4;
+ typedef vector float __cl_float4;
+ #define __CL_UCHAR16__ 1
+ #define __CL_CHAR16__ 1
+ #define __CL_USHORT8__ 1
+ #define __CL_SHORT8__ 1
+ #define __CL_UINT4__ 1
+ #define __CL_INT4__ 1
+ #define __CL_FLOAT4__ 1
+#endif
+
+#if defined( __SSE__ )
+ #if defined( __MINGW64__ )
+ #include <intrin.h>
+ #else
+ #include <xmmintrin.h>
+ #endif
+ #if defined( __GNUC__ ) && !defined( __ICC )
+ typedef float __cl_float4 __attribute__((vector_size(16)));
+ #else
+ typedef __m128 __cl_float4;
+ #endif
+ #define __CL_FLOAT4__ 1
+#endif
+
+#if defined( __SSE2__ )
+ #if defined( __MINGW64__ )
+ #include <intrin.h>
+ #else
+ #include <emmintrin.h>
+ #endif
+ #if defined( __GNUC__ ) && !defined( __ICC )
+ typedef cl_uchar __cl_uchar16 __attribute__((vector_size(16)));
+ typedef cl_char __cl_char16 __attribute__((vector_size(16)));
+ typedef cl_ushort __cl_ushort8 __attribute__((vector_size(16)));
+ typedef cl_short __cl_short8 __attribute__((vector_size(16)));
+ typedef cl_uint __cl_uint4 __attribute__((vector_size(16)));
+ typedef cl_int __cl_int4 __attribute__((vector_size(16)));
+ typedef cl_ulong __cl_ulong2 __attribute__((vector_size(16)));
+ typedef cl_long __cl_long2 __attribute__((vector_size(16)));
+ typedef cl_double __cl_double2 __attribute__((vector_size(16)));
+ #else
+ typedef __m128i __cl_uchar16;
+ typedef __m128i __cl_char16;
+ typedef __m128i __cl_ushort8;
+ typedef __m128i __cl_short8;
+ typedef __m128i __cl_uint4;
+ typedef __m128i __cl_int4;
+ typedef __m128i __cl_ulong2;
+ typedef __m128i __cl_long2;
+ typedef __m128d __cl_double2;
+ #endif
+ #define __CL_UCHAR16__ 1
+ #define __CL_CHAR16__ 1
+ #define __CL_USHORT8__ 1
+ #define __CL_SHORT8__ 1
+ #define __CL_INT4__ 1
+ #define __CL_UINT4__ 1
+ #define __CL_ULONG2__ 1
+ #define __CL_LONG2__ 1
+ #define __CL_DOUBLE2__ 1
+#endif
+
+#if defined( __MMX__ )
+ #include <mmintrin.h>
+ #if defined( __GNUC__ ) && !defined( __ICC )
+ typedef cl_uchar __cl_uchar8 __attribute__((vector_size(8)));
+ typedef cl_char __cl_char8 __attribute__((vector_size(8)));
+ typedef cl_ushort __cl_ushort4 __attribute__((vector_size(8)));
+ typedef cl_short __cl_short4 __attribute__((vector_size(8)));
+ typedef cl_uint __cl_uint2 __attribute__((vector_size(8)));
+ typedef cl_int __cl_int2 __attribute__((vector_size(8)));
+ typedef cl_ulong __cl_ulong1 __attribute__((vector_size(8)));
+ typedef cl_long __cl_long1 __attribute__((vector_size(8)));
+ typedef cl_float __cl_float2 __attribute__((vector_size(8)));
+ #else
+ typedef __m64 __cl_uchar8;
+ typedef __m64 __cl_char8;
+ typedef __m64 __cl_ushort4;
+ typedef __m64 __cl_short4;
+ typedef __m64 __cl_uint2;
+ typedef __m64 __cl_int2;
+ typedef __m64 __cl_ulong1;
+ typedef __m64 __cl_long1;
+ typedef __m64 __cl_float2;
+ #endif
+ #define __CL_UCHAR8__ 1
+ #define __CL_CHAR8__ 1
+ #define __CL_USHORT4__ 1
+ #define __CL_SHORT4__ 1
+ #define __CL_INT2__ 1
+ #define __CL_UINT2__ 1
+ #define __CL_ULONG1__ 1
+ #define __CL_LONG1__ 1
+ #define __CL_FLOAT2__ 1
+#endif
+
+#if defined( __AVX__ )
+ #if defined( __MINGW64__ )
+ #include <intrin.h>
+ #else
+ #include <immintrin.h>
+ #endif
+ #if defined( __GNUC__ ) && !defined( __ICC )
+ typedef cl_float __cl_float8 __attribute__((vector_size(32)));
+ typedef cl_double __cl_double4 __attribute__((vector_size(32)));
+ #else
+ typedef __m256 __cl_float8;
+ typedef __m256d __cl_double4;
+ #endif
+ #define __CL_FLOAT8__ 1
+ #define __CL_DOUBLE4__ 1
+#endif
+
+/* Define alignment keys */
+#if defined( __GNUC__ )
+ #define CL_ALIGNED(_x) __attribute__ ((aligned(_x)))
+#elif defined( _WIN32) && (_MSC_VER)
+ /* Alignment keys neutered on windows because MSVC can't swallow function arguments with alignment requirements */
+ /* http://msdn.microsoft.com/en-us/library/373ak2y1%28VS.71%29.aspx */
+ /* #include <crtdefs.h> */
+ /* #define CL_ALIGNED(_x) _CRT_ALIGN(_x) */
+ #define CL_ALIGNED(_x)
+#else
+ #warning Need to implement some method to align data here
+ #define CL_ALIGNED(_x)
+#endif
+
+/* Indicate whether .xyzw, .s0123 and .hi.lo are supported */
+#if (defined( __GNUC__) && ! defined( __STRICT_ANSI__ )) || (defined( _MSC_VER ) && ! defined( __STDC__ ))
+ /* .xyzw and .s0123...{f|F} are supported */
+ #define CL_HAS_NAMED_VECTOR_FIELDS 1
+ /* .hi and .lo are supported */
+ #define CL_HAS_HI_LO_VECTOR_FIELDS 1
+
+ #define CL_NAMED_STRUCT_SUPPORTED
+#endif
+
+#if defined( CL_NAMED_STRUCT_SUPPORTED) && defined( _MSC_VER )
+#define __extension__ __pragma(warning(suppress:4201))
+#endif
+
+/* Define cl_vector types */
+
+/* ---- cl_charn ---- */
+typedef union
+{
+ cl_char CL_ALIGNED(2) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_char x, y; };
+ __extension__ struct{ cl_char s0, s1; };
+ __extension__ struct{ cl_char lo, hi; };
+#endif
+#if defined( __CL_CHAR2__)
+ __cl_char2 v2;
+#endif
+}cl_char2;
+
+typedef union
+{
+ cl_char CL_ALIGNED(4) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_char x, y, z, w; };
+ __extension__ struct{ cl_char s0, s1, s2, s3; };
+ __extension__ struct{ cl_char2 lo, hi; };
+#endif
+#if defined( __CL_CHAR2__)
+ __cl_char2 v2[2];
+#endif
+#if defined( __CL_CHAR4__)
+ __cl_char4 v4;
+#endif
+}cl_char4;
+
+/* cl_char3 is identical in size, alignment and behavior to cl_char4. See section 6.1.5. */
+typedef cl_char4 cl_char3;
+
+typedef union
+{
+ cl_char CL_ALIGNED(8) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_char x, y, z, w; };
+ __extension__ struct{ cl_char s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_char4 lo, hi; };
+#endif
+#if defined( __CL_CHAR2__)
+ __cl_char2 v2[4];
+#endif
+#if defined( __CL_CHAR4__)
+ __cl_char4 v4[2];
+#endif
+#if defined( __CL_CHAR8__ )
+ __cl_char8 v8;
+#endif
+}cl_char8;
+
+typedef union
+{
+ cl_char CL_ALIGNED(16) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_char x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_char s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_char8 lo, hi; };
+#endif
+#if defined( __CL_CHAR2__)
+ __cl_char2 v2[8];
+#endif
+#if defined( __CL_CHAR4__)
+ __cl_char4 v4[4];
+#endif
+#if defined( __CL_CHAR8__ )
+ __cl_char8 v8[2];
+#endif
+#if defined( __CL_CHAR16__ )
+ __cl_char16 v16;
+#endif
+}cl_char16;
+
+
+/* ---- cl_ucharn ---- */
+typedef union
+{
+ cl_uchar CL_ALIGNED(2) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uchar x, y; };
+ __extension__ struct{ cl_uchar s0, s1; };
+ __extension__ struct{ cl_uchar lo, hi; };
+#endif
+#if defined( __cl_uchar2__)
+ __cl_uchar2 v2;
+#endif
+}cl_uchar2;
+
+typedef union
+{
+ cl_uchar CL_ALIGNED(4) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uchar x, y, z, w; };
+ __extension__ struct{ cl_uchar s0, s1, s2, s3; };
+ __extension__ struct{ cl_uchar2 lo, hi; };
+#endif
+#if defined( __CL_UCHAR2__)
+ __cl_uchar2 v2[2];
+#endif
+#if defined( __CL_UCHAR4__)
+ __cl_uchar4 v4;
+#endif
+}cl_uchar4;
+
+/* cl_uchar3 is identical in size, alignment and behavior to cl_uchar4. See section 6.1.5. */
+typedef cl_uchar4 cl_uchar3;
+
+typedef union
+{
+ cl_uchar CL_ALIGNED(8) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uchar x, y, z, w; };
+ __extension__ struct{ cl_uchar s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_uchar4 lo, hi; };
+#endif
+#if defined( __CL_UCHAR2__)
+ __cl_uchar2 v2[4];
+#endif
+#if defined( __CL_UCHAR4__)
+ __cl_uchar4 v4[2];
+#endif
+#if defined( __CL_UCHAR8__ )
+ __cl_uchar8 v8;
+#endif
+}cl_uchar8;
+
+typedef union
+{
+ cl_uchar CL_ALIGNED(16) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uchar x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_uchar s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_uchar8 lo, hi; };
+#endif
+#if defined( __CL_UCHAR2__)
+ __cl_uchar2 v2[8];
+#endif
+#if defined( __CL_UCHAR4__)
+ __cl_uchar4 v4[4];
+#endif
+#if defined( __CL_UCHAR8__ )
+ __cl_uchar8 v8[2];
+#endif
+#if defined( __CL_UCHAR16__ )
+ __cl_uchar16 v16;
+#endif
+}cl_uchar16;
+
+
+/* ---- cl_shortn ---- */
+typedef union
+{
+ cl_short CL_ALIGNED(4) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_short x, y; };
+ __extension__ struct{ cl_short s0, s1; };
+ __extension__ struct{ cl_short lo, hi; };
+#endif
+#if defined( __CL_SHORT2__)
+ __cl_short2 v2;
+#endif
+}cl_short2;
+
+typedef union
+{
+ cl_short CL_ALIGNED(8) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_short x, y, z, w; };
+ __extension__ struct{ cl_short s0, s1, s2, s3; };
+ __extension__ struct{ cl_short2 lo, hi; };
+#endif
+#if defined( __CL_SHORT2__)
+ __cl_short2 v2[2];
+#endif
+#if defined( __CL_SHORT4__)
+ __cl_short4 v4;
+#endif
+}cl_short4;
+
+/* cl_short3 is identical in size, alignment and behavior to cl_short4. See section 6.1.5. */
+typedef cl_short4 cl_short3;
+
+typedef union
+{
+ cl_short CL_ALIGNED(16) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_short x, y, z, w; };
+ __extension__ struct{ cl_short s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_short4 lo, hi; };
+#endif
+#if defined( __CL_SHORT2__)
+ __cl_short2 v2[4];
+#endif
+#if defined( __CL_SHORT4__)
+ __cl_short4 v4[2];
+#endif
+#if defined( __CL_SHORT8__ )
+ __cl_short8 v8;
+#endif
+}cl_short8;
+
+typedef union
+{
+ cl_short CL_ALIGNED(32) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_short x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_short s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_short8 lo, hi; };
+#endif
+#if defined( __CL_SHORT2__)
+ __cl_short2 v2[8];
+#endif
+#if defined( __CL_SHORT4__)
+ __cl_short4 v4[4];
+#endif
+#if defined( __CL_SHORT8__ )
+ __cl_short8 v8[2];
+#endif
+#if defined( __CL_SHORT16__ )
+ __cl_short16 v16;
+#endif
+}cl_short16;
+
+
+/* ---- cl_ushortn ---- */
+typedef union
+{
+ cl_ushort CL_ALIGNED(4) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ushort x, y; };
+ __extension__ struct{ cl_ushort s0, s1; };
+ __extension__ struct{ cl_ushort lo, hi; };
+#endif
+#if defined( __CL_USHORT2__)
+ __cl_ushort2 v2;
+#endif
+}cl_ushort2;
+
+typedef union
+{
+ cl_ushort CL_ALIGNED(8) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ushort x, y, z, w; };
+ __extension__ struct{ cl_ushort s0, s1, s2, s3; };
+ __extension__ struct{ cl_ushort2 lo, hi; };
+#endif
+#if defined( __CL_USHORT2__)
+ __cl_ushort2 v2[2];
+#endif
+#if defined( __CL_USHORT4__)
+ __cl_ushort4 v4;
+#endif
+}cl_ushort4;
+
+/* cl_ushort3 is identical in size, alignment and behavior to cl_ushort4. See section 6.1.5. */
+typedef cl_ushort4 cl_ushort3;
+
+typedef union
+{
+ cl_ushort CL_ALIGNED(16) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ushort x, y, z, w; };
+ __extension__ struct{ cl_ushort s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_ushort4 lo, hi; };
+#endif
+#if defined( __CL_USHORT2__)
+ __cl_ushort2 v2[4];
+#endif
+#if defined( __CL_USHORT4__)
+ __cl_ushort4 v4[2];
+#endif
+#if defined( __CL_USHORT8__ )
+ __cl_ushort8 v8;
+#endif
+}cl_ushort8;
+
+typedef union
+{
+ cl_ushort CL_ALIGNED(32) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ushort x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_ushort s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_ushort8 lo, hi; };
+#endif
+#if defined( __CL_USHORT2__)
+ __cl_ushort2 v2[8];
+#endif
+#if defined( __CL_USHORT4__)
+ __cl_ushort4 v4[4];
+#endif
+#if defined( __CL_USHORT8__ )
+ __cl_ushort8 v8[2];
+#endif
+#if defined( __CL_USHORT16__ )
+ __cl_ushort16 v16;
+#endif
+}cl_ushort16;
+
+/* ---- cl_intn ---- */
+typedef union
+{
+ cl_int CL_ALIGNED(8) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_int x, y; };
+ __extension__ struct{ cl_int s0, s1; };
+ __extension__ struct{ cl_int lo, hi; };
+#endif
+#if defined( __CL_INT2__)
+ __cl_int2 v2;
+#endif
+}cl_int2;
+
+typedef union
+{
+ cl_int CL_ALIGNED(16) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_int x, y, z, w; };
+ __extension__ struct{ cl_int s0, s1, s2, s3; };
+ __extension__ struct{ cl_int2 lo, hi; };
+#endif
+#if defined( __CL_INT2__)
+ __cl_int2 v2[2];
+#endif
+#if defined( __CL_INT4__)
+ __cl_int4 v4;
+#endif
+}cl_int4;
+
+/* cl_int3 is identical in size, alignment and behavior to cl_int4. See section 6.1.5. */
+typedef cl_int4 cl_int3;
+
+typedef union
+{
+ cl_int CL_ALIGNED(32) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_int x, y, z, w; };
+ __extension__ struct{ cl_int s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_int4 lo, hi; };
+#endif
+#if defined( __CL_INT2__)
+ __cl_int2 v2[4];
+#endif
+#if defined( __CL_INT4__)
+ __cl_int4 v4[2];
+#endif
+#if defined( __CL_INT8__ )
+ __cl_int8 v8;
+#endif
+}cl_int8;
+
+typedef union
+{
+ cl_int CL_ALIGNED(64) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_int x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_int s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_int8 lo, hi; };
+#endif
+#if defined( __CL_INT2__)
+ __cl_int2 v2[8];
+#endif
+#if defined( __CL_INT4__)
+ __cl_int4 v4[4];
+#endif
+#if defined( __CL_INT8__ )
+ __cl_int8 v8[2];
+#endif
+#if defined( __CL_INT16__ )
+ __cl_int16 v16;
+#endif
+}cl_int16;
+
+
+/* ---- cl_uintn ---- */
+typedef union
+{
+ cl_uint CL_ALIGNED(8) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uint x, y; };
+ __extension__ struct{ cl_uint s0, s1; };
+ __extension__ struct{ cl_uint lo, hi; };
+#endif
+#if defined( __CL_UINT2__)
+ __cl_uint2 v2;
+#endif
+}cl_uint2;
+
+typedef union
+{
+ cl_uint CL_ALIGNED(16) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uint x, y, z, w; };
+ __extension__ struct{ cl_uint s0, s1, s2, s3; };
+ __extension__ struct{ cl_uint2 lo, hi; };
+#endif
+#if defined( __CL_UINT2__)
+ __cl_uint2 v2[2];
+#endif
+#if defined( __CL_UINT4__)
+ __cl_uint4 v4;
+#endif
+}cl_uint4;
+
+/* cl_uint3 is identical in size, alignment and behavior to cl_uint4. See section 6.1.5. */
+typedef cl_uint4 cl_uint3;
+
+typedef union
+{
+ cl_uint CL_ALIGNED(32) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uint x, y, z, w; };
+ __extension__ struct{ cl_uint s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_uint4 lo, hi; };
+#endif
+#if defined( __CL_UINT2__)
+ __cl_uint2 v2[4];
+#endif
+#if defined( __CL_UINT4__)
+ __cl_uint4 v4[2];
+#endif
+#if defined( __CL_UINT8__ )
+ __cl_uint8 v8;
+#endif
+}cl_uint8;
+
+typedef union
+{
+ cl_uint CL_ALIGNED(64) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uint x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_uint s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_uint8 lo, hi; };
+#endif
+#if defined( __CL_UINT2__)
+ __cl_uint2 v2[8];
+#endif
+#if defined( __CL_UINT4__)
+ __cl_uint4 v4[4];
+#endif
+#if defined( __CL_UINT8__ )
+ __cl_uint8 v8[2];
+#endif
+#if defined( __CL_UINT16__ )
+ __cl_uint16 v16;
+#endif
+}cl_uint16;
+
+/* ---- cl_longn ---- */
+typedef union
+{
+ cl_long CL_ALIGNED(16) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_long x, y; };
+ __extension__ struct{ cl_long s0, s1; };
+ __extension__ struct{ cl_long lo, hi; };
+#endif
+#if defined( __CL_LONG2__)
+ __cl_long2 v2;
+#endif
+}cl_long2;
+
+typedef union
+{
+ cl_long CL_ALIGNED(32) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_long x, y, z, w; };
+ __extension__ struct{ cl_long s0, s1, s2, s3; };
+ __extension__ struct{ cl_long2 lo, hi; };
+#endif
+#if defined( __CL_LONG2__)
+ __cl_long2 v2[2];
+#endif
+#if defined( __CL_LONG4__)
+ __cl_long4 v4;
+#endif
+}cl_long4;
+
+/* cl_long3 is identical in size, alignment and behavior to cl_long4. See section 6.1.5. */
+typedef cl_long4 cl_long3;
+
+typedef union
+{
+ cl_long CL_ALIGNED(64) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_long x, y, z, w; };
+ __extension__ struct{ cl_long s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_long4 lo, hi; };
+#endif
+#if defined( __CL_LONG2__)
+ __cl_long2 v2[4];
+#endif
+#if defined( __CL_LONG4__)
+ __cl_long4 v4[2];
+#endif
+#if defined( __CL_LONG8__ )
+ __cl_long8 v8;
+#endif
+}cl_long8;
+
+typedef union
+{
+ cl_long CL_ALIGNED(128) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_long x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_long s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_long8 lo, hi; };
+#endif
+#if defined( __CL_LONG2__)
+ __cl_long2 v2[8];
+#endif
+#if defined( __CL_LONG4__)
+ __cl_long4 v4[4];
+#endif
+#if defined( __CL_LONG8__ )
+ __cl_long8 v8[2];
+#endif
+#if defined( __CL_LONG16__ )
+ __cl_long16 v16;
+#endif
+}cl_long16;
+
+
+/* ---- cl_ulongn ---- */
+typedef union
+{
+ cl_ulong CL_ALIGNED(16) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ulong x, y; };
+ __extension__ struct{ cl_ulong s0, s1; };
+ __extension__ struct{ cl_ulong lo, hi; };
+#endif
+#if defined( __CL_ULONG2__)
+ __cl_ulong2 v2;
+#endif
+}cl_ulong2;
+
+typedef union
+{
+ cl_ulong CL_ALIGNED(32) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ulong x, y, z, w; };
+ __extension__ struct{ cl_ulong s0, s1, s2, s3; };
+ __extension__ struct{ cl_ulong2 lo, hi; };
+#endif
+#if defined( __CL_ULONG2__)
+ __cl_ulong2 v2[2];
+#endif
+#if defined( __CL_ULONG4__)
+ __cl_ulong4 v4;
+#endif
+}cl_ulong4;
+
+/* cl_ulong3 is identical in size, alignment and behavior to cl_ulong4. See section 6.1.5. */
+typedef cl_ulong4 cl_ulong3;
+
+typedef union
+{
+ cl_ulong CL_ALIGNED(64) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ulong x, y, z, w; };
+ __extension__ struct{ cl_ulong s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_ulong4 lo, hi; };
+#endif
+#if defined( __CL_ULONG2__)
+ __cl_ulong2 v2[4];
+#endif
+#if defined( __CL_ULONG4__)
+ __cl_ulong4 v4[2];
+#endif
+#if defined( __CL_ULONG8__ )
+ __cl_ulong8 v8;
+#endif
+}cl_ulong8;
+
+typedef union
+{
+ cl_ulong CL_ALIGNED(128) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ulong x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_ulong s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_ulong8 lo, hi; };
+#endif
+#if defined( __CL_ULONG2__)
+ __cl_ulong2 v2[8];
+#endif
+#if defined( __CL_ULONG4__)
+ __cl_ulong4 v4[4];
+#endif
+#if defined( __CL_ULONG8__ )
+ __cl_ulong8 v8[2];
+#endif
+#if defined( __CL_ULONG16__ )
+ __cl_ulong16 v16;
+#endif
+}cl_ulong16;
+
+
+/* --- cl_floatn ---- */
+
+typedef union
+{
+ cl_float CL_ALIGNED(8) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_float x, y; };
+ __extension__ struct{ cl_float s0, s1; };
+ __extension__ struct{ cl_float lo, hi; };
+#endif
+#if defined( __CL_FLOAT2__)
+ __cl_float2 v2;
+#endif
+}cl_float2;
+
+typedef union
+{
+ cl_float CL_ALIGNED(16) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_float x, y, z, w; };
+ __extension__ struct{ cl_float s0, s1, s2, s3; };
+ __extension__ struct{ cl_float2 lo, hi; };
+#endif
+#if defined( __CL_FLOAT2__)
+ __cl_float2 v2[2];
+#endif
+#if defined( __CL_FLOAT4__)
+ __cl_float4 v4;
+#endif
+}cl_float4;
+
+/* cl_float3 is identical in size, alignment and behavior to cl_float4. See section 6.1.5. */
+typedef cl_float4 cl_float3;
+
+typedef union
+{
+ cl_float CL_ALIGNED(32) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_float x, y, z, w; };
+ __extension__ struct{ cl_float s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_float4 lo, hi; };
+#endif
+#if defined( __CL_FLOAT2__)
+ __cl_float2 v2[4];
+#endif
+#if defined( __CL_FLOAT4__)
+ __cl_float4 v4[2];
+#endif
+#if defined( __CL_FLOAT8__ )
+ __cl_float8 v8;
+#endif
+}cl_float8;
+
+typedef union
+{
+ cl_float CL_ALIGNED(64) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_float x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_float s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_float8 lo, hi; };
+#endif
+#if defined( __CL_FLOAT2__)
+ __cl_float2 v2[8];
+#endif
+#if defined( __CL_FLOAT4__)
+ __cl_float4 v4[4];
+#endif
+#if defined( __CL_FLOAT8__ )
+ __cl_float8 v8[2];
+#endif
+#if defined( __CL_FLOAT16__ )
+ __cl_float16 v16;
+#endif
+}cl_float16;
+
+/* --- cl_doublen ---- */
+
+typedef union
+{
+ cl_double CL_ALIGNED(16) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_double x, y; };
+ __extension__ struct{ cl_double s0, s1; };
+ __extension__ struct{ cl_double lo, hi; };
+#endif
+#if defined( __CL_DOUBLE2__)
+ __cl_double2 v2;
+#endif
+}cl_double2;
+
+typedef union
+{
+ cl_double CL_ALIGNED(32) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_double x, y, z, w; };
+ __extension__ struct{ cl_double s0, s1, s2, s3; };
+ __extension__ struct{ cl_double2 lo, hi; };
+#endif
+#if defined( __CL_DOUBLE2__)
+ __cl_double2 v2[2];
+#endif
+#if defined( __CL_DOUBLE4__)
+ __cl_double4 v4;
+#endif
+}cl_double4;
+
+/* cl_double3 is identical in size, alignment and behavior to cl_double4. See section 6.1.5. */
+typedef cl_double4 cl_double3;
+
+typedef union
+{
+ cl_double CL_ALIGNED(64) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_double x, y, z, w; };
+ __extension__ struct{ cl_double s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_double4 lo, hi; };
+#endif
+#if defined( __CL_DOUBLE2__)
+ __cl_double2 v2[4];
+#endif
+#if defined( __CL_DOUBLE4__)
+ __cl_double4 v4[2];
+#endif
+#if defined( __CL_DOUBLE8__ )
+ __cl_double8 v8;
+#endif
+}cl_double8;
+
+typedef union
+{
+ cl_double CL_ALIGNED(128) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_double x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_double s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_double8 lo, hi; };
+#endif
+#if defined( __CL_DOUBLE2__)
+ __cl_double2 v2[8];
+#endif
+#if defined( __CL_DOUBLE4__)
+ __cl_double4 v4[4];
+#endif
+#if defined( __CL_DOUBLE8__ )
+ __cl_double8 v8[2];
+#endif
+#if defined( __CL_DOUBLE16__ )
+ __cl_double16 v16;
+#endif
+}cl_double16;
+
+/* Macro to facilitate debugging
+ * Usage:
+ * Place CL_PROGRAM_STRING_DEBUG_INFO on the line before the first line of your source.
+ * The first line ends with: CL_PROGRAM_STRING_BEGIN \"
+ * Each line thereafter of OpenCL C source must end with: \n\
+ * The last line ends in ";
+ *
+ * Example:
+ *
+ * const char *my_program = CL_PROGRAM_STRING_BEGIN "\
+ * kernel void foo( int a, float * b ) \n\
+ * { \n\
+ * // my comment \n\
+ * *b[ get_global_id(0)] = a; \n\
+ * } \n\
+ * ";
+ *
+ * This should correctly set up the line, (column) and file information for your source
+ * string so you can do source level debugging.
+ */
+#define __CL_STRINGIFY( _x ) # _x
+#define _CL_STRINGIFY( _x ) __CL_STRINGIFY( _x )
+#define CL_PROGRAM_STRING_DEBUG_INFO "#line " _CL_STRINGIFY(__LINE__) " \"" __FILE__ "\" \n\n"
+
+// CL.h contents
+/******************************************************************************/
+
+typedef struct _cl_platform_id * cl_platform_id;
+typedef struct _cl_device_id * cl_device_id;
+typedef struct _cl_context * cl_context;
+typedef struct _cl_command_queue * cl_command_queue;
+typedef struct _cl_mem * cl_mem;
+typedef struct _cl_program * cl_program;
+typedef struct _cl_kernel * cl_kernel;
+typedef struct _cl_event * cl_event;
+typedef struct _cl_sampler * cl_sampler;
+
+typedef cl_uint cl_bool; /* WARNING! Unlike cl_ types in cl_platform.h, cl_bool is not guaranteed to be the same size as the bool in kernels. */
+typedef cl_ulong cl_bitfield;
+typedef cl_bitfield cl_device_type;
+typedef cl_uint cl_platform_info;
+typedef cl_uint cl_device_info;
+typedef cl_bitfield cl_device_fp_config;
+typedef cl_uint cl_device_mem_cache_type;
+typedef cl_uint cl_device_local_mem_type;
+typedef cl_bitfield cl_device_exec_capabilities;
+typedef cl_bitfield cl_command_queue_properties;
+typedef intptr_t cl_device_partition_property;
+typedef cl_bitfield cl_device_affinity_domain;
+
+typedef intptr_t cl_context_properties;
+typedef cl_uint cl_context_info;
+typedef cl_uint cl_command_queue_info;
+typedef cl_uint cl_channel_order;
+typedef cl_uint cl_channel_type;
+typedef cl_bitfield cl_mem_flags;
+typedef cl_uint cl_mem_object_type;
+typedef cl_uint cl_mem_info;
+typedef cl_uint cl_image_info;
+typedef cl_uint cl_buffer_create_type;
+typedef cl_uint cl_addressing_mode;
+typedef cl_uint cl_filter_mode;
+typedef cl_uint cl_sampler_info;
+typedef cl_bitfield cl_map_flags;
+typedef cl_uint cl_program_info;
+typedef cl_uint cl_program_build_info;
+typedef cl_int cl_build_status;
+typedef cl_uint cl_kernel_info;
+typedef cl_uint cl_kernel_work_group_info;
+typedef cl_uint cl_event_info;
+typedef cl_uint cl_command_type;
+typedef cl_uint cl_profiling_info;
+
+typedef struct _cl_image_format {
+ cl_channel_order image_channel_order;
+ cl_channel_type image_channel_data_type;
+} cl_image_format;
+
+typedef struct _cl_image_desc {
+ cl_mem_object_type image_type;
+ size_t image_width;
+ size_t image_height;
+ size_t image_depth;
+ size_t image_array_size;
+ size_t image_row_pitch;
+ size_t image_slice_pitch;
+ cl_uint num_mip_levels;
+ cl_uint num_samples;
+ cl_mem buffer;
+ } cl_image_desc;
+
+typedef struct _cl_buffer_region {
+ size_t origin;
+ size_t size;
+} cl_buffer_region;
+
+/******************************************************************************/
+
+/* Error Codes */
+#define CL_SUCCESS 0
+#define CL_DEVICE_NOT_FOUND -1
+#define CL_DEVICE_NOT_AVAILABLE -2
+#define CL_COMPILER_NOT_AVAILABLE -3
+#define CL_MEM_OBJECT_ALLOCATION_FAILURE -4
+#define CL_OUT_OF_RESOURCES -5
+#define CL_OUT_OF_HOST_MEMORY -6
+#define CL_PROFILING_INFO_NOT_AVAILABLE -7
+#define CL_MEM_COPY_OVERLAP -8
+#define CL_IMAGE_FORMAT_MISMATCH -9
+#define CL_IMAGE_FORMAT_NOT_SUPPORTED -10
+#define CL_BUILD_PROGRAM_FAILURE -11
+#define CL_MAP_FAILURE -12
+#define CL_MISALIGNED_SUB_BUFFER_OFFSET -13
+#define CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST -14
+#define CL_COMPILE_PROGRAM_FAILURE -15
+#define CL_LINKER_NOT_AVAILABLE -16
+#define CL_LINK_PROGRAM_FAILURE -17
+#define CL_DEVICE_PARTITION_FAILED -18
+#define CL_KERNEL_ARG_INFO_NOT_AVAILABLE -19
+
+#define CL_INVALID_VALUE -30
+#define CL_INVALID_DEVICE_TYPE -31
+#define CL_INVALID_PLATFORM -32
+#define CL_INVALID_DEVICE -33
+#define CL_INVALID_CONTEXT -34
+#define CL_INVALID_QUEUE_PROPERTIES -35
+#define CL_INVALID_COMMAND_QUEUE -36
+#define CL_INVALID_HOST_PTR -37
+#define CL_INVALID_MEM_OBJECT -38
+#define CL_INVALID_IMAGE_FORMAT_DESCRIPTOR -39
+#define CL_INVALID_IMAGE_SIZE -40
+#define CL_INVALID_SAMPLER -41
+#define CL_INVALID_BINARY -42
+#define CL_INVALID_BUILD_OPTIONS -43
+#define CL_INVALID_PROGRAM -44
+#define CL_INVALID_PROGRAM_EXECUTABLE -45
+#define CL_INVALID_KERNEL_NAME -46
+#define CL_INVALID_KERNEL_DEFINITION -47
+#define CL_INVALID_KERNEL -48
+#define CL_INVALID_ARG_INDEX -49
+#define CL_INVALID_ARG_VALUE -50
+#define CL_INVALID_ARG_SIZE -51
+#define CL_INVALID_KERNEL_ARGS -52
+#define CL_INVALID_WORK_DIMENSION -53
+#define CL_INVALID_WORK_GROUP_SIZE -54
+#define CL_INVALID_WORK_ITEM_SIZE -55
+#define CL_INVALID_GLOBAL_OFFSET -56
+#define CL_INVALID_EVENT_WAIT_LIST -57
+#define CL_INVALID_EVENT -58
+#define CL_INVALID_OPERATION -59
+#define CL_INVALID_GL_OBJECT -60
+#define CL_INVALID_BUFFER_SIZE -61
+#define CL_INVALID_MIP_LEVEL -62
+#define CL_INVALID_GLOBAL_WORK_SIZE -63
+#define CL_INVALID_PROPERTY -64
+#define CL_INVALID_IMAGE_DESCRIPTOR -65
+#define CL_INVALID_COMPILER_OPTIONS -66
+#define CL_INVALID_LINKER_OPTIONS -67
+#define CL_INVALID_DEVICE_PARTITION_COUNT -68
+
+/* OpenCL Version */
+#define CL_VERSION_1_0 1
+#define CL_VERSION_1_1 1
+#define CL_VERSION_1_2 1
+
+/* cl_bool */
+#define CL_FALSE 0
+#define CL_TRUE 1
+#define CL_BLOCKING CL_TRUE
+#define CL_NON_BLOCKING CL_FALSE
+
+/* cl_platform_info */
+#define CL_PLATFORM_PROFILE 0x0900
+#define CL_PLATFORM_VERSION 0x0901
+#define CL_PLATFORM_NAME 0x0902
+#define CL_PLATFORM_VENDOR 0x0903
+#define CL_PLATFORM_EXTENSIONS 0x0904
+
+/* cl_device_type - bitfield */
+#define CL_DEVICE_TYPE_DEFAULT (1 << 0)
+#define CL_DEVICE_TYPE_CPU (1 << 1)
+#define CL_DEVICE_TYPE_GPU (1 << 2)
+#define CL_DEVICE_TYPE_ACCELERATOR (1 << 3)
+#define CL_DEVICE_TYPE_CUSTOM (1 << 4)
+#define CL_DEVICE_TYPE_ALL 0xFFFFFFFF
+
+/* cl_device_info */
+#define CL_DEVICE_TYPE 0x1000
+#define CL_DEVICE_VENDOR_ID 0x1001
+#define CL_DEVICE_MAX_COMPUTE_UNITS 0x1002
+#define CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS 0x1003
+#define CL_DEVICE_MAX_WORK_GROUP_SIZE 0x1004
+#define CL_DEVICE_MAX_WORK_ITEM_SIZES 0x1005
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR 0x1006
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT 0x1007
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT 0x1008
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG 0x1009
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT 0x100A
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE 0x100B
+#define CL_DEVICE_MAX_CLOCK_FREQUENCY 0x100C
+#define CL_DEVICE_ADDRESS_BITS 0x100D
+#define CL_DEVICE_MAX_READ_IMAGE_ARGS 0x100E
+#define CL_DEVICE_MAX_WRITE_IMAGE_ARGS 0x100F
+#define CL_DEVICE_MAX_MEM_ALLOC_SIZE 0x1010
+#define CL_DEVICE_IMAGE2D_MAX_WIDTH 0x1011
+#define CL_DEVICE_IMAGE2D_MAX_HEIGHT 0x1012
+#define CL_DEVICE_IMAGE3D_MAX_WIDTH 0x1013
+#define CL_DEVICE_IMAGE3D_MAX_HEIGHT 0x1014
+#define CL_DEVICE_IMAGE3D_MAX_DEPTH 0x1015
+#define CL_DEVICE_IMAGE_SUPPORT 0x1016
+#define CL_DEVICE_MAX_PARAMETER_SIZE 0x1017
+#define CL_DEVICE_MAX_SAMPLERS 0x1018
+#define CL_DEVICE_MEM_BASE_ADDR_ALIGN 0x1019
+#define CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE 0x101A
+#define CL_DEVICE_SINGLE_FP_CONFIG 0x101B
+#define CL_DEVICE_GLOBAL_MEM_CACHE_TYPE 0x101C
+#define CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE 0x101D
+#define CL_DEVICE_GLOBAL_MEM_CACHE_SIZE 0x101E
+#define CL_DEVICE_GLOBAL_MEM_SIZE 0x101F
+#define CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE 0x1020
+#define CL_DEVICE_MAX_CONSTANT_ARGS 0x1021
+#define CL_DEVICE_LOCAL_MEM_TYPE 0x1022
+#define CL_DEVICE_LOCAL_MEM_SIZE 0x1023
+#define CL_DEVICE_ERROR_CORRECTION_SUPPORT 0x1024
+#define CL_DEVICE_PROFILING_TIMER_RESOLUTION 0x1025
+#define CL_DEVICE_ENDIAN_LITTLE 0x1026
+#define CL_DEVICE_AVAILABLE 0x1027
+#define CL_DEVICE_COMPILER_AVAILABLE 0x1028
+#define CL_DEVICE_EXECUTION_CAPABILITIES 0x1029
+#define CL_DEVICE_QUEUE_PROPERTIES 0x102A
+#define CL_DEVICE_NAME 0x102B
+#define CL_DEVICE_VENDOR 0x102C
+#define CL_DRIVER_VERSION 0x102D
+#define CL_DEVICE_PROFILE 0x102E
+#define CL_DEVICE_VERSION 0x102F
+#define CL_DEVICE_EXTENSIONS 0x1030
+#define CL_DEVICE_PLATFORM 0x1031
+#define CL_DEVICE_DOUBLE_FP_CONFIG 0x1032
+/* 0x1033 reserved for CL_DEVICE_HALF_FP_CONFIG */
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF 0x1034
+#define CL_DEVICE_HOST_UNIFIED_MEMORY 0x1035
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR 0x1036
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT 0x1037
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_INT 0x1038
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG 0x1039
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT 0x103A
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE 0x103B
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF 0x103C
+#define CL_DEVICE_OPENCL_C_VERSION 0x103D
+#define CL_DEVICE_LINKER_AVAILABLE 0x103E
+#define CL_DEVICE_BUILT_IN_KERNELS 0x103F
+#define CL_DEVICE_IMAGE_MAX_BUFFER_SIZE 0x1040
+#define CL_DEVICE_IMAGE_MAX_ARRAY_SIZE 0x1041
+#define CL_DEVICE_PARENT_DEVICE 0x1042
+#define CL_DEVICE_PARTITION_MAX_SUB_DEVICES 0x1043
+#define CL_DEVICE_PARTITION_PROPERTIES 0x1044
+#define CL_DEVICE_PARTITION_AFFINITY_DOMAIN 0x1045
+#define CL_DEVICE_PARTITION_TYPE 0x1046
+#define CL_DEVICE_REFERENCE_COUNT 0x1047
+#define CL_DEVICE_PREFERRED_INTEROP_USER_SYNC 0x1048
+#define CL_DEVICE_PRINTF_BUFFER_SIZE 0x1049
+#define CL_DEVICE_IMAGE_PITCH_ALIGNMENT 0x104A
+#define CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT 0x104B
+
+/* cl_device_fp_config - bitfield */
+#define CL_FP_DENORM (1 << 0)
+#define CL_FP_INF_NAN (1 << 1)
+#define CL_FP_ROUND_TO_NEAREST (1 << 2)
+#define CL_FP_ROUND_TO_ZERO (1 << 3)
+#define CL_FP_ROUND_TO_INF (1 << 4)
+#define CL_FP_FMA (1 << 5)
+#define CL_FP_SOFT_FLOAT (1 << 6)
+#define CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT (1 << 7)
+
+/* cl_device_mem_cache_type */
+#define CL_NONE 0x0
+#define CL_READ_ONLY_CACHE 0x1
+#define CL_READ_WRITE_CACHE 0x2
+
+/* cl_device_local_mem_type */
+#define CL_LOCAL 0x1
+#define CL_GLOBAL 0x2
+
+/* cl_device_exec_capabilities - bitfield */
+#define CL_EXEC_KERNEL (1 << 0)
+#define CL_EXEC_NATIVE_KERNEL (1 << 1)
+
+/* cl_command_queue_properties - bitfield */
+#define CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE (1 << 0)
+#define CL_QUEUE_PROFILING_ENABLE (1 << 1)
+
+/* cl_context_info */
+#define CL_CONTEXT_REFERENCE_COUNT 0x1080
+#define CL_CONTEXT_DEVICES 0x1081
+#define CL_CONTEXT_PROPERTIES 0x1082
+#define CL_CONTEXT_NUM_DEVICES 0x1083
+
+/* cl_context_info + cl_context_properties */
+#define CL_CONTEXT_PLATFORM 0x1084
+#define CL_CONTEXT_INTEROP_USER_SYNC 0x1085
+
+/* cl_device_partition_property */
+#define CL_DEVICE_PARTITION_EQUALLY 0x1086
+#define CL_DEVICE_PARTITION_BY_COUNTS 0x1087
+#define CL_DEVICE_PARTITION_BY_COUNTS_LIST_END 0x0
+#define CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN 0x1088
+
+/* cl_device_affinity_domain */
+#define CL_DEVICE_AFFINITY_DOMAIN_NUMA (1 << 0)
+#define CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE (1 << 1)
+#define CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE (1 << 2)
+#define CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE (1 << 3)
+#define CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE (1 << 4)
+#define CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE (1 << 5)
+
+/* cl_command_queue_info */
+#define CL_QUEUE_CONTEXT 0x1090
+#define CL_QUEUE_DEVICE 0x1091
+#define CL_QUEUE_REFERENCE_COUNT 0x1092
+#define CL_QUEUE_PROPERTIES 0x1093
+
+/* cl_mem_flags - bitfield */
+#define CL_MEM_READ_WRITE (1 << 0)
+#define CL_MEM_WRITE_ONLY (1 << 1)
+#define CL_MEM_READ_ONLY (1 << 2)
+#define CL_MEM_USE_HOST_PTR (1 << 3)
+#define CL_MEM_ALLOC_HOST_PTR (1 << 4)
+#define CL_MEM_COPY_HOST_PTR (1 << 5)
+// reserved (1 << 6)
+#define CL_MEM_HOST_WRITE_ONLY (1 << 7)
+#define CL_MEM_HOST_READ_ONLY (1 << 8)
+#define CL_MEM_HOST_NO_ACCESS (1 << 9)
+
+/* cl_mem_migration_flags - bitfield */
+#define CL_MIGRATE_MEM_OBJECT_HOST (1 << 0)
+#define CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED (1 << 1)
+
+/* cl_channel_order */
+#define CL_R 0x10B0
+#define CL_A 0x10B1
+#define CL_RG 0x10B2
+#define CL_RA 0x10B3
+#define CL_RGB 0x10B4
+#define CL_RGBA 0x10B5
+#define CL_BGRA 0x10B6
+#define CL_ARGB 0x10B7
+#define CL_INTENSITY 0x10B8
+#define CL_LUMINANCE 0x10B9
+#define CL_Rx 0x10BA
+#define CL_RGx 0x10BB
+#define CL_RGBx 0x10BC
+#define CL_DEPTH 0x10BD
+#define CL_DEPTH_STENCIL 0x10BE
+
+/* cl_channel_type */
+#define CL_SNORM_INT8 0x10D0
+#define CL_SNORM_INT16 0x10D1
+#define CL_UNORM_INT8 0x10D2
+#define CL_UNORM_INT16 0x10D3
+#define CL_UNORM_SHORT_565 0x10D4
+#define CL_UNORM_SHORT_555 0x10D5
+#define CL_UNORM_INT_101010 0x10D6
+#define CL_SIGNED_INT8 0x10D7
+#define CL_SIGNED_INT16 0x10D8
+#define CL_SIGNED_INT32 0x10D9
+#define CL_UNSIGNED_INT8 0x10DA
+#define CL_UNSIGNED_INT16 0x10DB
+#define CL_UNSIGNED_INT32 0x10DC
+#define CL_HALF_FLOAT 0x10DD
+#define CL_FLOAT 0x10DE
+#define CL_UNORM_INT24 0x10DF
+
+/* cl_mem_object_type */
+#define CL_MEM_OBJECT_BUFFER 0x10F0
+#define CL_MEM_OBJECT_IMAGE2D 0x10F1
+#define CL_MEM_OBJECT_IMAGE3D 0x10F2
+#define CL_MEM_OBJECT_IMAGE2D_ARRAY 0x10F3
+#define CL_MEM_OBJECT_IMAGE1D 0x10F4
+#define CL_MEM_OBJECT_IMAGE1D_ARRAY 0x10F5
+#define CL_MEM_OBJECT_IMAGE1D_BUFFER 0x10F6
+
+/* cl_mem_info */
+#define CL_MEM_TYPE 0x1100
+#define CL_MEM_FLAGS 0x1101
+#define CL_MEM_SIZE 0x1102
+#define CL_MEM_HOST_PTR 0x1103
+#define CL_MEM_MAP_COUNT 0x1104
+#define CL_MEM_REFERENCE_COUNT 0x1105
+#define CL_MEM_CONTEXT 0x1106
+#define CL_MEM_ASSOCIATED_MEMOBJECT 0x1107
+#define CL_MEM_OFFSET 0x1108
+
+/* cl_image_info */
+#define CL_IMAGE_FORMAT 0x1110
+#define CL_IMAGE_ELEMENT_SIZE 0x1111
+#define CL_IMAGE_ROW_PITCH 0x1112
+#define CL_IMAGE_SLICE_PITCH 0x1113
+#define CL_IMAGE_WIDTH 0x1114
+#define CL_IMAGE_HEIGHT 0x1115
+#define CL_IMAGE_DEPTH 0x1116
+#define CL_IMAGE_ARRAY_SIZE 0x1117
+#define CL_IMAGE_BUFFER 0x1118
+#define CL_IMAGE_NUM_MIP_LEVELS 0x1119
+#define CL_IMAGE_NUM_SAMPLES 0x111A
+
+/* cl_addressing_mode */
+#define CL_ADDRESS_NONE 0x1130
+#define CL_ADDRESS_CLAMP_TO_EDGE 0x1131
+#define CL_ADDRESS_CLAMP 0x1132
+#define CL_ADDRESS_REPEAT 0x1133
+#define CL_ADDRESS_MIRRORED_REPEAT 0x1134
+
+/* cl_filter_mode */
+#define CL_FILTER_NEAREST 0x1140
+#define CL_FILTER_LINEAR 0x1141
+
+/* cl_sampler_info */
+#define CL_SAMPLER_REFERENCE_COUNT 0x1150
+#define CL_SAMPLER_CONTEXT 0x1151
+#define CL_SAMPLER_NORMALIZED_COORDS 0x1152
+#define CL_SAMPLER_ADDRESSING_MODE 0x1153
+#define CL_SAMPLER_FILTER_MODE 0x1154
+
+/* cl_map_flags - bitfield */
+#define CL_MAP_READ (1 << 0)
+#define CL_MAP_WRITE (1 << 1)
+#define CL_MAP_WRITE_INVALIDATE_REGION (1 << 2)
+
+/* cl_program_info */
+#define CL_PROGRAM_REFERENCE_COUNT 0x1160
+#define CL_PROGRAM_CONTEXT 0x1161
+#define CL_PROGRAM_NUM_DEVICES 0x1162
+#define CL_PROGRAM_DEVICES 0x1163
+#define CL_PROGRAM_SOURCE 0x1164
+#define CL_PROGRAM_BINARY_SIZES 0x1165
+#define CL_PROGRAM_BINARIES 0x1166
+#define CL_PROGRAM_NUM_KERNELS 0x1167
+#define CL_PROGRAM_KERNEL_NAMES 0x1168
+
+/* cl_program_build_info */
+#define CL_PROGRAM_BUILD_STATUS 0x1181
+#define CL_PROGRAM_BUILD_OPTIONS 0x1182
+#define CL_PROGRAM_BUILD_LOG 0x1183
+#define CL_PROGRAM_BINARY_TYPE 0x1184
+
+/* cl_build_status */
+#define CL_BUILD_SUCCESS 0
+#define CL_BUILD_NONE -1
+#define CL_BUILD_ERROR -2
+#define CL_BUILD_IN_PROGRESS -3
+
+/* cl_kernel_info */
+#define CL_KERNEL_FUNCTION_NAME 0x1190
+#define CL_KERNEL_NUM_ARGS 0x1191
+#define CL_KERNEL_REFERENCE_COUNT 0x1192
+#define CL_KERNEL_CONTEXT 0x1193
+#define CL_KERNEL_PROGRAM 0x1194
+#define CL_KERNEL_ATTRIBUTES 0x1195
+
+/* cl_kernel_arg_info */
+#define CL_KERNEL_ARG_ADDRESS_QUALIFIER 0x1196
+#define CL_KERNEL_ARG_ACCESS_QUALIFIER 0x1197
+#define CL_KERNEL_ARG_TYPE_NAME 0x1198
+#define CL_KERNEL_ARG_TYPE_QUALIFIER 0x1199
+#define CL_KERNEL_ARG_NAME 0x119A
+
+/* cl_kernel_arg_address_qualifier */
+#define CL_KERNEL_ARG_ADDRESS_GLOBAL 0x119B
+#define CL_KERNEL_ARG_ADDRESS_LOCAL 0x119C
+#define CL_KERNEL_ARG_ADDRESS_CONSTANT 0x119D
+#define CL_KERNEL_ARG_ADDRESS_PRIVATE 0x119E
+
+/* cl_kernel_arg_access_qualifier */
+#define CL_KERNEL_ARG_ACCESS_READ_ONLY 0x11A0
+#define CL_KERNEL_ARG_ACCESS_WRITE_ONLY 0x11A1
+#define CL_KERNEL_ARG_ACCESS_READ_WRITE 0x11A2
+#define CL_KERNEL_ARG_ACCESS_NONE 0x11A3
+
+/* cl_kernel_arg_type_qualifer */
+#define CL_KERNEL_ARG_TYPE_NONE 0
+#define CL_KERNEL_ARG_TYPE_CONST (1 << 0)
+#define CL_KERNEL_ARG_TYPE_RESTRICT (1 << 1)
+#define CL_KERNEL_ARG_TYPE_VOLATILE (1 << 2)
+
+/* cl_kernel_work_group_info */
+#define CL_KERNEL_WORK_GROUP_SIZE 0x11B0
+#define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1
+#define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2
+#define CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE 0x11B3
+#define CL_KERNEL_PRIVATE_MEM_SIZE 0x11B4
+#define CL_KERNEL_GLOBAL_WORK_SIZE 0x11B5
+
+/* cl_event_info */
+#define CL_EVENT_COMMAND_QUEUE 0x11D0
+#define CL_EVENT_COMMAND_TYPE 0x11D1
+#define CL_EVENT_REFERENCE_COUNT 0x11D2
+#define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3
+#define CL_EVENT_CONTEXT 0x11D4
+
+/* cl_command_type */
+#define CL_COMMAND_NDRANGE_KERNEL 0x11F0
+#define CL_COMMAND_TASK 0x11F1
+#define CL_COMMAND_NATIVE_KERNEL 0x11F2
+#define CL_COMMAND_READ_BUFFER 0x11F3
+#define CL_COMMAND_WRITE_BUFFER 0x11F4
+#define CL_COMMAND_COPY_BUFFER 0x11F5
+#define CL_COMMAND_READ_IMAGE 0x11F6
+#define CL_COMMAND_WRITE_IMAGE 0x11F7
+#define CL_COMMAND_COPY_IMAGE 0x11F8
+#define CL_COMMAND_COPY_IMAGE_TO_BUFFER 0x11F9
+#define CL_COMMAND_COPY_BUFFER_TO_IMAGE 0x11FA
+#define CL_COMMAND_MAP_BUFFER 0x11FB
+#define CL_COMMAND_MAP_IMAGE 0x11FC
+#define CL_COMMAND_UNMAP_MEM_OBJECT 0x11FD
+#define CL_COMMAND_MARKER 0x11FE
+#define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x11FF
+#define CL_COMMAND_RELEASE_GL_OBJECTS 0x1200
+#define CL_COMMAND_READ_BUFFER_RECT 0x1201
+#define CL_COMMAND_WRITE_BUFFER_RECT 0x1202
+#define CL_COMMAND_COPY_BUFFER_RECT 0x1203
+#define CL_COMMAND_USER 0x1204
+#define CL_COMMAND_BARRIER 0x1205
+#define CL_COMMAND_MIGRATE_MEM_OBJECTS 0x1206
+#define CL_COMMAND_FILL_BUFFER 0x1207
+#define CL_COMMAND_FILL_IMAGE 0x1208
+
+/* command execution status */
+#define CL_COMPLETE 0x0
+#define CL_RUNNING 0x1
+#define CL_SUBMITTED 0x2
+#define CL_QUEUED 0x3
+
+/* cl_buffer_create_type */
+#define CL_BUFFER_CREATE_TYPE_REGION 0x1220
+
+/* cl_profiling_info */
+#define CL_PROFILING_COMMAND_QUEUED 0x1280
+#define CL_PROFILING_COMMAND_SUBMIT 0x1281
+#define CL_PROFILING_COMMAND_START 0x1282
+#define CL_PROFILING_COMMAND_END 0x1283
+
+/********************************************************************************************************/
+
+/********************************************************************************************************/
+
+/* Function signature typedef's */
+
+/* Platform API */
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETPLATFORMIDS)(cl_uint /* num_entries */,
+ cl_platform_id * /* platforms */,
+ cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETPLATFORMINFO)(cl_platform_id /* platform */,
+ cl_platform_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Device APIs */
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETDEVICEIDS)(cl_platform_id /* platform */,
+ cl_device_type /* device_type */,
+ cl_uint /* num_entries */,
+ cl_device_id * /* devices */,
+ cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETDEVICEINFO)(cl_device_id /* device */,
+ cl_device_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLCREATESUBDEVICES)(cl_device_id /* in_device */,
+ const cl_device_partition_property * /* properties */,
+ cl_uint /* num_devices */,
+ cl_device_id * /* out_devices */,
+ cl_uint * /* num_devices_ret */) CL_API_SUFFIX__VERSION_1_2;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINDEVICE)(cl_device_id /* device */) CL_API_SUFFIX__VERSION_1_2;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASEDEVICE)(cl_device_id /* device */) CL_API_SUFFIX__VERSION_1_2;
+
+// Context APIs
+typedef CL_API_ENTRY cl_context (CL_API_CALL *
+PFNCLCREATECONTEXT)(const cl_context_properties * /* properties */,
+ cl_uint /* num_devices */,
+ const cl_device_id * /* devices */,
+ void (CL_CALLBACK * /* pfn_notify */)(const char *, const void *, size_t, void *),
+ void * /* user_data */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_context (CL_API_CALL *
+PFNCLCREATECONTEXTFROMTYPE)(const cl_context_properties * /* properties */,
+ cl_device_type /* device_type */,
+ void (CL_CALLBACK * /* pfn_notify*/ )(const char *, const void *, size_t, void *),
+ void * /* user_data */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINCONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASECONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETCONTEXTINFO)(cl_context /* context */,
+ cl_context_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Command Queue APIs */
+typedef CL_API_ENTRY cl_command_queue (CL_API_CALL *
+PFNCLCREATECOMMANDQUEUE)(cl_context /* context */,
+ cl_device_id /* device */,
+ cl_command_queue_properties /* properties */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINCOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASECOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETCOMMANDQUEUEINFO)(cl_command_queue /* command_queue */,
+ cl_command_queue_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLSETCOMMANDQUEUEPROPERTY)(cl_command_queue /* command_queue */,
+ cl_command_queue_properties /* properties */,
+ cl_bool /* enable */,
+ cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Memory Object APIs */
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *
+PFNCLCREATEBUFFER)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ size_t /* size */,
+ void * /* host_ptr */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *
+PFNCLCREATESUBBUFFER)(cl_mem /* buffer */,
+ cl_mem_flags /* flags */,
+ cl_buffer_create_type /* buffer_create_type */,
+ const void * /* buffer_create_info */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
+
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *
+PFNCLCREATEIMAGE)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ const cl_image_format * /* image_format */,
+ const cl_image_desc * /* image_desc */,
+ void * /* host_ptr */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASEMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETSUPPORTEDIMAGEFORMATS)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ cl_mem_object_type /* image_type */,
+ cl_uint /* num_entries */,
+ cl_image_format * /* image_formats */,
+ cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETMEMOBJECTINFO)(cl_mem /* memobj */,
+ cl_mem_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETIMAGEINFO)(cl_mem /* image */,
+ cl_image_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLSETMEMOBJECTDESTRUCTORCALLBACK)( cl_mem /* memobj */,
+ void (CL_CALLBACK * /*pfn_notify*/)( cl_mem /* memobj */, void* /*user_data*/),
+ void * /*user_data */ ) CL_API_SUFFIX__VERSION_1_1;
+
+/* Sampler APIs */
+typedef CL_API_ENTRY cl_sampler (CL_API_CALL *
+PFNCLCREATESAMPLER)(cl_context /* context */,
+ cl_bool /* normalized_coords */,
+ cl_addressing_mode /* addressing_mode */,
+ cl_filter_mode /* filter_mode */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINSAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASESAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETSAMPLERINFO)(cl_sampler /* sampler */,
+ cl_sampler_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Program Object APIs */
+typedef CL_API_ENTRY cl_program (CL_API_CALL *
+PFNCLCREATEPROGRAMWITHSOURCE)(cl_context /* context */,
+ cl_uint /* count */,
+ const char ** /* strings */,
+ const size_t * /* lengths */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_program (CL_API_CALL *
+PFNCLCREATEPROGRAMWITHBINARY)(cl_context /* context */,
+ cl_uint /* num_devices */,
+ const cl_device_id * /* device_list */,
+ const size_t * /* lengths */,
+ const unsigned char ** /* binaries */,
+ cl_int * /* binary_status */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_program (CL_API_CALL *
+PFNCLCREATEPROGRAMWITHBUILTINKERNELS)(cl_context /* context */,
+ cl_uint /* num_devices */,
+ const cl_device_id * /* device_list */,
+ const char * /* kernel_names */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASEPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLBUILDPROGRAM)(cl_program /* program */,
+ cl_uint /* num_devices */,
+ const cl_device_id * /* device_list */,
+ const char * /* options */,
+ void (CL_CALLBACK * /* pfn_notify */)(cl_program /* program */, void * /* user_data */),
+ void * /* user_data */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETPROGRAMINFO)(cl_program /* program */,
+ cl_program_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETPROGRAMBUILDINFO)(cl_program /* program */,
+ cl_device_id /* device */,
+ cl_program_build_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Kernel Object APIs */
+typedef CL_API_ENTRY cl_kernel (CL_API_CALL *
+PFNCLCREATEKERNEL)(cl_program /* program */,
+ const char * /* kernel_name */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLCREATEKERNELSINPROGRAM)(cl_program /* program */,
+ cl_uint /* num_kernels */,
+ cl_kernel * /* kernels */,
+ cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASEKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLSETKERNELARG)(cl_kernel /* kernel */,
+ cl_uint /* arg_index */,
+ size_t /* arg_size */,
+ const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETKERNELINFO)(cl_kernel /* kernel */,
+ cl_kernel_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETKERNELWORKGROUPINFO)(cl_kernel /* kernel */,
+ cl_device_id /* device */,
+ cl_kernel_work_group_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+// Event Object APIs
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLWAITFOREVENTS)(cl_uint /* num_events */,
+ const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETEVENTINFO)(cl_event /* event */,
+ cl_event_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_event (CL_API_CALL *
+PFNCLCREATEUSEREVENT)(cl_context /* context */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASEEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLSETUSEREVENTSTATUS)(cl_event /* event */,
+ cl_int /* execution_status */) CL_API_SUFFIX__VERSION_1_1;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLSETEVENTCALLBACK)( cl_event /* event */,
+ cl_int /* command_exec_callback_type */,
+ void (CL_CALLBACK * /* pfn_notify */)(cl_event, cl_int, void *),
+ void * /* user_data */) CL_API_SUFFIX__VERSION_1_1;
+
+/* Profiling APIs */
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETEVENTPROFILINGINFO)(cl_event /* event */,
+ cl_profiling_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+// Flush and Finish APIs
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLFLUSH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLFINISH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Enqueued Commands APIs */
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEREADBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_read */,
+ size_t /* offset */,
+ size_t /* cb */,
+ void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEREADBUFFERRECT)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_read */,
+ const size_t * /* buffer_origin */,
+ const size_t * /* host_origin */,
+ const size_t * /* region */,
+ size_t /* buffer_row_pitch */,
+ size_t /* buffer_slice_pitch */,
+ size_t /* host_row_pitch */,
+ size_t /* host_slice_pitch */,
+ void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEWRITEBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_write */,
+ size_t /* offset */,
+ size_t /* cb */,
+ const void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEWRITEBUFFERRECT)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_write */,
+ const size_t * /* buffer_origin */,
+ const size_t * /* host_origin */,
+ const size_t * /* region */,
+ size_t /* buffer_row_pitch */,
+ size_t /* buffer_slice_pitch */,
+ size_t /* host_row_pitch */,
+ size_t /* host_slice_pitch */,
+ const void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUECOPYBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* src_buffer */,
+ cl_mem /* dst_buffer */,
+ size_t /* src_offset */,
+ size_t /* dst_offset */,
+ size_t /* cb */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUECOPYBUFFERRECT)(cl_command_queue /* command_queue */,
+ cl_mem /* src_buffer */,
+ cl_mem /* dst_buffer */,
+ const size_t * /* src_origin */,
+ const size_t * /* dst_origin */,
+ const size_t * /* region */,
+ size_t /* src_row_pitch */,
+ size_t /* src_slice_pitch */,
+ size_t /* dst_row_pitch */,
+ size_t /* dst_slice_pitch */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEREADIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* image */,
+ cl_bool /* blocking_read */,
+ const size_t * /* origin[3] */,
+ const size_t * /* region[3] */,
+ size_t /* row_pitch */,
+ size_t /* slice_pitch */,
+ void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEWRITEIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* image */,
+ cl_bool /* blocking_write */,
+ const size_t * /* origin[3] */,
+ const size_t * /* region[3] */,
+ size_t /* input_row_pitch */,
+ size_t /* input_slice_pitch */,
+ const void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUECOPYIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* src_image */,
+ cl_mem /* dst_image */,
+ const size_t * /* src_origin[3] */,
+ const size_t * /* dst_origin[3] */,
+ const size_t * /* region[3] */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUECOPYIMAGETOBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* src_image */,
+ cl_mem /* dst_buffer */,
+ const size_t * /* src_origin[3] */,
+ const size_t * /* region[3] */,
+ size_t /* dst_offset */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUECOPYBUFFERTOIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* src_buffer */,
+ cl_mem /* dst_image */,
+ size_t /* src_offset */,
+ const size_t * /* dst_origin[3] */,
+ const size_t * /* region[3] */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY void * (CL_API_CALL *
+PFNCLENQUEUEMAPBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_map */,
+ cl_map_flags /* map_flags */,
+ size_t /* offset */,
+ size_t /* cb */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY void * (CL_API_CALL *
+PFNCLENQUEUEMAPIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* image */,
+ cl_bool /* blocking_map */,
+ cl_map_flags /* map_flags */,
+ const size_t * /* origin[3] */,
+ const size_t * /* region[3] */,
+ size_t * /* image_row_pitch */,
+ size_t * /* image_slice_pitch */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEUNMAPMEMOBJECT)(cl_command_queue /* command_queue */,
+ cl_mem /* memobj */,
+ void * /* mapped_ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUENDRANGEKERNEL)(cl_command_queue /* command_queue */,
+ cl_kernel /* kernel */,
+ cl_uint /* work_dim */,
+ const size_t * /* global_work_offset */,
+ const size_t * /* global_work_size */,
+ const size_t * /* local_work_size */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUETASK)(cl_command_queue /* command_queue */,
+ cl_kernel /* kernel */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUENATIVEKERNEL)(cl_command_queue /* command_queue */,
+ void (*user_func)(void *),
+ void * /* args */,
+ size_t /* cb_args */,
+ cl_uint /* num_mem_objects */,
+ const cl_mem * /* mem_list */,
+ const void ** /* args_mem_loc */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Extension function access
+*
+* Returns the extension function address for the given function name,
+* or NULL if a valid function can not be found. The client must
+* check to make sure the address is not NULL, before using or
+* calling the returned function address.
+*/
+typedef CL_API_ENTRY void * (CL_API_CALL *
+PFNCLGETEXTENSIONFUNCTIONADDRESSFORPLATFORM)(cl_platform_id /* platform */,
+ const char * /* func_name */) CL_API_SUFFIX__VERSION_1_2;
+#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS
+// Deprecated OpenCL 1.1 APIs
+typedef CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem (CL_API_CALL *
+PFNCLCREATEIMAGE2D)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ const cl_image_format * /* image_format */,
+ size_t /* image_width */,
+ size_t /* image_height */,
+ size_t /* image_row_pitch */,
+ void * /* host_ptr */,
+ cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
+
+typedef CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem (CL_API_CALL *
+PFNCLCREATEIMAGE3D)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ const cl_image_format * /* image_format */,
+ size_t /* image_width */,
+ size_t /* image_height */,
+ size_t /* image_depth */,
+ size_t /* image_row_pitch */,
+ size_t /* image_slice_pitch */,
+ void * /* host_ptr */,
+ cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
+
+typedef CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int (CL_API_CALL *
+PFNCLENQUEUEMARKER)(cl_command_queue /* command_queue */,
+ cl_event * /* event */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
+
+typedef CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int (CL_API_CALL *
+PFNCLENQUEUEWAITFOREVENTS)(cl_command_queue /* command_queue */,
+ cl_uint /* num_events */,
+ const cl_event * /* event_list */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
+
+typedef CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int (CL_API_CALL *
+PFNCLENQUEUEBARRIER)(cl_command_queue /* command_queue */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
+
+typedef CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int (CL_API_CALL *
+PFNCLUNLOADCOMPILER)(void) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
+
+typedef CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED void * (CL_API_CALL *
+PFNCLGETEXTENSIONFUNCTIONADDRESS)(const char * /* func_name */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
+#endif
+
+
+/* cl_gl */
+
+typedef cl_uint cl_gl_object_type;
+typedef cl_uint cl_gl_texture_info;
+typedef cl_uint cl_gl_platform_info;
+typedef struct __GLsync *cl_GLsync;
+
+/* cl_gl_object_type = 0x2000 - 0x200F enum values are currently taken */
+#define CL_GL_OBJECT_BUFFER 0x2000
+#define CL_GL_OBJECT_TEXTURE2D 0x2001
+#define CL_GL_OBJECT_TEXTURE3D 0x2002
+#define CL_GL_OBJECT_RENDERBUFFER 0x2003
+#define CL_GL_OBJECT_TEXTURE2D_ARRAY 0x200E
+#define CL_GL_OBJECT_TEXTURE1D 0x200F
+#define CL_GL_OBJECT_TEXTURE1D_ARRAY 0x2010
+#define CL_GL_OBJECT_TEXTURE_BUFFER 0x2011
+
+/* cl_gl_texture_info */
+#define CL_GL_TEXTURE_TARGET 0x2004
+#define CL_GL_MIPMAP_LEVEL 0x2005
+#define CL_GL_NUM_SAMPLES 0x2012
+
+
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *
+PFNCLCREATEFROMGLBUFFER)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ cl_GLuint /* bufobj */,
+ int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *
+PFNCLCREATEFROMGLTEXTURE)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ cl_GLenum /* target */,
+ cl_GLint /* miplevel */,
+ cl_GLuint /* texture */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2;
+
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *
+PFNCLCREATEFROMGLRENDERBUFFER)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ cl_GLuint /* renderbuffer */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETGLOBJECTINFO)(cl_mem /* memobj */,
+ cl_gl_object_type * /* gl_object_type */,
+ cl_GLuint * /* gl_object_name */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETGLTEXTUREINFO)(cl_mem /* memobj */,
+ cl_gl_texture_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEACQUIREGLOBJECTS)(cl_command_queue /* command_queue */,
+ cl_uint /* num_objects */,
+ const cl_mem * /* mem_objects */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUERELEASEGLOBJECTS)(cl_command_queue /* command_queue */,
+ cl_uint /* num_objects */,
+ const cl_mem * /* mem_objects */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+
+// Deprecated OpenCL 1.1 APIs
+#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS
+typedef CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem (CL_API_CALL *
+PFNCLCREATEFROMGLTEXTURE2D)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ cl_GLenum /* target */,
+ cl_GLint /* miplevel */,
+ cl_GLuint /* texture */,
+ cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
+
+typedef CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem (CL_API_CALL *
+PFNCLCREATEFROMGLTEXTURE3D)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ cl_GLenum /* target */,
+ cl_GLint /* miplevel */,
+ cl_GLuint /* texture */,
+ cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
+#endif
+
+/* cl_khr_gl_sharing extension */
+
+#define cl_khr_gl_sharing 1
+
+typedef cl_uint cl_gl_context_info;
+
+/* Additional Error Codes */
+#define CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR -1000
+
+/* cl_gl_context_info */
+#define CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR 0x2006
+#define CL_DEVICES_FOR_GL_CONTEXT_KHR 0x2007
+
+/* Additional cl_context_properties */
+#define CL_GL_CONTEXT_KHR 0x2008
+#define CL_EGL_DISPLAY_KHR 0x2009
+#define CL_GLX_DISPLAY_KHR 0x200A
+#define CL_WGL_HDC_KHR 0x200B
+#define CL_CGL_SHAREGROUP_KHR 0x200C
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETGLCONTEXTINFOKHR)(const cl_context_properties * /* properties */,
+ cl_gl_context_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetGLContextInfoKHR_fn)(
+ const cl_context_properties * properties,
+ cl_gl_context_info param_name,
+ size_t param_value_size,
+ void * param_value,
+ size_t * param_value_size_ret);
+
+#define CLEW_STATIC
+
+#ifdef CLEW_STATIC
+# define CLEWAPI extern
+#else
+# ifdef CLEW_BUILD
+# define CLEWAPI extern __declspec(dllexport)
+# else
+# define CLEWAPI extern __declspec(dllimport)
+# endif
+#endif
+
+#if defined(_WIN32)
+#define CLEW_FUN_EXPORT extern
+#else
+#define CLEW_FUN_EXPORT CLEWAPI
+#endif
+
+#define CLEW_GET_FUN(x) x
+
+
+// Variables holding function entry points
+CLEW_FUN_EXPORT PFNCLGETPLATFORMIDS __clewGetPlatformIDs ;
+CLEW_FUN_EXPORT PFNCLGETPLATFORMINFO __clewGetPlatformInfo ;
+CLEW_FUN_EXPORT PFNCLGETDEVICEIDS __clewGetDeviceIDs ;
+CLEW_FUN_EXPORT PFNCLGETDEVICEINFO __clewGetDeviceInfo ;
+CLEW_FUN_EXPORT PFNCLCREATESUBDEVICES __clewCreateSubDevices ;
+CLEW_FUN_EXPORT PFNCLRETAINDEVICE __clewRetainDevice ;
+CLEW_FUN_EXPORT PFNCLRELEASEDEVICE __clewReleaseDevice ;
+CLEW_FUN_EXPORT PFNCLCREATECONTEXT __clewCreateContext ;
+CLEW_FUN_EXPORT PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType ;
+CLEW_FUN_EXPORT PFNCLRETAINCONTEXT __clewRetainContext ;
+CLEW_FUN_EXPORT PFNCLRELEASECONTEXT __clewReleaseContext ;
+CLEW_FUN_EXPORT PFNCLGETCONTEXTINFO __clewGetContextInfo ;
+CLEW_FUN_EXPORT PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue ;
+CLEW_FUN_EXPORT PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue ;
+CLEW_FUN_EXPORT PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue ;
+CLEW_FUN_EXPORT PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo ;
+CLEW_FUN_EXPORT PFNCLCREATEBUFFER __clewCreateBuffer ;
+CLEW_FUN_EXPORT PFNCLCREATESUBBUFFER __clewCreateSubBuffer ;
+CLEW_FUN_EXPORT PFNCLCREATEIMAGE __clewCreateImage ;
+CLEW_FUN_EXPORT PFNCLRETAINMEMOBJECT __clewRetainMemObject ;
+CLEW_FUN_EXPORT PFNCLRELEASEMEMOBJECT __clewReleaseMemObject ;
+CLEW_FUN_EXPORT PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats ;
+CLEW_FUN_EXPORT PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo ;
+CLEW_FUN_EXPORT PFNCLGETIMAGEINFO __clewGetImageInfo ;
+CLEW_FUN_EXPORT PFNCLSETMEMOBJECTDESTRUCTORCALLBACK __clewSetMemObjectDestructorCallback;
+CLEW_FUN_EXPORT PFNCLCREATESAMPLER __clewCreateSampler ;
+CLEW_FUN_EXPORT PFNCLRETAINSAMPLER __clewRetainSampler ;
+CLEW_FUN_EXPORT PFNCLRELEASESAMPLER __clewReleaseSampler ;
+CLEW_FUN_EXPORT PFNCLGETSAMPLERINFO __clewGetSamplerInfo ;
+CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource ;
+CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary ;
+CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHBUILTINKERNELS __clewCreateProgramWithBuiltInKernels;
+CLEW_FUN_EXPORT PFNCLRETAINPROGRAM __clewRetainProgram ;
+CLEW_FUN_EXPORT PFNCLRELEASEPROGRAM __clewReleaseProgram ;
+CLEW_FUN_EXPORT PFNCLBUILDPROGRAM __clewBuildProgram ;
+CLEW_FUN_EXPORT PFNCLGETPROGRAMINFO __clewGetProgramInfo ;
+CLEW_FUN_EXPORT PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo ;
+CLEW_FUN_EXPORT PFNCLCREATEKERNEL __clewCreateKernel ;
+CLEW_FUN_EXPORT PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram ;
+CLEW_FUN_EXPORT PFNCLRETAINKERNEL __clewRetainKernel ;
+CLEW_FUN_EXPORT PFNCLRELEASEKERNEL __clewReleaseKernel ;
+CLEW_FUN_EXPORT PFNCLSETKERNELARG __clewSetKernelArg ;
+CLEW_FUN_EXPORT PFNCLGETKERNELINFO __clewGetKernelInfo ;
+CLEW_FUN_EXPORT PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo ;
+CLEW_FUN_EXPORT PFNCLWAITFOREVENTS __clewWaitForEvents ;
+CLEW_FUN_EXPORT PFNCLGETEVENTINFO __clewGetEventInfo ;
+CLEW_FUN_EXPORT PFNCLCREATEUSEREVENT __clewCreateUserEvent ;
+CLEW_FUN_EXPORT PFNCLRETAINEVENT __clewRetainEvent ;
+CLEW_FUN_EXPORT PFNCLRELEASEEVENT __clewReleaseEvent ;
+CLEW_FUN_EXPORT PFNCLSETUSEREVENTSTATUS __clewSetUserEventStatus ;
+CLEW_FUN_EXPORT PFNCLSETEVENTCALLBACK __clewSetEventCallback ;
+CLEW_FUN_EXPORT PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo ;
+CLEW_FUN_EXPORT PFNCLFLUSH __clewFlush ;
+CLEW_FUN_EXPORT PFNCLFINISH __clewFinish ;
+CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer ;
+CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFERRECT __clewEnqueueReadBufferRect ;
+CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer ;
+CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFERRECT __clewEnqueueWriteBufferRect ;
+CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer ;
+CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERRECT __clewEnqueueCopyBufferRect ;
+CLEW_FUN_EXPORT PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage ;
+CLEW_FUN_EXPORT PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage ;
+CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage ;
+CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer ;
+CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage ;
+CLEW_FUN_EXPORT PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer ;
+CLEW_FUN_EXPORT PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage ;
+CLEW_FUN_EXPORT PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject ;
+CLEW_FUN_EXPORT PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel ;
+CLEW_FUN_EXPORT PFNCLENQUEUETASK __clewEnqueueTask ;
+CLEW_FUN_EXPORT PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel ;
+CLEW_FUN_EXPORT PFNCLGETEXTENSIONFUNCTIONADDRESSFORPLATFORM __clewGetExtensionFunctionAddressForPlatform;
+
+#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+CLEW_FUN_EXPORT PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty ;
+#endif
+
+#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS
+CLEW_FUN_EXPORT PFNCLCREATEIMAGE2D __clewCreateImage2D ;
+CLEW_FUN_EXPORT PFNCLCREATEIMAGE3D __clewCreateImage3D ;
+CLEW_FUN_EXPORT PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress ;
+CLEW_FUN_EXPORT PFNCLUNLOADCOMPILER __clewUnloadCompiler ;
+CLEW_FUN_EXPORT PFNCLENQUEUEMARKER __clewEnqueueMarker ;
+CLEW_FUN_EXPORT PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents ;
+CLEW_FUN_EXPORT PFNCLENQUEUEBARRIER __clewEnqueueBarrier ;
+#endif
+
+/* cl_gl */
+CLEW_FUN_EXPORT PFNCLCREATEFROMGLBUFFER __clewCreateFromGLBuffer ;
+CLEW_FUN_EXPORT PFNCLCREATEFROMGLTEXTURE __clewCreateFromGLTexture ;
+CLEW_FUN_EXPORT PFNCLCREATEFROMGLRENDERBUFFER __clewCreateFromGLRenderbuffer ;
+CLEW_FUN_EXPORT PFNCLGETGLOBJECTINFO __clewGetGLObjectInfo ;
+CLEW_FUN_EXPORT PFNCLGETGLTEXTUREINFO __clewGetGLTextureInfo ;
+CLEW_FUN_EXPORT PFNCLENQUEUEACQUIREGLOBJECTS __clewEnqueueAcquireGLObjects ;
+CLEW_FUN_EXPORT PFNCLENQUEUERELEASEGLOBJECTS __clewEnqueueReleaseGLObjects ;
+#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS
+CLEW_FUN_EXPORT PFNCLCREATEFROMGLTEXTURE2D __clewCreateFromGLTexture2D ;
+CLEW_FUN_EXPORT PFNCLCREATEFROMGLTEXTURE3D __clewCreateFromGLTexture3D ;
+#endif
+CLEW_FUN_EXPORT PFNCLGETGLCONTEXTINFOKHR __clewGetGLContextInfoKHR ;
+
+#define clGetPlatformIDs CLEW_GET_FUN(__clewGetPlatformIDs )
+#define clGetPlatformInfo CLEW_GET_FUN(__clewGetPlatformInfo )
+#define clGetDeviceIDs CLEW_GET_FUN(__clewGetDeviceIDs )
+#define clGetDeviceInfo CLEW_GET_FUN(__clewGetDeviceInfo )
+#define clCreateContext CLEW_GET_FUN(__clewCreateContext )
+#define clCreateContextFromType CLEW_GET_FUN(__clewCreateContextFromType )
+#define clRetainContext CLEW_GET_FUN(__clewRetainContext )
+#define clReleaseContext CLEW_GET_FUN(__clewReleaseContext )
+#define clGetContextInfo CLEW_GET_FUN(__clewGetContextInfo )
+#define clCreateCommandQueue CLEW_GET_FUN(__clewCreateCommandQueue )
+#define clRetainCommandQueue CLEW_GET_FUN(__clewRetainCommandQueue )
+#define clReleaseCommandQueue CLEW_GET_FUN(__clewReleaseCommandQueue )
+#define clGetCommandQueueInfo CLEW_GET_FUN(__clewGetCommandQueueInfo )
+#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+#warning CL_USE_DEPRECATED_OPENCL_1_0_APIS is defined. These APIs are unsupported and untested in OpenCL 1.1!
+/*
+ * WARNING:
+ * This API introduces mutable state into the OpenCL implementation. It has been REMOVED
+ * to better facilitate thread safety. The 1.0 API is not thread safe. It is not tested by the
+ * OpenCL 1.1 conformance test, and consequently may not work or may not work dependably.
+ * It is likely to be non-performant. Use of this API is not advised. Use at your own risk.
+ *
+ * Software developers previously relying on this API are instructed to set the command queue
+ * properties when creating the queue, instead.
+ */
+#define clSetCommandQueueProperty CLEW_GET_FUN(__clewSetCommandQueueProperty )
+#endif /* CL_USE_DEPRECATED_OPENCL_1_0_APIS */
+#define clCreateBuffer CLEW_GET_FUN(__clewCreateBuffer )
+#define clCreateSubBuffer CLEW_GET_FUN(__clewCreateSubBuffer )
+#define clCreateImage CLEW_GET_FUN(__clewCreateImage )
+#define clRetainMemObject CLEW_GET_FUN(__clewRetainMemObject )
+#define clReleaseMemObject CLEW_GET_FUN(__clewReleaseMemObject )
+#define clGetSupportedImageFormats CLEW_GET_FUN(__clewGetSupportedImageFormats )
+#define clGetMemObjectInfo CLEW_GET_FUN(__clewGetMemObjectInfo )
+#define clGetImageInfo CLEW_GET_FUN(__clewGetImageInfo )
+#define clSetMemObjectDestructorCallback CLEW_GET_FUN(__clewSetMemObjectDestructorCallback)
+#define clCreateSampler CLEW_GET_FUN(__clewCreateSampler )
+#define clRetainSampler CLEW_GET_FUN(__clewRetainSampler )
+#define clReleaseSampler CLEW_GET_FUN(__clewReleaseSampler )
+#define clGetSamplerInfo CLEW_GET_FUN(__clewGetSamplerInfo )
+#define clCreateProgramWithSource CLEW_GET_FUN(__clewCreateProgramWithSource )
+#define clCreateProgramWithBinary CLEW_GET_FUN(__clewCreateProgramWithBinary )
+#define clCreateProgramWithBuiltInKernels CLEW_GET_FUN(__clewCreateProgramWithBuiltInKernels)
+#define clRetainProgram CLEW_GET_FUN(__clewRetainProgram )
+#define clReleaseProgram CLEW_GET_FUN(__clewReleaseProgram )
+#define clBuildProgram CLEW_GET_FUN(__clewBuildProgram )
+#define clGetProgramInfo CLEW_GET_FUN(__clewGetProgramInfo )
+#define clGetProgramBuildInfo CLEW_GET_FUN(__clewGetProgramBuildInfo )
+#define clCreateKernel CLEW_GET_FUN(__clewCreateKernel )
+#define clCreateKernelsInProgram CLEW_GET_FUN(__clewCreateKernelsInProgram )
+#define clRetainKernel CLEW_GET_FUN(__clewRetainKernel )
+#define clReleaseKernel CLEW_GET_FUN(__clewReleaseKernel )
+#define clSetKernelArg CLEW_GET_FUN(__clewSetKernelArg )
+#define clGetKernelInfo CLEW_GET_FUN(__clewGetKernelInfo )
+#define clGetKernelWorkGroupInfo CLEW_GET_FUN(__clewGetKernelWorkGroupInfo )
+#define clWaitForEvents CLEW_GET_FUN(__clewWaitForEvents )
+#define clGetEventInfo CLEW_GET_FUN(__clewGetEventInfo )
+#define clCreateUserEvent CLEW_GET_FUN(__clewCreateUserEvent )
+#define clRetainEvent CLEW_GET_FUN(__clewRetainEvent )
+#define clReleaseEvent CLEW_GET_FUN(__clewReleaseEvent )
+#define clSetUserEventStatus CLEW_GET_FUN(__clewSetUserEventStatus )
+#define clSetEventCallback CLEW_GET_FUN(__clewSetEventCallback )
+#define clGetEventProfilingInfo CLEW_GET_FUN(__clewGetEventProfilingInfo )
+#define clFlush CLEW_GET_FUN(__clewFlush )
+#define clFinish CLEW_GET_FUN(__clewFinish )
+#define clEnqueueReadBuffer CLEW_GET_FUN(__clewEnqueueReadBuffer )
+#define clEnqueueReadBufferRect CLEW_GET_FUN(__clewEnqueueReadBufferRect )
+#define clEnqueueWriteBuffer CLEW_GET_FUN(__clewEnqueueWriteBuffer )
+#define clEnqueueWriteBufferRect CLEW_GET_FUN(__clewEnqueueWriteBufferRect )
+#define clEnqueueCopyBuffer CLEW_GET_FUN(__clewEnqueueCopyBuffer )
+#define clEnqueueCopyBufferRect CLEW_GET_FUN(__clewEnqueueCopyBufferRect )
+#define clEnqueueReadImage CLEW_GET_FUN(__clewEnqueueReadImage )
+#define clEnqueueWriteImage CLEW_GET_FUN(__clewEnqueueWriteImage )
+#define clEnqueueCopyImage CLEW_GET_FUN(__clewEnqueueCopyImage )
+#define clEnqueueCopyImageToBuffer CLEW_GET_FUN(__clewEnqueueCopyImageToBuffer )
+#define clEnqueueCopyBufferToImage CLEW_GET_FUN(__clewEnqueueCopyBufferToImage )
+#define clEnqueueMapBuffer CLEW_GET_FUN(__clewEnqueueMapBuffer )
+#define clEnqueueMapImage CLEW_GET_FUN(__clewEnqueueMapImage )
+#define clEnqueueUnmapMemObject CLEW_GET_FUN(__clewEnqueueUnmapMemObject )
+#define clEnqueueNDRangeKernel CLEW_GET_FUN(__clewEnqueueNDRangeKernel )
+#define clEnqueueTask CLEW_GET_FUN(__clewEnqueueTask )
+#define clEnqueueNativeKernel CLEW_GET_FUN(__clewEnqueueNativeKernel )
+
+#define clGetExtensionFunctionAddressForPlatform CLEW_GET_FUN(__clewGetExtensionFunctionAddressForPlatform)
+
+#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS
+#define clCreateImage2D CLEW_GET_FUN(__clewCreateImage2D )
+#define clCreateImage3D CLEW_GET_FUN(__clewCreateImage3D )
+#define clGetExtensionFunctionAddress CLEW_GET_FUN(__clewGetExtensionFunctionAddress )
+#define clEnqueueMarker CLEW_GET_FUN(__clewEnqueueMarker )
+#define clEnqueueWaitForEvents CLEW_GET_FUN(__clewEnqueueWaitForEvents )
+#define clEnqueueBarrier CLEW_GET_FUN(__clewEnqueueBarrier )
+#define clUnloadCompiler CLEW_GET_FUN(__clewUnloadCompiler )
+#endif
+
+/* cl_gl */
+#define clCreateFromGLBuffer CLEW_GET_FUN(__clewCreateFromGLBuffer )
+#define clCreateFromGLTexture CLEW_GET_FUN(__clewCreateFromGLTexture )
+#define clCreateFromGLRenderbuffer CLEW_GET_FUN(__clewCreateFromGLRenderbuffer )
+#define clGetGLObjectInfo CLEW_GET_FUN(__clewGetGLObjectInfo )
+#define clGetGLTextureInfo CLEW_GET_FUN(__clGetGLTextureInfo )
+#define clEnqueueAcquireGLObjects CLEW_GET_FUN(__clewEnqueueAcquireGLObjects )
+#define clEnqueueReleaseGLObjects CLEW_GET_FUN(__clewEnqueueReleaseGLObjects )
+#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS
+#define clCreateFromGLTexture2D CLEW_GET_FUN(__clewCreateFromGLTexture2D )
+#define clCreateFromGLTexture3D CLEW_GET_FUN(__clewCreateFromGLTexture3D )
+#endif
+#define clGetGLContextInfoKHR CLEW_GET_FUN(__clewGetGLContextInfoKHR )
+
+
+#define CLEW_SUCCESS 0 //!< Success error code
+#define CLEW_ERROR_OPEN_FAILED -1 //!< Error code for failing to open the dynamic library
+#define CLEW_ERROR_ATEXIT_FAILED -2 //!< Error code for failing to queue the closing of the dynamic library to atexit()
+
+//! \brief Load OpenCL dynamic library and set function entry points
+int clewInit ();
+//! \brief Convert an OpenCL error code to its string equivalent
+const char* clewErrorString (cl_int error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // CLEW_HPP_INCLUDED
diff --git a/extern/clew/src/clew.c b/extern/clew/src/clew.c
new file mode 100644
index 00000000000..8c9316d3c9c
--- /dev/null
+++ b/extern/clew/src/clew.c
@@ -0,0 +1,382 @@
+//////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2009 Organic Vectory B.V.
+// Written by George van Venrooij
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file license.txt)
+//////////////////////////////////////////////////////////////////////////
+
+#include "clew.h"
+
+#ifdef _WIN32
+ #define WIN32_LEAN_AND_MEAN
+ #define VC_EXTRALEAN
+ #include <windows.h>
+
+ typedef HMODULE CLEW_DYNLIB_HANDLE;
+
+ #define CLEW_DYNLIB_OPEN LoadLibrary
+ #define CLEW_DYNLIB_CLOSE FreeLibrary
+ #define CLEW_DYNLIB_IMPORT GetProcAddress
+#else
+ #include <dlfcn.h>
+
+ typedef void* CLEW_DYNLIB_HANDLE;
+
+ #define CLEW_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL)
+ #define CLEW_DYNLIB_CLOSE dlclose
+ #define CLEW_DYNLIB_IMPORT dlsym
+#endif
+
+#include <stdlib.h>
+
+//! \brief module handle
+static CLEW_DYNLIB_HANDLE module = NULL;
+
+// Variables holding function entry points
+PFNCLGETPLATFORMIDS __clewGetPlatformIDs = NULL;
+PFNCLGETPLATFORMINFO __clewGetPlatformInfo = NULL;
+PFNCLGETDEVICEIDS __clewGetDeviceIDs = NULL;
+PFNCLGETDEVICEINFO __clewGetDeviceInfo = NULL;
+PFNCLCREATESUBDEVICES __clewCreateSubDevices = NULL;
+PFNCLRETAINDEVICE __clewRetainDevice = NULL;
+PFNCLRELEASEDEVICE __clewReleaseDevice = NULL;
+PFNCLCREATECONTEXT __clewCreateContext = NULL;
+PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType = NULL;
+PFNCLRETAINCONTEXT __clewRetainContext = NULL;
+PFNCLRELEASECONTEXT __clewReleaseContext = NULL;
+PFNCLGETCONTEXTINFO __clewGetContextInfo = NULL;
+PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue = NULL;
+PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue = NULL;
+PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue = NULL;
+PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo = NULL;
+#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty = NULL;
+#endif
+PFNCLCREATEBUFFER __clewCreateBuffer = NULL;
+PFNCLCREATESUBBUFFER __clewCreateSubBuffer = NULL;
+PFNCLCREATEIMAGE __clewCreateImage = NULL;
+PFNCLRETAINMEMOBJECT __clewRetainMemObject = NULL;
+PFNCLRELEASEMEMOBJECT __clewReleaseMemObject = NULL;
+PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats = NULL;
+PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo = NULL;
+PFNCLGETIMAGEINFO __clewGetImageInfo = NULL;
+PFNCLSETMEMOBJECTDESTRUCTORCALLBACK __clewSetMemObjectDestructorCallback = NULL;
+PFNCLCREATESAMPLER __clewCreateSampler = NULL;
+PFNCLRETAINSAMPLER __clewRetainSampler = NULL;
+PFNCLRELEASESAMPLER __clewReleaseSampler = NULL;
+PFNCLGETSAMPLERINFO __clewGetSamplerInfo = NULL;
+PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource = NULL;
+PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary = NULL;
+PFNCLCREATEPROGRAMWITHBUILTINKERNELS __clewCreateProgramWithBuiltInKernels = NULL;
+PFNCLRETAINPROGRAM __clewRetainProgram = NULL;
+PFNCLRELEASEPROGRAM __clewReleaseProgram = NULL;
+PFNCLBUILDPROGRAM __clewBuildProgram = NULL;
+PFNCLGETPROGRAMINFO __clewGetProgramInfo = NULL;
+PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo = NULL;
+PFNCLCREATEKERNEL __clewCreateKernel = NULL;
+PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram = NULL;
+PFNCLRETAINKERNEL __clewRetainKernel = NULL;
+PFNCLRELEASEKERNEL __clewReleaseKernel = NULL;
+PFNCLSETKERNELARG __clewSetKernelArg = NULL;
+PFNCLGETKERNELINFO __clewGetKernelInfo = NULL;
+PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo = NULL;
+PFNCLWAITFOREVENTS __clewWaitForEvents = NULL;
+PFNCLGETEVENTINFO __clewGetEventInfo = NULL;
+PFNCLCREATEUSEREVENT __clewCreateUserEvent = NULL;
+PFNCLRETAINEVENT __clewRetainEvent = NULL;
+PFNCLRELEASEEVENT __clewReleaseEvent = NULL;
+PFNCLSETUSEREVENTSTATUS __clewSetUserEventStatus = NULL;
+PFNCLSETEVENTCALLBACK __clewSetEventCallback = NULL;
+PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo = NULL;
+PFNCLFLUSH __clewFlush = NULL;
+PFNCLFINISH __clewFinish = NULL;
+PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer = NULL;
+PFNCLENQUEUEREADBUFFERRECT __clewEnqueueReadBufferRect = NULL;
+PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer = NULL;
+PFNCLENQUEUEWRITEBUFFERRECT __clewEnqueueWriteBufferRect = NULL;
+PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer = NULL;
+PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage = NULL;
+PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage = NULL;
+PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage = NULL;
+PFNCLENQUEUECOPYBUFFERRECT __clewEnqueueCopyBufferRect = NULL;
+PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer = NULL;
+PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage = NULL;
+PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer = NULL;
+PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage = NULL;
+PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject = NULL;
+PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel = NULL;
+PFNCLENQUEUETASK __clewEnqueueTask = NULL;
+PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel = NULL;
+
+
+
+PFNCLGETEXTENSIONFUNCTIONADDRESSFORPLATFORM __clewGetExtensionFunctionAddressForPlatform = NULL;
+
+#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS
+PFNCLCREATEIMAGE2D __clewCreateImage2D = NULL;
+PFNCLCREATEIMAGE3D __clewCreateImage3D = NULL;
+PFNCLENQUEUEMARKER __clewEnqueueMarker = NULL;
+PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents = NULL;
+PFNCLENQUEUEBARRIER __clewEnqueueBarrier = NULL;
+PFNCLUNLOADCOMPILER __clewUnloadCompiler = NULL;
+PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress = NULL;
+#endif
+
+/* cl_gl */
+PFNCLCREATEFROMGLBUFFER __clewCreateFromGLBuffer = NULL;
+PFNCLCREATEFROMGLTEXTURE __clewCreateFromGLTexture = NULL;
+PFNCLCREATEFROMGLRENDERBUFFER __clewCreateFromGLRenderbuffer = NULL;
+PFNCLGETGLOBJECTINFO __clewGetGLObjectInfo = NULL;
+PFNCLGETGLTEXTUREINFO __clewGetGLTextureInfo = NULL;
+PFNCLENQUEUEACQUIREGLOBJECTS __clewEnqueueAcquireGLObjects = NULL;
+PFNCLENQUEUERELEASEGLOBJECTS __clewEnqueueReleaseGLObjects = NULL;
+#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS
+PFNCLCREATEFROMGLTEXTURE2D __clewCreateFromGLTexture2D = NULL;
+PFNCLCREATEFROMGLTEXTURE3D __clewCreateFromGLTexture3D = NULL;
+#endif
+PFNCLGETGLCONTEXTINFOKHR __clewGetGLContextInfoKHR = NULL;
+
+
+static void clewExit(void)
+{
+ if (module != NULL)
+ {
+ // Ignore errors
+ CLEW_DYNLIB_CLOSE(module);
+ module = NULL;
+ }
+}
+
+int clewInit()
+{
+#ifdef _WIN32
+ const char *path = "OpenCL.dll";
+#elif defined(__APPLE__)
+ const char *path = "/Library/Frameworks/OpenCL.framework/OpenCL";
+#else
+ const char *path = "libOpenCL.so";
+#endif
+
+ int error = 0;
+
+ // Check if already initialized
+ if (module != NULL)
+ {
+ return CLEW_SUCCESS;
+ }
+
+ // Load library
+ module = CLEW_DYNLIB_OPEN(path);
+
+ // Check for errors
+ if (module == NULL)
+ {
+ return CLEW_ERROR_OPEN_FAILED;
+ }
+
+ // Set unloading
+ error = atexit(clewExit);
+
+ if (error)
+ {
+ // Failure queuing atexit, shutdown with error
+ CLEW_DYNLIB_CLOSE(module);
+ module = NULL;
+
+ return CLEW_ERROR_ATEXIT_FAILED;
+ }
+
+ // Determine function entry-points
+ __clewGetPlatformIDs = (PFNCLGETPLATFORMIDS )CLEW_DYNLIB_IMPORT(module, "clGetPlatformIDs");
+ __clewGetPlatformInfo = (PFNCLGETPLATFORMINFO )CLEW_DYNLIB_IMPORT(module, "clGetPlatformInfo");
+ __clewGetDeviceIDs = (PFNCLGETDEVICEIDS )CLEW_DYNLIB_IMPORT(module, "clGetDeviceIDs");
+ __clewGetDeviceInfo = (PFNCLGETDEVICEINFO )CLEW_DYNLIB_IMPORT(module, "clGetDeviceInfo");
+ __clewCreateSubDevices = (PFNCLCREATESUBDEVICES )CLEW_DYNLIB_IMPORT(module, "clCreateSubDevices");
+ __clewRetainDevice = (PFNCLRETAINDEVICE )CLEW_DYNLIB_IMPORT(module, "clRetainDevice");
+ __clewReleaseDevice = (PFNCLRELEASEDEVICE )CLEW_DYNLIB_IMPORT(module, "clReleaseDevice");
+ __clewCreateContext = (PFNCLCREATECONTEXT )CLEW_DYNLIB_IMPORT(module, "clCreateContext");
+ __clewCreateContextFromType = (PFNCLCREATECONTEXTFROMTYPE )CLEW_DYNLIB_IMPORT(module, "clCreateContextFromType");
+ __clewRetainContext = (PFNCLRETAINCONTEXT )CLEW_DYNLIB_IMPORT(module, "clRetainContext");
+ __clewReleaseContext = (PFNCLRELEASECONTEXT )CLEW_DYNLIB_IMPORT(module, "clReleaseContext");
+ __clewGetContextInfo = (PFNCLGETCONTEXTINFO )CLEW_DYNLIB_IMPORT(module, "clGetContextInfo");
+ __clewCreateCommandQueue = (PFNCLCREATECOMMANDQUEUE )CLEW_DYNLIB_IMPORT(module, "clCreateCommandQueue");
+ __clewRetainCommandQueue = (PFNCLRETAINCOMMANDQUEUE )CLEW_DYNLIB_IMPORT(module, "clRetainCommandQueue");
+ __clewReleaseCommandQueue = (PFNCLRELEASECOMMANDQUEUE )CLEW_DYNLIB_IMPORT(module, "clReleaseCommandQueue");
+ __clewGetCommandQueueInfo = (PFNCLGETCOMMANDQUEUEINFO )CLEW_DYNLIB_IMPORT(module, "clGetCommandQueueInfo");
+#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+ __clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY )CLEW_DYNLIB_IMPORT(module, "clSetCommandQueueProperty");
+#endif
+ __clewCreateBuffer = (PFNCLCREATEBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
+ __clewCreateSubBuffer = (PFNCLCREATESUBBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
+ __clewCreateImage = (PFNCLCREATEIMAGE )CLEW_DYNLIB_IMPORT(module, "clCreateImage");
+ __clewRetainMemObject = (PFNCLRETAINMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clRetainMemObject");
+ __clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clReleaseMemObject");
+ __clewGetSupportedImageFormats = (PFNCLGETSUPPORTEDIMAGEFORMATS )CLEW_DYNLIB_IMPORT(module, "clGetSupportedImageFormats");
+ __clewGetMemObjectInfo = (PFNCLGETMEMOBJECTINFO )CLEW_DYNLIB_IMPORT(module, "clGetMemObjectInfo");
+ __clewGetImageInfo = (PFNCLGETIMAGEINFO )CLEW_DYNLIB_IMPORT(module, "clGetImageInfo");
+ __clewSetMemObjectDestructorCallback = (PFNCLSETMEMOBJECTDESTRUCTORCALLBACK)CLEW_DYNLIB_IMPORT(module, "clSetMemObjectDestructorCallback");
+ __clewCreateSampler = (PFNCLCREATESAMPLER )CLEW_DYNLIB_IMPORT(module, "clCreateSampler");
+ __clewRetainSampler = (PFNCLRETAINSAMPLER )CLEW_DYNLIB_IMPORT(module, "clRetainSampler");
+ __clewReleaseSampler = (PFNCLRELEASESAMPLER )CLEW_DYNLIB_IMPORT(module, "clReleaseSampler");
+ __clewGetSamplerInfo = (PFNCLGETSAMPLERINFO )CLEW_DYNLIB_IMPORT(module, "clGetSamplerInfo");
+ __clewCreateProgramWithSource = (PFNCLCREATEPROGRAMWITHSOURCE )CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithSource");
+ __clewCreateProgramWithBinary = (PFNCLCREATEPROGRAMWITHBINARY )CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithBinary");
+ __clewCreateProgramWithBuiltInKernels =(PFNCLCREATEPROGRAMWITHBUILTINKERNELS)CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithBuiltInKernels");
+ __clewRetainProgram = (PFNCLRETAINPROGRAM )CLEW_DYNLIB_IMPORT(module, "clRetainProgram");
+ __clewReleaseProgram = (PFNCLRELEASEPROGRAM )CLEW_DYNLIB_IMPORT(module, "clReleaseProgram");
+ __clewBuildProgram = (PFNCLBUILDPROGRAM )CLEW_DYNLIB_IMPORT(module, "clBuildProgram");
+
+ __clewGetProgramInfo = (PFNCLGETPROGRAMINFO )CLEW_DYNLIB_IMPORT(module, "clGetProgramInfo");
+ __clewGetProgramBuildInfo = (PFNCLGETPROGRAMBUILDINFO )CLEW_DYNLIB_IMPORT(module, "clGetProgramBuildInfo");
+ __clewCreateKernel = (PFNCLCREATEKERNEL )CLEW_DYNLIB_IMPORT(module, "clCreateKernel");
+ __clewCreateKernelsInProgram = (PFNCLCREATEKERNELSINPROGRAM )CLEW_DYNLIB_IMPORT(module, "clCreateKernelsInProgram");
+ __clewRetainKernel = (PFNCLRETAINKERNEL )CLEW_DYNLIB_IMPORT(module, "clRetainKernel");
+ __clewReleaseKernel = (PFNCLRELEASEKERNEL )CLEW_DYNLIB_IMPORT(module, "clReleaseKernel");
+ __clewSetKernelArg = (PFNCLSETKERNELARG )CLEW_DYNLIB_IMPORT(module, "clSetKernelArg");
+ __clewGetKernelInfo = (PFNCLGETKERNELINFO )CLEW_DYNLIB_IMPORT(module, "clGetKernelInfo");
+ __clewGetKernelWorkGroupInfo = (PFNCLGETKERNELWORKGROUPINFO )CLEW_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo");
+ __clewWaitForEvents = (PFNCLWAITFOREVENTS )CLEW_DYNLIB_IMPORT(module, "clWaitForEvents");
+ __clewGetEventInfo = (PFNCLGETEVENTINFO )CLEW_DYNLIB_IMPORT(module, "clGetEventInfo");
+ __clewCreateUserEvent = (PFNCLCREATEUSEREVENT )CLEW_DYNLIB_IMPORT(module, "clCreateUserEvent");
+ __clewRetainEvent = (PFNCLRETAINEVENT )CLEW_DYNLIB_IMPORT(module, "clRetainEvent");
+ __clewReleaseEvent = (PFNCLRELEASEEVENT )CLEW_DYNLIB_IMPORT(module, "clReleaseEvent");
+ __clewSetUserEventStatus = (PFNCLSETUSEREVENTSTATUS )CLEW_DYNLIB_IMPORT(module, "clSetUserEventStatus");
+ __clewSetEventCallback = (PFNCLSETEVENTCALLBACK )CLEW_DYNLIB_IMPORT(module, "clSetEventCallback");
+ __clewGetEventProfilingInfo = (PFNCLGETEVENTPROFILINGINFO )CLEW_DYNLIB_IMPORT(module, "clGetEventProfilingInfo");
+ __clewFlush = (PFNCLFLUSH )CLEW_DYNLIB_IMPORT(module, "clFlush");
+ __clewFinish = (PFNCLFINISH )CLEW_DYNLIB_IMPORT(module, "clFinish");
+ __clewEnqueueReadBuffer = (PFNCLENQUEUEREADBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueReadBuffer");
+ __clewEnqueueReadBufferRect = (PFNCLENQUEUEREADBUFFERRECT )CLEW_DYNLIB_IMPORT(module, "clEnqueueReadBufferRect");
+ __clewEnqueueWriteBuffer = (PFNCLENQUEUEWRITEBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer");
+ __clewEnqueueWriteBufferRect = (PFNCLENQUEUEWRITEBUFFERRECT )CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteBufferRect");
+ __clewEnqueueCopyBuffer = (PFNCLENQUEUECOPYBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer");
+ __clewEnqueueCopyBufferRect = (PFNCLENQUEUECOPYBUFFERRECT )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBufferRect");
+ __clewEnqueueReadImage = (PFNCLENQUEUEREADIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueReadImage");
+ __clewEnqueueWriteImage = (PFNCLENQUEUEWRITEIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteImage");
+ __clewEnqueueCopyImage = (PFNCLENQUEUECOPYIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyImage");
+ __clewEnqueueCopyImageToBuffer = (PFNCLENQUEUECOPYIMAGETOBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer");
+ __clewEnqueueCopyBufferToImage = (PFNCLENQUEUECOPYBUFFERTOIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage");
+ __clewEnqueueMapBuffer = (PFNCLENQUEUEMAPBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueMapBuffer");
+ __clewEnqueueMapImage = (PFNCLENQUEUEMAPIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueMapImage");
+ __clewEnqueueUnmapMemObject = (PFNCLENQUEUEUNMAPMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject");
+ __clewEnqueueNDRangeKernel = (PFNCLENQUEUENDRANGEKERNEL )CLEW_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel");
+ __clewEnqueueTask = (PFNCLENQUEUETASK )CLEW_DYNLIB_IMPORT(module, "clEnqueueTask");
+ __clewEnqueueNativeKernel = (PFNCLENQUEUENATIVEKERNEL )CLEW_DYNLIB_IMPORT(module, "clEnqueueNativeKernel");
+
+
+ __clewGetExtensionFunctionAddressForPlatform = (PFNCLGETEXTENSIONFUNCTIONADDRESSFORPLATFORM)CLEW_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddressForPlatform");
+#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS
+ __clewCreateImage2D = (PFNCLCREATEIMAGE2D )CLEW_DYNLIB_IMPORT(module, "clCreateImage2D");
+ __clewCreateImage3D = (PFNCLCREATEIMAGE3D )CLEW_DYNLIB_IMPORT(module, "clCreateImage3D");
+ __clewEnqueueMarker = (PFNCLENQUEUEMARKER )CLEW_DYNLIB_IMPORT(module, "clEnqueueMarker");
+ __clewEnqueueWaitForEvents = (PFNCLENQUEUEWAITFOREVENTS )CLEW_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents");
+ __clewEnqueueBarrier = (PFNCLENQUEUEBARRIER )CLEW_DYNLIB_IMPORT(module, "clEnqueueBarrier");
+ __clewUnloadCompiler = (PFNCLUNLOADCOMPILER )CLEW_DYNLIB_IMPORT(module, "clUnloadCompiler");
+ __clewGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS )CLEW_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress");
+#endif
+
+
+ /* cl_gl */
+ __clewCreateFromGLBuffer = (PFNCLCREATEFROMGLBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateFromGLBuffer");
+ __clewCreateFromGLTexture = (PFNCLCREATEFROMGLTEXTURE )CLEW_DYNLIB_IMPORT(module, "clCreateFromGLTexture");
+ __clewCreateFromGLRenderbuffer = (PFNCLCREATEFROMGLRENDERBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateFromGLRenderbuffer");
+ __clewGetGLObjectInfo = (PFNCLGETGLOBJECTINFO )CLEW_DYNLIB_IMPORT(module, "clGetGLObjectInfo");
+ __clewGetGLTextureInfo = (PFNCLGETGLTEXTUREINFO )CLEW_DYNLIB_IMPORT(module, "clGetGLTextureInfo");
+ __clewEnqueueAcquireGLObjects = (PFNCLENQUEUEACQUIREGLOBJECTS )CLEW_DYNLIB_IMPORT(module, "clEnqueueAcquireGLObjects");
+ __clewEnqueueReleaseGLObjects = (PFNCLENQUEUERELEASEGLOBJECTS )CLEW_DYNLIB_IMPORT(module, "clEnqueueReleaseGLObjects");
+ #ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS
+ __clewCreateFromGLTexture2D = (PFNCLCREATEFROMGLTEXTURE2D )CLEW_DYNLIB_IMPORT(module, "clCreateFromGLTexture2D");
+ __clewCreateFromGLTexture3D = (PFNCLCREATEFROMGLTEXTURE3D )CLEW_DYNLIB_IMPORT(module, "clCreateFromGLTexture3D");
+ #endif
+ __clewGetGLContextInfoKHR = (PFNCLGETGLCONTEXTINFOKHR )CLEW_DYNLIB_IMPORT(module, "clGetGLContextInfoKHR");
+
+
+ if(__clewGetPlatformIDs == NULL) return 0;
+ if(__clewGetPlatformInfo == NULL) return 0;
+ if(__clewGetDeviceIDs == NULL) return 0;
+ if(__clewGetDeviceInfo == NULL) return 0;
+
+ return CLEW_SUCCESS;
+}
+
+const char* clewErrorString(cl_int error)
+{
+ static const char* strings[] =
+ {
+ // Error Codes
+ "CL_SUCCESS" // 0
+ , "CL_DEVICE_NOT_FOUND" // -1
+ , "CL_DEVICE_NOT_AVAILABLE" // -2
+ , "CL_COMPILER_NOT_AVAILABLE" // -3
+ , "CL_MEM_OBJECT_ALLOCATION_FAILURE" // -4
+ , "CL_OUT_OF_RESOURCES" // -5
+ , "CL_OUT_OF_HOST_MEMORY" // -6
+ , "CL_PROFILING_INFO_NOT_AVAILABLE" // -7
+ , "CL_MEM_COPY_OVERLAP" // -8
+ , "CL_IMAGE_FORMAT_MISMATCH" // -9
+ , "CL_IMAGE_FORMAT_NOT_SUPPORTED" // -10
+ , "CL_BUILD_PROGRAM_FAILURE" // -11
+ , "CL_MAP_FAILURE" // -12
+ , "CL_MISALIGNED_SUB_BUFFER_OFFSET" // -13
+ , "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST"// -14
+ , "CL_COMPILE_PROGRAM_FAILURE" // -15
+ , "CL_LINKER_NOT_AVAILABLE" // -16
+ , "CL_LINK_PROGRAM_FAILURE" // -17
+ , "CL_DEVICE_PARTITION_FAILED" // -18
+ , "CL_KERNEL_ARG_INFO_NOT_AVAILABLE" // -19
+
+ , "" // -20
+ , "" // -21
+ , "" // -22
+ , "" // -23
+ , "" // -24
+ , "" // -25
+ , "" // -26
+ , "" // -27
+ , "" // -28
+ , "" // -29
+
+ , "CL_INVALID_VALUE" // -30
+ , "CL_INVALID_DEVICE_TYPE" // -31
+ , "CL_INVALID_PLATFORM" // -32
+ , "CL_INVALID_DEVICE" // -33
+ , "CL_INVALID_CONTEXT" // -34
+ , "CL_INVALID_QUEUE_PROPERTIES" // -35
+ , "CL_INVALID_COMMAND_QUEUE" // -36
+ , "CL_INVALID_HOST_PTR" // -37
+ , "CL_INVALID_MEM_OBJECT" // -38
+ , "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" // -39
+ , "CL_INVALID_IMAGE_SIZE" // -40
+ , "CL_INVALID_SAMPLER" // -41
+ , "CL_INVALID_BINARY" // -42
+ , "CL_INVALID_BUILD_OPTIONS" // -43
+ , "CL_INVALID_PROGRAM" // -44
+ , "CL_INVALID_PROGRAM_EXECUTABLE" // -45
+ , "CL_INVALID_KERNEL_NAME" // -46
+ , "CL_INVALID_KERNEL_DEFINITION" // -47
+ , "CL_INVALID_KERNEL" // -48
+ , "CL_INVALID_ARG_INDEX" // -49
+ , "CL_INVALID_ARG_VALUE" // -50
+ , "CL_INVALID_ARG_SIZE" // -51
+ , "CL_INVALID_KERNEL_ARGS" // -52
+ , "CL_INVALID_WORK_DIMENSION" // -53
+ , "CL_INVALID_WORK_GROUP_SIZE" // -54
+ , "CL_INVALID_WORK_ITEM_SIZE" // -55
+ , "CL_INVALID_GLOBAL_OFFSET" // -56
+ , "CL_INVALID_EVENT_WAIT_LIST" // -57
+ , "CL_INVALID_EVENT" // -58
+ , "CL_INVALID_OPERATION" // -59
+ , "CL_INVALID_GL_OBJECT" // -60
+ , "CL_INVALID_BUFFER_SIZE" // -61
+ , "CL_INVALID_MIP_LEVEL" // -62
+ , "CL_INVALID_GLOBAL_WORK_SIZE" // -63
+ , "CL_INVALID_PROPERTY" // -64
+ , "CL_INVALID_IMAGE_DESCRIPTOR" // -65
+ , "CL_INVALID_COMPILER_OPTIONS" // -66
+ , "CL_INVALID_LINKER_OPTIONS" // -67
+ , "CL_INVALID_DEVICE_PARTITION_COUNT" // -68
+ };
+
+ return strings[-error];
+}
diff --git a/intern/opencl/CMakeLists.txt b/extern/cuew/CMakeLists.txt
index 03855cfdf8b..284fbbc6aca 100644
--- a/intern/opencl/CMakeLists.txt
+++ b/extern/cuew/CMakeLists.txt
@@ -25,6 +25,7 @@
set(INC
.
+ include
)
set(INC_SYS
@@ -32,11 +33,8 @@ set(INC_SYS
)
set(SRC
- OCL_opencl.h
- intern/clew.h
- intern/clew.c
- intern/OCL_opencl.c
+ include/cuew.h
+ src/cuew.c
)
-
-blender_add_lib(bf_intern_opencl "${SRC}" "${INC}" "${INC_SYS}")
+blender_add_lib(extern_cuew "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/extern/cuew/LICENSE b/extern/cuew/LICENSE
new file mode 100644
index 00000000000..c7533090bbe
--- /dev/null
+++ b/extern/cuew/LICENSE
@@ -0,0 +1,174 @@
+
+ Modified Apache 2.0 License
+
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor
+ and its affiliates, except as required to comply with Section 4(c) of
+ the License and to reproduce the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/extern/cuew/README b/extern/cuew/README
new file mode 100644
index 00000000000..3c43b7278d9
--- /dev/null
+++ b/extern/cuew/README
@@ -0,0 +1,12 @@
+The CUDA Extension Wrangler Library (CUEW) is a cross-platform open-source
+C/C++ extension loading library. CUEW provides efficient run-time mechanisms
+for determining which CUDA functions and extensions extensions are supported
+on the target platform.
+
+CUDA core and extension functionality is exposed in a single header file.
+GUEW has been tested on a variety of operating systems, including Windows,
+Linux, Mac OS X.
+
+LICENSE
+
+CUEW library is released under the Apache 2.0 license.
diff --git a/intern/opencl/SConscript b/extern/cuew/SConscript
index 41a6d720098..9c12c71133c 100644
--- a/intern/opencl/SConscript
+++ b/extern/cuew/SConscript
@@ -27,8 +27,9 @@
Import ('env')
-sources = env.Glob('intern/*.c')
+sources = env.Glob('src/cuew.c')
-incs = '.'
+incs = 'include'
+defs = []
-env.BlenderLib ( 'bf_intern_opencl', sources, Split(incs), libtype=['core','player'], priority = [192,192] )
+env.BlenderLib ('extern_cuew', sources, Split(incs), defines=defs, libtype=['system'], priority = [0])
diff --git a/extern/cuew/auto/cuda_errors.py b/extern/cuew/auto/cuda_errors.py
new file mode 100644
index 00000000000..464b7765234
--- /dev/null
+++ b/extern/cuew/auto/cuda_errors.py
@@ -0,0 +1,35 @@
+CUDA_ERRORS={
+'CUDA_SUCCESS': "No errors",
+'CUDA_ERROR_INVALID_VALUE': "Invalid value",
+'CUDA_ERROR_OUT_OF_MEMORY': "Out of memory",
+'CUDA_ERROR_NOT_INITIALIZED': "Driver not initialized",
+'CUDA_ERROR_DEINITIALIZED': "Driver deinitialized",
+'CUDA_ERROR_NO_DEVICE': "No CUDA-capable device available",
+'CUDA_ERROR_INVALID_DEVICE': "Invalid device",
+'CUDA_ERROR_INVALID_IMAGE': "Invalid kernel image",
+'CUDA_ERROR_INVALID_CONTEXT': "Invalid context",
+'CUDA_ERROR_CONTEXT_ALREADY_CURRENT': "Context already current",
+'CUDA_ERROR_MAP_FAILED': "Map failed",
+'CUDA_ERROR_UNMAP_FAILED': "Unmap failed",
+'CUDA_ERROR_ARRAY_IS_MAPPED': "Array is mapped",
+'CUDA_ERROR_ALREADY_MAPPED': "Already mapped",
+'CUDA_ERROR_NO_BINARY_FOR_GPU': "No binary for GPU",
+'CUDA_ERROR_ALREADY_ACQUIRED': "Already acquired",
+'CUDA_ERROR_NOT_MAPPED': "Not mapped",
+'CUDA_ERROR_NOT_MAPPED_AS_ARRAY': "Mapped resource not available for access as an array",
+'CUDA_ERROR_NOT_MAPPED_AS_POINTER': "Mapped resource not available for access as a pointer",
+'CUDA_ERROR_ECC_UNCORRECTABLE': "Uncorrectable ECC error detected",
+'CUDA_ERROR_UNSUPPORTED_LIMIT': "CUlimit not supported by device",
+'CUDA_ERROR_INVALID_SOURCE': "Invalid source",
+'CUDA_ERROR_FILE_NOT_FOUND': "File not found",
+'CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND': "Link to a shared object failed to resolve",
+'CUDA_ERROR_SHARED_OBJECT_INIT_FAILED': "Shared object initialization failed",
+'CUDA_ERROR_INVALID_HANDLE': "Invalid handle",
+'CUDA_ERROR_NOT_FOUND': "Not found",
+'CUDA_ERROR_NOT_READY': "CUDA not ready",
+'CUDA_ERROR_LAUNCH_FAILED': "Launch failed",
+'CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES': "Launch exceeded resources",
+'CUDA_ERROR_LAUNCH_TIMEOUT': "Launch exceeded timeout",
+'CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING': "Launch with incompatible texturing",
+'CUDA_ERROR_UNKNOWN': "Unknown error",
+}
diff --git a/extern/cuew/auto/cuda_extra.py b/extern/cuew/auto/cuda_extra.py
new file mode 100644
index 00000000000..fd4f466df83
--- /dev/null
+++ b/extern/cuew/auto/cuda_extra.py
@@ -0,0 +1,125 @@
+extra_code = """
+static void path_join(const char *path1,
+ const char *path2,
+ int maxlen,
+ char *result) {
+#if defined(WIN32) || defined(_WIN32)
+ const char separator = '\\\\';
+#else
+ const char separator = '/';
+#endif
+ int n = snprintf(result, maxlen, "%s%c%s", path1, separator, path2);
+ if (n != -1 && n < maxlen) {
+ result[n] = '\\0';
+ }
+ else {
+ result[maxlen - 1] = '\\0';
+ }
+}
+
+static int path_exists(const char *path) {
+ struct stat st;
+ if (stat(path, &st)) {
+ return 0;
+ }
+ return 1;
+}
+
+const char *cuewCompilerPath(void) {
+#ifdef _WIN32
+ const char *defaultpaths[] = {"C:/CUDA/bin", NULL};
+ const char *executable = "nvcc.exe";
+#else
+ const char *defaultpaths[] = {
+ "/Developer/NVIDIA/CUDA-5.0/bin",
+ "/usr/local/cuda-5.0/bin",
+ "/usr/local/cuda/bin",
+ "/Developer/NVIDIA/CUDA-6.0/bin",
+ "/usr/local/cuda-6.0/bin",
+ "/Developer/NVIDIA/CUDA-5.5/bin",
+ "/usr/local/cuda-5.5/bin",
+ NULL};
+ const char *executable = "nvcc";
+#endif
+ int i;
+
+ const char *binpath = getenv("CUDA_BIN_PATH");
+
+ static char nvcc[65536];
+
+ if (binpath) {
+ path_join(binpath, executable, sizeof(nvcc), nvcc);
+ if (path_exists(nvcc))
+ return nvcc;
+ }
+
+ for (i = 0; defaultpaths[i]; ++i) {
+ path_join(defaultpaths[i], executable, sizeof(nvcc), nvcc);
+ if (path_exists(nvcc))
+ return nvcc;
+ }
+
+#ifndef _WIN32
+ {
+ FILE *handle = popen("which nvcc", "r");
+ if (handle) {
+ char buffer[4096] = {0};
+ int len = fread(buffer, 1, sizeof(buffer) - 1, handle);
+ buffer[len] = '\\0';
+ pclose(handle);
+
+ if (buffer[0])
+ return "nvcc";
+ }
+ }
+#endif
+
+ return NULL;
+}
+
+int cuewCompilerVersion(void) {
+ const char *path = cuewCompilerPath();
+ const char *marker = "Cuda compilation tools, release ";
+ FILE *pipe;
+ int major, minor;
+ char *versionstr;
+ char buf[128];
+ char output[65536] = "\\0";
+ char command[65536] = "\\0";
+
+ if (path == NULL)
+ return 0;
+
+ /* get --version output */
+ strncpy(command, path, sizeof(command));
+ strncat(command, " --version", sizeof(command) - strlen(path));
+ pipe = popen(command, "r");
+ if (!pipe) {
+ fprintf(stderr, "CUDA: failed to run compiler to retrieve version");
+ return 0;
+ }
+
+ while (!feof(pipe)) {
+ if (fgets(buf, sizeof(buf), pipe) != NULL) {
+ strncat(output, buf, sizeof(output) - strlen(output));
+ }
+ }
+
+ pclose(pipe);
+
+ /* parse version number */
+ versionstr = strstr(output, marker);
+ if (versionstr == NULL) {
+ fprintf(stderr, "CUDA: failed to find version number in:\\n\\n%s\\n", output);
+ return 0;
+ }
+ versionstr += strlen(marker);
+
+ if (sscanf(versionstr, "%d.%d", &major, &minor) < 2) {
+ fprintf(stderr, "CUDA: failed to parse version number from:\\n\\n%s\\n", output);
+ return 0;
+ }
+
+ return 10 * major + minor;
+}
+"""
diff --git a/extern/cuew/auto/cuew_gen.py b/extern/cuew/auto/cuew_gen.py
new file mode 100644
index 00000000000..a94525c52b1
--- /dev/null
+++ b/extern/cuew/auto/cuew_gen.py
@@ -0,0 +1,591 @@
+#!/usr/bin/env python3
+#
+# Copyright 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
+
+# This script generates either header or implementation file from
+# a CUDA header files.
+#
+# Usage: cuew hdr|impl [/path/to/cuda/includes]
+# - hdr means header file will be generated and printed to stdout.
+# - impl means implementation file will be generated and printed to stdout.
+# - /path/to/cuda/includes is a path to a folder with cuda.h and cudaGL.h
+# for which wrangler will be generated.
+
+import os
+import sys
+from cuda_errors import CUDA_ERRORS
+from pycparser import c_parser, c_ast, parse_file
+from subprocess import Popen, PIPE
+
+INCLUDE_DIR = "/usr/include"
+LIB = "CUEW"
+REAL_LIB = "CUDA"
+VERSION_MAJOR = "1"
+VERSION_MINOR = "2"
+COPYRIGHT = """/*
+ * 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
+ */"""
+FILES = ["cuda.h", "cudaGL.h"]
+
+TYPEDEFS = []
+FUNC_TYPEDEFS = []
+SYMBOLS = []
+DEFINES = []
+DEFINES_V2 = []
+ERRORS = []
+
+
+class FuncDefVisitor(c_ast.NodeVisitor):
+ indent = 0
+ prev_complex = False
+ dummy_typedefs = ['size_t', 'CUdeviceptr']
+
+ def _get_quals_string(self, node):
+ if node.quals:
+ return ' '.join(node.quals) + ' '
+ return ''
+
+ def _get_ident_type(self, node):
+ if isinstance(node, c_ast.PtrDecl):
+ return self._get_ident_type(node.type.type) + '*'
+ if isinstance(node, c_ast.ArrayDecl):
+ return self._get_ident_type(node.type)
+ elif isinstance(node, c_ast.Struct):
+ if node.name:
+ return 'struct ' + node.name
+ else:
+ self.indent += 1
+ struct = self._stringify_struct(node)
+ self.indent -= 1
+ return "struct {\n" + \
+ struct + (" " * self.indent) + "}"
+ elif isinstance(node, c_ast.Union):
+ self.indent += 1
+ union = self._stringify_struct(node)
+ self.indent -= 1
+ return "union {\n" + union + (" " * self.indent) + "}"
+ elif isinstance(node, c_ast.Enum):
+ return 'enum ' + node.name
+ elif isinstance(node, c_ast.TypeDecl):
+ return self._get_ident_type(node.type)
+ else:
+ return node.names[0]
+
+ def _stringify_param(self, param):
+ param_type = param.type
+ result = self._get_quals_string(param)
+ result += self._get_ident_type(param_type)
+ if param.name:
+ result += ' ' + param.name
+ if isinstance(param_type, c_ast.ArrayDecl):
+ # TODO(sergey): Workaround to deal with the
+ # preprocessed file where array size got
+ # substituded.
+ dim = param_type.dim.value
+ if param.name == "reserved" and dim == "64":
+ dim = "CU_IPC_HANDLE_SIZE"
+ result += '[' + dim + ']'
+ return result
+
+ def _stringify_params(self, params):
+ result = []
+ for param in params:
+ result.append(self._stringify_param(param))
+ return ', '.join(result)
+
+ def _stringify_struct(self, node):
+ result = ""
+ children = node.children()
+ for child in children:
+ member = self._stringify_param(child[1])
+ result += (" " * self.indent) + member + ";\n"
+ return result
+
+ def _stringify_enum(self, node):
+ result = ""
+ children = node.children()
+ for child in children:
+ if isinstance(child[1], c_ast.EnumeratorList):
+ enumerators = child[1].enumerators
+ for enumerator in enumerators:
+ result += (" " * self.indent) + enumerator.name
+ if enumerator.value:
+ result += " = " + enumerator.value.value
+ result += ",\n"
+ if enumerator.name.startswith("CUDA_ERROR_"):
+ ERRORS.append(enumerator.name)
+ return result
+
+ def visit_Decl(self, node):
+ if node.type.__class__.__name__ == 'FuncDecl':
+ if isinstance(node.type, c_ast.FuncDecl):
+ func_decl = node.type
+ func_decl_type = func_decl.type
+
+ typedef = 'typedef '
+ symbol_name = None
+
+ if isinstance(func_decl_type, c_ast.TypeDecl):
+ symbol_name = func_decl_type.declname
+ typedef += self._get_quals_string(func_decl_type)
+ typedef += self._get_ident_type(func_decl_type.type)
+ typedef += ' CUDAAPI'
+ typedef += ' t' + symbol_name
+ elif isinstance(func_decl_type, c_ast.PtrDecl):
+ ptr_type = func_decl_type.type
+ symbol_name = ptr_type.declname
+ typedef += self._get_quals_string(ptr_type)
+ typedef += self._get_ident_type(func_decl_type)
+ typedef += ' CUDAAPI'
+ typedef += ' t' + symbol_name
+
+ typedef += '(' + \
+ self._stringify_params(func_decl.args.params) + \
+ ');'
+
+ SYMBOLS.append(symbol_name)
+ FUNC_TYPEDEFS.append(typedef)
+
+ def visit_Typedef(self, node):
+ if node.name in self.dummy_typedefs:
+ return
+
+ complex = False
+ type = self._get_ident_type(node.type)
+ quals = self._get_quals_string(node)
+
+ if isinstance(node.type.type, c_ast.Struct):
+ self.indent += 1
+ struct = self._stringify_struct(node.type.type)
+ self.indent -= 1
+ typedef = quals + type + " {\n" + struct + "} " + node.name
+ complex = True
+ elif isinstance(node.type.type, c_ast.Enum):
+ self.indent += 1
+ enum = self._stringify_enum(node.type.type)
+ self.indent -= 1
+ typedef = quals + type + " {\n" + enum + "} " + node.name
+ complex = True
+ else:
+ typedef = quals + type + " " + node.name
+ if complex or self.prev_complex:
+ typedef = "\ntypedef " + typedef + ";"
+ else:
+ typedef = "typedef " + typedef + ";"
+
+ TYPEDEFS.append(typedef)
+
+ self.prev_complex = complex
+
+
+def get_latest_cpp():
+ path_prefix = "/usr/bin"
+ for cpp_version in ["9", "8", "7", "6", "5", "4"]:
+ test_cpp = os.path.join(path_prefix, "cpp-4." + cpp_version)
+ if os.path.exists(test_cpp):
+ return test_cpp
+ return None
+
+
+def preprocess_file(filename, cpp_path):
+ args = [cpp_path, "-I./"]
+ if filename.endswith("GL.h"):
+ args.append("-DCUDAAPI= ")
+ args.append(filename)
+
+ try:
+ pipe = Popen(args,
+ stdout=PIPE,
+ universal_newlines=True)
+ text = pipe.communicate()[0]
+ except OSError as e:
+ raise RuntimeError("Unable to invoke 'cpp'. " +
+ 'Make sure its path was passed correctly\n' +
+ ('Original error: %s' % e))
+
+ return text
+
+
+def parse_files():
+ parser = c_parser.CParser()
+ cpp_path = get_latest_cpp()
+
+ for filename in FILES:
+ filepath = os.path.join(INCLUDE_DIR, filename)
+ dummy_typedefs = {}
+ text = preprocess_file(filepath, cpp_path)
+
+ if filepath.endswith("GL.h"):
+ dummy_typedefs = {
+ "CUresult": "int",
+ "CUgraphicsResource": "void *",
+ "CUdevice": "void *",
+ "CUcontext": "void *",
+ "CUdeviceptr": "void *",
+ "CUstream": "void *"
+ }
+
+ text = "typedef int GLint;\n" + text
+ text = "typedef unsigned int GLuint;\n" + text
+ text = "typedef unsigned int GLenum;\n" + text
+ text = "typedef long size_t;\n" + text
+
+ for typedef in sorted(dummy_typedefs):
+ text = "typedef " + dummy_typedefs[typedef] + " " + \
+ typedef + ";\n" + text
+
+ ast = parser.parse(text, filepath)
+
+ with open(filepath) as f:
+ lines = f.readlines()
+ for line in lines:
+ if line.startswith("#define"):
+ line = line[8:-1]
+ token = line.split()
+ if token[0] not in ("__cuda_cuda_h__",
+ "CUDA_CB",
+ "CUDAAPI"):
+ DEFINES.append(token)
+
+ for line in lines:
+ # TODO(sergey): Use better matching rule for _v2 symbols.
+ if line[0].isspace() and line.lstrip().startswith("#define"):
+ line = line[12:-1]
+ token = line.split()
+ if len(token) == 2 and token[1].endswith("_v2"):
+ DEFINES_V2.append(token)
+
+ v = FuncDefVisitor()
+ for typedef in dummy_typedefs:
+ v.dummy_typedefs.append(typedef)
+ v.visit(ast)
+
+ FUNC_TYPEDEFS.append('')
+ SYMBOLS.append('')
+
+
+def print_copyright():
+ print(COPYRIGHT)
+ print("")
+
+
+def open_header_guard():
+ print("#ifndef __%s_H__" % (LIB))
+ print("#define __%s_H__" % (LIB))
+ print("")
+ print("#ifdef __cplusplus")
+ print("extern \"C\" {")
+ print("#endif")
+ print("")
+
+
+def close_header_guard():
+ print("")
+ print("#ifdef __cplusplus")
+ print("}")
+ print("#endif")
+ print("")
+ print("#endif /* __%s_H__ */" % (LIB))
+
+
+def print_header():
+ print_copyright()
+ open_header_guard()
+
+ # Fot size_t.
+ print("#include <stdlib.h>")
+ print("")
+
+ print("/* Defines. */")
+ print("#define %s_VERSION_MAJOR %s" % (LIB, VERSION_MAJOR))
+ print("#define %s_VERSION_MINOR %s" % (LIB, VERSION_MINOR))
+ print("")
+ for define in DEFINES:
+ print('#define %s' % (' '.join(define)))
+ print("")
+
+ print("""/* Functions which changed 3.1 -> 3.2 for 64 bit stuff,
+ * the cuda library has both the old ones for compatibility and new
+ * ones with _v2 postfix,
+ */""")
+ for define in DEFINES_V2:
+ print('#define %s' % (' '.join(define)))
+ print("")
+
+ print("/* Types. */")
+
+ # We handle this specially because of the file is
+ # getting preprocessed.
+ print("""#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64)
+typedef unsigned long long CUdeviceptr;
+#else
+typedef unsigned int CUdeviceptr;
+#endif
+""")
+
+ for typedef in TYPEDEFS:
+ print('%s' % (typedef))
+
+ # TDO(sergey): This is only specific to CUDA wrapper.
+ print("""
+#ifdef _WIN32
+# define CUDAAPI __stdcall
+# define CUDA_CB __stdcall
+#else
+# define CUDAAPI
+# define CUDA_CB
+#endif
+""")
+
+ print("/* Function types. */")
+ for func_typedef in FUNC_TYPEDEFS:
+ print('%s' % (func_typedef))
+ print("")
+
+ print("/* Function declarations. */")
+ for symbol in SYMBOLS:
+ if symbol:
+ print('extern t%s *%s;' % (symbol, symbol))
+ else:
+ print("")
+
+ print("")
+ print("enum {")
+ print(" CUEW_SUCCESS = 0,")
+ print(" CUEW_ERROR_OPEN_FAILED = -1,")
+ print(" CUEW_ERROR_ATEXIT_FAILED = -2,")
+ print("};")
+ print("")
+ print("int %sInit(void);" % (LIB.lower()))
+ # TODO(sergey): Get rid of hardcoded CUresult.
+ print("const char *%sErrorString(CUresult result);" % (LIB.lower()))
+ print("const char *cuewCompilerPath(void);")
+ print("int cuewCompilerVersion(void);")
+
+ close_header_guard()
+
+
+def print_dl_wrapper():
+ print("""#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# define VC_EXTRALEAN
+# include <windows.h>
+
+/* Utility macros. */
+
+typedef HMODULE DynamicLibrary;
+
+# define dynamic_library_open(path) LoadLibrary(path)
+# define dynamic_library_close(lib) FreeLibrary(lib)
+# define dynamic_library_find(lib, symbol) GetProcAddress(lib, symbol)
+#else
+# include <dlfcn.h>
+
+typedef void* DynamicLibrary;
+
+# define dynamic_library_open(path) dlopen(path, RTLD_NOW)
+# define dynamic_library_close(lib) dlclose(lib)
+# define dynamic_library_find(lib, symbol) dlsym(lib, symbol)
+#endif
+""")
+
+
+def print_dl_helper_macro():
+ print("""#define %s_LIBRARY_FIND_CHECKED(name) \\
+ name = (t##name *)dynamic_library_find(lib, #name); \\
+ assert(name);
+
+#define %s_LIBRARY_FIND(name) \\
+ name = (t##name *)dynamic_library_find(lib, #name);
+
+static DynamicLibrary lib;""" % (REAL_LIB, REAL_LIB))
+ print("")
+
+
+def print_dl_close():
+ print("""static void %sExit(void) {
+ if(lib != NULL) {
+ /* Ignore errors. */
+ dynamic_library_close(lib);
+ lib = NULL;
+ }
+}""" % (LIB.lower()))
+ print("")
+
+
+def print_lib_path():
+ # TODO(sergey): get rid of hardcoded libraries.
+ print("""#ifdef _WIN32
+ /* Expected in c:/windows/system or similar, no path needed. */
+ const char *path = "nvcuda.dll";
+#elif defined(__APPLE__)
+ /* Default installation path. */
+ const char *path = "/usr/local/cuda/lib/libcuda.dylib";
+#else
+ const char *path = "libcuda.so";
+#endif""")
+
+
+def print_init_guard():
+ print(""" static int initialized = 0;
+ static int result = 0;
+ int error, driver_version;
+
+ if (initialized) {
+ return result;
+ }
+
+ initialized = 1;
+
+ error = atexit(cuewExit);
+ if (error) {
+ result = CUEW_ERROR_ATEXIT_FAILED;
+ return result;
+ }
+
+ /* Load library. */
+ lib = dynamic_library_open(path);
+
+ if (lib == NULL) {
+ result = CUEW_ERROR_OPEN_FAILED;
+ return result;
+ }""")
+ print("")
+
+
+def print_driver_version_guard():
+ # TODO(sergey): Currently it's hardcoded for CUDA only.
+ print(""" /* Detect driver version. */
+ driver_version = 1000;
+
+ %s_LIBRARY_FIND_CHECKED(cuDriverGetVersion);
+ if (cuDriverGetVersion) {
+ cuDriverGetVersion(&driver_version);
+ }
+
+ /* We require version 4.0. */
+ if (driver_version < 4000) {
+ result = CUEW_ERROR_OPEN_FAILED;
+ return result;
+ }""" % (REAL_LIB))
+
+
+def print_dl_init():
+ print("int %sInit(void) {" % (LIB.lower()))
+
+ print(" /* Library paths. */")
+ print_lib_path()
+ print_init_guard()
+ print_driver_version_guard()
+
+ print(" /* Fetch all function pointers. */")
+ for symbol in SYMBOLS:
+ if symbol:
+ print(" %s_LIBRARY_FIND(%s);" % (REAL_LIB, symbol))
+ else:
+ print("")
+
+ print("")
+ print(" result = CUEW_SUCCESS;")
+ print(" return result;")
+
+ print("}")
+
+
+def print_implementation():
+ print_copyright()
+
+ # TODO(sergey): Get rid of hardcoded header.
+ print("""#ifdef _MSC_VER
+# define snprintf _snprintf
+# define popen _popen
+# define pclose _pclose
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+""")
+ print("#include <cuew.h>")
+ print("#include <assert.h>")
+ print("#include <stdio.h>")
+ print("#include <string.h>")
+ print("#include <sys/stat.h>")
+ print("")
+
+ print_dl_wrapper()
+ print_dl_helper_macro()
+
+ print("/* Function definitions. */")
+ for symbol in SYMBOLS:
+ if symbol:
+ print('t%s *%s;' % (symbol, symbol))
+ else:
+ print("")
+ print("")
+
+ print_dl_close()
+
+ print("/* Implementation function. */")
+ print_dl_init()
+
+ print("")
+ # TODO(sergey): Get rid of hardcoded CUresult.
+ print("const char *%sErrorString(CUresult result) {" % (LIB.lower()))
+ print(" switch(result) {")
+ print(" case CUDA_SUCCESS: return \"No errors\";")
+
+ for error in ERRORS:
+ if error in CUDA_ERRORS:
+ str = CUDA_ERRORS[error]
+ else:
+ str = error[11:]
+ print(" case %s: return \"%s\";" % (error, str))
+
+ print(" default: return \"Unknown CUDA error value\";")
+ print(" }")
+ print("}")
+
+ from cuda_extra import extra_code
+ print(extra_code)
+
+if __name__ == "__main__":
+
+ if len(sys.argv) != 2 and len(sys.argv) != 3:
+ print("Usage: %s hdr|impl [/path/to/cuda/toolkit/include]" %
+ (sys.argv[0]))
+ exit(1)
+
+ if len(sys.argv) == 3:
+ INCLUDE_DIR = sys.argv[2]
+
+ parse_files()
+
+ if sys.argv[1] == "hdr":
+ print_header()
+ elif sys.argv[1] == "impl":
+ print_implementation()
+ else:
+ print("Unknown command %s" % (sys.argv[1]))
+ exit(1)
diff --git a/extern/cuew/auto/cuew_gen.sh b/extern/cuew/auto/cuew_gen.sh
new file mode 100755
index 00000000000..b44987b801d
--- /dev/null
+++ b/extern/cuew/auto/cuew_gen.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# This script invokes cuew_gen.py and updates the
+# header and source files in the repository.
+
+SCRIPT=`realpath -s $0`
+DIR=`dirname $SCRIPT`
+
+python ${DIR}/cuew_gen.py hdr $@ > $DIR/../include/cuew.h
+python ${DIR}/cuew_gen.py impl $@ > $DIR/../src/cuew.c
diff --git a/extern/cuew/auto/stdlib.h b/extern/cuew/auto/stdlib.h
new file mode 100644
index 00000000000..75976c8574f
--- /dev/null
+++ b/extern/cuew/auto/stdlib.h
@@ -0,0 +1,3 @@
+/* This file is needed to workaround issue with parsing system headers. */
+
+typedef long size_t;
diff --git a/extern/cuew/include/cuew.h b/extern/cuew/include/cuew.h
new file mode 100644
index 00000000000..fd03311ad41
--- /dev/null
+++ b/extern/cuew/include/cuew.h
@@ -0,0 +1,1138 @@
+/*
+ * 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
+ */
+
+#ifndef __CUEW_H__
+#define __CUEW_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+
+/* Defines. */
+#define CUEW_VERSION_MAJOR 1
+#define CUEW_VERSION_MINOR 2
+
+#define CUDA_VERSION 6000
+#define CU_IPC_HANDLE_SIZE 64
+#define CU_MEMHOSTALLOC_PORTABLE 0x01
+#define CU_MEMHOSTALLOC_DEVICEMAP 0x02
+#define CU_MEMHOSTALLOC_WRITECOMBINED 0x04
+#define CU_MEMHOSTREGISTER_PORTABLE 0x01
+#define CU_MEMHOSTREGISTER_DEVICEMAP 0x02
+#define CUDA_ARRAY3D_LAYERED 0x01
+#define CUDA_ARRAY3D_2DARRAY 0x01
+#define CUDA_ARRAY3D_SURFACE_LDST 0x02
+#define CUDA_ARRAY3D_CUBEMAP 0x04
+#define CUDA_ARRAY3D_TEXTURE_GATHER 0x08
+#define CUDA_ARRAY3D_DEPTH_TEXTURE 0x10
+#define CU_TRSA_OVERRIDE_FORMAT 0x01
+#define CU_TRSF_READ_AS_INTEGER 0x01
+#define CU_TRSF_NORMALIZED_COORDINATES 0x02
+#define CU_TRSF_SRGB 0x10
+#define CU_LAUNCH_PARAM_END ((void*)0x00)
+#define CU_LAUNCH_PARAM_BUFFER_POINTER ((void*)0x01)
+#define CU_LAUNCH_PARAM_BUFFER_SIZE ((void*)0x02)
+#define CU_PARAM_TR_DEFAULT -1
+#define CUDAGL_H
+
+/* Functions which changed 3.1 -> 3.2 for 64 bit stuff,
+ * the cuda library has both the old ones for compatibility and new
+ * ones with _v2 postfix,
+ */
+#define cuDeviceTotalMem cuDeviceTotalMem_v2
+#define cuCtxCreate cuCtxCreate_v2
+#define cuModuleGetGlobal cuModuleGetGlobal_v2
+#define cuMemGetInfo cuMemGetInfo_v2
+#define cuMemAlloc cuMemAlloc_v2
+#define cuMemAllocPitch cuMemAllocPitch_v2
+#define cuMemFree cuMemFree_v2
+#define cuMemGetAddressRange cuMemGetAddressRange_v2
+#define cuMemAllocHost cuMemAllocHost_v2
+#define cuMemHostGetDevicePointer cuMemHostGetDevicePointer_v2
+#define cuMemcpyHtoD cuMemcpyHtoD_v2
+#define cuMemcpyDtoH cuMemcpyDtoH_v2
+#define cuMemcpyDtoD cuMemcpyDtoD_v2
+#define cuMemcpyDtoA cuMemcpyDtoA_v2
+#define cuMemcpyAtoD cuMemcpyAtoD_v2
+#define cuMemcpyHtoA cuMemcpyHtoA_v2
+#define cuMemcpyAtoH cuMemcpyAtoH_v2
+#define cuMemcpyAtoA cuMemcpyAtoA_v2
+#define cuMemcpyHtoAAsync cuMemcpyHtoAAsync_v2
+#define cuMemcpyAtoHAsync cuMemcpyAtoHAsync_v2
+#define cuMemcpy2D cuMemcpy2D_v2
+#define cuMemcpy2DUnaligned cuMemcpy2DUnaligned_v2
+#define cuMemcpy3D cuMemcpy3D_v2
+#define cuMemcpyHtoDAsync cuMemcpyHtoDAsync_v2
+#define cuMemcpyDtoHAsync cuMemcpyDtoHAsync_v2
+#define cuMemcpyDtoDAsync cuMemcpyDtoDAsync_v2
+#define cuMemcpy2DAsync cuMemcpy2DAsync_v2
+#define cuMemcpy3DAsync cuMemcpy3DAsync_v2
+#define cuMemsetD8 cuMemsetD8_v2
+#define cuMemsetD16 cuMemsetD16_v2
+#define cuMemsetD32 cuMemsetD32_v2
+#define cuMemsetD2D8 cuMemsetD2D8_v2
+#define cuMemsetD2D16 cuMemsetD2D16_v2
+#define cuMemsetD2D32 cuMemsetD2D32_v2
+#define cuArrayCreate cuArrayCreate_v2
+#define cuArrayGetDescriptor cuArrayGetDescriptor_v2
+#define cuArray3DCreate cuArray3DCreate_v2
+#define cuArray3DGetDescriptor cuArray3DGetDescriptor_v2
+#define cuTexRefSetAddress cuTexRefSetAddress_v2
+#define cuTexRefGetAddress cuTexRefGetAddress_v2
+#define cuGraphicsResourceGetMappedPointer cuGraphicsResourceGetMappedPointer_v2
+#define cuCtxDestroy cuCtxDestroy_v2
+#define cuCtxPopCurrent cuCtxPopCurrent_v2
+#define cuCtxPushCurrent cuCtxPushCurrent_v2
+#define cuStreamDestroy cuStreamDestroy_v2
+#define cuEventDestroy cuEventDestroy_v2
+#define cuTexRefSetAddress2D cuTexRefSetAddress2D_v2
+#define cuGLCtxCreate cuGLCtxCreate_v2
+#define cuGLMapBufferObject cuGLMapBufferObject_v2
+#define cuGLMapBufferObjectAsync cuGLMapBufferObjectAsync_v2
+
+/* Types. */
+#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64)
+typedef unsigned long long CUdeviceptr;
+#else
+typedef unsigned int CUdeviceptr;
+#endif
+
+typedef int CUdevice;
+typedef struct CUctx_st* CUcontext;
+typedef struct CUmod_st* CUmodule;
+typedef struct CUfunc_st* CUfunction;
+typedef struct CUarray_st* CUarray;
+typedef struct CUmipmappedArray_st* CUmipmappedArray;
+typedef struct CUtexref_st* CUtexref;
+typedef struct CUsurfref_st* CUsurfref;
+typedef struct CUevent_st* CUevent;
+typedef struct CUstream_st* CUstream;
+typedef struct CUgraphicsResource_st* CUgraphicsResource;
+typedef unsigned CUtexObject;
+typedef unsigned CUsurfObject;
+
+typedef struct CUuuid_st {
+ char bytes[16];
+} CUuuid;
+
+typedef struct CUipcEventHandle_st {
+ char reserved[CU_IPC_HANDLE_SIZE];
+} CUipcEventHandle;
+
+typedef struct CUipcMemHandle_st {
+ char reserved[CU_IPC_HANDLE_SIZE];
+} CUipcMemHandle;
+
+typedef enum CUipcMem_flags_enum {
+ CU_IPC_MEM_LAZY_ENABLE_PEER_ACCESS = 0x1,
+} CUipcMem_flags;
+
+typedef enum CUmemAttach_flags_enum {
+ CU_MEM_ATTACH_GLOBAL = 0x1,
+ CU_MEM_ATTACH_HOST = 0x2,
+ CU_MEM_ATTACH_SINGLE = 0x4,
+} CUmemAttach_flags;
+
+typedef enum CUctx_flags_enum {
+ CU_CTX_SCHED_AUTO = 0x00,
+ CU_CTX_SCHED_SPIN = 0x01,
+ CU_CTX_SCHED_YIELD = 0x02,
+ CU_CTX_SCHED_BLOCKING_SYNC = 0x04,
+ CU_CTX_BLOCKING_SYNC = 0x04,
+ CU_CTX_SCHED_MASK = 0x07,
+ CU_CTX_MAP_HOST = 0x08,
+ CU_CTX_LMEM_RESIZE_TO_MAX = 0x10,
+ CU_CTX_FLAGS_MASK = 0x1f,
+} CUctx_flags;
+
+typedef enum CUstream_flags_enum {
+ CU_STREAM_DEFAULT = 0x0,
+ CU_STREAM_NON_BLOCKING = 0x1,
+} CUstream_flags;
+
+typedef enum CUevent_flags_enum {
+ CU_EVENT_DEFAULT = 0x0,
+ CU_EVENT_BLOCKING_SYNC = 0x1,
+ CU_EVENT_DISABLE_TIMING = 0x2,
+ CU_EVENT_INTERPROCESS = 0x4,
+} CUevent_flags;
+
+typedef enum CUarray_format_enum {
+ CU_AD_FORMAT_UNSIGNED_INT8 = 0x01,
+ CU_AD_FORMAT_UNSIGNED_INT16 = 0x02,
+ CU_AD_FORMAT_UNSIGNED_INT32 = 0x03,
+ CU_AD_FORMAT_SIGNED_INT8 = 0x08,
+ CU_AD_FORMAT_SIGNED_INT16 = 0x09,
+ CU_AD_FORMAT_SIGNED_INT32 = 0x0a,
+ CU_AD_FORMAT_HALF = 0x10,
+ CU_AD_FORMAT_FLOAT = 0x20,
+} CUarray_format;
+
+typedef enum CUaddress_mode_enum {
+ CU_TR_ADDRESS_MODE_WRAP = 0,
+ CU_TR_ADDRESS_MODE_CLAMP = 1,
+ CU_TR_ADDRESS_MODE_MIRROR = 2,
+ CU_TR_ADDRESS_MODE_BORDER = 3,
+} CUaddress_mode;
+
+typedef enum CUfilter_mode_enum {
+ CU_TR_FILTER_MODE_POINT = 0,
+ CU_TR_FILTER_MODE_LINEAR = 1,
+} CUfilter_mode;
+
+typedef enum CUdevice_attribute_enum {
+ CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK = 1,
+ CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_X = 2,
+ CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_Y = 3,
+ CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_Z = 4,
+ CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_X = 5,
+ CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_Y = 6,
+ CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_Z = 7,
+ CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_BLOCK = 8,
+ CU_DEVICE_ATTRIBUTE_SHARED_MEMORY_PER_BLOCK = 8,
+ CU_DEVICE_ATTRIBUTE_TOTAL_CONSTANT_MEMORY = 9,
+ CU_DEVICE_ATTRIBUTE_WARP_SIZE = 10,
+ CU_DEVICE_ATTRIBUTE_MAX_PITCH = 11,
+ CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_BLOCK = 12,
+ CU_DEVICE_ATTRIBUTE_REGISTERS_PER_BLOCK = 12,
+ CU_DEVICE_ATTRIBUTE_CLOCK_RATE = 13,
+ CU_DEVICE_ATTRIBUTE_TEXTURE_ALIGNMENT = 14,
+ CU_DEVICE_ATTRIBUTE_GPU_OVERLAP = 15,
+ CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT = 16,
+ CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT = 17,
+ CU_DEVICE_ATTRIBUTE_INTEGRATED = 18,
+ CU_DEVICE_ATTRIBUTE_CAN_MAP_HOST_MEMORY = 19,
+ CU_DEVICE_ATTRIBUTE_COMPUTE_MODE = 20,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE1D_WIDTH = 21,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_WIDTH = 22,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_HEIGHT = 23,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_WIDTH = 24,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_HEIGHT = 25,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_DEPTH = 26,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_LAYERED_WIDTH = 27,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_LAYERED_HEIGHT = 28,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_LAYERED_LAYERS = 29,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_ARRAY_WIDTH = 27,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_ARRAY_HEIGHT = 28,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_ARRAY_NUMSLICES = 29,
+ CU_DEVICE_ATTRIBUTE_SURFACE_ALIGNMENT = 30,
+ CU_DEVICE_ATTRIBUTE_CONCURRENT_KERNELS = 31,
+ CU_DEVICE_ATTRIBUTE_ECC_ENABLED = 32,
+ CU_DEVICE_ATTRIBUTE_PCI_BUS_ID = 33,
+ CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID = 34,
+ CU_DEVICE_ATTRIBUTE_TCC_DRIVER = 35,
+ CU_DEVICE_ATTRIBUTE_MEMORY_CLOCK_RATE = 36,
+ CU_DEVICE_ATTRIBUTE_GLOBAL_MEMORY_BUS_WIDTH = 37,
+ CU_DEVICE_ATTRIBUTE_L2_CACHE_SIZE = 38,
+ CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_MULTIPROCESSOR = 39,
+ CU_DEVICE_ATTRIBUTE_ASYNC_ENGINE_COUNT = 40,
+ CU_DEVICE_ATTRIBUTE_UNIFIED_ADDRESSING = 41,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE1D_LAYERED_WIDTH = 42,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE1D_LAYERED_LAYERS = 43,
+ CU_DEVICE_ATTRIBUTE_CAN_TEX2D_GATHER = 44,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_GATHER_WIDTH = 45,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_GATHER_HEIGHT = 46,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_WIDTH_ALTERNATE = 47,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_HEIGHT_ALTERNATE = 48,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_DEPTH_ALTERNATE = 49,
+ CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID = 50,
+ CU_DEVICE_ATTRIBUTE_TEXTURE_PITCH_ALIGNMENT = 51,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURECUBEMAP_WIDTH = 52,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURECUBEMAP_LAYERED_WIDTH = 53,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURECUBEMAP_LAYERED_LAYERS = 54,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE1D_WIDTH = 55,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE2D_WIDTH = 56,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE2D_HEIGHT = 57,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE3D_WIDTH = 58,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE3D_HEIGHT = 59,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE3D_DEPTH = 60,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE1D_LAYERED_WIDTH = 61,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE1D_LAYERED_LAYERS = 62,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE2D_LAYERED_WIDTH = 63,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE2D_LAYERED_HEIGHT = 64,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACE2D_LAYERED_LAYERS = 65,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACECUBEMAP_WIDTH = 66,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACECUBEMAP_LAYERED_WIDTH = 67,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_SURFACECUBEMAP_LAYERED_LAYERS = 68,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE1D_LINEAR_WIDTH = 69,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_LINEAR_WIDTH = 70,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_LINEAR_HEIGHT = 71,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_LINEAR_PITCH = 72,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_MIPMAPPED_WIDTH = 73,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_MIPMAPPED_HEIGHT = 74,
+ CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR = 75,
+ CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR = 76,
+ CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE1D_MIPMAPPED_WIDTH = 77,
+ CU_DEVICE_ATTRIBUTE_STREAM_PRIORITIES_SUPPORTED = 78,
+ CU_DEVICE_ATTRIBUTE_GLOBAL_L1_CACHE_SUPPORTED = 79,
+ CU_DEVICE_ATTRIBUTE_LOCAL_L1_CACHE_SUPPORTED = 80,
+ CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_MULTIPROCESSOR = 81,
+ CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_MULTIPROCESSOR = 82,
+ 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_MAX,
+} CUdevice_attribute;
+
+typedef struct CUdevprop_st {
+ int maxThreadsPerBlock;
+ int maxThreadsDim[3];
+ int maxGridSize[3];
+ int sharedMemPerBlock;
+ int totalConstantMemory;
+ int SIMDWidth;
+ int memPitch;
+ int regsPerBlock;
+ int clockRate;
+ int textureAlign;
+} CUdevprop;
+
+typedef enum CUpointer_attribute_enum {
+ CU_POINTER_ATTRIBUTE_CONTEXT = 1,
+ CU_POINTER_ATTRIBUTE_MEMORY_TYPE = 2,
+ CU_POINTER_ATTRIBUTE_DEVICE_POINTER = 3,
+ CU_POINTER_ATTRIBUTE_HOST_POINTER = 4,
+ CU_POINTER_ATTRIBUTE_P2P_TOKENS = 5,
+ CU_POINTER_ATTRIBUTE_SYNC_MEMOPS = 6,
+ CU_POINTER_ATTRIBUTE_BUFFER_ID = 7,
+ CU_POINTER_ATTRIBUTE_IS_MANAGED = 8,
+} CUpointer_attribute;
+
+typedef enum CUfunction_attribute_enum {
+ CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK = 0,
+ CU_FUNC_ATTRIBUTE_SHARED_SIZE_BYTES = 1,
+ CU_FUNC_ATTRIBUTE_CONST_SIZE_BYTES = 2,
+ CU_FUNC_ATTRIBUTE_LOCAL_SIZE_BYTES = 3,
+ CU_FUNC_ATTRIBUTE_NUM_REGS = 4,
+ CU_FUNC_ATTRIBUTE_PTX_VERSION = 5,
+ CU_FUNC_ATTRIBUTE_BINARY_VERSION = 6,
+ CU_FUNC_ATTRIBUTE_CACHE_MODE_CA = 7,
+ CU_FUNC_ATTRIBUTE_MAX,
+} CUfunction_attribute;
+
+typedef enum CUfunc_cache_enum {
+ CU_FUNC_CACHE_PREFER_NONE = 0x00,
+ CU_FUNC_CACHE_PREFER_SHARED = 0x01,
+ CU_FUNC_CACHE_PREFER_L1 = 0x02,
+ CU_FUNC_CACHE_PREFER_EQUAL = 0x03,
+} CUfunc_cache;
+
+typedef enum CUsharedconfig_enum {
+ CU_SHARED_MEM_CONFIG_DEFAULT_BANK_SIZE = 0x00,
+ CU_SHARED_MEM_CONFIG_FOUR_BYTE_BANK_SIZE = 0x01,
+ CU_SHARED_MEM_CONFIG_EIGHT_BYTE_BANK_SIZE = 0x02,
+} CUsharedconfig;
+
+typedef enum CUmemorytype_enum {
+ CU_MEMORYTYPE_HOST = 0x01,
+ CU_MEMORYTYPE_DEVICE = 0x02,
+ CU_MEMORYTYPE_ARRAY = 0x03,
+ CU_MEMORYTYPE_UNIFIED = 0x04,
+} CUmemorytype;
+
+typedef enum CUcomputemode_enum {
+ CU_COMPUTEMODE_DEFAULT = 0,
+ CU_COMPUTEMODE_EXCLUSIVE = 1,
+ CU_COMPUTEMODE_PROHIBITED = 2,
+ CU_COMPUTEMODE_EXCLUSIVE_PROCESS = 3,
+} CUcomputemode;
+
+typedef enum CUjit_option_enum {
+ CU_JIT_MAX_REGISTERS = 0,
+ CU_JIT_THREADS_PER_BLOCK,
+ CU_JIT_WALL_TIME,
+ CU_JIT_INFO_LOG_BUFFER,
+ CU_JIT_INFO_LOG_BUFFER_SIZE_BYTES,
+ CU_JIT_ERROR_LOG_BUFFER,
+ CU_JIT_ERROR_LOG_BUFFER_SIZE_BYTES,
+ CU_JIT_OPTIMIZATION_LEVEL,
+ CU_JIT_TARGET_FROM_CUCONTEXT,
+ CU_JIT_TARGET,
+ CU_JIT_FALLBACK_STRATEGY,
+ CU_JIT_GENERATE_DEBUG_INFO,
+ CU_JIT_LOG_VERBOSE,
+ CU_JIT_GENERATE_LINE_INFO,
+ CU_JIT_CACHE_MODE,
+ CU_JIT_NUM_OPTIONS,
+} CUjit_option;
+
+typedef enum CUjit_target_enum {
+ CU_TARGET_COMPUTE_10 = 10,
+ CU_TARGET_COMPUTE_11 = 11,
+ CU_TARGET_COMPUTE_12 = 12,
+ CU_TARGET_COMPUTE_13 = 13,
+ CU_TARGET_COMPUTE_20 = 20,
+ CU_TARGET_COMPUTE_21 = 21,
+ CU_TARGET_COMPUTE_30 = 30,
+ CU_TARGET_COMPUTE_32 = 32,
+ CU_TARGET_COMPUTE_35 = 35,
+ CU_TARGET_COMPUTE_50 = 50,
+} CUjit_target;
+
+typedef enum CUjit_fallback_enum {
+ CU_PREFER_PTX = 0,
+ CU_PREFER_BINARY,
+} CUjit_fallback;
+
+typedef enum CUjit_cacheMode_enum {
+ CU_JIT_CACHE_OPTION_NONE = 0,
+ CU_JIT_CACHE_OPTION_CG,
+ CU_JIT_CACHE_OPTION_CA,
+} CUjit_cacheMode;
+
+typedef enum CUjitInputType_enum {
+ CU_JIT_INPUT_CUBIN = 0,
+ CU_JIT_INPUT_PTX,
+ CU_JIT_INPUT_FATBINARY,
+ CU_JIT_INPUT_OBJECT,
+ CU_JIT_INPUT_LIBRARY,
+ CU_JIT_NUM_INPUT_TYPES,
+} CUjitInputType;
+
+typedef struct CUlinkState_st* CUlinkState;
+
+typedef enum CUgraphicsRegisterFlags_enum {
+ CU_GRAPHICS_REGISTER_FLAGS_NONE = 0x00,
+ CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY = 0x01,
+ CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD = 0x02,
+ CU_GRAPHICS_REGISTER_FLAGS_SURFACE_LDST = 0x04,
+ CU_GRAPHICS_REGISTER_FLAGS_TEXTURE_GATHER = 0x08,
+} CUgraphicsRegisterFlags;
+
+typedef enum CUgraphicsMapResourceFlags_enum {
+ CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE = 0x00,
+ CU_GRAPHICS_MAP_RESOURCE_FLAGS_READ_ONLY = 0x01,
+ CU_GRAPHICS_MAP_RESOURCE_FLAGS_WRITE_DISCARD = 0x02,
+} CUgraphicsMapResourceFlags;
+
+typedef enum CUarray_cubemap_face_enum {
+ CU_CUBEMAP_FACE_POSITIVE_X = 0x00,
+ CU_CUBEMAP_FACE_NEGATIVE_X = 0x01,
+ CU_CUBEMAP_FACE_POSITIVE_Y = 0x02,
+ CU_CUBEMAP_FACE_NEGATIVE_Y = 0x03,
+ CU_CUBEMAP_FACE_POSITIVE_Z = 0x04,
+ CU_CUBEMAP_FACE_NEGATIVE_Z = 0x05,
+} CUarray_cubemap_face;
+
+typedef enum CUlimit_enum {
+ CU_LIMIT_STACK_SIZE = 0x00,
+ CU_LIMIT_PRINTF_FIFO_SIZE = 0x01,
+ CU_LIMIT_MALLOC_HEAP_SIZE = 0x02,
+ CU_LIMIT_DEV_RUNTIME_SYNC_DEPTH = 0x03,
+ CU_LIMIT_DEV_RUNTIME_PENDING_LAUNCH_COUNT = 0x04,
+ CU_LIMIT_MAX,
+} CUlimit;
+
+typedef enum CUresourcetype_enum {
+ CU_RESOURCE_TYPE_ARRAY = 0x00,
+ CU_RESOURCE_TYPE_MIPMAPPED_ARRAY = 0x01,
+ CU_RESOURCE_TYPE_LINEAR = 0x02,
+ CU_RESOURCE_TYPE_PITCH2D = 0x03,
+} CUresourcetype;
+
+typedef enum cudaError_enum {
+ CUDA_SUCCESS = 0,
+ CUDA_ERROR_INVALID_VALUE = 1,
+ CUDA_ERROR_OUT_OF_MEMORY = 2,
+ CUDA_ERROR_NOT_INITIALIZED = 3,
+ CUDA_ERROR_DEINITIALIZED = 4,
+ CUDA_ERROR_PROFILER_DISABLED = 5,
+ CUDA_ERROR_PROFILER_NOT_INITIALIZED = 6,
+ CUDA_ERROR_PROFILER_ALREADY_STARTED = 7,
+ CUDA_ERROR_PROFILER_ALREADY_STOPPED = 8,
+ CUDA_ERROR_NO_DEVICE = 100,
+ CUDA_ERROR_INVALID_DEVICE = 101,
+ CUDA_ERROR_INVALID_IMAGE = 200,
+ CUDA_ERROR_INVALID_CONTEXT = 201,
+ CUDA_ERROR_CONTEXT_ALREADY_CURRENT = 202,
+ CUDA_ERROR_MAP_FAILED = 205,
+ CUDA_ERROR_UNMAP_FAILED = 206,
+ CUDA_ERROR_ARRAY_IS_MAPPED = 207,
+ CUDA_ERROR_ALREADY_MAPPED = 208,
+ CUDA_ERROR_NO_BINARY_FOR_GPU = 209,
+ CUDA_ERROR_ALREADY_ACQUIRED = 210,
+ CUDA_ERROR_NOT_MAPPED = 211,
+ CUDA_ERROR_NOT_MAPPED_AS_ARRAY = 212,
+ CUDA_ERROR_NOT_MAPPED_AS_POINTER = 213,
+ CUDA_ERROR_ECC_UNCORRECTABLE = 214,
+ CUDA_ERROR_UNSUPPORTED_LIMIT = 215,
+ CUDA_ERROR_CONTEXT_ALREADY_IN_USE = 216,
+ CUDA_ERROR_PEER_ACCESS_UNSUPPORTED = 217,
+ CUDA_ERROR_INVALID_PTX = 218,
+ CUDA_ERROR_INVALID_SOURCE = 300,
+ CUDA_ERROR_FILE_NOT_FOUND = 301,
+ CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND = 302,
+ CUDA_ERROR_SHARED_OBJECT_INIT_FAILED = 303,
+ CUDA_ERROR_OPERATING_SYSTEM = 304,
+ CUDA_ERROR_INVALID_HANDLE = 400,
+ CUDA_ERROR_NOT_FOUND = 500,
+ CUDA_ERROR_NOT_READY = 600,
+ CUDA_ERROR_ILLEGAL_ADDRESS = 700,
+ CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES = 701,
+ CUDA_ERROR_LAUNCH_TIMEOUT = 702,
+ CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING = 703,
+ CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED = 704,
+ CUDA_ERROR_PEER_ACCESS_NOT_ENABLED = 705,
+ CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE = 708,
+ CUDA_ERROR_CONTEXT_IS_DESTROYED = 709,
+ CUDA_ERROR_ASSERT = 710,
+ CUDA_ERROR_TOO_MANY_PEERS = 711,
+ CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED = 712,
+ CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED = 713,
+ CUDA_ERROR_HARDWARE_STACK_ERROR = 714,
+ CUDA_ERROR_ILLEGAL_INSTRUCTION = 715,
+ CUDA_ERROR_MISALIGNED_ADDRESS = 716,
+ CUDA_ERROR_INVALID_ADDRESS_SPACE = 717,
+ CUDA_ERROR_INVALID_PC = 718,
+ CUDA_ERROR_LAUNCH_FAILED = 719,
+ CUDA_ERROR_NOT_PERMITTED = 800,
+ CUDA_ERROR_NOT_SUPPORTED = 801,
+ CUDA_ERROR_UNKNOWN = 999,
+} CUresult;
+
+typedef void* CUstreamCallback;
+
+typedef struct CUDA_MEMCPY2D_st {
+ size_t srcXInBytes;
+ size_t srcY;
+ CUmemorytype srcMemoryType;
+ const void* srcHost;
+ CUdeviceptr srcDevice;
+ CUarray srcArray;
+ size_t srcPitch;
+ size_t dstXInBytes;
+ size_t dstY;
+ CUmemorytype dstMemoryType;
+ void* dstHost;
+ CUdeviceptr dstDevice;
+ CUarray dstArray;
+ size_t dstPitch;
+ size_t WidthInBytes;
+ size_t Height;
+} CUDA_MEMCPY2D;
+
+typedef struct CUDA_MEMCPY3D_st {
+ size_t srcXInBytes;
+ size_t srcY;
+ size_t srcZ;
+ size_t srcLOD;
+ CUmemorytype srcMemoryType;
+ const void* srcHost;
+ CUdeviceptr srcDevice;
+ CUarray srcArray;
+ void* reserved0;
+ size_t srcPitch;
+ size_t srcHeight;
+ size_t dstXInBytes;
+ size_t dstY;
+ size_t dstZ;
+ size_t dstLOD;
+ CUmemorytype dstMemoryType;
+ void* dstHost;
+ CUdeviceptr dstDevice;
+ CUarray dstArray;
+ void* reserved1;
+ size_t dstPitch;
+ size_t dstHeight;
+ size_t WidthInBytes;
+ size_t Height;
+ size_t Depth;
+} CUDA_MEMCPY3D;
+
+typedef struct CUDA_MEMCPY3D_PEER_st {
+ size_t srcXInBytes;
+ size_t srcY;
+ size_t srcZ;
+ size_t srcLOD;
+ CUmemorytype srcMemoryType;
+ const void* srcHost;
+ CUdeviceptr srcDevice;
+ CUarray srcArray;
+ CUcontext srcContext;
+ size_t srcPitch;
+ size_t srcHeight;
+ size_t dstXInBytes;
+ size_t dstY;
+ size_t dstZ;
+ size_t dstLOD;
+ CUmemorytype dstMemoryType;
+ void* dstHost;
+ CUdeviceptr dstDevice;
+ CUarray dstArray;
+ CUcontext dstContext;
+ size_t dstPitch;
+ size_t dstHeight;
+ size_t WidthInBytes;
+ size_t Height;
+ size_t Depth;
+} CUDA_MEMCPY3D_PEER;
+
+typedef struct CUDA_ARRAY_DESCRIPTOR_st {
+ size_t Width;
+ size_t Height;
+ CUarray_format Format;
+ unsigned NumChannels;
+} CUDA_ARRAY_DESCRIPTOR;
+
+typedef struct CUDA_ARRAY3D_DESCRIPTOR_st {
+ size_t Width;
+ size_t Height;
+ size_t Depth;
+ CUarray_format Format;
+ unsigned NumChannels;
+ unsigned Flags;
+} CUDA_ARRAY3D_DESCRIPTOR;
+
+typedef struct CUDA_RESOURCE_DESC_st {
+ CUresourcetype resType;
+ union {
+ struct {
+ CUarray hArray;
+ } array;
+ struct {
+ CUmipmappedArray hMipmappedArray;
+ } mipmap;
+ struct {
+ CUdeviceptr devPtr;
+ CUarray_format format;
+ unsigned numChannels;
+ size_t sizeInBytes;
+ } linear;
+ struct {
+ CUdeviceptr devPtr;
+ CUarray_format format;
+ unsigned numChannels;
+ size_t width;
+ size_t height;
+ size_t pitchInBytes;
+ } pitch2D;
+ struct {
+ int reserved[32];
+ } reserved;
+ } res;
+ unsigned flags;
+} CUDA_RESOURCE_DESC;
+
+typedef struct CUDA_TEXTURE_DESC_st {
+ CUaddress_mode addressMode[3];
+ CUfilter_mode filterMode;
+ unsigned flags;
+ unsigned maxAnisotropy;
+ CUfilter_mode mipmapFilterMode;
+ float mipmapLevelBias;
+ float minMipmapLevelClamp;
+ float maxMipmapLevelClamp;
+ int reserved[16];
+} CUDA_TEXTURE_DESC;
+
+typedef enum CUresourceViewFormat_enum {
+ CU_RES_VIEW_FORMAT_NONE = 0x00,
+ CU_RES_VIEW_FORMAT_UINT_1X8 = 0x01,
+ CU_RES_VIEW_FORMAT_UINT_2X8 = 0x02,
+ CU_RES_VIEW_FORMAT_UINT_4X8 = 0x03,
+ CU_RES_VIEW_FORMAT_SINT_1X8 = 0x04,
+ CU_RES_VIEW_FORMAT_SINT_2X8 = 0x05,
+ CU_RES_VIEW_FORMAT_SINT_4X8 = 0x06,
+ CU_RES_VIEW_FORMAT_UINT_1X16 = 0x07,
+ CU_RES_VIEW_FORMAT_UINT_2X16 = 0x08,
+ CU_RES_VIEW_FORMAT_UINT_4X16 = 0x09,
+ CU_RES_VIEW_FORMAT_SINT_1X16 = 0x0a,
+ CU_RES_VIEW_FORMAT_SINT_2X16 = 0x0b,
+ CU_RES_VIEW_FORMAT_SINT_4X16 = 0x0c,
+ CU_RES_VIEW_FORMAT_UINT_1X32 = 0x0d,
+ CU_RES_VIEW_FORMAT_UINT_2X32 = 0x0e,
+ CU_RES_VIEW_FORMAT_UINT_4X32 = 0x0f,
+ CU_RES_VIEW_FORMAT_SINT_1X32 = 0x10,
+ CU_RES_VIEW_FORMAT_SINT_2X32 = 0x11,
+ CU_RES_VIEW_FORMAT_SINT_4X32 = 0x12,
+ CU_RES_VIEW_FORMAT_FLOAT_1X16 = 0x13,
+ CU_RES_VIEW_FORMAT_FLOAT_2X16 = 0x14,
+ CU_RES_VIEW_FORMAT_FLOAT_4X16 = 0x15,
+ CU_RES_VIEW_FORMAT_FLOAT_1X32 = 0x16,
+ CU_RES_VIEW_FORMAT_FLOAT_2X32 = 0x17,
+ CU_RES_VIEW_FORMAT_FLOAT_4X32 = 0x18,
+ CU_RES_VIEW_FORMAT_UNSIGNED_BC1 = 0x19,
+ CU_RES_VIEW_FORMAT_UNSIGNED_BC2 = 0x1a,
+ CU_RES_VIEW_FORMAT_UNSIGNED_BC3 = 0x1b,
+ CU_RES_VIEW_FORMAT_UNSIGNED_BC4 = 0x1c,
+ CU_RES_VIEW_FORMAT_SIGNED_BC4 = 0x1d,
+ CU_RES_VIEW_FORMAT_UNSIGNED_BC5 = 0x1e,
+ CU_RES_VIEW_FORMAT_SIGNED_BC5 = 0x1f,
+ CU_RES_VIEW_FORMAT_UNSIGNED_BC6H = 0x20,
+ CU_RES_VIEW_FORMAT_SIGNED_BC6H = 0x21,
+ CU_RES_VIEW_FORMAT_UNSIGNED_BC7 = 0x22,
+} CUresourceViewFormat;
+
+typedef struct CUDA_RESOURCE_VIEW_DESC_st {
+ CUresourceViewFormat format;
+ size_t width;
+ size_t height;
+ size_t depth;
+ unsigned firstMipmapLevel;
+ unsigned lastMipmapLevel;
+ unsigned firstLayer;
+ unsigned lastLayer;
+ unsigned reserved[16];
+} CUDA_RESOURCE_VIEW_DESC;
+
+typedef struct CUDA_POINTER_ATTRIBUTE_P2P_TOKENS_st {
+ unsigned p2pToken;
+ unsigned vaSpaceToken;
+} CUDA_POINTER_ATTRIBUTE_P2P_TOKENS;
+typedef unsigned GLenum;
+typedef unsigned GLuint;
+typedef int GLint;
+
+typedef enum CUGLDeviceList_enum {
+ CU_GL_DEVICE_LIST_ALL = 0x01,
+ CU_GL_DEVICE_LIST_CURRENT_FRAME = 0x02,
+ CU_GL_DEVICE_LIST_NEXT_FRAME = 0x03,
+} CUGLDeviceList;
+
+typedef enum CUGLmap_flags_enum {
+ CU_GL_MAP_RESOURCE_FLAGS_NONE = 0x00,
+ CU_GL_MAP_RESOURCE_FLAGS_READ_ONLY = 0x01,
+ CU_GL_MAP_RESOURCE_FLAGS_WRITE_DISCARD = 0x02,
+} CUGLmap_flags;
+
+#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 tcuInit(unsigned Flags);
+typedef CUresult CUDAAPI tcuDriverGetVersion(int* driverVersion);
+typedef CUresult CUDAAPI tcuDeviceGet(CUdevice* device, int ordinal);
+typedef CUresult CUDAAPI tcuDeviceGetCount(int* count);
+typedef CUresult CUDAAPI tcuDeviceGetName(char* name, int len, CUdevice dev);
+typedef CUresult CUDAAPI tcuDeviceTotalMem_v2(size_t* bytes, CUdevice dev);
+typedef CUresult CUDAAPI tcuDeviceGetAttribute(int* pi, CUdevice_attribute attrib, CUdevice dev);
+typedef CUresult CUDAAPI tcuDeviceGetProperties(CUdevprop* prop, CUdevice dev);
+typedef CUresult CUDAAPI tcuDeviceComputeCapability(int* major, int* minor, CUdevice dev);
+typedef CUresult CUDAAPI tcuCtxCreate_v2(CUcontext* pctx, unsigned flags, CUdevice dev);
+typedef CUresult CUDAAPI tcuCtxDestroy_v2(CUcontext ctx);
+typedef CUresult CUDAAPI tcuCtxPushCurrent_v2(CUcontext ctx);
+typedef CUresult CUDAAPI tcuCtxPopCurrent_v2(CUcontext* pctx);
+typedef CUresult CUDAAPI tcuCtxSetCurrent(CUcontext ctx);
+typedef CUresult CUDAAPI tcuCtxGetCurrent(CUcontext* pctx);
+typedef CUresult CUDAAPI tcuCtxGetDevice(CUdevice* device);
+typedef CUresult CUDAAPI tcuCtxSynchronize(void);
+typedef CUresult CUDAAPI tcuCtxSetLimit(CUlimit limit, size_t value);
+typedef CUresult CUDAAPI tcuCtxGetLimit(size_t* pvalue, CUlimit limit);
+typedef CUresult CUDAAPI tcuCtxGetCacheConfig(CUfunc_cache* pconfig);
+typedef CUresult CUDAAPI tcuCtxSetCacheConfig(CUfunc_cache config);
+typedef CUresult CUDAAPI tcuCtxGetSharedMemConfig(CUsharedconfig* pConfig);
+typedef CUresult CUDAAPI tcuCtxSetSharedMemConfig(CUsharedconfig config);
+typedef CUresult CUDAAPI tcuCtxGetApiVersion(CUcontext ctx, unsigned* version);
+typedef CUresult CUDAAPI tcuCtxGetStreamPriorityRange(int* leastPriority, int* greatestPriority);
+typedef CUresult CUDAAPI tcuCtxAttach(CUcontext* pctx, unsigned 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 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(unsigned numOptions, CUjit_option* options, void* optionValues, CUlinkState* stateOut);
+typedef CUresult CUDAAPI tcuLinkAddData(CUlinkState state, CUjitInputType type, void* data, size_t size, const char* name, unsigned numOptions, CUjit_option* options, void* optionValues);
+typedef CUresult CUDAAPI tcuLinkAddFile(CUlinkState state, CUjitInputType type, const char* path, unsigned 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 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 tcuMemFreeHost(void* p);
+typedef CUresult CUDAAPI tcuMemHostAlloc(void* pp, size_t bytesize, unsigned Flags);
+typedef CUresult CUDAAPI tcuMemHostGetDevicePointer_v2(CUdeviceptr* pdptr, void* p, unsigned Flags);
+typedef CUresult CUDAAPI tcuMemHostGetFlags(unsigned* pFlags, void* p);
+typedef CUresult CUDAAPI tcuMemAllocManaged(CUdeviceptr* dptr, size_t bytesize, unsigned flags);
+typedef CUresult CUDAAPI tcuDeviceGetByPCIBusId(CUdevice* dev, const char* pciBusId);
+typedef CUresult CUDAAPI tcuDeviceGetPCIBusId(char* pciBusId, int len, CUdevice dev);
+typedef CUresult CUDAAPI tcuIpcGetEventHandle(CUipcEventHandle* pHandle, CUevent event);
+typedef CUresult CUDAAPI tcuIpcOpenEventHandle(CUevent* phEvent, CUipcEventHandle handle);
+typedef CUresult CUDAAPI tcuIpcGetMemHandle(CUipcMemHandle* pHandle, CUdeviceptr dptr);
+typedef CUresult CUDAAPI tcuIpcOpenMemHandle(CUdeviceptr* pdptr, CUipcMemHandle handle, unsigned Flags);
+typedef CUresult CUDAAPI tcuIpcCloseMemHandle(CUdeviceptr dptr);
+typedef CUresult CUDAAPI tcuMemHostRegister(void* p, size_t bytesize, unsigned Flags);
+typedef CUresult CUDAAPI tcuMemHostUnregister(void* p);
+typedef CUresult CUDAAPI tcuMemcpy(CUdeviceptr dst, CUdeviceptr src, size_t ByteCount);
+typedef CUresult CUDAAPI tcuMemcpyPeer(CUdeviceptr dstDevice, CUcontext dstContext, CUdeviceptr srcDevice, CUcontext srcContext, size_t ByteCount);
+typedef CUresult CUDAAPI tcuMemcpyHtoD_v2(CUdeviceptr dstDevice, const void* srcHost, size_t ByteCount);
+typedef CUresult CUDAAPI tcuMemcpyDtoH_v2(void* dstHost, CUdeviceptr srcDevice, size_t ByteCount);
+typedef CUresult CUDAAPI tcuMemcpyDtoD_v2(CUdeviceptr dstDevice, CUdeviceptr srcDevice, size_t ByteCount);
+typedef CUresult CUDAAPI tcuMemcpyDtoA_v2(CUarray dstArray, size_t dstOffset, CUdeviceptr srcDevice, size_t ByteCount);
+typedef CUresult CUDAAPI tcuMemcpyAtoD_v2(CUdeviceptr dstDevice, CUarray srcArray, size_t srcOffset, size_t ByteCount);
+typedef CUresult CUDAAPI tcuMemcpyHtoA_v2(CUarray dstArray, size_t dstOffset, const void* srcHost, size_t ByteCount);
+typedef CUresult CUDAAPI tcuMemcpyAtoH_v2(void* dstHost, CUarray srcArray, size_t srcOffset, size_t ByteCount);
+typedef CUresult CUDAAPI tcuMemcpyAtoA_v2(CUarray dstArray, size_t dstOffset, CUarray srcArray, size_t srcOffset, size_t ByteCount);
+typedef CUresult CUDAAPI tcuMemcpy2D_v2(const CUDA_MEMCPY2D* pCopy);
+typedef CUresult CUDAAPI tcuMemcpy2DUnaligned_v2(const CUDA_MEMCPY2D* pCopy);
+typedef CUresult CUDAAPI tcuMemcpy3D_v2(const CUDA_MEMCPY3D* pCopy);
+typedef CUresult CUDAAPI tcuMemcpy3DPeer(const CUDA_MEMCPY3D_PEER* pCopy);
+typedef CUresult CUDAAPI tcuMemcpyAsync(CUdeviceptr dst, CUdeviceptr src, size_t ByteCount, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemcpyPeerAsync(CUdeviceptr dstDevice, CUcontext dstContext, CUdeviceptr srcDevice, CUcontext srcContext, size_t ByteCount, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemcpyHtoDAsync_v2(CUdeviceptr dstDevice, const void* srcHost, size_t ByteCount, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemcpyDtoHAsync_v2(void* dstHost, CUdeviceptr srcDevice, size_t ByteCount, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemcpyDtoDAsync_v2(CUdeviceptr dstDevice, CUdeviceptr srcDevice, size_t ByteCount, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemcpyHtoAAsync_v2(CUarray dstArray, size_t dstOffset, const void* srcHost, size_t ByteCount, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemcpyAtoHAsync_v2(void* dstHost, CUarray srcArray, size_t srcOffset, size_t ByteCount, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemcpy2DAsync_v2(const CUDA_MEMCPY2D* pCopy, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemcpy3DAsync_v2(const CUDA_MEMCPY3D* pCopy, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemcpy3DPeerAsync(const CUDA_MEMCPY3D_PEER* pCopy, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemsetD8_v2(CUdeviceptr dstDevice, unsigned uc, size_t N);
+typedef CUresult CUDAAPI tcuMemsetD16_v2(CUdeviceptr dstDevice, unsigned us, size_t N);
+typedef CUresult CUDAAPI tcuMemsetD32_v2(CUdeviceptr dstDevice, unsigned ui, size_t N);
+typedef CUresult CUDAAPI tcuMemsetD2D8_v2(CUdeviceptr dstDevice, size_t dstPitch, unsigned uc, size_t Width, size_t Height);
+typedef CUresult CUDAAPI tcuMemsetD2D16_v2(CUdeviceptr dstDevice, size_t dstPitch, unsigned us, size_t Width, size_t Height);
+typedef CUresult CUDAAPI tcuMemsetD2D32_v2(CUdeviceptr dstDevice, size_t dstPitch, unsigned ui, size_t Width, size_t Height);
+typedef CUresult CUDAAPI tcuMemsetD8Async(CUdeviceptr dstDevice, unsigned uc, size_t N, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemsetD16Async(CUdeviceptr dstDevice, unsigned us, size_t N, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemsetD32Async(CUdeviceptr dstDevice, unsigned ui, size_t N, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemsetD2D8Async(CUdeviceptr dstDevice, size_t dstPitch, unsigned uc, size_t Width, size_t Height, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemsetD2D16Async(CUdeviceptr dstDevice, size_t dstPitch, unsigned us, size_t Width, size_t Height, CUstream hStream);
+typedef CUresult CUDAAPI tcuMemsetD2D32Async(CUdeviceptr dstDevice, size_t dstPitch, unsigned ui, size_t Width, size_t Height, CUstream hStream);
+typedef CUresult CUDAAPI tcuArrayCreate_v2(CUarray* pHandle, const CUDA_ARRAY_DESCRIPTOR* pAllocateArray);
+typedef CUresult CUDAAPI tcuArrayGetDescriptor_v2(CUDA_ARRAY_DESCRIPTOR* pArrayDescriptor, CUarray hArray);
+typedef CUresult CUDAAPI tcuArrayDestroy(CUarray hArray);
+typedef CUresult CUDAAPI tcuArray3DCreate_v2(CUarray* pHandle, const CUDA_ARRAY3D_DESCRIPTOR* pAllocateArray);
+typedef CUresult CUDAAPI tcuArray3DGetDescriptor_v2(CUDA_ARRAY3D_DESCRIPTOR* pArrayDescriptor, CUarray hArray);
+typedef CUresult CUDAAPI tcuMipmappedArrayCreate(CUmipmappedArray* pHandle, const CUDA_ARRAY3D_DESCRIPTOR* pMipmappedArrayDesc, unsigned numMipmapLevels);
+typedef CUresult CUDAAPI tcuMipmappedArrayGetLevel(CUarray* pLevelArray, CUmipmappedArray hMipmappedArray, unsigned level);
+typedef CUresult CUDAAPI tcuMipmappedArrayDestroy(CUmipmappedArray hMipmappedArray);
+typedef CUresult CUDAAPI tcuPointerGetAttribute(void* data, CUpointer_attribute attribute, CUdeviceptr ptr);
+typedef CUresult CUDAAPI tcuPointerSetAttribute(const void* value, CUpointer_attribute attribute, CUdeviceptr ptr);
+typedef CUresult CUDAAPI tcuStreamCreate(CUstream* phStream, unsigned Flags);
+typedef CUresult CUDAAPI tcuStreamCreateWithPriority(CUstream* phStream, unsigned flags, int priority);
+typedef CUresult CUDAAPI tcuStreamGetPriority(CUstream hStream, int* priority);
+typedef CUresult CUDAAPI tcuStreamGetFlags(CUstream hStream, unsigned* flags);
+typedef CUresult CUDAAPI tcuStreamWaitEvent(CUstream hStream, CUevent hEvent, unsigned Flags);
+typedef CUresult CUDAAPI tcuStreamAddCallback(CUstream hStream, CUstreamCallback callback, void* userData, unsigned flags);
+typedef CUresult CUDAAPI tcuStreamAttachMemAsync(CUstream hStream, CUdeviceptr dptr, size_t length, unsigned flags);
+typedef CUresult CUDAAPI tcuStreamQuery(CUstream hStream);
+typedef CUresult CUDAAPI tcuStreamSynchronize(CUstream hStream);
+typedef CUresult CUDAAPI tcuStreamDestroy_v2(CUstream hStream);
+typedef CUresult CUDAAPI tcuEventCreate(CUevent* phEvent, unsigned Flags);
+typedef CUresult CUDAAPI tcuEventRecord(CUevent hEvent, CUstream hStream);
+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 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 gridDimX, unsigned gridDimY, unsigned gridDimZ, unsigned blockDimX, unsigned blockDimY, unsigned blockDimZ, unsigned 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 bytes);
+typedef CUresult CUDAAPI tcuParamSetSize(CUfunction hfunc, unsigned numbytes);
+typedef CUresult CUDAAPI tcuParamSeti(CUfunction hfunc, int offset, unsigned value);
+typedef CUresult CUDAAPI tcuParamSetf(CUfunction hfunc, int offset, float value);
+typedef CUresult CUDAAPI tcuParamSetv(CUfunction hfunc, int offset, void* ptr, unsigned numbytes);
+typedef CUresult CUDAAPI tcuLaunch(CUfunction f);
+typedef CUresult CUDAAPI tcuLaunchGrid(CUfunction f, int grid_width, int grid_height);
+typedef CUresult CUDAAPI tcuLaunchGridAsync(CUfunction f, int grid_width, int grid_height, CUstream hStream);
+typedef CUresult CUDAAPI tcuParamSetTexRef(CUfunction hfunc, int texunit, CUtexref hTexRef);
+typedef CUresult CUDAAPI tcuTexRefSetArray(CUtexref hTexRef, CUarray hArray, unsigned Flags);
+typedef CUresult CUDAAPI tcuTexRefSetMipmappedArray(CUtexref hTexRef, CUmipmappedArray hMipmappedArray, unsigned Flags);
+typedef CUresult CUDAAPI tcuTexRefSetAddress_v2(size_t* ByteOffset, CUtexref hTexRef, CUdeviceptr dptr, size_t bytes);
+typedef CUresult CUDAAPI tcuTexRefSetAddress2D_v3(CUtexref hTexRef, const CUDA_ARRAY_DESCRIPTOR* desc, CUdeviceptr dptr, size_t Pitch);
+typedef CUresult CUDAAPI tcuTexRefSetFormat(CUtexref hTexRef, CUarray_format fmt, int NumPackedComponents);
+typedef CUresult CUDAAPI tcuTexRefSetAddressMode(CUtexref hTexRef, int dim, CUaddress_mode am);
+typedef CUresult CUDAAPI tcuTexRefSetFilterMode(CUtexref hTexRef, CUfilter_mode fm);
+typedef CUresult CUDAAPI tcuTexRefSetMipmapFilterMode(CUtexref hTexRef, CUfilter_mode fm);
+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 maxAniso);
+typedef CUresult CUDAAPI tcuTexRefSetFlags(CUtexref hTexRef, unsigned Flags);
+typedef CUresult CUDAAPI tcuTexRefGetAddress_v2(CUdeviceptr* pdptr, CUtexref hTexRef);
+typedef CUresult CUDAAPI tcuTexRefGetArray(CUarray* phArray, CUtexref hTexRef);
+typedef CUresult CUDAAPI tcuTexRefGetMipmappedArray(CUmipmappedArray* phMipmappedArray, CUtexref hTexRef);
+typedef CUresult CUDAAPI tcuTexRefGetAddressMode(CUaddress_mode* pam, CUtexref hTexRef, int dim);
+typedef CUresult CUDAAPI tcuTexRefGetFilterMode(CUfilter_mode* pfm, CUtexref hTexRef);
+typedef CUresult CUDAAPI tcuTexRefGetFormat(CUarray_format* pFormat, int* pNumChannels, CUtexref hTexRef);
+typedef CUresult CUDAAPI tcuTexRefGetMipmapFilterMode(CUfilter_mode* pfm, CUtexref hTexRef);
+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 tcuTexRefGetFlags(unsigned* pFlags, CUtexref hTexRef);
+typedef CUresult CUDAAPI tcuTexRefCreate(CUtexref* pTexRef);
+typedef CUresult CUDAAPI tcuTexRefDestroy(CUtexref hTexRef);
+typedef CUresult CUDAAPI tcuSurfRefSetArray(CUsurfref hSurfRef, CUarray hArray, unsigned Flags);
+typedef CUresult CUDAAPI tcuSurfRefGetArray(CUarray* phArray, CUsurfref hSurfRef);
+typedef CUresult CUDAAPI tcuTexObjectCreate(CUtexObject* pTexObject, const CUDA_RESOURCE_DESC* pResDesc, const CUDA_TEXTURE_DESC* pTexDesc, const CUDA_RESOURCE_VIEW_DESC* pResViewDesc);
+typedef CUresult CUDAAPI tcuTexObjectDestroy(CUtexObject texObject);
+typedef CUresult CUDAAPI tcuTexObjectGetResourceDesc(CUDA_RESOURCE_DESC* pResDesc, CUtexObject texObject);
+typedef CUresult CUDAAPI tcuTexObjectGetTextureDesc(CUDA_TEXTURE_DESC* pTexDesc, CUtexObject texObject);
+typedef CUresult CUDAAPI tcuTexObjectGetResourceViewDesc(CUDA_RESOURCE_VIEW_DESC* pResViewDesc, CUtexObject texObject);
+typedef CUresult CUDAAPI tcuSurfObjectCreate(CUsurfObject* pSurfObject, const CUDA_RESOURCE_DESC* pResDesc);
+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 tcuCtxEnablePeerAccess(CUcontext peerContext, unsigned Flags);
+typedef CUresult CUDAAPI tcuCtxDisablePeerAccess(CUcontext peerContext);
+typedef CUresult CUDAAPI tcuGraphicsUnregisterResource(CUgraphicsResource resource);
+typedef CUresult CUDAAPI tcuGraphicsSubResourceGetMappedArray(CUarray* pArray, CUgraphicsResource resource, unsigned arrayIndex, unsigned mipLevel);
+typedef CUresult CUDAAPI tcuGraphicsResourceGetMappedMipmappedArray(CUmipmappedArray* pMipmappedArray, CUgraphicsResource resource);
+typedef CUresult CUDAAPI tcuGraphicsResourceGetMappedPointer_v2(CUdeviceptr* pDevPtr, size_t* pSize, CUgraphicsResource resource);
+typedef CUresult CUDAAPI tcuGraphicsResourceSetMapFlags(CUgraphicsResource resource, unsigned flags);
+typedef CUresult CUDAAPI tcuGraphicsMapResources(unsigned count, CUgraphicsResource* resources, CUstream hStream);
+typedef CUresult CUDAAPI tcuGraphicsUnmapResources(unsigned count, CUgraphicsResource* resources, CUstream hStream);
+typedef CUresult CUDAAPI tcuGetExportTable(const void* ppExportTable, const CUuuid* pExportTableId);
+
+typedef CUresult CUDAAPI tcuGraphicsGLRegisterBuffer(CUgraphicsResource* pCudaResource, GLuint buffer, unsigned Flags);
+typedef CUresult CUDAAPI tcuGraphicsGLRegisterImage(CUgraphicsResource* pCudaResource, GLuint image, GLenum target, unsigned Flags);
+typedef CUresult CUDAAPI tcuGLGetDevices(unsigned* pCudaDeviceCount, CUdevice* pCudaDevices, unsigned cudaDeviceCount, CUGLDeviceList deviceList);
+typedef CUresult CUDAAPI tcuGLCtxCreate_v2(CUcontext* pCtx, unsigned Flags, CUdevice device);
+typedef CUresult CUDAAPI tcuGLInit(void);
+typedef CUresult CUDAAPI tcuGLRegisterBufferObject(GLuint buffer);
+typedef CUresult CUDAAPI tcuGLMapBufferObject_v2(CUdeviceptr* dptr, size_t* size, GLuint buffer);
+typedef CUresult CUDAAPI tcuGLUnmapBufferObject(GLuint buffer);
+typedef CUresult CUDAAPI tcuGLUnregisterBufferObject(GLuint buffer);
+typedef CUresult CUDAAPI tcuGLSetBufferObjectMapFlags(GLuint buffer, unsigned Flags);
+typedef CUresult CUDAAPI tcuGLMapBufferObjectAsync_v2(CUdeviceptr* dptr, size_t* size, GLuint buffer, CUstream hStream);
+typedef CUresult CUDAAPI tcuGLUnmapBufferObjectAsync(GLuint buffer, CUstream hStream);
+
+
+/* Function declarations. */
+extern tcuGetErrorString *cuGetErrorString;
+extern tcuGetErrorName *cuGetErrorName;
+extern tcuInit *cuInit;
+extern tcuDriverGetVersion *cuDriverGetVersion;
+extern tcuDeviceGet *cuDeviceGet;
+extern tcuDeviceGetCount *cuDeviceGetCount;
+extern tcuDeviceGetName *cuDeviceGetName;
+extern tcuDeviceTotalMem_v2 *cuDeviceTotalMem_v2;
+extern tcuDeviceGetAttribute *cuDeviceGetAttribute;
+extern tcuDeviceGetProperties *cuDeviceGetProperties;
+extern tcuDeviceComputeCapability *cuDeviceComputeCapability;
+extern tcuCtxCreate_v2 *cuCtxCreate_v2;
+extern tcuCtxDestroy_v2 *cuCtxDestroy_v2;
+extern tcuCtxPushCurrent_v2 *cuCtxPushCurrent_v2;
+extern tcuCtxPopCurrent_v2 *cuCtxPopCurrent_v2;
+extern tcuCtxSetCurrent *cuCtxSetCurrent;
+extern tcuCtxGetCurrent *cuCtxGetCurrent;
+extern tcuCtxGetDevice *cuCtxGetDevice;
+extern tcuCtxSynchronize *cuCtxSynchronize;
+extern tcuCtxSetLimit *cuCtxSetLimit;
+extern tcuCtxGetLimit *cuCtxGetLimit;
+extern tcuCtxGetCacheConfig *cuCtxGetCacheConfig;
+extern tcuCtxSetCacheConfig *cuCtxSetCacheConfig;
+extern tcuCtxGetSharedMemConfig *cuCtxGetSharedMemConfig;
+extern tcuCtxSetSharedMemConfig *cuCtxSetSharedMemConfig;
+extern tcuCtxGetApiVersion *cuCtxGetApiVersion;
+extern tcuCtxGetStreamPriorityRange *cuCtxGetStreamPriorityRange;
+extern tcuCtxAttach *cuCtxAttach;
+extern tcuCtxDetach *cuCtxDetach;
+extern tcuModuleLoad *cuModuleLoad;
+extern tcuModuleLoadData *cuModuleLoadData;
+extern tcuModuleLoadDataEx *cuModuleLoadDataEx;
+extern tcuModuleLoadFatBinary *cuModuleLoadFatBinary;
+extern tcuModuleUnload *cuModuleUnload;
+extern tcuModuleGetFunction *cuModuleGetFunction;
+extern tcuModuleGetGlobal_v2 *cuModuleGetGlobal_v2;
+extern tcuModuleGetTexRef *cuModuleGetTexRef;
+extern tcuModuleGetSurfRef *cuModuleGetSurfRef;
+extern tcuLinkCreate *cuLinkCreate;
+extern tcuLinkAddData *cuLinkAddData;
+extern tcuLinkAddFile *cuLinkAddFile;
+extern tcuLinkComplete *cuLinkComplete;
+extern tcuLinkDestroy *cuLinkDestroy;
+extern tcuMemGetInfo_v2 *cuMemGetInfo_v2;
+extern tcuMemAlloc_v2 *cuMemAlloc_v2;
+extern tcuMemAllocPitch_v2 *cuMemAllocPitch_v2;
+extern tcuMemFree_v2 *cuMemFree_v2;
+extern tcuMemGetAddressRange_v2 *cuMemGetAddressRange_v2;
+extern tcuMemAllocHost_v2 *cuMemAllocHost_v2;
+extern tcuMemFreeHost *cuMemFreeHost;
+extern tcuMemHostAlloc *cuMemHostAlloc;
+extern tcuMemHostGetDevicePointer_v2 *cuMemHostGetDevicePointer_v2;
+extern tcuMemHostGetFlags *cuMemHostGetFlags;
+extern tcuMemAllocManaged *cuMemAllocManaged;
+extern tcuDeviceGetByPCIBusId *cuDeviceGetByPCIBusId;
+extern tcuDeviceGetPCIBusId *cuDeviceGetPCIBusId;
+extern tcuIpcGetEventHandle *cuIpcGetEventHandle;
+extern tcuIpcOpenEventHandle *cuIpcOpenEventHandle;
+extern tcuIpcGetMemHandle *cuIpcGetMemHandle;
+extern tcuIpcOpenMemHandle *cuIpcOpenMemHandle;
+extern tcuIpcCloseMemHandle *cuIpcCloseMemHandle;
+extern tcuMemHostRegister *cuMemHostRegister;
+extern tcuMemHostUnregister *cuMemHostUnregister;
+extern tcuMemcpy *cuMemcpy;
+extern tcuMemcpyPeer *cuMemcpyPeer;
+extern tcuMemcpyHtoD_v2 *cuMemcpyHtoD_v2;
+extern tcuMemcpyDtoH_v2 *cuMemcpyDtoH_v2;
+extern tcuMemcpyDtoD_v2 *cuMemcpyDtoD_v2;
+extern tcuMemcpyDtoA_v2 *cuMemcpyDtoA_v2;
+extern tcuMemcpyAtoD_v2 *cuMemcpyAtoD_v2;
+extern tcuMemcpyHtoA_v2 *cuMemcpyHtoA_v2;
+extern tcuMemcpyAtoH_v2 *cuMemcpyAtoH_v2;
+extern tcuMemcpyAtoA_v2 *cuMemcpyAtoA_v2;
+extern tcuMemcpy2D_v2 *cuMemcpy2D_v2;
+extern tcuMemcpy2DUnaligned_v2 *cuMemcpy2DUnaligned_v2;
+extern tcuMemcpy3D_v2 *cuMemcpy3D_v2;
+extern tcuMemcpy3DPeer *cuMemcpy3DPeer;
+extern tcuMemcpyAsync *cuMemcpyAsync;
+extern tcuMemcpyPeerAsync *cuMemcpyPeerAsync;
+extern tcuMemcpyHtoDAsync_v2 *cuMemcpyHtoDAsync_v2;
+extern tcuMemcpyDtoHAsync_v2 *cuMemcpyDtoHAsync_v2;
+extern tcuMemcpyDtoDAsync_v2 *cuMemcpyDtoDAsync_v2;
+extern tcuMemcpyHtoAAsync_v2 *cuMemcpyHtoAAsync_v2;
+extern tcuMemcpyAtoHAsync_v2 *cuMemcpyAtoHAsync_v2;
+extern tcuMemcpy2DAsync_v2 *cuMemcpy2DAsync_v2;
+extern tcuMemcpy3DAsync_v2 *cuMemcpy3DAsync_v2;
+extern tcuMemcpy3DPeerAsync *cuMemcpy3DPeerAsync;
+extern tcuMemsetD8_v2 *cuMemsetD8_v2;
+extern tcuMemsetD16_v2 *cuMemsetD16_v2;
+extern tcuMemsetD32_v2 *cuMemsetD32_v2;
+extern tcuMemsetD2D8_v2 *cuMemsetD2D8_v2;
+extern tcuMemsetD2D16_v2 *cuMemsetD2D16_v2;
+extern tcuMemsetD2D32_v2 *cuMemsetD2D32_v2;
+extern tcuMemsetD8Async *cuMemsetD8Async;
+extern tcuMemsetD16Async *cuMemsetD16Async;
+extern tcuMemsetD32Async *cuMemsetD32Async;
+extern tcuMemsetD2D8Async *cuMemsetD2D8Async;
+extern tcuMemsetD2D16Async *cuMemsetD2D16Async;
+extern tcuMemsetD2D32Async *cuMemsetD2D32Async;
+extern tcuArrayCreate_v2 *cuArrayCreate_v2;
+extern tcuArrayGetDescriptor_v2 *cuArrayGetDescriptor_v2;
+extern tcuArrayDestroy *cuArrayDestroy;
+extern tcuArray3DCreate_v2 *cuArray3DCreate_v2;
+extern tcuArray3DGetDescriptor_v2 *cuArray3DGetDescriptor_v2;
+extern tcuMipmappedArrayCreate *cuMipmappedArrayCreate;
+extern tcuMipmappedArrayGetLevel *cuMipmappedArrayGetLevel;
+extern tcuMipmappedArrayDestroy *cuMipmappedArrayDestroy;
+extern tcuPointerGetAttribute *cuPointerGetAttribute;
+extern tcuPointerSetAttribute *cuPointerSetAttribute;
+extern tcuStreamCreate *cuStreamCreate;
+extern tcuStreamCreateWithPriority *cuStreamCreateWithPriority;
+extern tcuStreamGetPriority *cuStreamGetPriority;
+extern tcuStreamGetFlags *cuStreamGetFlags;
+extern tcuStreamWaitEvent *cuStreamWaitEvent;
+extern tcuStreamAddCallback *cuStreamAddCallback;
+extern tcuStreamAttachMemAsync *cuStreamAttachMemAsync;
+extern tcuStreamQuery *cuStreamQuery;
+extern tcuStreamSynchronize *cuStreamSynchronize;
+extern tcuStreamDestroy_v2 *cuStreamDestroy_v2;
+extern tcuEventCreate *cuEventCreate;
+extern tcuEventRecord *cuEventRecord;
+extern tcuEventQuery *cuEventQuery;
+extern tcuEventSynchronize *cuEventSynchronize;
+extern tcuEventDestroy_v2 *cuEventDestroy_v2;
+extern tcuEventElapsedTime *cuEventElapsedTime;
+extern tcuFuncGetAttribute *cuFuncGetAttribute;
+extern tcuFuncSetCacheConfig *cuFuncSetCacheConfig;
+extern tcuFuncSetSharedMemConfig *cuFuncSetSharedMemConfig;
+extern tcuLaunchKernel *cuLaunchKernel;
+extern tcuFuncSetBlockShape *cuFuncSetBlockShape;
+extern tcuFuncSetSharedSize *cuFuncSetSharedSize;
+extern tcuParamSetSize *cuParamSetSize;
+extern tcuParamSeti *cuParamSeti;
+extern tcuParamSetf *cuParamSetf;
+extern tcuParamSetv *cuParamSetv;
+extern tcuLaunch *cuLaunch;
+extern tcuLaunchGrid *cuLaunchGrid;
+extern tcuLaunchGridAsync *cuLaunchGridAsync;
+extern tcuParamSetTexRef *cuParamSetTexRef;
+extern tcuTexRefSetArray *cuTexRefSetArray;
+extern tcuTexRefSetMipmappedArray *cuTexRefSetMipmappedArray;
+extern tcuTexRefSetAddress_v2 *cuTexRefSetAddress_v2;
+extern tcuTexRefSetAddress2D_v3 *cuTexRefSetAddress2D_v3;
+extern tcuTexRefSetFormat *cuTexRefSetFormat;
+extern tcuTexRefSetAddressMode *cuTexRefSetAddressMode;
+extern tcuTexRefSetFilterMode *cuTexRefSetFilterMode;
+extern tcuTexRefSetMipmapFilterMode *cuTexRefSetMipmapFilterMode;
+extern tcuTexRefSetMipmapLevelBias *cuTexRefSetMipmapLevelBias;
+extern tcuTexRefSetMipmapLevelClamp *cuTexRefSetMipmapLevelClamp;
+extern tcuTexRefSetMaxAnisotropy *cuTexRefSetMaxAnisotropy;
+extern tcuTexRefSetFlags *cuTexRefSetFlags;
+extern tcuTexRefGetAddress_v2 *cuTexRefGetAddress_v2;
+extern tcuTexRefGetArray *cuTexRefGetArray;
+extern tcuTexRefGetMipmappedArray *cuTexRefGetMipmappedArray;
+extern tcuTexRefGetAddressMode *cuTexRefGetAddressMode;
+extern tcuTexRefGetFilterMode *cuTexRefGetFilterMode;
+extern tcuTexRefGetFormat *cuTexRefGetFormat;
+extern tcuTexRefGetMipmapFilterMode *cuTexRefGetMipmapFilterMode;
+extern tcuTexRefGetMipmapLevelBias *cuTexRefGetMipmapLevelBias;
+extern tcuTexRefGetMipmapLevelClamp *cuTexRefGetMipmapLevelClamp;
+extern tcuTexRefGetMaxAnisotropy *cuTexRefGetMaxAnisotropy;
+extern tcuTexRefGetFlags *cuTexRefGetFlags;
+extern tcuTexRefCreate *cuTexRefCreate;
+extern tcuTexRefDestroy *cuTexRefDestroy;
+extern tcuSurfRefSetArray *cuSurfRefSetArray;
+extern tcuSurfRefGetArray *cuSurfRefGetArray;
+extern tcuTexObjectCreate *cuTexObjectCreate;
+extern tcuTexObjectDestroy *cuTexObjectDestroy;
+extern tcuTexObjectGetResourceDesc *cuTexObjectGetResourceDesc;
+extern tcuTexObjectGetTextureDesc *cuTexObjectGetTextureDesc;
+extern tcuTexObjectGetResourceViewDesc *cuTexObjectGetResourceViewDesc;
+extern tcuSurfObjectCreate *cuSurfObjectCreate;
+extern tcuSurfObjectDestroy *cuSurfObjectDestroy;
+extern tcuSurfObjectGetResourceDesc *cuSurfObjectGetResourceDesc;
+extern tcuDeviceCanAccessPeer *cuDeviceCanAccessPeer;
+extern tcuCtxEnablePeerAccess *cuCtxEnablePeerAccess;
+extern tcuCtxDisablePeerAccess *cuCtxDisablePeerAccess;
+extern tcuGraphicsUnregisterResource *cuGraphicsUnregisterResource;
+extern tcuGraphicsSubResourceGetMappedArray *cuGraphicsSubResourceGetMappedArray;
+extern tcuGraphicsResourceGetMappedMipmappedArray *cuGraphicsResourceGetMappedMipmappedArray;
+extern tcuGraphicsResourceGetMappedPointer_v2 *cuGraphicsResourceGetMappedPointer_v2;
+extern tcuGraphicsResourceSetMapFlags *cuGraphicsResourceSetMapFlags;
+extern tcuGraphicsMapResources *cuGraphicsMapResources;
+extern tcuGraphicsUnmapResources *cuGraphicsUnmapResources;
+extern tcuGetExportTable *cuGetExportTable;
+
+extern tcuGraphicsGLRegisterBuffer *cuGraphicsGLRegisterBuffer;
+extern tcuGraphicsGLRegisterImage *cuGraphicsGLRegisterImage;
+extern tcuGLGetDevices *cuGLGetDevices;
+extern tcuGLCtxCreate_v2 *cuGLCtxCreate_v2;
+extern tcuGLInit *cuGLInit;
+extern tcuGLRegisterBufferObject *cuGLRegisterBufferObject;
+extern tcuGLMapBufferObject_v2 *cuGLMapBufferObject_v2;
+extern tcuGLUnmapBufferObject *cuGLUnmapBufferObject;
+extern tcuGLUnregisterBufferObject *cuGLUnregisterBufferObject;
+extern tcuGLSetBufferObjectMapFlags *cuGLSetBufferObjectMapFlags;
+extern tcuGLMapBufferObjectAsync_v2 *cuGLMapBufferObjectAsync_v2;
+extern tcuGLUnmapBufferObjectAsync *cuGLUnmapBufferObjectAsync;
+
+
+enum {
+ CUEW_SUCCESS = 0,
+ CUEW_ERROR_OPEN_FAILED = -1,
+ CUEW_ERROR_ATEXIT_FAILED = -2,
+};
+
+int cuewInit(void);
+const char *cuewErrorString(CUresult result);
+const char *cuewCompilerPath(void);
+int cuewCompilerVersion(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUEW_H__ */
diff --git a/extern/cuew/src/cuew.c b/extern/cuew/src/cuew.c
new file mode 100644
index 00000000000..da892efc0f4
--- /dev/null
+++ b/extern/cuew/src/cuew.c
@@ -0,0 +1,710 @@
+/*
+ * 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
+ */
+
+#ifdef _MSC_VER
+# define snprintf _snprintf
+# define popen _popen
+# define pclose _pclose
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include <cuew.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# define VC_EXTRALEAN
+# include <windows.h>
+
+/* Utility macros. */
+
+typedef HMODULE DynamicLibrary;
+
+# define dynamic_library_open(path) LoadLibrary(path)
+# define dynamic_library_close(lib) FreeLibrary(lib)
+# define dynamic_library_find(lib, symbol) GetProcAddress(lib, symbol)
+#else
+# include <dlfcn.h>
+
+typedef void* DynamicLibrary;
+
+# define dynamic_library_open(path) dlopen(path, RTLD_NOW)
+# define dynamic_library_close(lib) dlclose(lib)
+# define dynamic_library_find(lib, symbol) dlsym(lib, symbol)
+#endif
+
+#define CUDA_LIBRARY_FIND_CHECKED(name) \
+ name = (t##name *)dynamic_library_find(lib, #name); \
+ assert(name);
+
+#define CUDA_LIBRARY_FIND(name) \
+ name = (t##name *)dynamic_library_find(lib, #name);
+
+static DynamicLibrary lib;
+
+/* Function definitions. */
+tcuGetErrorString *cuGetErrorString;
+tcuGetErrorName *cuGetErrorName;
+tcuInit *cuInit;
+tcuDriverGetVersion *cuDriverGetVersion;
+tcuDeviceGet *cuDeviceGet;
+tcuDeviceGetCount *cuDeviceGetCount;
+tcuDeviceGetName *cuDeviceGetName;
+tcuDeviceTotalMem_v2 *cuDeviceTotalMem_v2;
+tcuDeviceGetAttribute *cuDeviceGetAttribute;
+tcuDeviceGetProperties *cuDeviceGetProperties;
+tcuDeviceComputeCapability *cuDeviceComputeCapability;
+tcuCtxCreate_v2 *cuCtxCreate_v2;
+tcuCtxDestroy_v2 *cuCtxDestroy_v2;
+tcuCtxPushCurrent_v2 *cuCtxPushCurrent_v2;
+tcuCtxPopCurrent_v2 *cuCtxPopCurrent_v2;
+tcuCtxSetCurrent *cuCtxSetCurrent;
+tcuCtxGetCurrent *cuCtxGetCurrent;
+tcuCtxGetDevice *cuCtxGetDevice;
+tcuCtxSynchronize *cuCtxSynchronize;
+tcuCtxSetLimit *cuCtxSetLimit;
+tcuCtxGetLimit *cuCtxGetLimit;
+tcuCtxGetCacheConfig *cuCtxGetCacheConfig;
+tcuCtxSetCacheConfig *cuCtxSetCacheConfig;
+tcuCtxGetSharedMemConfig *cuCtxGetSharedMemConfig;
+tcuCtxSetSharedMemConfig *cuCtxSetSharedMemConfig;
+tcuCtxGetApiVersion *cuCtxGetApiVersion;
+tcuCtxGetStreamPriorityRange *cuCtxGetStreamPriorityRange;
+tcuCtxAttach *cuCtxAttach;
+tcuCtxDetach *cuCtxDetach;
+tcuModuleLoad *cuModuleLoad;
+tcuModuleLoadData *cuModuleLoadData;
+tcuModuleLoadDataEx *cuModuleLoadDataEx;
+tcuModuleLoadFatBinary *cuModuleLoadFatBinary;
+tcuModuleUnload *cuModuleUnload;
+tcuModuleGetFunction *cuModuleGetFunction;
+tcuModuleGetGlobal_v2 *cuModuleGetGlobal_v2;
+tcuModuleGetTexRef *cuModuleGetTexRef;
+tcuModuleGetSurfRef *cuModuleGetSurfRef;
+tcuLinkCreate *cuLinkCreate;
+tcuLinkAddData *cuLinkAddData;
+tcuLinkAddFile *cuLinkAddFile;
+tcuLinkComplete *cuLinkComplete;
+tcuLinkDestroy *cuLinkDestroy;
+tcuMemGetInfo_v2 *cuMemGetInfo_v2;
+tcuMemAlloc_v2 *cuMemAlloc_v2;
+tcuMemAllocPitch_v2 *cuMemAllocPitch_v2;
+tcuMemFree_v2 *cuMemFree_v2;
+tcuMemGetAddressRange_v2 *cuMemGetAddressRange_v2;
+tcuMemAllocHost_v2 *cuMemAllocHost_v2;
+tcuMemFreeHost *cuMemFreeHost;
+tcuMemHostAlloc *cuMemHostAlloc;
+tcuMemHostGetDevicePointer_v2 *cuMemHostGetDevicePointer_v2;
+tcuMemHostGetFlags *cuMemHostGetFlags;
+tcuMemAllocManaged *cuMemAllocManaged;
+tcuDeviceGetByPCIBusId *cuDeviceGetByPCIBusId;
+tcuDeviceGetPCIBusId *cuDeviceGetPCIBusId;
+tcuIpcGetEventHandle *cuIpcGetEventHandle;
+tcuIpcOpenEventHandle *cuIpcOpenEventHandle;
+tcuIpcGetMemHandle *cuIpcGetMemHandle;
+tcuIpcOpenMemHandle *cuIpcOpenMemHandle;
+tcuIpcCloseMemHandle *cuIpcCloseMemHandle;
+tcuMemHostRegister *cuMemHostRegister;
+tcuMemHostUnregister *cuMemHostUnregister;
+tcuMemcpy *cuMemcpy;
+tcuMemcpyPeer *cuMemcpyPeer;
+tcuMemcpyHtoD_v2 *cuMemcpyHtoD_v2;
+tcuMemcpyDtoH_v2 *cuMemcpyDtoH_v2;
+tcuMemcpyDtoD_v2 *cuMemcpyDtoD_v2;
+tcuMemcpyDtoA_v2 *cuMemcpyDtoA_v2;
+tcuMemcpyAtoD_v2 *cuMemcpyAtoD_v2;
+tcuMemcpyHtoA_v2 *cuMemcpyHtoA_v2;
+tcuMemcpyAtoH_v2 *cuMemcpyAtoH_v2;
+tcuMemcpyAtoA_v2 *cuMemcpyAtoA_v2;
+tcuMemcpy2D_v2 *cuMemcpy2D_v2;
+tcuMemcpy2DUnaligned_v2 *cuMemcpy2DUnaligned_v2;
+tcuMemcpy3D_v2 *cuMemcpy3D_v2;
+tcuMemcpy3DPeer *cuMemcpy3DPeer;
+tcuMemcpyAsync *cuMemcpyAsync;
+tcuMemcpyPeerAsync *cuMemcpyPeerAsync;
+tcuMemcpyHtoDAsync_v2 *cuMemcpyHtoDAsync_v2;
+tcuMemcpyDtoHAsync_v2 *cuMemcpyDtoHAsync_v2;
+tcuMemcpyDtoDAsync_v2 *cuMemcpyDtoDAsync_v2;
+tcuMemcpyHtoAAsync_v2 *cuMemcpyHtoAAsync_v2;
+tcuMemcpyAtoHAsync_v2 *cuMemcpyAtoHAsync_v2;
+tcuMemcpy2DAsync_v2 *cuMemcpy2DAsync_v2;
+tcuMemcpy3DAsync_v2 *cuMemcpy3DAsync_v2;
+tcuMemcpy3DPeerAsync *cuMemcpy3DPeerAsync;
+tcuMemsetD8_v2 *cuMemsetD8_v2;
+tcuMemsetD16_v2 *cuMemsetD16_v2;
+tcuMemsetD32_v2 *cuMemsetD32_v2;
+tcuMemsetD2D8_v2 *cuMemsetD2D8_v2;
+tcuMemsetD2D16_v2 *cuMemsetD2D16_v2;
+tcuMemsetD2D32_v2 *cuMemsetD2D32_v2;
+tcuMemsetD8Async *cuMemsetD8Async;
+tcuMemsetD16Async *cuMemsetD16Async;
+tcuMemsetD32Async *cuMemsetD32Async;
+tcuMemsetD2D8Async *cuMemsetD2D8Async;
+tcuMemsetD2D16Async *cuMemsetD2D16Async;
+tcuMemsetD2D32Async *cuMemsetD2D32Async;
+tcuArrayCreate_v2 *cuArrayCreate_v2;
+tcuArrayGetDescriptor_v2 *cuArrayGetDescriptor_v2;
+tcuArrayDestroy *cuArrayDestroy;
+tcuArray3DCreate_v2 *cuArray3DCreate_v2;
+tcuArray3DGetDescriptor_v2 *cuArray3DGetDescriptor_v2;
+tcuMipmappedArrayCreate *cuMipmappedArrayCreate;
+tcuMipmappedArrayGetLevel *cuMipmappedArrayGetLevel;
+tcuMipmappedArrayDestroy *cuMipmappedArrayDestroy;
+tcuPointerGetAttribute *cuPointerGetAttribute;
+tcuPointerSetAttribute *cuPointerSetAttribute;
+tcuStreamCreate *cuStreamCreate;
+tcuStreamCreateWithPriority *cuStreamCreateWithPriority;
+tcuStreamGetPriority *cuStreamGetPriority;
+tcuStreamGetFlags *cuStreamGetFlags;
+tcuStreamWaitEvent *cuStreamWaitEvent;
+tcuStreamAddCallback *cuStreamAddCallback;
+tcuStreamAttachMemAsync *cuStreamAttachMemAsync;
+tcuStreamQuery *cuStreamQuery;
+tcuStreamSynchronize *cuStreamSynchronize;
+tcuStreamDestroy_v2 *cuStreamDestroy_v2;
+tcuEventCreate *cuEventCreate;
+tcuEventRecord *cuEventRecord;
+tcuEventQuery *cuEventQuery;
+tcuEventSynchronize *cuEventSynchronize;
+tcuEventDestroy_v2 *cuEventDestroy_v2;
+tcuEventElapsedTime *cuEventElapsedTime;
+tcuFuncGetAttribute *cuFuncGetAttribute;
+tcuFuncSetCacheConfig *cuFuncSetCacheConfig;
+tcuFuncSetSharedMemConfig *cuFuncSetSharedMemConfig;
+tcuLaunchKernel *cuLaunchKernel;
+tcuFuncSetBlockShape *cuFuncSetBlockShape;
+tcuFuncSetSharedSize *cuFuncSetSharedSize;
+tcuParamSetSize *cuParamSetSize;
+tcuParamSeti *cuParamSeti;
+tcuParamSetf *cuParamSetf;
+tcuParamSetv *cuParamSetv;
+tcuLaunch *cuLaunch;
+tcuLaunchGrid *cuLaunchGrid;
+tcuLaunchGridAsync *cuLaunchGridAsync;
+tcuParamSetTexRef *cuParamSetTexRef;
+tcuTexRefSetArray *cuTexRefSetArray;
+tcuTexRefSetMipmappedArray *cuTexRefSetMipmappedArray;
+tcuTexRefSetAddress_v2 *cuTexRefSetAddress_v2;
+tcuTexRefSetAddress2D_v3 *cuTexRefSetAddress2D_v3;
+tcuTexRefSetFormat *cuTexRefSetFormat;
+tcuTexRefSetAddressMode *cuTexRefSetAddressMode;
+tcuTexRefSetFilterMode *cuTexRefSetFilterMode;
+tcuTexRefSetMipmapFilterMode *cuTexRefSetMipmapFilterMode;
+tcuTexRefSetMipmapLevelBias *cuTexRefSetMipmapLevelBias;
+tcuTexRefSetMipmapLevelClamp *cuTexRefSetMipmapLevelClamp;
+tcuTexRefSetMaxAnisotropy *cuTexRefSetMaxAnisotropy;
+tcuTexRefSetFlags *cuTexRefSetFlags;
+tcuTexRefGetAddress_v2 *cuTexRefGetAddress_v2;
+tcuTexRefGetArray *cuTexRefGetArray;
+tcuTexRefGetMipmappedArray *cuTexRefGetMipmappedArray;
+tcuTexRefGetAddressMode *cuTexRefGetAddressMode;
+tcuTexRefGetFilterMode *cuTexRefGetFilterMode;
+tcuTexRefGetFormat *cuTexRefGetFormat;
+tcuTexRefGetMipmapFilterMode *cuTexRefGetMipmapFilterMode;
+tcuTexRefGetMipmapLevelBias *cuTexRefGetMipmapLevelBias;
+tcuTexRefGetMipmapLevelClamp *cuTexRefGetMipmapLevelClamp;
+tcuTexRefGetMaxAnisotropy *cuTexRefGetMaxAnisotropy;
+tcuTexRefGetFlags *cuTexRefGetFlags;
+tcuTexRefCreate *cuTexRefCreate;
+tcuTexRefDestroy *cuTexRefDestroy;
+tcuSurfRefSetArray *cuSurfRefSetArray;
+tcuSurfRefGetArray *cuSurfRefGetArray;
+tcuTexObjectCreate *cuTexObjectCreate;
+tcuTexObjectDestroy *cuTexObjectDestroy;
+tcuTexObjectGetResourceDesc *cuTexObjectGetResourceDesc;
+tcuTexObjectGetTextureDesc *cuTexObjectGetTextureDesc;
+tcuTexObjectGetResourceViewDesc *cuTexObjectGetResourceViewDesc;
+tcuSurfObjectCreate *cuSurfObjectCreate;
+tcuSurfObjectDestroy *cuSurfObjectDestroy;
+tcuSurfObjectGetResourceDesc *cuSurfObjectGetResourceDesc;
+tcuDeviceCanAccessPeer *cuDeviceCanAccessPeer;
+tcuCtxEnablePeerAccess *cuCtxEnablePeerAccess;
+tcuCtxDisablePeerAccess *cuCtxDisablePeerAccess;
+tcuGraphicsUnregisterResource *cuGraphicsUnregisterResource;
+tcuGraphicsSubResourceGetMappedArray *cuGraphicsSubResourceGetMappedArray;
+tcuGraphicsResourceGetMappedMipmappedArray *cuGraphicsResourceGetMappedMipmappedArray;
+tcuGraphicsResourceGetMappedPointer_v2 *cuGraphicsResourceGetMappedPointer_v2;
+tcuGraphicsResourceSetMapFlags *cuGraphicsResourceSetMapFlags;
+tcuGraphicsMapResources *cuGraphicsMapResources;
+tcuGraphicsUnmapResources *cuGraphicsUnmapResources;
+tcuGetExportTable *cuGetExportTable;
+
+tcuGraphicsGLRegisterBuffer *cuGraphicsGLRegisterBuffer;
+tcuGraphicsGLRegisterImage *cuGraphicsGLRegisterImage;
+tcuGLGetDevices *cuGLGetDevices;
+tcuGLCtxCreate_v2 *cuGLCtxCreate_v2;
+tcuGLInit *cuGLInit;
+tcuGLRegisterBufferObject *cuGLRegisterBufferObject;
+tcuGLMapBufferObject_v2 *cuGLMapBufferObject_v2;
+tcuGLUnmapBufferObject *cuGLUnmapBufferObject;
+tcuGLUnregisterBufferObject *cuGLUnregisterBufferObject;
+tcuGLSetBufferObjectMapFlags *cuGLSetBufferObjectMapFlags;
+tcuGLMapBufferObjectAsync_v2 *cuGLMapBufferObjectAsync_v2;
+tcuGLUnmapBufferObjectAsync *cuGLUnmapBufferObjectAsync;
+
+
+static void cuewExit(void) {
+ if(lib != NULL) {
+ /* Ignore errors. */
+ dynamic_library_close(lib);
+ lib = NULL;
+ }
+}
+
+/* Implementation function. */
+int cuewInit(void) {
+ /* Library paths. */
+#ifdef _WIN32
+ /* Expected in c:/windows/system or similar, no path needed. */
+ const char *path = "nvcuda.dll";
+#elif defined(__APPLE__)
+ /* Default installation path. */
+ const char *path = "/usr/local/cuda/lib/libcuda.dylib";
+#else
+ const char *path = "libcuda.so";
+#endif
+ static int initialized = 0;
+ static int result = 0;
+ int error, driver_version;
+
+ if (initialized) {
+ return result;
+ }
+
+ initialized = 1;
+
+ error = atexit(cuewExit);
+ if (error) {
+ result = CUEW_ERROR_ATEXIT_FAILED;
+ return result;
+ }
+
+ /* Load library. */
+ lib = dynamic_library_open(path);
+
+ if (lib == NULL) {
+ result = CUEW_ERROR_OPEN_FAILED;
+ return result;
+ }
+
+ /* Detect driver version. */
+ driver_version = 1000;
+
+ CUDA_LIBRARY_FIND_CHECKED(cuDriverGetVersion);
+ if (cuDriverGetVersion) {
+ cuDriverGetVersion(&driver_version);
+ }
+
+ /* We require version 4.0. */
+ if (driver_version < 4000) {
+ result = CUEW_ERROR_OPEN_FAILED;
+ return result;
+ }
+ /* Fetch all function pointers. */
+ CUDA_LIBRARY_FIND(cuGetErrorString);
+ CUDA_LIBRARY_FIND(cuGetErrorName);
+ CUDA_LIBRARY_FIND(cuInit);
+ CUDA_LIBRARY_FIND(cuDriverGetVersion);
+ CUDA_LIBRARY_FIND(cuDeviceGet);
+ CUDA_LIBRARY_FIND(cuDeviceGetCount);
+ CUDA_LIBRARY_FIND(cuDeviceGetName);
+ CUDA_LIBRARY_FIND(cuDeviceTotalMem_v2);
+ CUDA_LIBRARY_FIND(cuDeviceGetAttribute);
+ CUDA_LIBRARY_FIND(cuDeviceGetProperties);
+ CUDA_LIBRARY_FIND(cuDeviceComputeCapability);
+ CUDA_LIBRARY_FIND(cuCtxCreate_v2);
+ CUDA_LIBRARY_FIND(cuCtxDestroy_v2);
+ CUDA_LIBRARY_FIND(cuCtxPushCurrent_v2);
+ CUDA_LIBRARY_FIND(cuCtxPopCurrent_v2);
+ CUDA_LIBRARY_FIND(cuCtxSetCurrent);
+ CUDA_LIBRARY_FIND(cuCtxGetCurrent);
+ CUDA_LIBRARY_FIND(cuCtxGetDevice);
+ CUDA_LIBRARY_FIND(cuCtxSynchronize);
+ CUDA_LIBRARY_FIND(cuCtxSetLimit);
+ CUDA_LIBRARY_FIND(cuCtxGetLimit);
+ CUDA_LIBRARY_FIND(cuCtxGetCacheConfig);
+ CUDA_LIBRARY_FIND(cuCtxSetCacheConfig);
+ CUDA_LIBRARY_FIND(cuCtxGetSharedMemConfig);
+ CUDA_LIBRARY_FIND(cuCtxSetSharedMemConfig);
+ CUDA_LIBRARY_FIND(cuCtxGetApiVersion);
+ CUDA_LIBRARY_FIND(cuCtxGetStreamPriorityRange);
+ CUDA_LIBRARY_FIND(cuCtxAttach);
+ CUDA_LIBRARY_FIND(cuCtxDetach);
+ CUDA_LIBRARY_FIND(cuModuleLoad);
+ CUDA_LIBRARY_FIND(cuModuleLoadData);
+ CUDA_LIBRARY_FIND(cuModuleLoadDataEx);
+ CUDA_LIBRARY_FIND(cuModuleLoadFatBinary);
+ CUDA_LIBRARY_FIND(cuModuleUnload);
+ CUDA_LIBRARY_FIND(cuModuleGetFunction);
+ CUDA_LIBRARY_FIND(cuModuleGetGlobal_v2);
+ CUDA_LIBRARY_FIND(cuModuleGetTexRef);
+ CUDA_LIBRARY_FIND(cuModuleGetSurfRef);
+ CUDA_LIBRARY_FIND(cuLinkCreate);
+ CUDA_LIBRARY_FIND(cuLinkAddData);
+ CUDA_LIBRARY_FIND(cuLinkAddFile);
+ CUDA_LIBRARY_FIND(cuLinkComplete);
+ CUDA_LIBRARY_FIND(cuLinkDestroy);
+ CUDA_LIBRARY_FIND(cuMemGetInfo_v2);
+ CUDA_LIBRARY_FIND(cuMemAlloc_v2);
+ CUDA_LIBRARY_FIND(cuMemAllocPitch_v2);
+ CUDA_LIBRARY_FIND(cuMemFree_v2);
+ CUDA_LIBRARY_FIND(cuMemGetAddressRange_v2);
+ CUDA_LIBRARY_FIND(cuMemAllocHost_v2);
+ CUDA_LIBRARY_FIND(cuMemFreeHost);
+ CUDA_LIBRARY_FIND(cuMemHostAlloc);
+ CUDA_LIBRARY_FIND(cuMemHostGetDevicePointer_v2);
+ CUDA_LIBRARY_FIND(cuMemHostGetFlags);
+ CUDA_LIBRARY_FIND(cuMemAllocManaged);
+ CUDA_LIBRARY_FIND(cuDeviceGetByPCIBusId);
+ CUDA_LIBRARY_FIND(cuDeviceGetPCIBusId);
+ CUDA_LIBRARY_FIND(cuIpcGetEventHandle);
+ CUDA_LIBRARY_FIND(cuIpcOpenEventHandle);
+ CUDA_LIBRARY_FIND(cuIpcGetMemHandle);
+ CUDA_LIBRARY_FIND(cuIpcOpenMemHandle);
+ CUDA_LIBRARY_FIND(cuIpcCloseMemHandle);
+ CUDA_LIBRARY_FIND(cuMemHostRegister);
+ CUDA_LIBRARY_FIND(cuMemHostUnregister);
+ CUDA_LIBRARY_FIND(cuMemcpy);
+ CUDA_LIBRARY_FIND(cuMemcpyPeer);
+ CUDA_LIBRARY_FIND(cuMemcpyHtoD_v2);
+ CUDA_LIBRARY_FIND(cuMemcpyDtoH_v2);
+ CUDA_LIBRARY_FIND(cuMemcpyDtoD_v2);
+ CUDA_LIBRARY_FIND(cuMemcpyDtoA_v2);
+ CUDA_LIBRARY_FIND(cuMemcpyAtoD_v2);
+ CUDA_LIBRARY_FIND(cuMemcpyHtoA_v2);
+ CUDA_LIBRARY_FIND(cuMemcpyAtoH_v2);
+ CUDA_LIBRARY_FIND(cuMemcpyAtoA_v2);
+ CUDA_LIBRARY_FIND(cuMemcpy2D_v2);
+ CUDA_LIBRARY_FIND(cuMemcpy2DUnaligned_v2);
+ CUDA_LIBRARY_FIND(cuMemcpy3D_v2);
+ CUDA_LIBRARY_FIND(cuMemcpy3DPeer);
+ CUDA_LIBRARY_FIND(cuMemcpyAsync);
+ CUDA_LIBRARY_FIND(cuMemcpyPeerAsync);
+ CUDA_LIBRARY_FIND(cuMemcpyHtoDAsync_v2);
+ CUDA_LIBRARY_FIND(cuMemcpyDtoHAsync_v2);
+ CUDA_LIBRARY_FIND(cuMemcpyDtoDAsync_v2);
+ CUDA_LIBRARY_FIND(cuMemcpyHtoAAsync_v2);
+ CUDA_LIBRARY_FIND(cuMemcpyAtoHAsync_v2);
+ CUDA_LIBRARY_FIND(cuMemcpy2DAsync_v2);
+ CUDA_LIBRARY_FIND(cuMemcpy3DAsync_v2);
+ CUDA_LIBRARY_FIND(cuMemcpy3DPeerAsync);
+ CUDA_LIBRARY_FIND(cuMemsetD8_v2);
+ CUDA_LIBRARY_FIND(cuMemsetD16_v2);
+ CUDA_LIBRARY_FIND(cuMemsetD32_v2);
+ CUDA_LIBRARY_FIND(cuMemsetD2D8_v2);
+ CUDA_LIBRARY_FIND(cuMemsetD2D16_v2);
+ CUDA_LIBRARY_FIND(cuMemsetD2D32_v2);
+ CUDA_LIBRARY_FIND(cuMemsetD8Async);
+ CUDA_LIBRARY_FIND(cuMemsetD16Async);
+ CUDA_LIBRARY_FIND(cuMemsetD32Async);
+ CUDA_LIBRARY_FIND(cuMemsetD2D8Async);
+ CUDA_LIBRARY_FIND(cuMemsetD2D16Async);
+ CUDA_LIBRARY_FIND(cuMemsetD2D32Async);
+ CUDA_LIBRARY_FIND(cuArrayCreate_v2);
+ CUDA_LIBRARY_FIND(cuArrayGetDescriptor_v2);
+ CUDA_LIBRARY_FIND(cuArrayDestroy);
+ CUDA_LIBRARY_FIND(cuArray3DCreate_v2);
+ CUDA_LIBRARY_FIND(cuArray3DGetDescriptor_v2);
+ CUDA_LIBRARY_FIND(cuMipmappedArrayCreate);
+ CUDA_LIBRARY_FIND(cuMipmappedArrayGetLevel);
+ CUDA_LIBRARY_FIND(cuMipmappedArrayDestroy);
+ CUDA_LIBRARY_FIND(cuPointerGetAttribute);
+ CUDA_LIBRARY_FIND(cuPointerSetAttribute);
+ CUDA_LIBRARY_FIND(cuStreamCreate);
+ CUDA_LIBRARY_FIND(cuStreamCreateWithPriority);
+ CUDA_LIBRARY_FIND(cuStreamGetPriority);
+ CUDA_LIBRARY_FIND(cuStreamGetFlags);
+ CUDA_LIBRARY_FIND(cuStreamWaitEvent);
+ CUDA_LIBRARY_FIND(cuStreamAddCallback);
+ CUDA_LIBRARY_FIND(cuStreamAttachMemAsync);
+ CUDA_LIBRARY_FIND(cuStreamQuery);
+ CUDA_LIBRARY_FIND(cuStreamSynchronize);
+ CUDA_LIBRARY_FIND(cuStreamDestroy_v2);
+ CUDA_LIBRARY_FIND(cuEventCreate);
+ CUDA_LIBRARY_FIND(cuEventRecord);
+ CUDA_LIBRARY_FIND(cuEventQuery);
+ CUDA_LIBRARY_FIND(cuEventSynchronize);
+ CUDA_LIBRARY_FIND(cuEventDestroy_v2);
+ CUDA_LIBRARY_FIND(cuEventElapsedTime);
+ CUDA_LIBRARY_FIND(cuFuncGetAttribute);
+ CUDA_LIBRARY_FIND(cuFuncSetCacheConfig);
+ CUDA_LIBRARY_FIND(cuFuncSetSharedMemConfig);
+ CUDA_LIBRARY_FIND(cuLaunchKernel);
+ CUDA_LIBRARY_FIND(cuFuncSetBlockShape);
+ CUDA_LIBRARY_FIND(cuFuncSetSharedSize);
+ CUDA_LIBRARY_FIND(cuParamSetSize);
+ CUDA_LIBRARY_FIND(cuParamSeti);
+ CUDA_LIBRARY_FIND(cuParamSetf);
+ CUDA_LIBRARY_FIND(cuParamSetv);
+ CUDA_LIBRARY_FIND(cuLaunch);
+ CUDA_LIBRARY_FIND(cuLaunchGrid);
+ CUDA_LIBRARY_FIND(cuLaunchGridAsync);
+ CUDA_LIBRARY_FIND(cuParamSetTexRef);
+ CUDA_LIBRARY_FIND(cuTexRefSetArray);
+ CUDA_LIBRARY_FIND(cuTexRefSetMipmappedArray);
+ CUDA_LIBRARY_FIND(cuTexRefSetAddress_v2);
+ CUDA_LIBRARY_FIND(cuTexRefSetAddress2D_v3);
+ CUDA_LIBRARY_FIND(cuTexRefSetFormat);
+ CUDA_LIBRARY_FIND(cuTexRefSetAddressMode);
+ CUDA_LIBRARY_FIND(cuTexRefSetFilterMode);
+ CUDA_LIBRARY_FIND(cuTexRefSetMipmapFilterMode);
+ CUDA_LIBRARY_FIND(cuTexRefSetMipmapLevelBias);
+ CUDA_LIBRARY_FIND(cuTexRefSetMipmapLevelClamp);
+ CUDA_LIBRARY_FIND(cuTexRefSetMaxAnisotropy);
+ CUDA_LIBRARY_FIND(cuTexRefSetFlags);
+ CUDA_LIBRARY_FIND(cuTexRefGetAddress_v2);
+ CUDA_LIBRARY_FIND(cuTexRefGetArray);
+ CUDA_LIBRARY_FIND(cuTexRefGetMipmappedArray);
+ CUDA_LIBRARY_FIND(cuTexRefGetAddressMode);
+ CUDA_LIBRARY_FIND(cuTexRefGetFilterMode);
+ CUDA_LIBRARY_FIND(cuTexRefGetFormat);
+ CUDA_LIBRARY_FIND(cuTexRefGetMipmapFilterMode);
+ CUDA_LIBRARY_FIND(cuTexRefGetMipmapLevelBias);
+ CUDA_LIBRARY_FIND(cuTexRefGetMipmapLevelClamp);
+ CUDA_LIBRARY_FIND(cuTexRefGetMaxAnisotropy);
+ CUDA_LIBRARY_FIND(cuTexRefGetFlags);
+ CUDA_LIBRARY_FIND(cuTexRefCreate);
+ CUDA_LIBRARY_FIND(cuTexRefDestroy);
+ CUDA_LIBRARY_FIND(cuSurfRefSetArray);
+ CUDA_LIBRARY_FIND(cuSurfRefGetArray);
+ CUDA_LIBRARY_FIND(cuTexObjectCreate);
+ CUDA_LIBRARY_FIND(cuTexObjectDestroy);
+ CUDA_LIBRARY_FIND(cuTexObjectGetResourceDesc);
+ CUDA_LIBRARY_FIND(cuTexObjectGetTextureDesc);
+ CUDA_LIBRARY_FIND(cuTexObjectGetResourceViewDesc);
+ CUDA_LIBRARY_FIND(cuSurfObjectCreate);
+ CUDA_LIBRARY_FIND(cuSurfObjectDestroy);
+ CUDA_LIBRARY_FIND(cuSurfObjectGetResourceDesc);
+ CUDA_LIBRARY_FIND(cuDeviceCanAccessPeer);
+ CUDA_LIBRARY_FIND(cuCtxEnablePeerAccess);
+ CUDA_LIBRARY_FIND(cuCtxDisablePeerAccess);
+ CUDA_LIBRARY_FIND(cuGraphicsUnregisterResource);
+ CUDA_LIBRARY_FIND(cuGraphicsSubResourceGetMappedArray);
+ CUDA_LIBRARY_FIND(cuGraphicsResourceGetMappedMipmappedArray);
+ CUDA_LIBRARY_FIND(cuGraphicsResourceGetMappedPointer_v2);
+ CUDA_LIBRARY_FIND(cuGraphicsResourceSetMapFlags);
+ CUDA_LIBRARY_FIND(cuGraphicsMapResources);
+ CUDA_LIBRARY_FIND(cuGraphicsUnmapResources);
+ CUDA_LIBRARY_FIND(cuGetExportTable);
+
+ CUDA_LIBRARY_FIND(cuGraphicsGLRegisterBuffer);
+ CUDA_LIBRARY_FIND(cuGraphicsGLRegisterImage);
+ CUDA_LIBRARY_FIND(cuGLGetDevices);
+ CUDA_LIBRARY_FIND(cuGLCtxCreate_v2);
+ CUDA_LIBRARY_FIND(cuGLInit);
+ CUDA_LIBRARY_FIND(cuGLRegisterBufferObject);
+ CUDA_LIBRARY_FIND(cuGLMapBufferObject_v2);
+ CUDA_LIBRARY_FIND(cuGLUnmapBufferObject);
+ CUDA_LIBRARY_FIND(cuGLUnregisterBufferObject);
+ CUDA_LIBRARY_FIND(cuGLSetBufferObjectMapFlags);
+ CUDA_LIBRARY_FIND(cuGLMapBufferObjectAsync_v2);
+ CUDA_LIBRARY_FIND(cuGLUnmapBufferObjectAsync);
+
+
+ result = CUEW_SUCCESS;
+ return result;
+}
+
+const char *cuewErrorString(CUresult result) {
+ switch(result) {
+ case CUDA_SUCCESS: return "No errors";
+ case CUDA_ERROR_INVALID_VALUE: return "Invalid value";
+ case CUDA_ERROR_OUT_OF_MEMORY: return "Out of memory";
+ case CUDA_ERROR_NOT_INITIALIZED: return "Driver not initialized";
+ case CUDA_ERROR_DEINITIALIZED: return "Driver deinitialized";
+ case CUDA_ERROR_PROFILER_DISABLED: return "PROFILER_DISABLED";
+ case CUDA_ERROR_PROFILER_NOT_INITIALIZED: return "PROFILER_NOT_INITIALIZED";
+ case CUDA_ERROR_PROFILER_ALREADY_STARTED: return "PROFILER_ALREADY_STARTED";
+ case CUDA_ERROR_PROFILER_ALREADY_STOPPED: return "PROFILER_ALREADY_STOPPED";
+ case CUDA_ERROR_NO_DEVICE: return "No CUDA-capable device available";
+ case CUDA_ERROR_INVALID_DEVICE: return "Invalid device";
+ case CUDA_ERROR_INVALID_IMAGE: return "Invalid kernel image";
+ case CUDA_ERROR_INVALID_CONTEXT: return "Invalid context";
+ case CUDA_ERROR_CONTEXT_ALREADY_CURRENT: return "Context already current";
+ case CUDA_ERROR_MAP_FAILED: return "Map failed";
+ case CUDA_ERROR_UNMAP_FAILED: return "Unmap failed";
+ case CUDA_ERROR_ARRAY_IS_MAPPED: return "Array is mapped";
+ case CUDA_ERROR_ALREADY_MAPPED: return "Already mapped";
+ case CUDA_ERROR_NO_BINARY_FOR_GPU: return "No binary for GPU";
+ case CUDA_ERROR_ALREADY_ACQUIRED: return "Already acquired";
+ case CUDA_ERROR_NOT_MAPPED: return "Not mapped";
+ case CUDA_ERROR_NOT_MAPPED_AS_ARRAY: return "Mapped resource not available for access as an array";
+ case CUDA_ERROR_NOT_MAPPED_AS_POINTER: return "Mapped resource not available for access as a pointer";
+ case CUDA_ERROR_ECC_UNCORRECTABLE: return "Uncorrectable ECC error detected";
+ case CUDA_ERROR_UNSUPPORTED_LIMIT: return "CUlimit not supported by device";
+ case CUDA_ERROR_CONTEXT_ALREADY_IN_USE: return "CONTEXT_ALREADY_IN_USE";
+ case CUDA_ERROR_PEER_ACCESS_UNSUPPORTED: return "PEER_ACCESS_UNSUPPORTED";
+ case CUDA_ERROR_INVALID_PTX: return "INVALID_PTX";
+ 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";
+ case CUDA_ERROR_SHARED_OBJECT_INIT_FAILED: return "Shared object initialization failed";
+ case CUDA_ERROR_OPERATING_SYSTEM: return "OPERATING_SYSTEM";
+ case CUDA_ERROR_INVALID_HANDLE: return "Invalid handle";
+ case CUDA_ERROR_NOT_FOUND: return "Not found";
+ case CUDA_ERROR_NOT_READY: return "CUDA not ready";
+ case CUDA_ERROR_ILLEGAL_ADDRESS: return "ILLEGAL_ADDRESS";
+ case CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES: return "Launch exceeded resources";
+ case CUDA_ERROR_LAUNCH_TIMEOUT: return "Launch exceeded timeout";
+ case CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING: return "Launch with incompatible texturing";
+ case CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED: return "PEER_ACCESS_ALREADY_ENABLED";
+ case CUDA_ERROR_PEER_ACCESS_NOT_ENABLED: return "PEER_ACCESS_NOT_ENABLED";
+ case CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE: return "PRIMARY_CONTEXT_ACTIVE";
+ case CUDA_ERROR_CONTEXT_IS_DESTROYED: return "CONTEXT_IS_DESTROYED";
+ case CUDA_ERROR_ASSERT: return "ASSERT";
+ case CUDA_ERROR_TOO_MANY_PEERS: return "TOO_MANY_PEERS";
+ case CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED: return "HOST_MEMORY_ALREADY_REGISTERED";
+ case CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED: return "HOST_MEMORY_NOT_REGISTERED";
+ case CUDA_ERROR_HARDWARE_STACK_ERROR: return "HARDWARE_STACK_ERROR";
+ case CUDA_ERROR_ILLEGAL_INSTRUCTION: return "ILLEGAL_INSTRUCTION";
+ case CUDA_ERROR_MISALIGNED_ADDRESS: return "MISALIGNED_ADDRESS";
+ case CUDA_ERROR_INVALID_ADDRESS_SPACE: return "INVALID_ADDRESS_SPACE";
+ case CUDA_ERROR_INVALID_PC: return "INVALID_PC";
+ case CUDA_ERROR_LAUNCH_FAILED: return "Launch failed";
+ case CUDA_ERROR_NOT_PERMITTED: return "NOT_PERMITTED";
+ case CUDA_ERROR_NOT_SUPPORTED: return "NOT_SUPPORTED";
+ case CUDA_ERROR_UNKNOWN: return "Unknown error";
+ default: return "Unknown CUDA error value";
+ }
+}
+
+static void path_join(const char *path1,
+ const char *path2,
+ int maxlen,
+ char *result) {
+#if defined(WIN32) || defined(_WIN32)
+ const char separator = '\\';
+#else
+ const char separator = '/';
+#endif
+ int n = snprintf(result, maxlen, "%s%c%s", path1, separator, path2);
+ if (n != -1 && n < maxlen) {
+ result[n] = '\0';
+ }
+ else {
+ result[maxlen - 1] = '\0';
+ }
+}
+
+static int path_exists(const char *path) {
+ struct stat st;
+ if (stat(path, &st)) {
+ return 0;
+ }
+ return 1;
+}
+
+const char *cuewCompilerPath(void) {
+#ifdef _WIN32
+ const char *defaultpaths[] = {"C:/CUDA/bin", NULL};
+ const char *executable = "nvcc.exe";
+#else
+ const char *defaultpaths[] = {
+ "/Developer/NVIDIA/CUDA-5.0/bin",
+ "/usr/local/cuda-5.0/bin",
+ "/usr/local/cuda/bin",
+ "/Developer/NVIDIA/CUDA-6.0/bin",
+ "/usr/local/cuda-6.0/bin",
+ "/Developer/NVIDIA/CUDA-5.5/bin",
+ "/usr/local/cuda-5.5/bin",
+ NULL};
+ const char *executable = "nvcc";
+#endif
+ int i;
+
+ const char *binpath = getenv("CUDA_BIN_PATH");
+
+ static char nvcc[65536];
+
+ if (binpath) {
+ path_join(binpath, executable, sizeof(nvcc), nvcc);
+ if (path_exists(nvcc))
+ return nvcc;
+ }
+
+ for (i = 0; defaultpaths[i]; ++i) {
+ path_join(defaultpaths[i], executable, sizeof(nvcc), nvcc);
+ if (path_exists(nvcc))
+ return nvcc;
+ }
+
+#ifndef _WIN32
+ {
+ FILE *handle = popen("which nvcc", "r");
+ if (handle) {
+ char buffer[4096] = {0};
+ int len = fread(buffer, 1, sizeof(buffer) - 1, handle);
+ buffer[len] = '\0';
+ pclose(handle);
+
+ if (buffer[0])
+ return "nvcc";
+ }
+ }
+#endif
+
+ return NULL;
+}
+
+int cuewCompilerVersion(void) {
+ const char *path = cuewCompilerPath();
+ const char *marker = "Cuda compilation tools, release ";
+ FILE *pipe;
+ int major, minor;
+ char *versionstr;
+ char buf[128];
+ char output[65536] = "\0";
+ char command[65536] = "\0";
+
+ if (path == NULL)
+ return 0;
+
+ /* get --version output */
+ strncpy(command, path, sizeof(command));
+ strncat(command, " --version", sizeof(command) - strlen(path));
+ pipe = popen(command, "r");
+ if (!pipe) {
+ fprintf(stderr, "CUDA: failed to run compiler to retrieve version");
+ return 0;
+ }
+
+ while (!feof(pipe)) {
+ if (fgets(buf, sizeof(buf), pipe) != NULL) {
+ strncat(output, buf, sizeof(output) - strlen(output) - 1 );
+ }
+ }
+
+ pclose(pipe);
+
+ /* parse version number */
+ versionstr = strstr(output, marker);
+ if (versionstr == NULL) {
+ fprintf(stderr, "CUDA: failed to find version number in:\n\n%s\n", output);
+ return 0;
+ }
+ versionstr += strlen(marker);
+
+ if (sscanf(versionstr, "%d.%d", &major, &minor) < 2) {
+ fprintf(stderr, "CUDA: failed to parse version number from:\n\n%s\n", output);
+ return 0;
+ }
+
+ return 10 * major + minor;
+}
+
diff --git a/extern/gtest/CMakeLists.txt b/extern/gtest/CMakeLists.txt
index b5e40027513..86f2aaa314a 100644
--- a/extern/gtest/CMakeLists.txt
+++ b/extern/gtest/CMakeLists.txt
@@ -39,6 +39,7 @@ set(SRC
src/gtest-test-part.cc
src/gtest-typed-test.cc
+ src/gtest-internal-inl.h
include/gtest/gtest-death-test.h
include/gtest/gtest.h
include/gtest/gtest-message.h
diff --git a/extern/libmv/libmv/simple_pipeline/bundle.cc b/extern/libmv/libmv/simple_pipeline/bundle.cc
index fc1882a0b72..09b55f34eef 100644
--- a/extern/libmv/libmv/simple_pipeline/bundle.cc
+++ b/extern/libmv/libmv/simple_pipeline/bundle.cc
@@ -539,9 +539,8 @@ void EuclideanBundleCommonIntrinsics(
}
zero_weight_tracks_flags[marker.track] = false;
+ num_residuals++;
}
-
- num_residuals++;
}
LG << "Number of residuals: " << num_residuals;
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index d0d0ef2fd1c..74048c2a4cc 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -73,10 +73,6 @@ if(WITH_BULLET)
add_subdirectory(rigidbody)
endif()
-if(WITH_COMPOSITOR)
- add_subdirectory(opencl)
-endif()
-
if(WITH_OPENNL)
add_subdirectory(opennl)
endif()
diff --git a/intern/SConscript b/intern/SConscript
index 20803884a39..0b39fcb5d26 100644
--- a/intern/SConscript
+++ b/intern/SConscript
@@ -59,9 +59,6 @@ if env['WITH_BF_INTERNATIONAL']:
if env['WITH_BF_BULLET']:
SConscript (['rigidbody/SConscript'])
-if env['WITH_BF_COMPOSITOR']:
- SConscript (['opencl/SConscript'])
-
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'):
SConscript(['utfconv/SConscript'])
diff --git a/intern/atomic/atomic_ops.h b/intern/atomic/atomic_ops.h
index bb55ac1a11f..127552f8bd4 100644
--- a/intern/atomic/atomic_ops.h
+++ b/intern/atomic/atomic_ops.h
@@ -61,7 +61,10 @@
# endif
#endif
-#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) || defined(__s390x__) || defined(__powerpc64__) || defined(__aarch64__) || (defined(__sparc__) && defined(__arch64__))
+/* This is becoming a bit nastier that it was originally foreseen,
+ * consider using autoconfig detection instead.
+ */
+#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) || defined(__s390x__) || defined(__powerpc64__) || defined(__aarch64__) || (defined(__sparc__) && defined(__arch64__)) || defined(__alpha__) || defined(__mips64)
# define LG_SIZEOF_PTR 3
# define LG_SIZEOF_INT 2
#else
diff --git a/intern/audaspace/FX/AUD_PitchReader.cpp b/intern/audaspace/FX/AUD_PitchReader.cpp
index 218af4fc090..b3775c71a28 100644
--- a/intern/audaspace/FX/AUD_PitchReader.cpp
+++ b/intern/audaspace/FX/AUD_PitchReader.cpp
@@ -48,5 +48,7 @@ float AUD_PitchReader::getPitch() const
void AUD_PitchReader::setPitch(float pitch)
{
+ if(pitch <= 0)
+ pitch = 1;
m_pitch = pitch;
}
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
index 7bf59cd6f31..6ffa5e1fcae 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
@@ -422,6 +422,8 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::setPitch(float pitch)
{
if(!m_status)
return false;
+ if(pitch <= 0)
+ pitch = 1;
m_user_pitch = pitch;
return true;
}
diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript
index 00acde28560..a6c947bfca8 100644
--- a/intern/cycles/SConscript
+++ b/intern/cycles/SConscript
@@ -62,7 +62,7 @@ if env['WITH_BF_CYCLES_OSL']:
incs.extend('. bvh render device kernel kernel/osl kernel/svm util subd'.split())
incs.extend('#intern/guardedalloc #source/blender/makesrna #source/blender/makesdna #source/blender/blenlib'.split())
incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.split())
-incs.extend('#extern/glew/include #intern/mikktspace'.split())
+incs.extend('#extern/glew/include #extern/clew/include #extern/cuew/include #intern/mikktspace'.split())
incs.append(cycles['BF_OIIO_INC'])
incs.append(cycles['BF_BOOST_INC'])
incs.append(cycles['BF_OPENEXR_INC'].split())
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index 00544ae16f1..34e958190f6 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -28,6 +28,8 @@ set(LIBRARIES
${JPEG_LIBRARIES}
${ZLIB_LIBRARIES}
${TIFF_LIBRARY}
+ extern_clew
+ extern_cuew
)
add_definitions(${GL_DEFINITIONS})
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 915ef96a517..431796e106b 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -304,7 +304,8 @@ static void xml_read_integrator(const XMLReadState& state, pugi::xml_node node)
xml_read_int(&integrator->volume_max_steps, node, "volume_max_steps");
/* Various Settings */
- xml_read_bool(&integrator->no_caustics, node, "no_caustics");
+ xml_read_bool(&integrator->caustics_reflective, node, "caustics_reflective");
+ xml_read_bool(&integrator->caustics_refractive, node, "caustics_refractive");
xml_read_float(&integrator->filter_glossy, node, "filter_glossy");
xml_read_int(&integrator->seed, node, "seed");
@@ -329,6 +330,7 @@ static void xml_read_camera(const XMLReadState& state, pugi::xml_node node)
xml_read_float(&cam->aperturesize, node, "aperturesize"); // 0.5*focallength/fstop
xml_read_float(&cam->focaldistance, node, "focaldistance");
xml_read_float(&cam->shuttertime, node, "shuttertime");
+ xml_read_float(&cam->aperture_ratio, node, "aperture_ratio");
if(xml_equal_string(node, "type", "orthographic"))
cam->type = CAMERA_ORTHOGRAPHIC;
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index ad553fb1d62..e97ad2e71f5 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -44,6 +44,7 @@ set(ADDON_FILES
addon/presets.py
addon/properties.py
addon/ui.py
+ addon/version_update.py
)
add_definitions(${GL_DEFINITIONS})
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 27d986900c8..d1d27df8dc3 100644
--- a/intern/cycles/blender/addon/__init__.py
+++ b/intern/cycles/blender/addon/__init__.py
@@ -31,7 +31,7 @@ bl_info = {
import bpy
from . import engine
-
+from . import version_update
class CyclesRender(bpy.types.RenderEngine):
bl_idname = 'CYCLES'
@@ -100,12 +100,16 @@ def register():
presets.register()
bpy.utils.register_module(__name__)
+ bpy.app.handlers.version_update.append(version_update.do_versions)
+
def unregister():
from . import ui
from . import properties
from . import presets
+ bpy.app.handlers.version_update.remove(version_update.do_versions)
+
ui.unregister()
properties.unregister()
presets.unregister()
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 21a92a29cfc..18235eca790 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -65,6 +65,7 @@ def bake(engine, obj, pass_type, pixel_array, num_pixels, depth, result):
if session is not None:
_cycles.bake(engine.session, obj.as_pointer(), pass_type, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
+
def reset(engine, data, scene):
import _cycles
data = data.as_pointer()
diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py
index 9991fdb8e3b..2ec65d7183a 100644
--- a/intern/cycles/blender/addon/presets.py
+++ b/intern/cycles/blender/addon/presets.py
@@ -33,12 +33,16 @@ class AddPresetIntegrator(AddPresetBase, Operator):
preset_values = [
"cycles.max_bounces",
"cycles.min_bounces",
- "cycles.no_caustics",
"cycles.diffuse_bounces",
"cycles.glossy_bounces",
"cycles.transmission_bounces",
+ "cycles.volume_bounces",
"cycles.transparent_min_bounces",
- "cycles.transparent_max_bounces"
+ "cycles.transparent_max_bounces",
+ "cycles.use_transparent_shadows",
+ "cycles.caustics_reflective",
+ "cycles.caustics_refractive",
+ "cycles.blur_glossy"
]
preset_subdir = "cycles/integrator"
@@ -66,10 +70,13 @@ class AddPresetSampling(AddPresetBase, Operator):
"cycles.mesh_light_samples",
"cycles.subsurface_samples",
"cycles.volume_samples",
- "cycles.no_caustics",
- "cycles.blur_glossy",
"cycles.use_square_samples",
- "cycles.progressive"
+ "cycles.progressive",
+ "cycles.seed",
+ "cycles.sample_clamp_direct",
+ "cycles.sample_clamp_indirect",
+ "cycles.sample_all_lights_direct",
+ "cycles.sample_all_lights_indirect",
]
preset_subdir = "cycles/sampling"
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index b4a1b10f8b4..0ac0e0f091e 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -259,11 +259,18 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default=True,
)
- cls.no_caustics = BoolProperty(
- name="No Caustics",
- description="Leave out caustics, resulting in a darker image with less noise",
- default=False,
+ cls.caustics_reflective = BoolProperty(
+ name="Reflective Caustics",
+ description="Use reflective caustics, resulting in a brighter image (more noise but added realism)",
+ default=True,
+ )
+
+ cls.caustics_refractive = BoolProperty(
+ name="Refractive Caustics",
+ description="Use refractive caustics, resulting in a brighter image (more noise but added realism)",
+ default=True,
)
+
cls.blur_glossy = FloatProperty(
name="Filter Glossy",
description="Adaptively blur glossy shaders after blurry bounces, "
@@ -544,6 +551,13 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
subtype='ANGLE',
default=0,
)
+ cls.aperture_ratio = FloatProperty(
+ name="Aperture Ratio",
+ description="Distortion to simulate anamorphic lens bokeh",
+ min=0.01, soft_min=1.0, soft_max=2.0,
+ default=1.0,
+ precision=4,
+ )
cls.panorama_type = EnumProperty(
name="Panorama Type",
description="Distortion to use for the calculation",
@@ -724,6 +738,11 @@ class CyclesVisibilitySettings(bpy.types.PropertyGroup):
description="Object visibility for shadow rays",
default=True,
)
+ cls.scatter = BoolProperty(
+ name="Volume Scatter",
+ description="Object visibility for volume scatter rays",
+ default=True,
+ )
@classmethod
def unregister(cls):
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 35ae8ecb7c1..6e40c42fb2d 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -154,7 +154,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
sub.prop(cscene, "subsurface_samples", text="Subsurface")
sub.prop(cscene, "volume_samples", text="Volume")
- if cscene.feature_set == 'EXPERIMENTAL' and use_cpu(context):
+ if use_cpu(context) or cscene.feature_set == 'EXPERIMENTAL':
layout.row().prop(cscene, "sampling_pattern", text="Pattern")
for rl in scene.render.layers:
@@ -210,7 +210,8 @@ class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
col.separator()
- col.prop(cscene, "no_caustics")
+ col.prop(cscene, "caustics_reflective")
+ col.prop(cscene, "caustics_refractive")
col.prop(cscene, "blur_glossy")
col = split.column()
@@ -468,6 +469,7 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
sub = col.column(align=True)
sub.prop(ccam, "aperture_blades", text="Blades")
sub.prop(ccam, "aperture_rotation", text="Rotation")
+ sub.prop(ccam, "aperture_ratio", text="Ratio")
class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
@@ -617,6 +619,7 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
flow.prop(visibility, "diffuse")
flow.prop(visibility, "glossy")
flow.prop(visibility, "transmission")
+ flow.prop(visibility, "scatter")
if ob.type != 'LAMP':
flow.prop(visibility, "shadow")
@@ -629,7 +632,8 @@ class CYCLES_OT_use_shading_nodes(Operator):
@classmethod
def poll(cls, context):
- return context.material or context.world or context.lamp
+ return (getattr(context, "material", False) or getattr(context, "world", False) or
+ getattr(context, "lamp", False))
def execute(self, context):
if context.material:
@@ -895,6 +899,7 @@ class CyclesWorld_PT_ray_visibility(CyclesButtonsPanel, Panel):
flow.prop(visibility, "diffuse")
flow.prop(visibility, "glossy")
flow.prop(visibility, "transmission")
+ flow.prop(visibility, "scatter")
class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
@@ -928,7 +933,9 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
col = split.column()
col.label(text="Volume:")
- col.prop(cworld, "volume_sampling", text="")
+ sub = col.column()
+ sub.active = use_cpu(context)
+ sub.prop(cworld, "volume_sampling", text="")
col.prop(cworld, "homogeneous_volume", text="Homogeneous")
@@ -1030,7 +1037,9 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
col = split.column()
col.label(text="Volume:")
- col.prop(cmat, "volume_sampling", text="")
+ sub = col.column()
+ sub.active = use_cpu(context)
+ sub.prop(cmat, "volume_sampling", text="")
col.prop(cmat, "homogeneous_volume", text="Homogeneous")
@@ -1244,13 +1253,13 @@ class CyclesRender_PT_bake(CyclesButtonsPanel, Panel):
scene = context.scene
cscene = scene.cycles
cbk = scene.render.bake
-
+
layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type
-
+
col = layout.column()
col.prop(cscene, "bake_type")
col.separator()
-
+
split = layout.split()
col = split.column()
diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py
new file mode 100644
index 00000000000..6f9509e7d99
--- /dev/null
+++ b/intern/cycles/blender/addon/version_update.py
@@ -0,0 +1,44 @@
+#
+# 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
+#
+
+# <pep8 compliant>
+
+import bpy
+
+from bpy.app.handlers import persistent
+
+
+@persistent
+def do_versions(self):
+ # We don't modify startup file because it assumes to
+ # have all the default values only.
+ if not bpy.data.is_saved:
+ return
+
+ if bpy.data.version <= (2, 71, 0):
+ for scene in bpy.data.scenes:
+ cscene = scene.cycles
+ if not cscene.is_property_set("volume_bounces"):
+ cscene.volume_bounces = 1
+
+ for scene in bpy.data.scenes:
+ cscene = scene.cycles
+ if (cscene.get("no_caustics", False) and
+ not cscene.is_property_set("caustics_reflective") and
+ not cscene.is_property_set("caustics_refractive")):
+
+ cscene.caustics_reflective = False
+ cscene.caustics_refractive = False
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index 1a85561c6d5..ce8c64c4819 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -46,6 +46,8 @@ struct BlenderCamera {
float2 pixelaspect;
+ float aperture_ratio;
+
PanoramaType panorama_type;
float fisheye_fov;
float fisheye_lens;
@@ -167,6 +169,7 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, boo
bcam->apertureblades = RNA_int_get(&ccamera, "aperture_blades");
bcam->aperturerotation = RNA_float_get(&ccamera, "aperture_rotation");
bcam->focaldistance = blender_camera_focal_distance(b_ob, b_camera);
+ bcam->aperture_ratio = RNA_float_get(&ccamera, "aperture_ratio");
bcam->shift.x = b_camera.shift_x();
bcam->shift.y = b_camera.shift_y();
@@ -328,6 +331,9 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
cam->fisheye_fov = bcam->fisheye_fov;
cam->fisheye_lens = bcam->fisheye_lens;
+ /* anamorphic lens bokeh */
+ cam->aperture_ratio = bcam->aperture_ratio;
+
/* perspective */
cam->fov = 2.0f * atanf((0.5f * sensor_size) / bcam->lens / aspectratio);
cam->focaldistance = bcam->focaldistance;
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 7b1a8ec0b15..8cfaea59a06 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -15,10 +15,11 @@
*/
#include "attribute.h"
+#include "camera.h"
+#include "curves.h"
#include "mesh.h"
#include "object.h"
#include "scene.h"
-#include "curves.h"
#include "blender_sync.h"
#include "blender_util.h"
@@ -39,7 +40,8 @@ bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Parti
bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num);
bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background);
void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData);
-void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam);
+void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
+ float3 RotCam, bool is_ortho);
void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resolution);
void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata);
void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata);
@@ -328,7 +330,8 @@ static void set_resolution(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, BL::S
}
}
-void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam)
+void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
+ float3 RotCam, bool is_ortho)
{
int vertexno = mesh->verts.size();
int vertexindex = vertexno;
@@ -362,7 +365,10 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotC
float3 ickey_loc = CData->curvekey_co[CData->curve_firstkey[curve]];
float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.0f);
v1 = CData->curvekey_co[CData->curve_firstkey[curve] + 1] - CData->curvekey_co[CData->curve_firstkey[curve]];
- xbasis = normalize(cross(RotCam - ickey_loc,v1));
+ if(is_ortho)
+ xbasis = normalize(cross(RotCam, v1));
+ else
+ xbasis = normalize(cross(RotCam - ickey_loc, v1));
float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
mesh->verts.push_back(ickey_loc_shfl);
@@ -386,7 +392,10 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotC
if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
- xbasis = normalize(cross(RotCam - ickey_loc,v1));
+ if(is_ortho)
+ xbasis = normalize(cross(RotCam, v1));
+ else
+ xbasis = normalize(cross(RotCam - ickey_loc, v1));
float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
mesh->verts.push_back(ickey_loc_shfl);
@@ -858,20 +867,26 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview);
- /* obtain camera parameters */
- BL::Object b_CamOb = b_scene.camera();
- float3 RotCam = make_float3(0.0f, 0.0f, 0.0f);
- if(b_CamOb) {
- Transform ctfm = get_transform(b_CamOb.matrix_world());
- Transform tfm = get_transform(b_ob.matrix_world());
- Transform itfm = transform_quick_inverse(tfm);
- RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w));
- }
-
/* add hair geometry to mesh */
if(primitive == CURVE_TRIANGLES) {
- if(triangle_method == CURVE_CAMERA_TRIANGLES)
- ExportCurveTrianglePlanes(mesh, &CData, RotCam);
+ if(triangle_method == CURVE_CAMERA_TRIANGLES) {
+ /* obtain camera parameters */
+ float3 RotCam;
+ Camera *camera = scene->camera;
+ Transform &ctfm = camera->matrix;
+ if(camera->type == CAMERA_ORTHOGRAPHIC) {
+ RotCam = -make_float3(ctfm.x.z, ctfm.y.z, ctfm.z.z);
+ }
+ else {
+ Transform tfm = get_transform(b_ob.matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+ RotCam = transform_point(&itfm, make_float3(ctfm.x.w,
+ ctfm.y.w,
+ ctfm.z.w));
+ }
+ bool is_ortho = camera->type == CAMERA_ORTHOGRAPHIC;
+ ExportCurveTrianglePlanes(mesh, &CData, RotCam, is_ortho);
+ }
else {
ExportCurveTriangleGeometry(mesh, &CData, resolution);
used_res = resolution;
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index e7c18c9706b..a5e4b7bd2ae 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -35,14 +35,14 @@ CCL_NAMESPACE_BEGIN
/* Tangent Space */
struct MikkUserData {
- MikkUserData(const BL::Mesh mesh_, const BL::MeshTextureFaceLayer layer_, int num_faces_)
+ MikkUserData(const BL::Mesh mesh_, BL::MeshTextureFaceLayer *layer_, int num_faces_)
: mesh(mesh_), layer(layer_), num_faces(num_faces_)
{
tangent.resize(num_faces*4);
}
BL::Mesh mesh;
- BL::MeshTextureFaceLayer layer;
+ BL::MeshTextureFaceLayer *layer;
int num_faces;
vector<float4> tangent;
};
@@ -78,26 +78,34 @@ static void mikk_get_position(const SMikkTSpaceContext *context, float P[3], con
static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float uv[2], const int face_num, const int vert_num)
{
MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
- BL::MeshTextureFace tf = userdata->layer.data[face_num];
- float3 tfuv;
-
- switch (vert_num) {
- case 0:
- tfuv = get_float3(tf.uv1());
- break;
- case 1:
- tfuv = get_float3(tf.uv2());
- break;
- case 2:
- tfuv = get_float3(tf.uv3());
- break;
- default:
- tfuv = get_float3(tf.uv4());
- break;
+ if(userdata->layer != NULL) {
+ BL::MeshTextureFace tf = userdata->layer->data[face_num];
+ float3 tfuv;
+
+ switch (vert_num) {
+ case 0:
+ tfuv = get_float3(tf.uv1());
+ break;
+ case 1:
+ tfuv = get_float3(tf.uv2());
+ break;
+ case 2:
+ tfuv = get_float3(tf.uv3());
+ break;
+ default:
+ tfuv = get_float3(tf.uv4());
+ break;
+ }
+
+ uv[0] = tfuv.x;
+ uv[1] = tfuv.y;
+ }
+ else {
+ int vert_idx = userdata->mesh.tessfaces[face_num].vertices()[vert_num];
+ float3 orco =
+ get_float3(userdata->mesh.vertices[vert_idx].undeformed_co());
+ map_to_sphere(&uv[0], &uv[1], orco[0], orco[1], orco[2]);
}
-
- uv[0] = tfuv.x;
- uv[1] = tfuv.y;
}
static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], const int face_num, const int vert_num)
@@ -127,7 +135,7 @@ static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const floa
userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign);
}
-static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector<int>& nverts, bool need_sign, bool active_render)
+static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer *b_layer, Mesh *mesh, vector<int>& nverts, bool need_sign, bool active_render)
{
/* setup userdata */
MikkUserData userdata(b_mesh, b_layer, nverts.size());
@@ -153,7 +161,11 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la
/* create tangent attributes */
Attribute *attr;
- ustring name = ustring((string(b_layer.name().c_str()) + ".tangent").c_str());
+ ustring name;
+ if(b_layer != NULL)
+ name = ustring((string(b_layer->name().c_str()) + ".tangent").c_str());
+ else
+ name = ustring("orco.tangent");
if(active_render)
attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name);
@@ -167,7 +179,11 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la
if(need_sign) {
Attribute *attr_sign;
- ustring name_sign = ustring((string(b_layer.name().c_str()) + ".tangent_sign").c_str());
+ ustring name_sign;
+ if(b_layer != NULL)
+ name_sign = ustring((string(b_layer->name().c_str()) + ".tangent_sign").c_str());
+ else
+ name_sign = ustring("orco.tangent_sign");
if(active_render)
attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
@@ -371,7 +387,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
}
/* create uv map attributes */
- {
+ if (b_mesh.tessface_uv_textures.length() != 0) {
BL::Mesh::tessface_uv_textures_iterator l;
for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
@@ -416,10 +432,14 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str());
bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std));
- mikk_compute_tangents(b_mesh, *l, mesh, nverts, need_sign, active_render);
+ mikk_compute_tangents(b_mesh, &(*l), mesh, nverts, need_sign, active_render);
}
}
}
+ else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) {
+ bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN);
+ mikk_compute_tangents(b_mesh, NULL, mesh, nverts, need_sign, true);
+ }
/* for volume objects, create a matrix to transform from object space to
* mesh texture space. this does not work with deformations but that can
@@ -505,15 +525,16 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
}
/* test if we need to sync */
+ bool use_mesh_geometry = render_layer.use_surfaces || render_layer.use_hair;
Mesh *mesh;
if(!mesh_map.sync(&mesh, key)) {
-
/* if transform was applied to mesh, need full update */
if(object_updated && mesh->transform_applied);
/* test if shaders changed, these can be object level so mesh
* does not get tagged for recalc */
else if(mesh->used_shaders != used_shaders);
+ else if(use_mesh_geometry != mesh->geometry_synced);
else {
/* even if not tagged for recalc, we may need to sync anyway
* because the shader needs different mesh attributes */
@@ -540,15 +561,21 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
vector<Mesh::Triangle> oldtriangle = mesh->triangles;
/* compares curve_keys rather than strands in order to handle quick hair
- * adjustsments in dynamic BVH - other methods could probably do this better*/
+ * adjustments in dynamic BVH - other methods could probably do this better*/
vector<float4> oldcurve_keys = mesh->curve_keys;
mesh->clear();
mesh->used_shaders = used_shaders;
mesh->name = ustring(b_ob_data.name().c_str());
- if(render_layer.use_surfaces || render_layer.use_hair) {
- if(preview)
+ if(use_mesh_geometry) {
+ /* mesh objects does have special handle in the dependency graph,
+ * they're ensured to have properly updated.
+ *
+ * updating meshes here will end up having derived mesh referencing
+ * freed data from the blender side.
+ */
+ if(preview && b_ob.type() != BL::Object::type_MESH)
b_ob.update_from_editmode();
bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
@@ -570,6 +597,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
/* free derived mesh */
b_data.meshes.remove(b_mesh);
}
+ mesh->geometry_synced = true;
}
/* displacement method */
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 94dec0b8244..1e07c5f9c96 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -82,6 +82,7 @@ static uint object_ray_visibility(BL::Object b_ob)
flag |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0;
flag |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0;
flag |= get_boolean(cvisibility, "shadow")? PATH_RAY_SHADOW: 0;
+ flag |= get_boolean(cvisibility, "scatter")? PATH_RAY_VOLUME_SCATTER: 0;
return flag;
}
@@ -172,6 +173,7 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI
light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0;
light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0;
light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0;
+ light->use_scatter = (visibility & PATH_RAY_VOLUME_SCATTER) != 0;
/* tag */
light->tag_update(scene);
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 1d18f564e32..b756d6acdb2 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -179,7 +179,7 @@ static PyObject *bake_func(PyObject *self, PyObject *args)
python_thread_state_save(&session->python_thread_state);
- session->bake(b_object, pass_type, b_bake_pixel, num_pixels, depth, (float *)b_result);
+ session->bake(b_object, pass_type, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result);
python_thread_state_restore(&session->python_thread_state);
@@ -363,7 +363,12 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
/* find socket socket */
BL::NodeSocket b_sock(PointerRNA_NULL);
if (param->isoutput) {
+#if OSL_LIBRARY_VERSION_CODE < 10500
b_sock = b_node.outputs[param->name];
+#else
+ b_sock = b_node.outputs[param->name.string()];
+#endif
+
/* remove if type no longer matches */
if(b_sock && b_sock.bl_idname() != socket_type) {
@@ -372,7 +377,11 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
}
}
else {
+#if OSL_LIBRARY_VERSION_CODE < 10500
b_sock = b_node.inputs[param->name];
+#else
+ b_sock = b_node.inputs[param->name.string()];
+#endif
/* remove if type no longer matches */
if(b_sock && b_sock.bl_idname() != socket_type) {
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 0f31e55d60d..4ff3d89f9f1 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -88,6 +88,7 @@ void BlenderSession::create_session()
{
SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
+ bool session_pause = BlenderSync::get_session_pause(b_scene, background);
/* reset status/progress */
last_status = "";
@@ -107,15 +108,17 @@ void BlenderSession::create_session()
session->scene = scene;
session->progress.set_update_callback(function_bind(&BlenderSession::tag_redraw, this));
session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this));
- session->set_pause(BlenderSync::get_session_pause(b_scene, background));
+ session->set_pause(session_pause);
/* create sync */
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, session_params.device.type == DEVICE_CPU);
if(b_v3d) {
- /* full data sync */
- sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state);
- sync->sync_view(b_v3d, b_rv3d, width, height);
+ if(session_pause == false) {
+ /* full data sync */
+ sync->sync_view(b_v3d, b_rv3d, width, height);
+ sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state);
+ }
}
else {
/* for final render we will do full data sync per render layer, only
@@ -492,7 +495,7 @@ static void populate_bake_data(BakeData *data, BL::BakePixel pixel_array, const
}
}
-void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, int num_pixels, int depth, float result[])
+void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float result[])
{
ShaderEvalType shader_type = get_shader_type(pass_type);
size_t object_index = OBJECT_NONE;
@@ -526,6 +529,7 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::Bake
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height);
+ scene->bake_manager->set_shader_limit((size_t)b_engine.tile_x(), (size_t)b_engine.tile_y());
scene->bake_manager->set_baking(true);
/* set number of samples */
@@ -554,6 +558,8 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::Bake
session->reset(buffer_params, session_params.samples);
session->update_scene();
+ session->progress.set_update_callback(function_bind(&BlenderSession::update_bake_progress, this));
+
scene->bake_manager->bake(scene->device, &scene->dscene, scene, session->progress, shader_type, bake_data, result);
/* free all memory used (host and device), so we wouldn't leave render
@@ -625,6 +631,7 @@ void BlenderSession::synchronize()
/* on session/scene parameter changes, we recreate session entirely */
SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
+ bool session_pause = BlenderSync::get_session_pause(b_scene, background);
if(session->params.modified(session_params) ||
scene->params.modified(scene_params))
@@ -637,12 +644,18 @@ void BlenderSession::synchronize()
/* increase samples, but never decrease */
session->set_samples(session_params.samples);
- session->set_pause(BlenderSync::get_session_pause(b_scene, background));
+ session->set_pause(session_pause);
/* copy recalc flags, outside of mutex so we can decide to do the real
* synchronization at a later time to not block on running updates */
sync->sync_recalc();
+ /* don't do synchronization if on pause */
+ if(session_pause) {
+ tag_update();
+ return;
+ }
+
/* try to acquire mutex. if we don't want to or can't, come back later */
if(!session->ready_to_reset() || !session->scene->mutex.try_lock()) {
tag_update();
@@ -718,10 +731,12 @@ bool BlenderSession::draw(int w, int h)
if(reset) {
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height);
+ bool session_pause = BlenderSync::get_session_pause(b_scene, background);
- session->reset(buffer_params, session_params.samples);
-
- start_resize_time = 0.0;
+ if(session_pause == false) {
+ session->reset(buffer_params, session_params.samples);
+ start_resize_time = 0.0;
+ }
}
}
else {
@@ -765,6 +780,26 @@ void BlenderSession::get_progress(float& progress, double& total_time)
progress = 0.0;
}
+void BlenderSession::update_bake_progress()
+{
+ float progress;
+ int sample, samples_per_task, parts_total;
+
+ sample = session->progress.get_sample();
+ samples_per_task = scene->bake_manager->num_samples;
+ parts_total = scene->bake_manager->num_parts;
+
+ if(samples_per_task)
+ progress = ((float)sample / (float)(parts_total * samples_per_task));
+ else
+ progress = 0.0;
+
+ if(progress != last_progress) {
+ b_engine.update_progress(progress);
+ last_progress = progress;
+ }
+}
+
void BlenderSession::update_status_progress()
{
string timestatus, status, substatus;
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index 0e44493d674..ac685118b3d 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -52,7 +52,7 @@ public:
/* offline render */
void render();
- void bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, int num_pixels, int depth, float pixels[]);
+ void bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float pixels[]);
void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile);
void write_render_tile(RenderTile& rtile);
@@ -73,6 +73,7 @@ public:
void get_progress(float& progress, double& total_time);
void test_cancel();
void update_status_progress();
+ void update_bake_progress();
bool background;
Session *session;
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 51d8a4da744..7752c1ce1bd 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -572,6 +572,13 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
image->animated = b_image_node.image_user().use_auto_refresh();
image->use_alpha = b_image.use_alpha();
+
+ /* TODO(sergey): Does not work properly when we change builtin type. */
+ if (b_image.is_updated()) {
+ scene->image_manager->tag_reload_image(image->filename,
+ image->builtin_data,
+ (InterpolationType)b_image_node.interpolation());
+ }
}
image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
@@ -602,6 +609,13 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
}
env->use_alpha = b_image.use_alpha();
+
+ /* TODO(sergey): Does not work properly when we change builtin type. */
+ if (b_image.is_updated()) {
+ scene->image_manager->tag_reload_image(env->filename,
+ env->builtin_data,
+ INTERPOLATION_LINEAR);
+ }
}
env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()];
@@ -1057,6 +1071,7 @@ void BlenderSync::sync_world(bool update_all)
visibility |= get_boolean(cvisibility, "diffuse")? PATH_RAY_DIFFUSE: 0;
visibility |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0;
visibility |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0;
+ visibility |= get_boolean(cvisibility, "scatter")? PATH_RAY_VOLUME_SCATTER: 0;
background->visibility = visibility;
}
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 19898bfa573..2ac90b34fd7 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -180,10 +180,12 @@ void BlenderSync::sync_integrator()
integrator->volume_max_steps = get_int(cscene, "volume_max_steps");
integrator->volume_step_size = get_float(cscene, "volume_step_size");
- integrator->no_caustics = get_boolean(cscene, "no_caustics");
+ integrator->caustics_reflective = get_boolean(cscene, "caustics_reflective");
+ integrator->caustics_refractive = get_boolean(cscene, "caustics_refractive");
integrator->filter_glossy = get_float(cscene, "blur_glossy");
integrator->seed = get_int(cscene, "seed");
+ integrator->sampling_pattern = (SamplingPattern)RNA_enum_get(&cscene, "sampling_pattern");
integrator->layer_flag = render_layer.layer;
@@ -231,10 +233,6 @@ void BlenderSync::sync_integrator()
integrator->subsurface_samples = subsurface_samples;
integrator->volume_samples = volume_samples;
}
-
-
- if(experimental)
- integrator->sampling_pattern = (SamplingPattern)RNA_enum_get(&cscene, "sampling_pattern");
if(integrator->modified(previntegrator))
integrator->tag_update(scene);
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 3c0c5c021c8..15bd814b8d5 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -103,18 +103,30 @@ bool BVH::cache_read(CacheData& key)
if(Cache::global.lookup(key, value)) {
cache_filename = key.get_filename();
- value.read(pack.root_index);
- value.read(pack.SAH);
-
- value.read(pack.nodes);
- value.read(pack.object_node);
- value.read(pack.tri_woop);
- value.read(pack.prim_type);
- value.read(pack.prim_visibility);
- value.read(pack.prim_index);
- value.read(pack.prim_object);
- value.read(pack.is_leaf);
-
+ if(!(value.read(pack.root_index) &&
+ value.read(pack.SAH) &&
+ value.read(pack.nodes) &&
+ value.read(pack.object_node) &&
+ value.read(pack.tri_woop) &&
+ value.read(pack.prim_type) &&
+ value.read(pack.prim_visibility) &&
+ value.read(pack.prim_index) &&
+ value.read(pack.prim_object) &&
+ value.read(pack.is_leaf)))
+ {
+ /* Clear the pack if load failed. */
+ pack.root_index = 0;
+ pack.SAH = 0.0f;
+ pack.nodes.clear();
+ pack.object_node.clear();
+ pack.tri_woop.clear();
+ pack.prim_type.clear();
+ pack.prim_visibility.clear();
+ pack.prim_index.clear();
+ pack.prim_object.clear();
+ pack.is_leaf.clear();
+ return false;
+ }
return true;
}
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index ed67690a07f..e073b69472e 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -123,7 +123,7 @@ protected:
/* BVH Range
*
* Build range used during construction, to indicate the bounds and place in
- * the reference array of a subset of pirmitives Again uses trickery to pack
+ * the reference array of a subset of primitives Again uses trickery to pack
* integers into BoundBox for alignment purposes. */
class BVHRange
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index 318e4467e00..998b35351e3 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -11,6 +11,8 @@ set(INC
set(INC_SYS
${GLEW_INCLUDE_PATH}
+ ../../../extern/cuew/include
+ ../../../extern/clew/include
)
set(SRC
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 97ec2423b73..0705ca9c487 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -20,12 +20,13 @@
#include "device.h"
#include "device_intern.h"
-#include "util_cuda.h"
+#include "cuew.h"
+#include "clew.h"
+
#include "util_debug.h"
#include "util_foreach.h"
#include "util_half.h"
#include "util_math.h"
-#include "util_opencl.h"
#include "util_opengl.h"
#include "util_time.h"
#include "util_types.h"
@@ -66,7 +67,7 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w
glColor3f(1.0f, 1.0f, 1.0f);
if(rgba.data_type == TYPE_HALF) {
- /* for multi devices, this assumes the ineffecient method that we allocate
+ /* for multi devices, this assumes the inefficient method that we allocate
* all pixels on the device even though we only render to a subset */
GLhalf *data_pointer = (GLhalf*)rgba.data_pointer;
data_pointer += 4*y*w;
@@ -143,7 +144,7 @@ Device *Device::create(DeviceInfo& info, Stats &stats, bool background)
break;
#ifdef WITH_CUDA
case DEVICE_CUDA:
- if(cuLibraryInit())
+ if(device_cuda_init())
device = device_cuda_create(info, stats, background);
else
device = NULL;
@@ -161,7 +162,7 @@ Device *Device::create(DeviceInfo& info, Stats &stats, bool background)
#endif
#ifdef WITH_OPENCL
case DEVICE_OPENCL:
- if(clLibraryInit())
+ if(device_opencl_init())
device = device_opencl_create(info, stats, background);
else
device = NULL;
@@ -215,12 +216,12 @@ vector<DeviceType>& Device::available_types()
types.push_back(DEVICE_CPU);
#ifdef WITH_CUDA
- if(cuLibraryInit())
+ if(device_cuda_init())
types.push_back(DEVICE_CUDA);
#endif
#ifdef WITH_OPENCL
- if(clLibraryInit())
+ if(device_opencl_init())
types.push_back(DEVICE_OPENCL);
#endif
@@ -244,12 +245,12 @@ vector<DeviceInfo>& Device::available_devices()
if(!devices_init) {
#ifdef WITH_CUDA
- if(cuLibraryInit())
+ if(device_cuda_init())
device_cuda_info(devices);
#endif
#ifdef WITH_OPENCL
- if(clLibraryInit())
+ if(device_opencl_init())
device_opencl_info(devices);
#endif
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index bcddd4f73e2..20ebfd391d6 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -122,6 +122,7 @@ public:
virtual bool load_kernels(bool experimental) { return true; }
/* tasks */
+ virtual int get_split_task_count(DeviceTask& task) = 0;
virtual void task_add(DeviceTask& task) = 0;
virtual void task_wait() = 0;
virtual void task_cancel() = 0;
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index 7308d036fe3..4623764d210 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -73,8 +73,8 @@ public:
void mem_alloc(device_memory& mem, MemoryType type)
{
mem.device_pointer = mem.data_pointer;
-
- stats.mem_alloc(mem.memory_size());
+ mem.device_size = mem.memory_size();
+ stats.mem_alloc(mem.device_size);
}
void mem_copy_to(device_memory& mem)
@@ -94,9 +94,11 @@ public:
void mem_free(device_memory& mem)
{
- mem.device_pointer = 0;
-
- stats.mem_free(mem.memory_size());
+ if(mem.device_pointer) {
+ mem.device_pointer = 0;
+ stats.mem_free(mem.device_size);
+ mem.device_size = 0;
+ }
}
void const_copy_to(const char *name, void *host, size_t size)
@@ -108,15 +110,17 @@ public:
{
kernel_tex_copy(&kernel_globals, name, mem.data_pointer, mem.data_width, mem.data_height, mem.data_depth, interpolation);
mem.device_pointer = mem.data_pointer;
-
- stats.mem_alloc(mem.memory_size());
+ mem.device_size = mem.memory_size();
+ stats.mem_alloc(mem.device_size);
}
void tex_free(device_memory& mem)
{
- mem.device_pointer = 0;
-
- stats.mem_free(mem.memory_size());
+ if(mem.device_pointer) {
+ mem.device_pointer = 0;
+ stats.mem_free(mem.device_size);
+ mem.device_size = 0;
+ }
}
void *osl_memory()
@@ -185,7 +189,7 @@ public:
tile.sample = sample + 1;
- task.update_progress(tile);
+ task.update_progress(&tile);
}
}
else
@@ -207,7 +211,7 @@ public:
tile.sample = sample + 1;
- task.update_progress(tile);
+ task.update_progress(&tile);
}
}
else
@@ -229,7 +233,7 @@ public:
tile.sample = sample + 1;
- task.update_progress(tile);
+ task.update_progress(&tile);
}
}
else
@@ -251,7 +255,7 @@ public:
tile.sample = sample + 1;
- task.update_progress(tile);
+ task.update_progress(&tile);
}
}
else
@@ -273,7 +277,7 @@ public:
tile.sample = sample + 1;
- task.update_progress(tile);
+ task.update_progress(&tile);
}
}
else
@@ -294,7 +298,7 @@ public:
tile.sample = sample + 1;
- task.update_progress(tile);
+ task.update_progress(&tile);
}
}
@@ -433,71 +437,89 @@ public:
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
if(system_cpu_support_avx2()) {
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
- for(int sample = 0; sample < task.num_samples; sample++)
- kernel_cpu_avx2_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x, sample);
+ for(int sample = 0; sample < task.num_samples; sample++) {
+ for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
+ kernel_cpu_avx2_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
+ task.shader_eval_type, x, task.offset, sample);
if(task.get_cancel() || task_pool.canceled())
break;
+
+ task.update_progress(NULL);
}
}
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
if(system_cpu_support_avx()) {
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
- for(int sample = 0; sample < task.num_samples; sample++)
- kernel_cpu_avx_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x, sample);
+ for(int sample = 0; sample < task.num_samples; sample++) {
+ for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
+ kernel_cpu_avx_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
+ task.shader_eval_type, x, task.offset, sample);
if(task.get_cancel() || task_pool.canceled())
break;
+
+ task.update_progress(NULL);
}
}
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
if(system_cpu_support_sse41()) {
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
- for(int sample = 0; sample < task.num_samples; sample++)
- kernel_cpu_sse41_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x, sample);
+ for(int sample = 0; sample < task.num_samples; sample++) {
+ for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
+ kernel_cpu_sse41_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
+ task.shader_eval_type, x, task.offset, sample);
if(task.get_cancel() || task_pool.canceled())
break;
+
+ task.update_progress(NULL);
}
}
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
if(system_cpu_support_sse3()) {
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
- for(int sample = 0; sample < task.num_samples; sample++)
- kernel_cpu_sse3_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x, sample);
+ for(int sample = 0; sample < task.num_samples; sample++) {
+ for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
+ kernel_cpu_sse3_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
+ task.shader_eval_type, x, task.offset, sample);
if(task.get_cancel() || task_pool.canceled())
break;
+
+ task.update_progress(NULL);
}
}
else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
if(system_cpu_support_sse2()) {
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
- for(int sample = 0; sample < task.num_samples; sample++)
- kernel_cpu_sse2_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x, sample);
+ for(int sample = 0; sample < task.num_samples; sample++) {
+ for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
+ kernel_cpu_sse2_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
+ task.shader_eval_type, x, task.offset, sample);
if(task.get_cancel() || task_pool.canceled())
break;
+
+ task.update_progress(NULL);
}
}
else
#endif
{
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
- for(int sample = 0; sample < task.num_samples; sample++)
- kernel_cpu_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x, sample);
+ for(int sample = 0; sample < task.num_samples; sample++) {
+ for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
+ kernel_cpu_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output,
+ task.shader_eval_type, x, task.offset, sample);
if(task.get_cancel() || task_pool.canceled())
break;
+
+ task.update_progress(NULL);
}
}
@@ -506,6 +528,14 @@ public:
#endif
}
+ int get_split_task_count(DeviceTask& task)
+ {
+ if (task.type == DeviceTask::SHADER)
+ return task.get_subtask_count(TaskScheduler::num_threads(), 256);
+ else
+ return task.get_subtask_count(TaskScheduler::num_threads());
+ }
+
void task_add(DeviceTask& task)
{
/* split task into smaller ones */
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index be738186b57..5e5af26c491 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -23,7 +23,7 @@
#include "buffers.h"
-#include "util_cuda.h"
+#include "cuew.h"
#include "util_debug.h"
#include "util_map.h"
#include "util_opengl.h"
@@ -61,65 +61,10 @@ public:
return (CUdeviceptr)mem;
}
- static const char *cuda_error_string(CUresult result)
+ static bool have_precompiled_kernels()
{
- switch(result) {
- case CUDA_SUCCESS: return "No errors";
- case CUDA_ERROR_INVALID_VALUE: return "Invalid value";
- case CUDA_ERROR_OUT_OF_MEMORY: return "Out of memory";
- case CUDA_ERROR_NOT_INITIALIZED: return "Driver not initialized";
- case CUDA_ERROR_DEINITIALIZED: return "Driver deinitialized";
-
- case CUDA_ERROR_NO_DEVICE: return "No CUDA-capable device available";
- case CUDA_ERROR_INVALID_DEVICE: return "Invalid device";
-
- case CUDA_ERROR_INVALID_IMAGE: return "Invalid kernel image";
- case CUDA_ERROR_INVALID_CONTEXT: return "Invalid context";
- case CUDA_ERROR_MAP_FAILED: return "Map failed";
- case CUDA_ERROR_UNMAP_FAILED: return "Unmap failed";
- case CUDA_ERROR_ARRAY_IS_MAPPED: return "Array is mapped";
- case CUDA_ERROR_ALREADY_MAPPED: return "Already mapped";
- case CUDA_ERROR_NO_BINARY_FOR_GPU: return "No binary for GPU";
- case CUDA_ERROR_ALREADY_ACQUIRED: return "Already acquired";
- case CUDA_ERROR_NOT_MAPPED: return "Not mapped";
- case CUDA_ERROR_NOT_MAPPED_AS_ARRAY: return "Mapped resource not available for access as an array";
- case CUDA_ERROR_NOT_MAPPED_AS_POINTER: return "Mapped resource not available for access as a pointer";
- case CUDA_ERROR_ECC_UNCORRECTABLE: return "Uncorrectable ECC error detected";
- case CUDA_ERROR_UNSUPPORTED_LIMIT: return "CUlimit not supported by device";
- case CUDA_ERROR_CONTEXT_ALREADY_IN_USE: return "Context already in use";
- case CUDA_ERROR_PEER_ACCESS_UNSUPPORTED: return "Peer access unsupported";
- case CUDA_ERROR_INVALID_PTX: return "Invalid PTX code";
-
- 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";
- case CUDA_ERROR_SHARED_OBJECT_INIT_FAILED: return "Shared object initialization failed";
- case CUDA_ERROR_OPERATING_SYSTEM: return "OS call failed";
-
- case CUDA_ERROR_INVALID_HANDLE: return "Invalid handle";
-
- case CUDA_ERROR_NOT_FOUND: return "Not found";
-
- case CUDA_ERROR_NOT_READY: return "CUDA not ready";
-
- case CUDA_ERROR_ILLEGAL_ADDRESS: return "Illegal address";
- case CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES: return "Launch exceeded resources";
- case CUDA_ERROR_LAUNCH_TIMEOUT: return "Launch exceeded time out";
- case CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING: return "Launch with incompatible texturing";
- case CUDA_ERROR_HARDWARE_STACK_ERROR: return "Stack error";
- case CUDA_ERROR_ILLEGAL_INSTRUCTION: return "Illegal instruction";
- case CUDA_ERROR_MISALIGNED_ADDRESS: return "Misaligned address";
- case CUDA_ERROR_INVALID_ADDRESS_SPACE: return "Invalid address space";
- case CUDA_ERROR_INVALID_PC: return "Invalid program counter";
- case CUDA_ERROR_LAUNCH_FAILED: return "Launch failed";
-
- case CUDA_ERROR_NOT_PERMITTED: return "Operation not permitted";
- case CUDA_ERROR_NOT_SUPPORTED: return "Operation not supported";
-
- case CUDA_ERROR_UNKNOWN: return "Unknown error";
-
- default: return "Unknown CUDA error value";
- }
+ string cubins_path = path_get("lib");
+ return path_exists(cubins_path);
}
/*#ifdef NDEBUG
@@ -141,7 +86,7 @@ public:
CUresult result = stmt; \
\
if(result != CUDA_SUCCESS) { \
- string message = string_printf("CUDA error: %s in %s", cuda_error_string(result), #stmt); \
+ string message = string_printf("CUDA error: %s in %s", cuewErrorString(result), #stmt); \
if(error_msg == "") \
error_msg = message; \
fprintf(stderr, "%s\n", message.c_str()); \
@@ -155,7 +100,7 @@ public:
if(result == CUDA_SUCCESS)
return false;
- string message = string_printf("CUDA error at %s: %s", stmt.c_str(), cuda_error_string(result));
+ string message = string_printf("CUDA error at %s: %s", stmt.c_str(), cuewErrorString(result));
if(error_msg == "")
error_msg = message;
fprintf(stderr, "%s\n", message.c_str());
@@ -252,14 +197,18 @@ public:
return true;
}
- string compile_kernel()
+ string compile_kernel(bool experimental)
{
/* compute cubin name */
int major, minor;
cuDeviceComputeCapability(&major, &minor, cuDevId);
/* attempt to use kernel provided with blender */
- string cubin = path_get(string_printf("lib/kernel_sm_%d%d.cubin", major, minor));
+ string cubin;
+ if(experimental)
+ cubin = path_get(string_printf("lib/kernel_experimental_sm_%d%d.cubin", major, minor));
+ else
+ cubin = path_get(string_printf("lib/kernel_sm_%d%d.cubin", major, minor));
if(path_exists(cubin))
return cubin;
@@ -267,7 +216,10 @@ public:
string kernel_path = path_get("kernel");
string md5 = path_files_md5_hash(kernel_path);
- cubin = string_printf("cycles_kernel_sm%d%d_%s.cubin", major, minor, md5.c_str());
+ if(experimental)
+ cubin = string_printf("cycles_kernel_experimental_sm%d%d_%s.cubin", major, minor, md5.c_str());
+ else
+ cubin = string_printf("cycles_kernel_sm%d%d_%s.cubin", major, minor, md5.c_str());
cubin = path_user_get(path_join("cache", cubin));
/* if exists already, use it */
@@ -275,7 +227,7 @@ public:
return cubin;
#ifdef _WIN32
- if(cuHavePrecompiledKernels()) {
+ if(have_precompiled_kernels()) {
if(major < 2)
cuda_error_message(string_printf("CUDA device requires compute capability 2.0 or up, found %d.%d. Your GPU is not supported.", major, minor));
else
@@ -285,25 +237,25 @@ public:
#endif
/* if not, find CUDA compiler */
- string nvcc = cuCompilerPath();
+ const char *nvcc = cuewCompilerPath();
- if(nvcc == "") {
+ if(nvcc == NULL) {
cuda_error_message("CUDA nvcc compiler not found. Install CUDA toolkit in default location.");
return "";
}
- int cuda_version = cuCompilerVersion();
+ int cuda_version = cuewCompilerVersion();
if(cuda_version == 0) {
cuda_error_message("CUDA nvcc compiler version could not be parsed.");
return "";
}
- if(cuda_version < 50) {
- printf("Unsupported CUDA version %d.%d detected, you need CUDA 6.0.\n", cuda_version/10, cuda_version%10);
+ if(cuda_version < 60) {
+ printf("Unsupported CUDA version %d.%d detected, you need CUDA 6.5.\n", cuda_version/10, cuda_version%10);
return "";
}
- else if(cuda_version != 60)
- printf("CUDA version %d.%d detected, build may succeed but only CUDA 6.0 is officially supported.\n", cuda_version/10, cuda_version%10);
+ else if(cuda_version != 65)
+ printf("CUDA version %d.%d detected, build may succeed but only CUDA 6.5 is officially supported.\n", cuda_version/10, cuda_version%10);
/* compile */
string kernel = path_join(kernel_path, "kernel.cu");
@@ -317,7 +269,10 @@ public:
string command = string_printf("\"%s\" -arch=sm_%d%d -m%d --cubin \"%s\" "
"-o \"%s\" --ptxas-options=\"-v\" -I\"%s\" -DNVCC -D__KERNEL_CUDA_VERSION__=%d",
- nvcc.c_str(), major, minor, machine, kernel.c_str(), cubin.c_str(), include.c_str(), cuda_version);
+ nvcc, major, minor, machine, kernel.c_str(), cubin.c_str(), include.c_str(), cuda_version);
+
+ if(experimental)
+ command += " -D__KERNEL_CUDA_EXPERIMENTAL__";
printf("%s\n", command.c_str());
@@ -348,7 +303,7 @@ public:
return false;
/* get kernel */
- string cubin = compile_kernel();
+ string cubin = compile_kernel(experimental);
if(cubin == "")
return false;
@@ -379,6 +334,7 @@ public:
size_t size = mem.memory_size();
cuda_assert(cuMemAlloc(&device_pointer, size));
mem.device_pointer = (device_ptr)device_pointer;
+ mem.device_size = size;
stats.mem_alloc(size);
cuda_pop_context();
}
@@ -426,7 +382,8 @@ public:
mem.device_pointer = 0;
- stats.mem_free(mem.memory_size());
+ stats.mem_free(mem.device_size);
+ mem.device_size = 0;
}
}
@@ -518,6 +475,7 @@ public:
cuda_assert(cuTexRefSetFlags(texref, CU_TRSF_NORMALIZED_COORDINATES));
mem.device_pointer = (device_ptr)handle;
+ mem.device_size = size;
stats.mem_alloc(size);
}
@@ -585,7 +543,8 @@ public:
tex_interp_map.erase(tex_interp_map.find(mem.device_pointer));
mem.device_pointer = 0;
- stats.mem_free(mem.memory_size());
+ stats.mem_free(mem.device_size);
+ mem.device_size = 0;
}
else {
tex_interp_map.erase(tex_interp_map.find(mem.device_pointer));
@@ -615,40 +574,17 @@ public:
if(have_error())
return;
-
- /* pass in parameters */
- int offset = 0;
-
- cuda_assert(cuParamSetv(cuPathTrace, offset, &d_buffer, sizeof(d_buffer)));
- offset += sizeof(d_buffer);
-
- cuda_assert(cuParamSetv(cuPathTrace, offset, &d_rng_state, sizeof(d_rng_state)));
- offset += sizeof(d_rng_state);
-
- offset = align_up(offset, __alignof(sample));
-
- cuda_assert(cuParamSeti(cuPathTrace, offset, sample));
- offset += sizeof(sample);
-
- cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.x));
- offset += sizeof(rtile.x);
-
- cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.y));
- offset += sizeof(rtile.y);
-
- cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.w));
- offset += sizeof(rtile.w);
-
- cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.h));
- offset += sizeof(rtile.h);
- cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.offset));
- offset += sizeof(rtile.offset);
-
- cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.stride));
- offset += sizeof(rtile.stride);
-
- cuda_assert(cuParamSetSize(cuPathTrace, offset));
+ /* pass in parameters */
+ void *args[] = {&d_buffer,
+ &d_rng_state,
+ &sample,
+ &rtile.x,
+ &rtile.y,
+ &rtile.w,
+ &rtile.h,
+ &rtile.offset,
+ &rtile.stride};
/* launch kernel */
int threads_per_block;
@@ -666,8 +602,11 @@ public:
int yblocks = (rtile.h + ythreads - 1)/ythreads;
cuda_assert(cuFuncSetCacheConfig(cuPathTrace, CU_FUNC_CACHE_PREFER_L1));
- cuda_assert(cuFuncSetBlockShape(cuPathTrace, xthreads, ythreads, 1));
- cuda_assert(cuLaunchGrid(cuPathTrace, xblocks, yblocks));
+
+ cuda_assert(cuLaunchKernel(cuPathTrace,
+ xblocks , yblocks, 1, /* blocks */
+ xthreads, ythreads, 1, /* threads */
+ 0, 0, args, 0));
cuda_assert(cuCtxSynchronize());
@@ -693,40 +632,19 @@ public:
cuda_assert(cuModuleGetFunction(&cuFilmConvert, cuModule, "kernel_cuda_convert_to_byte"));
}
- /* pass in parameters */
- int offset = 0;
-
- cuda_assert(cuParamSetv(cuFilmConvert, offset, &d_rgba, sizeof(d_rgba)));
- offset += sizeof(d_rgba);
-
- cuda_assert(cuParamSetv(cuFilmConvert, offset, &d_buffer, sizeof(d_buffer)));
- offset += sizeof(d_buffer);
float sample_scale = 1.0f/(task.sample + 1);
- offset = align_up(offset, __alignof(sample_scale));
-
- cuda_assert(cuParamSetf(cuFilmConvert, offset, sample_scale));
- offset += sizeof(sample_scale);
-
- cuda_assert(cuParamSeti(cuFilmConvert, offset, task.x));
- offset += sizeof(task.x);
-
- cuda_assert(cuParamSeti(cuFilmConvert, offset, task.y));
- offset += sizeof(task.y);
-
- cuda_assert(cuParamSeti(cuFilmConvert, offset, task.w));
- offset += sizeof(task.w);
-
- cuda_assert(cuParamSeti(cuFilmConvert, offset, task.h));
- offset += sizeof(task.h);
-
- cuda_assert(cuParamSeti(cuFilmConvert, offset, task.offset));
- offset += sizeof(task.offset);
- cuda_assert(cuParamSeti(cuFilmConvert, offset, task.stride));
- offset += sizeof(task.stride);
-
- cuda_assert(cuParamSetSize(cuFilmConvert, offset));
+ /* pass in parameters */
+ void *args[] = {&d_rgba,
+ &d_buffer,
+ &sample_scale,
+ &task.x,
+ &task.y,
+ &task.w,
+ &task.h,
+ &task.offset,
+ &task.stride};
/* launch kernel */
int threads_per_block;
@@ -738,8 +656,11 @@ public:
int yblocks = (task.h + ythreads - 1)/ythreads;
cuda_assert(cuFuncSetCacheConfig(cuFilmConvert, CU_FUNC_CACHE_PREFER_L1));
- cuda_assert(cuFuncSetBlockShape(cuFilmConvert, xthreads, ythreads, 1));
- cuda_assert(cuLaunchGrid(cuFilmConvert, xblocks, yblocks));
+
+ cuda_assert(cuLaunchKernel(cuFilmConvert,
+ xblocks , yblocks, 1, /* blocks */
+ xthreads, ythreads, 1, /* threads */
+ 0, 0, args, 0));
unmap_pixels((rgba_byte)? rgba_byte: rgba_half);
@@ -769,39 +690,21 @@ public:
const int shader_chunk_size = 65536;
const int start = task.shader_x;
const int end = task.shader_x + task.shader_w;
+ int offset = task.offset;
- for(int shader_x = start; shader_x < end; shader_x += shader_chunk_size) {
- if(task.get_cancel())
- break;
-
- int shader_w = min(shader_chunk_size, end - shader_x);
+ bool canceled = false;
+ for(int sample = 0; sample < task.num_samples && !canceled; sample++) {
+ for(int shader_x = start; shader_x < end; shader_x += shader_chunk_size) {
+ int shader_w = min(shader_chunk_size, end - shader_x);
- for(int sample = 0; sample < task.num_samples; sample++) {
/* pass in parameters */
- int offset = 0;
-
- cuda_assert(cuParamSetv(cuShader, offset, &d_input, sizeof(d_input)));
- offset += sizeof(d_input);
-
- cuda_assert(cuParamSetv(cuShader, offset, &d_output, sizeof(d_output)));
- offset += sizeof(d_output);
-
- int shader_eval_type = task.shader_eval_type;
- offset = align_up(offset, __alignof(shader_eval_type));
-
- cuda_assert(cuParamSeti(cuShader, offset, task.shader_eval_type));
- offset += sizeof(task.shader_eval_type);
-
- cuda_assert(cuParamSeti(cuShader, offset, shader_x));
- offset += sizeof(shader_x);
-
- cuda_assert(cuParamSeti(cuShader, offset, shader_w));
- offset += sizeof(shader_w);
-
- cuda_assert(cuParamSeti(cuShader, offset, sample));
- offset += sizeof(sample);
-
- cuda_assert(cuParamSetSize(cuShader, offset));
+ void *args[] = {&d_input,
+ &d_output,
+ &task.shader_eval_type,
+ &shader_x,
+ &shader_w,
+ &offset,
+ &sample};
/* launch kernel */
int threads_per_block;
@@ -810,11 +713,20 @@ public:
int xblocks = (shader_w + threads_per_block - 1)/threads_per_block;
cuda_assert(cuFuncSetCacheConfig(cuShader, CU_FUNC_CACHE_PREFER_L1));
- cuda_assert(cuFuncSetBlockShape(cuShader, threads_per_block, 1, 1));
- cuda_assert(cuLaunchGrid(cuShader, xblocks, 1));
+ cuda_assert(cuLaunchKernel(cuShader,
+ xblocks , 1, 1, /* blocks */
+ threads_per_block, 1, 1, /* threads */
+ 0, 0, args, 0));
cuda_assert(cuCtxSynchronize());
+
+ if(task.get_cancel()) {
+ canceled = false;
+ break;
+ }
}
+
+ task.update_progress(NULL);
}
cuda_pop_context();
@@ -882,7 +794,8 @@ public:
mem.device_pointer = pmem.cuTexId;
pixel_mem_map[mem.device_pointer] = pmem;
- stats.mem_alloc(mem.memory_size());
+ mem.device_size = mem.memory_size();
+ stats.mem_alloc(mem.device_size);
return;
}
@@ -939,7 +852,8 @@ public:
pixel_mem_map.erase(pixel_mem_map.find(mem.device_pointer));
mem.device_pointer = 0;
- stats.mem_free(mem.memory_size());
+ stats.mem_free(mem.device_size);
+ mem.device_size = 0;
return;
}
@@ -956,7 +870,7 @@ public:
cuda_push_context();
- /* for multi devices, this assumes the ineffecient method that we allocate
+ /* for multi devices, this assumes the inefficient method that we allocate
* all pixels on the device even though we only render to a subset */
size_t offset = 4*y*w;
@@ -1046,7 +960,7 @@ public:
tile.sample = sample + 1;
- task->update_progress(tile);
+ task->update_progress(&tile);
}
task->release_tile(tile);
@@ -1070,6 +984,11 @@ public:
}
};
+ int get_split_task_count(DeviceTask& task)
+ {
+ return 1;
+ }
+
void task_add(DeviceTask& task)
{
if(task.type == DeviceTask::FILM_CONVERT) {
@@ -1096,6 +1015,28 @@ public:
}
};
+bool device_cuda_init(void)
+{
+ static bool initialized = false;
+ static bool result = false;
+
+ if (initialized)
+ return result;
+
+ initialized = true;
+
+ if (cuewInit() == CUEW_SUCCESS) {
+ if(CUDADevice::have_precompiled_kernels())
+ result = true;
+#ifndef _WIN32
+ else if(cuewCompilerPath() != NULL)
+ result = true;
+#endif
+ }
+
+ return result;
+}
+
Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background)
{
return new CUDADevice(info, stats, background);
@@ -1109,13 +1050,13 @@ void device_cuda_info(vector<DeviceInfo>& devices)
result = cuInit(0);
if(result != CUDA_SUCCESS) {
if(result != CUDA_ERROR_NO_DEVICE)
- fprintf(stderr, "CUDA cuInit: %s\n", CUDADevice::cuda_error_string(result));
+ fprintf(stderr, "CUDA cuInit: %s\n", cuewErrorString(result));
return;
}
result = cuDeviceGetCount(&count);
if(result != CUDA_SUCCESS) {
- fprintf(stderr, "CUDA cuDeviceGetCount: %s\n", CUDADevice::cuda_error_string(result));
+ fprintf(stderr, "CUDA cuDeviceGetCount: %s\n", cuewErrorString(result));
return;
}
diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h
index 7eb66c25a81..80f1e2441a5 100644
--- a/intern/cycles/device/device_intern.h
+++ b/intern/cycles/device/device_intern.h
@@ -22,7 +22,9 @@ CCL_NAMESPACE_BEGIN
class Device;
Device *device_cpu_create(DeviceInfo& info, Stats &stats, bool background);
+bool device_opencl_init(void);
Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background);
+bool device_cuda_init(void);
Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background);
Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address);
Device *device_multi_create(DeviceInfo& info, Stats &stats, bool background);
diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h
index 8d6f4a49a9c..8eee6a2c79e 100644
--- a/intern/cycles/device/device_memory.h
+++ b/intern/cycles/device/device_memory.h
@@ -167,6 +167,7 @@ public:
int data_elements;
device_ptr data_pointer;
size_t data_size;
+ size_t device_size;
size_t data_width;
size_t data_height;
size_t data_depth;
@@ -194,6 +195,7 @@ public:
data_elements = device_type_traits<T>::num_elements;
data_pointer = 0;
data_size = 0;
+ device_size = 0;
data_width = 0;
data_height = 0;
data_depth = 0;
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index c866ebaaea2..7f055c79491 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -278,6 +278,22 @@ public:
return -1;
}
+ int get_split_task_count(DeviceTask& task)
+ {
+ int total_tasks = 0;
+ list<DeviceTask> tasks;
+ task.split(tasks, devices.size());
+ foreach(SubDevice& sub, devices) {
+ if(!tasks.empty()) {
+ DeviceTask subtask = tasks.front();
+ tasks.pop_front();
+
+ total_tasks += sub.device->get_split_task_count(subtask);
+ }
+ }
+ return total_tasks;
+ }
+
void task_add(DeviceTask& task)
{
list<DeviceTask> tasks;
diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp
index af051076009..dca9bf29e70 100644
--- a/intern/cycles/device/device_network.cpp
+++ b/intern/cycles/device/device_network.cpp
@@ -299,6 +299,11 @@ public:
snd.write();
}
+ int get_split_task_count(DeviceTask& task)
+ {
+ return 1;
+ }
+
private:
NetworkError error_func;
};
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index abfe445414a..d950d084cd4 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -25,11 +25,12 @@
#include "buffers.h"
+#include "clew.h"
+
#include "util_foreach.h"
#include "util_map.h"
#include "util_math.h"
#include "util_md5.h"
-#include "util_opencl.h"
#include "util_opengl.h"
#include "util_path.h"
#include "util_time.h"
@@ -334,63 +335,10 @@ public:
bool device_initialized;
string platform_name;
- const char *opencl_error_string(cl_int err)
- {
- switch (err) {
- case CL_SUCCESS: return "Success!";
- case CL_DEVICE_NOT_FOUND: return "Device not found.";
- case CL_DEVICE_NOT_AVAILABLE: return "Device not available";
- case CL_COMPILER_NOT_AVAILABLE: return "Compiler not available";
- case CL_MEM_OBJECT_ALLOCATION_FAILURE: return "Memory object allocation failure";
- case CL_OUT_OF_RESOURCES: return "Out of resources";
- case CL_OUT_OF_HOST_MEMORY: return "Out of host memory";
- case CL_PROFILING_INFO_NOT_AVAILABLE: return "Profiling information not available";
- case CL_MEM_COPY_OVERLAP: return "Memory copy overlap";
- case CL_IMAGE_FORMAT_MISMATCH: return "Image format mismatch";
- case CL_IMAGE_FORMAT_NOT_SUPPORTED: return "Image format not supported";
- case CL_BUILD_PROGRAM_FAILURE: return "Program build failure";
- case CL_MAP_FAILURE: return "Map failure";
- case CL_INVALID_VALUE: return "Invalid value";
- case CL_INVALID_DEVICE_TYPE: return "Invalid device type";
- case CL_INVALID_PLATFORM: return "Invalid platform";
- case CL_INVALID_DEVICE: return "Invalid device";
- case CL_INVALID_CONTEXT: return "Invalid context";
- case CL_INVALID_QUEUE_PROPERTIES: return "Invalid queue properties";
- case CL_INVALID_COMMAND_QUEUE: return "Invalid command queue";
- case CL_INVALID_HOST_PTR: return "Invalid host pointer";
- case CL_INVALID_MEM_OBJECT: return "Invalid memory object";
- case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: return "Invalid image format descriptor";
- case CL_INVALID_IMAGE_SIZE: return "Invalid image size";
- case CL_INVALID_SAMPLER: return "Invalid sampler";
- case CL_INVALID_BINARY: return "Invalid binary";
- case CL_INVALID_BUILD_OPTIONS: return "Invalid build options";
- case CL_INVALID_PROGRAM: return "Invalid program";
- case CL_INVALID_PROGRAM_EXECUTABLE: return "Invalid program executable";
- case CL_INVALID_KERNEL_NAME: return "Invalid kernel name";
- case CL_INVALID_KERNEL_DEFINITION: return "Invalid kernel definition";
- case CL_INVALID_KERNEL: return "Invalid kernel";
- case CL_INVALID_ARG_INDEX: return "Invalid argument index";
- case CL_INVALID_ARG_VALUE: return "Invalid argument value";
- case CL_INVALID_ARG_SIZE: return "Invalid argument size";
- case CL_INVALID_KERNEL_ARGS: return "Invalid kernel arguments";
- case CL_INVALID_WORK_DIMENSION: return "Invalid work dimension";
- case CL_INVALID_WORK_GROUP_SIZE: return "Invalid work group size";
- case CL_INVALID_WORK_ITEM_SIZE: return "Invalid work item size";
- case CL_INVALID_GLOBAL_OFFSET: return "Invalid global offset";
- case CL_INVALID_EVENT_WAIT_LIST: return "Invalid event wait list";
- case CL_INVALID_EVENT: return "Invalid event";
- case CL_INVALID_OPERATION: return "Invalid operation";
- case CL_INVALID_GL_OBJECT: return "Invalid OpenGL object";
- case CL_INVALID_BUFFER_SIZE: return "Invalid buffer size";
- case CL_INVALID_MIP_LEVEL: return "Invalid mip-map level";
- default: return "Unknown";
- }
- }
-
bool opencl_error(cl_int err)
{
if(err != CL_SUCCESS) {
- string message = string_printf("OpenCL error (%d): %s", err, opencl_error_string(err));
+ string message = string_printf("OpenCL error (%d): %s", err, clewErrorString(err));
if(error_msg == "")
error_msg = message;
fprintf(stderr, "%s\n", message.c_str());
@@ -412,7 +360,7 @@ public:
cl_int err = stmt; \
\
if(err != CL_SUCCESS) { \
- string message = string_printf("OpenCL error: %s in %s", opencl_error_string(err), #stmt); \
+ string message = string_printf("OpenCL error: %s in %s", clewErrorString(err), #stmt); \
if(error_msg == "") \
error_msg = message; \
fprintf(stderr, "%s\n", message.c_str()); \
@@ -422,7 +370,7 @@ public:
void opencl_assert_err(cl_int err, const char* where)
{
if(err != CL_SUCCESS) {
- string message = string_printf("OpenCL error (%d): %s in %s", err, opencl_error_string(err), where);
+ string message = string_printf("OpenCL error (%d): %s in %s", err, clewErrorString(err), where);
if(error_msg == "")
error_msg = message;
fprintf(stderr, "%s\n", message.c_str());
@@ -552,7 +500,7 @@ public:
device_initialized = true;
}
- static void context_notify_callback(const char *err_info,
+ static void CL_CALLBACK context_notify_callback(const char *err_info,
const void *private_info, size_t cb, void *user_data)
{
char name[256];
@@ -846,6 +794,7 @@ public:
opencl_assert_err(ciErr, "clCreateBuffer");
stats.mem_alloc(size);
+ mem.device_size = size;
}
void mem_copy_to(device_memory& mem)
@@ -877,7 +826,8 @@ public:
opencl_assert(clReleaseMemObject(CL_MEM_PTR(mem.device_pointer)));
mem.device_pointer = 0;
- stats.mem_free(mem.memory_size());
+ stats.mem_free(mem.device_size);
+ mem.device_size = 0;
}
}
@@ -1056,6 +1006,7 @@ public:
cl_int d_shader_eval_type = task.shader_eval_type;
cl_int d_shader_x = task.shader_x;
cl_int d_shader_w = task.shader_w;
+ cl_int d_offset = task.offset;
/* sample arguments */
cl_uint narg = 0;
@@ -1068,7 +1019,11 @@ public:
kernel = ckShaderKernel;
for(int sample = 0; sample < task.num_samples; sample++) {
- cl_int d_sample = task.sample;
+
+ if(task.get_cancel())
+ break;
+
+ cl_int d_sample = sample;
opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_data), (void*)&d_data));
opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_input), (void*)&d_input));
@@ -1081,9 +1036,12 @@ public:
opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_shader_eval_type), (void*)&d_shader_eval_type));
opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_shader_x), (void*)&d_shader_x));
opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_shader_w), (void*)&d_shader_w));
+ opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_offset), (void*)&d_offset));
opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_sample), (void*)&d_sample));
enqueue_kernel(kernel, task.shader_w, 1);
+
+ task.update_progress(NULL);
}
}
@@ -1113,7 +1071,7 @@ public:
tile.sample = sample + 1;
- task->update_progress(tile);
+ task->update_progress(&tile);
}
task->release_tile(tile);
@@ -1130,6 +1088,11 @@ public:
}
};
+ int get_split_task_count(DeviceTask& task)
+ {
+ return 1;
+ }
+
void task_add(DeviceTask& task)
{
task_pool.push(new OpenCLDeviceTask(this, task));
@@ -1151,6 +1114,26 @@ Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background)
return new OpenCLDevice(info, stats, background);
}
+bool device_opencl_init(void) {
+ static bool initialized = false;
+ static bool result = false;
+
+ if (initialized)
+ return result;
+
+ initialized = true;
+
+ // OpenCL disabled for now, only works with this environment variable set
+ if(!getenv("CYCLES_OPENCL_TEST")) {
+ result = false;
+ }
+ else {
+ result = clewInit() == CLEW_SUCCESS;
+ }
+
+ return result;
+}
+
void device_opencl_info(vector<DeviceInfo>& devices)
{
vector<cl_device_id> device_ids;
diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp
index f436b54df68..dc124f8cf37 100644
--- a/intern/cycles/device/device_task.cpp
+++ b/intern/cycles/device/device_task.cpp
@@ -35,7 +35,7 @@ DeviceTask::DeviceTask(Type type_)
last_update_time = time_dt();
}
-void DeviceTask::split(list<DeviceTask>& tasks, int num, int max_size)
+int DeviceTask::get_subtask_count(int num, int max_size)
{
if(max_size != 0) {
int max_size_num;
@@ -53,7 +53,21 @@ void DeviceTask::split(list<DeviceTask>& tasks, int num, int max_size)
if(type == SHADER) {
num = min(shader_w, num);
+ }
+ else if(type == PATH_TRACE) {
+ }
+ else {
+ num = min(h, num);
+ }
+ return num;
+}
+
+void DeviceTask::split(list<DeviceTask>& tasks, int num, int max_size)
+{
+ num = get_subtask_count(num, max_size);
+
+ if(type == SHADER) {
for(int i = 0; i < num; i++) {
int tx = shader_x + (shader_w/num)*i;
int tw = (i == num-1)? shader_w - i*(shader_w/num): shader_w/num;
@@ -71,8 +85,6 @@ void DeviceTask::split(list<DeviceTask>& tasks, int num, int max_size)
tasks.push_back(*this);
}
else {
- num = min(h, num);
-
for(int i = 0; i < num; i++) {
int ty = y + (h/num)*i;
int th = (i == num-1)? h - i*(h/num): h/num;
@@ -87,9 +99,10 @@ void DeviceTask::split(list<DeviceTask>& tasks, int num, int max_size)
}
}
-void DeviceTask::update_progress(RenderTile &rtile)
+void DeviceTask::update_progress(RenderTile *rtile)
{
- if (type != PATH_TRACE)
+ if((type != PATH_TRACE) &&
+ (type != SHADER))
return;
if(update_progress_sample)
@@ -99,7 +112,7 @@ void DeviceTask::update_progress(RenderTile &rtile)
double current_time = time_dt();
if (current_time - last_update_time >= 1.0) {
- update_tile_sample(rtile);
+ update_tile_sample(*rtile);
last_update_time = current_time;
}
diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h
index 91390674286..50216adefe2 100644
--- a/intern/cycles/device/device_task.h
+++ b/intern/cycles/device/device_task.h
@@ -52,9 +52,10 @@ public:
DeviceTask(Type type = PATH_TRACE);
+ int get_subtask_count(int num, int max_size = 0);
void split(list<DeviceTask>& tasks, int num, int max_size = 0);
- void update_progress(RenderTile &rtile);
+ void update_progress(RenderTile *rtile);
boost::function<bool(Device *device, RenderTile&)> acquire_tile;
boost::function<void(void)> update_progress_sample;
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 2ff6b53b0a5..8857f86890c 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -149,48 +149,61 @@ if(WITH_CYCLES_CUDA_BINARIES)
set(CUDA_VERSION "${CUDA_VERSION_MAJOR}${CUDA_VERSION_MINOR}")
# warn for other versions
- if(CUDA_VERSION MATCHES "60")
+ if(CUDA_VERSION MATCHES "65")
else()
message(WARNING
"CUDA version ${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR} detected, "
- "build may succeed but only CUDA 6.0 is officially supported")
+ "build may succeed but only CUDA 6.5 is officially supported")
endif()
# build for each arch
set(cuda_sources kernel.cu ${SRC_HEADERS} ${SRC_SVM_HEADERS} ${SRC_GEOM_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_UTIL_HEADERS})
set(cuda_cubins)
- foreach(arch ${CYCLES_CUDA_BINARIES_ARCH})
- set(cuda_cubin kernel_${arch}.cubin)
+ macro(CYCLES_CUDA_KERNEL_ADD arch experimental)
+ if(${experimental})
+ set(cuda_extra_flags "-D__KERNEL_CUDA_EXPERIMENTAL__")
+ set(cuda_cubin kernel_experimental_${arch}.cubin)
+ else()
+ set(cuda_extra_flags "")
+ set(cuda_cubin kernel_${arch}.cubin)
+ endif()
set(cuda_version_flags "-D__KERNEL_CUDA_VERSION__=${CUDA_VERSION}")
set(cuda_math_flags "--use_fast_math")
- if(CUDA_VERSION LESS 60 AND ${arch} MATCHES "sm_50")
- message(WARNING "Can't build kernel for CUDA sm_50 architecture, skipping")
- else()
- add_custom_command(
- OUTPUT ${cuda_cubin}
- COMMAND ${CUDA_NVCC_EXECUTABLE}
- -arch=${arch}
- -m${CUDA_BITS}
- --cubin ${CMAKE_CURRENT_SOURCE_DIR}/kernel.cu
- -o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_cubin}
- --ptxas-options="-v"
- ${cuda_arch_flags}
- ${cuda_version_flags}
- ${cuda_math_flags}
- -I${CMAKE_CURRENT_SOURCE_DIR}/../util
- -I${CMAKE_CURRENT_SOURCE_DIR}/svm
- -DCCL_NAMESPACE_BEGIN=
- -DCCL_NAMESPACE_END=
- -DNVCC
-
- DEPENDS ${cuda_sources})
-
- delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${cuda_cubin}" ${CYCLES_INSTALL_PATH}/lib)
- list(APPEND cuda_cubins ${cuda_cubin})
- endif()
+ add_custom_command(
+ OUTPUT ${cuda_cubin}
+ COMMAND ${CUDA_NVCC_EXECUTABLE}
+ -arch=${arch}
+ -m${CUDA_BITS}
+ --cubin ${CMAKE_CURRENT_SOURCE_DIR}/kernel.cu
+ -o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_cubin}
+ --ptxas-options="-v"
+ ${cuda_arch_flags}
+ ${cuda_version_flags}
+ ${cuda_math_flags}
+ ${cuda_extra_flags}
+ -I${CMAKE_CURRENT_SOURCE_DIR}/../util
+ -I${CMAKE_CURRENT_SOURCE_DIR}/svm
+ -DCCL_NAMESPACE_BEGIN=
+ -DCCL_NAMESPACE_END=
+ -DNVCC
+
+ DEPENDS ${cuda_sources})
+
+ delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${cuda_cubin}" ${CYCLES_INSTALL_PATH}/lib)
+ list(APPEND cuda_cubins ${cuda_cubin})
+
+ unset(cuda_extra_flags)
+ endmacro()
+
+ foreach(arch ${CYCLES_CUDA_BINARIES_ARCH})
+ # Compile regular kernel
+ CYCLES_CUDA_KERNEL_ADD(${arch} FALSE)
+
+ # Compile experimental kernel
+ CYCLES_CUDA_KERNEL_ADD(${arch} TRUE)
endforeach()
add_custom_target(cycles_kernel_cuda ALL DEPENDS ${cuda_cubins})
diff --git a/intern/cycles/kernel/SConscript b/intern/cycles/kernel/SConscript
index cfe12e8533d..5a9e57c5342 100644
--- a/intern/cycles/kernel/SConscript
+++ b/intern/cycles/kernel/SConscript
@@ -69,8 +69,8 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']:
cuda_major_minor = re.findall(r'release (\d+).(\d+)', output)[0]
cuda_version = int(cuda_major_minor[0])*10 + int(cuda_major_minor[1])
- if cuda_version != 60:
- print("CUDA version %d.%d detected, build may succeed but only CUDA 6.0 is officially supported." % (cuda_version/10, cuda_version%10))
+ if cuda_version != 65:
+ print("CUDA version %d.%d detected, build may succeed but only CUDA 6.5 is officially supported." % (cuda_version/10, cuda_version%10))
# nvcc flags
nvcc_flags = "-m%s" % (bits)
@@ -83,30 +83,35 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']:
dependencies = ['kernel.cu'] + kernel.Glob('*.h') + kernel.Glob('../util/*.h') + kernel.Glob('svm/*.h') + kernel.Glob('geom/*.h') + kernel.Glob('closure/*.h')
last_cubin_file = None
+ configs = (("kernel_%s.cubin", ''),
+ ("kernel_experimental_%s.cubin", ' -D__KERNEL_CUDA_EXPERIMENTAL__'))
+
# add command for each cuda architecture
for arch in cuda_archs:
- if cuda_version < 60 and arch == "sm_50":
- print("Can't build kernel for CUDA sm_50 architecture, skipping")
- continue
-
- cubin_file = os.path.join(build_dir, "kernel_%s.cubin" % arch)
-
- if env['BF_CYCLES_CUDA_ENV']:
- MS_SDK = "C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Bin\\SetEnv.cmd"
- command = "\"%s\" & \"%s\" -arch=%s %s \"%s\" -o \"%s\"" % (MS_SDK, nvcc, arch, nvcc_flags, kernel_file, cubin_file)
- else:
- command = "\"%s\" -arch=%s %s \"%s\" -o \"%s\"" % (nvcc, arch, nvcc_flags, kernel_file, cubin_file)
-
- kernel.Command(cubin_file, 'kernel.cu', command)
- kernel.Depends(cubin_file, dependencies)
-
- kernel_binaries.append(cubin_file)
-
- if not env['WITH_BF_CYCLES_CUDA_THREADED_COMPILE']:
- # trick to compile one kernel at a time to reduce memory usage
- if last_cubin_file:
- kernel.Depends(cubin_file, last_cubin_file)
- last_cubin_file = cubin_file
+ for config in configs:
+ # TODO(sergey): Use dict instead ocouple in order to increase readability?
+ name = config[0]
+ extra_flags = config[1]
+
+ cubin_file = os.path.join(build_dir, name % arch)
+ current_flags = nvcc_flags + extra_flags
+
+ if env['BF_CYCLES_CUDA_ENV']:
+ MS_SDK = "C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Bin\\SetEnv.cmd"
+ command = "\"%s\" & \"%s\" -arch=%s %s \"%s\" -o \"%s\"" % (MS_SDK, nvcc, arch, current_flags, kernel_file, cubin_file)
+ else:
+ command = "\"%s\" -arch=%s %s \"%s\" -o \"%s\"" % (nvcc, arch, current_flags, kernel_file, cubin_file)
+
+ kernel.Command(cubin_file, 'kernel.cu', command)
+ kernel.Depends(cubin_file, dependencies)
+
+ kernel_binaries.append(cubin_file)
+
+ if not env['WITH_BF_CYCLES_CUDA_THREADED_COMPILE']:
+ # trick to compile one kernel at a time to reduce memory usage
+ if last_cubin_file:
+ kernel.Depends(cubin_file, last_cubin_file)
+ last_cubin_file = cubin_file
Return('kernel_binaries')
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 81c239ea0c9..9961071c2ac 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -23,9 +23,7 @@
#include "../closure/bsdf_reflection.h"
#include "../closure/bsdf_refraction.h"
#include "../closure/bsdf_transparent.h"
-#ifdef __ANISOTROPIC__
#include "../closure/bsdf_ashikhmin_shirley.h"
-#endif
#include "../closure/bsdf_westin.h"
#include "../closure/bsdf_toon.h"
#include "../closure/bsdf_hair.h"
@@ -94,13 +92,11 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader
label = bsdf_microfacet_beckmann_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
-#ifdef __ANISOTROPIC__
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
label = bsdf_ashikhmin_shirley_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
-#endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
@@ -190,12 +186,10 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
break;
-#ifdef __ANISOTROPIC__
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
break;
-#endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
break;
@@ -260,12 +254,10 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
break;
-#ifdef __ANISOTROPIC__
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf);
break;
-#endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
break;
@@ -348,12 +340,10 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
bsdf_microfacet_beckmann_blur(sc, roughness);
break;
-#ifdef __ANISOTROPIC__
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
bsdf_ashikhmin_shirley_blur(sc, roughness);
break;
-#endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
bsdf_ashikhmin_velvet_blur(sc, roughness);
break;
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
index 6a5d0410e01..ad7864cb8ea 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
@@ -77,7 +77,7 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c
NdotI = fmaxf(NdotI, 1e-6f);
NdotO = fmaxf(NdotO, 1e-6f);
float3 H = normalize(omega_in + I);
- float HdotI = fmaxf(dot(H, I), 1e-6f);
+ float HdotI = fmaxf(fabsf(dot(H, I)), 1e-6f);
float HdotN = fmaxf(dot(H, N), 1e-6f);
float pump = 1.0f / fmaxf(1e-6f, (HdotI*fmaxf(NdotO, NdotI))); /* pump from original paper (first derivative disc., but cancels the HdotI in the pdf nicely) */
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index df0644becee..a0c59e6cbc0 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -362,7 +362,7 @@ ccl_device_inline float3 microfacet_sample_stretched(
* E. Heitz, Research Report 2014
*
* Anisotropy is only supported for reflection currently, but adding it for
- * tranmission is just a matter of copying code from reflection if needed. */
+ * transmission is just a matter of copying code from reflection if needed. */
ccl_device int bsdf_microfacet_ggx_setup(ShaderClosure *sc)
{
@@ -513,6 +513,10 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
float cosHO = dot(Ht, I);
float cosHI = dot(Ht, omega_in);
+ /* those situations makes chi+ terms in eq. 33, 34 be zero */
+ if(dot(Ht, N) <= 0.0f || cosHO * cosNO <= 0.0f || cosHI * cosNI <= 0.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
float D, G1o, G1i;
/* eq. 33: first we calculate D(m) with m=Ht: */
@@ -862,7 +866,11 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc
float cosHO = dot(Ht, I);
float cosHI = dot(Ht, omega_in);
- /* eq. 33: first we calculate D(m) with m=Ht: */
+ /* those situations makes chi+ terms in eq. 25, 27 be zero */
+ if(dot(Ht, N) <= 0.0f || cosHO * cosNO <= 0.0f || cosHI * cosNI <= 0.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ /* eq. 25: first we calculate D(m) with m=Ht: */
float alpha2 = alpha_x * alpha_y;
float cosThetaM = min(dot(N, Ht), 1.0f);
float cosThetaM2 = cosThetaM * cosThetaM;
diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h
index b3dcb9dcc38..05816bac2c1 100644
--- a/intern/cycles/kernel/closure/bsdf_util.h
+++ b/intern/cycles/kernel/closure/bsdf_util.h
@@ -111,16 +111,20 @@ ccl_device float fresnel_dielectric_cos(float cosi, float eta)
return 1.0f; // TIR(no refracted component)
}
-ccl_device float fresnel_conductor(float cosi, float eta, float k)
+#if 0
+ccl_device float3 fresnel_conductor(float cosi, const float3 eta, const float3 k)
{
- float tmp_f = eta * eta + k * k;
- float tmp = tmp_f * cosi * cosi;
- float Rparl2 = (tmp - (2.0f * eta * cosi) + 1)/
- (tmp + (2.0f * eta * cosi) + 1);
- float Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi * cosi)/
- (tmp_f + (2.0f * eta * cosi) + cosi * cosi);
+ float3 cosi2 = make_float3(cosi*cosi);
+ float3 one = make_float3(1.0f, 1.0f, 1.0f);
+ float3 tmp_f = eta * eta + k * k;
+ float3 tmp = tmp_f * cosi2;
+ float3 Rparl2 = (tmp - (2.0f * eta * cosi) + one) /
+ (tmp + (2.0f * eta * cosi) + one);
+ float3 Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi2) /
+ (tmp_f + (2.0f * eta * cosi) + cosi2);
return(Rparl2 + Rperp2) * 0.5f;
}
+#endif
ccl_device float smooth_step(float edge0, float edge1, float x)
{
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h
index 863836ffcea..c4e9e2ababe 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -936,9 +936,10 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
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) {
- tg = normalize(curvetangent(isect->u, p[0], p[1], p[2], p[3]));
sd->Ng = normalize(-(D - tg * (dot(tg, D))));
}
else {
@@ -950,7 +951,6 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
float gd = isect->v;
if(gd != 0.0f) {
- tg = normalize(curvetangent(isect->u, p[0], p[1], p[2], p[3]));
sd->Ng = sd->Ng - gd * tg;
sd->Ng = normalize(sd->Ng);
}
diff --git a/intern/cycles/kernel/geom/geom_motion_triangle.h b/intern/cycles/kernel/geom/geom_motion_triangle.h
index 5ab0b731bdd..7409aa0d014 100644
--- a/intern/cycles/kernel/geom/geom_motion_triangle.h
+++ b/intern/cycles/kernel/geom/geom_motion_triangle.h
@@ -272,7 +272,11 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg, ShaderD
#endif
/* compute face normal */
- float3 Ng = normalize(cross(verts[1] - verts[0], verts[2] - verts[0]));
+ float3 Ng;
+ if(sd->flag & SD_NEGATIVE_SCALE_APPLIED)
+ Ng = normalize(cross(verts[2] - verts[0], verts[1] - verts[0]));
+ else
+ Ng = normalize(cross(verts[1] - verts[0], verts[2] - verts[0]));
sd->Ng = Ng;
sd->N = Ng;
diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h
index f2f35c2efd0..41e9d183a96 100644
--- a/intern/cycles/kernel/geom/geom_triangle.h
+++ b/intern/cycles/kernel/geom/geom_triangle.h
@@ -18,7 +18,7 @@
/* Triangle Primitive
*
* Basic triangle with 3 vertices is used to represent mesh surfaces. For BVH
- * ray intersection we use a precomputed triangle storage to accelarate
+ * ray intersection we use a precomputed triangle storage to accelerate
* intersection at the cost of more memory usage */
CCL_NAMESPACE_BEGIN
@@ -117,21 +117,24 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, ShaderDat
}
/* normal on triangle */
-ccl_device_inline float3 triangle_normal(KernelGlobals *kg, int prim)
+ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
{
/* load triangle vertices */
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim));
+ float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
float3 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
float3 v2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
/* return normal */
- return normalize(cross(v1 - v0, v2 - v0));
+ if(sd->flag & SD_NEGATIVE_SCALE_APPLIED)
+ return normalize(cross(v2 - v0, v1 - v0));
+ else
+ return normalize(cross(v1 - v0, v2 - v0));
}
/* point and normal on triangle */
-ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int prim, float u, float v, float3 *P, float3 *Ng, int *shader)
+ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int object, int prim, float u, float v, float3 *P, float3 *Ng, int *shader)
{
/* load triangle vertices */
float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim));
@@ -144,8 +147,14 @@ ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int prim, float
float t = 1.0f - u - v;
*P = (u*v0 + v*v1 + t*v2);
+ /* get object flags, instance-aware */
+ int object_flag = kernel_tex_fetch(__object_flag, object >= 0 ? object : ~object);
+
/* compute normal */
- *Ng = normalize(cross(v1 - v0, v2 - v0));
+ if(object_flag & SD_NEGATIVE_SCALE_APPLIED)
+ *Ng = normalize(cross(v2 - v0, v1 - v0));
+ else
+ *Ng = normalize(cross(v1 - v0, v2 - v0));
/* shader`*/
*shader = __float_as_int(kernel_tex_fetch(__tri_shader, prim));
diff --git a/intern/cycles/kernel/kernel.cl b/intern/cycles/kernel/kernel.cl
index 2e0a49435a8..4f20ef9ca15 100644
--- a/intern/cycles/kernel/kernel.cl
+++ b/intern/cycles/kernel/kernel.cl
@@ -115,7 +115,7 @@ __kernel void kernel_ocl_shader(
ccl_global type *name,
#include "kernel_textures.h"
- int type, int sx, int sw, int sample)
+ int type, int sx, int sw, int offset, int sample)
{
KernelGlobals kglobals, *kg = &kglobals;
@@ -140,7 +140,7 @@ __kernel void kernel_ocl_bake(
ccl_global type *name,
#include "kernel_textures.h"
- int type, int sx, int sw, int sample)
+ int type, int sx, int sw, int offset, int sample)
{
KernelGlobals kglobals, *kg = &kglobals;
@@ -153,6 +153,6 @@ __kernel void kernel_ocl_bake(
int x = sx + get_global_id(0);
if(x < sx + sw)
- kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, x, sample);
+ kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, x, offset, sample);
}
diff --git a/intern/cycles/kernel/kernel.cpp b/intern/cycles/kernel/kernel.cpp
index 42eb9a62518..fa2113fbb46 100644
--- a/intern/cycles/kernel/kernel.cpp
+++ b/intern/cycles/kernel/kernel.cpp
@@ -120,10 +120,10 @@ void kernel_cpu_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, float *bu
/* Shader Evaluation */
-void kernel_cpu_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i, int sample)
+void kernel_cpu_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i, int offset, int sample)
{
if(type >= SHADER_EVAL_BAKE)
- kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, i, sample);
+ kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, i, offset, sample);
else
kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, i, sample);
}
diff --git a/intern/cycles/kernel/kernel.cu b/intern/cycles/kernel/kernel.cu
index 9208acc232e..d5b5293664c 100644
--- a/intern/cycles/kernel/kernel.cu
+++ b/intern/cycles/kernel/kernel.cu
@@ -146,7 +146,7 @@ kernel_cuda_convert_to_half_float(uchar4 *rgba, float *buffer, float sample_scal
extern "C" __global__ void
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
-kernel_cuda_shader(uint4 *input, float4 *output, int type, int sx, int sw, int sample)
+kernel_cuda_shader(uint4 *input, float4 *output, int type, int sx, int sw, int offset, int sample)
{
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
@@ -156,12 +156,12 @@ kernel_cuda_shader(uint4 *input, float4 *output, int type, int sx, int sw, int s
extern "C" __global__ void
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
-kernel_cuda_bake(uint4 *input, float4 *output, int type, int sx, int sw, int sample)
+kernel_cuda_bake(uint4 *input, float4 *output, int type, int sx, int sw, int offset, int sample)
{
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
if(x < sx + sw)
- kernel_bake_evaluate(NULL, input, output, (ShaderEvalType)type, x, sample);
+ kernel_bake_evaluate(NULL, input, output, (ShaderEvalType)type, x, offset, sample);
}
#endif
diff --git a/intern/cycles/kernel/kernel.h b/intern/cycles/kernel/kernel.h
index 264e5e3e4d0..19e06b88797 100644
--- a/intern/cycles/kernel/kernel.h
+++ b/intern/cycles/kernel/kernel.h
@@ -41,7 +41,7 @@ void kernel_cpu_convert_to_byte(KernelGlobals *kg, uchar4 *rgba, float *buffer,
void kernel_cpu_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, float *buffer,
float sample_scale, int x, int y, int offset, int stride);
void kernel_cpu_shader(KernelGlobals *kg, uint4 *input, float4 *output,
- int type, int i, int sample);
+ int type, int i, int offset, int sample);
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
void kernel_cpu_sse2_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state,
@@ -51,7 +51,7 @@ void kernel_cpu_sse2_convert_to_byte(KernelGlobals *kg, uchar4 *rgba, float *buf
void kernel_cpu_sse2_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, float *buffer,
float sample_scale, int x, int y, int offset, int stride);
void kernel_cpu_sse2_shader(KernelGlobals *kg, uint4 *input, float4 *output,
- int type, int i, int sample);
+ int type, int i, int offset, int sample);
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
@@ -62,7 +62,7 @@ void kernel_cpu_sse3_convert_to_byte(KernelGlobals *kg, uchar4 *rgba, float *buf
void kernel_cpu_sse3_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, float *buffer,
float sample_scale, int x, int y, int offset, int stride);
void kernel_cpu_sse3_shader(KernelGlobals *kg, uint4 *input, float4 *output,
- int type, int i, int sample);
+ int type, int i, int offset, int sample);
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
@@ -73,7 +73,7 @@ void kernel_cpu_sse41_convert_to_byte(KernelGlobals *kg, uchar4 *rgba, float *bu
void kernel_cpu_sse41_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, float *buffer,
float sample_scale, int x, int y, int offset, int stride);
void kernel_cpu_sse41_shader(KernelGlobals *kg, uint4 *input, float4 *output,
- int type, int i, int sample);
+ int type, int i, int offset, int sample);
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
@@ -84,7 +84,7 @@ void kernel_cpu_avx_convert_to_byte(KernelGlobals *kg, uchar4 *rgba, float *buff
void kernel_cpu_avx_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, float *buffer,
float sample_scale, int x, int y, int offset, int stride);
void kernel_cpu_avx_shader(KernelGlobals *kg, uint4 *input, float4 *output,
- int type, int i, int sample);
+ int type, int i, int offset, int sample);
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
@@ -95,7 +95,7 @@ void kernel_cpu_avx2_convert_to_byte(KernelGlobals *kg, uchar4 *rgba, float *buf
void kernel_cpu_avx2_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, float *buffer,
float sample_scale, int x, int y, int offset, int stride);
void kernel_cpu_avx2_shader(KernelGlobals *kg, uint4 *input, float4 *output,
- int type, int i, int sample);
+ int type, int i, int offset, int sample);
#endif
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index b4f6dcdace9..b0efcdc66a7 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -32,10 +32,11 @@ ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 v
eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
eval->transparent = make_float3(0.0f, 0.0f, 0.0f);
eval->subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ eval->scatter = make_float3(0.0f, 0.0f, 0.0f);
if(type == CLOSURE_BSDF_TRANSPARENT_ID)
eval->transparent = value;
- else if(CLOSURE_IS_BSDF_DIFFUSE(type) || CLOSURE_IS_PHASE(type))
+ else if(CLOSURE_IS_BSDF_DIFFUSE(type))
eval->diffuse = value;
else if(CLOSURE_IS_BSDF_GLOSSY(type))
eval->glossy = value;
@@ -43,6 +44,8 @@ ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 v
eval->transmission = value;
else if(CLOSURE_IS_BSDF_BSSRDF(type))
eval->subsurface = value;
+ else if(CLOSURE_IS_PHASE(type))
+ eval->scatter = value;
}
else
eval->diffuse = value;
@@ -51,11 +54,17 @@ ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 v
#endif
}
-ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
+/* TODO(sergey): This is just a workaround for annoying 6.5 compiler bug. */
+#if !defined(__KERNEL_CUDA__) || __CUDA_ARCH__ < 500
+ccl_device_inline
+#else
+ccl_device_noinline
+#endif
+void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
{
#ifdef __PASSES__
if(eval->use_light_pass) {
- if(CLOSURE_IS_BSDF_DIFFUSE(type) || CLOSURE_IS_PHASE(type))
+ if(CLOSURE_IS_BSDF_DIFFUSE(type))
eval->diffuse += value;
else if(CLOSURE_IS_BSDF_GLOSSY(type))
eval->glossy += value;
@@ -63,6 +72,8 @@ ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3
eval->transmission += value;
else if(CLOSURE_IS_BSDF_BSSRDF(type))
eval->subsurface += value;
+ else if(CLOSURE_IS_PHASE(type))
+ eval->scatter += value;
/* skipping transparent, this function is used by for eval(), will be zero then */
}
@@ -81,7 +92,8 @@ ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
&& is_zero(eval->glossy)
&& is_zero(eval->transmission)
&& is_zero(eval->transparent)
- && is_zero(eval->subsurface);
+ && is_zero(eval->subsurface)
+ && is_zero(eval->scatter);
}
else
return is_zero(eval->diffuse);
@@ -98,6 +110,7 @@ ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float3 value)
eval->glossy *= value;
eval->transmission *= value;
eval->subsurface *= value;
+ eval->scatter *= value;
/* skipping transparent, this function is used by for eval(), will be zero then */
}
@@ -111,7 +124,7 @@ ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float3 value)
/* Path Radiance
*
* We accumulate different render passes separately. After summing at the end
- * to get the combined result, it should be identical. We definte directly
+ * to get the combined result, it should be identical. We definite directly
* visible as the first non-transparent hit, while indirectly visible are the
* bounces after that. */
@@ -130,21 +143,25 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
L->color_glossy = make_float3(0.0f, 0.0f, 0.0f);
L->color_transmission = make_float3(0.0f, 0.0f, 0.0f);
L->color_subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->color_scatter = make_float3(0.0f, 0.0f, 0.0f);
L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_scatter = make_float3(0.0f, 0.0f, 0.0f);
L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect_scatter = make_float3(0.0f, 0.0f, 0.0f);
L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f);
L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
L->path_transmission = make_float3(0.0f, 0.0f, 0.0f);
L->path_subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->path_scatter = make_float3(0.0f, 0.0f, 0.0f);
L->emission = make_float3(0.0f, 0.0f, 0.0f);
L->background = make_float3(0.0f, 0.0f, 0.0f);
@@ -174,14 +191,16 @@ ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, float3 *throug
L->path_glossy = bsdf_eval->glossy*value;
L->path_transmission = bsdf_eval->transmission*value;
L->path_subsurface = bsdf_eval->subsurface*value;
+ L->path_scatter = bsdf_eval->scatter*value;
- *throughput = L->path_diffuse + L->path_glossy + L->path_transmission + L->path_subsurface;
+ *throughput = L->path_diffuse + L->path_glossy + L->path_transmission + L->path_subsurface + L->path_scatter;
L->direct_throughput = *throughput;
}
else {
/* transparent bounce before first hit, or indirectly visible through BSDF */
- float3 sum = (bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->transparent + bsdf_eval->subsurface)*inverse_pdf;
+ float3 sum = (bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->transparent +
+ bsdf_eval->subsurface + bsdf_eval->scatter) * inverse_pdf;
*throughput *= sum;
}
}
@@ -241,6 +260,7 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 through
L->direct_glossy += throughput*bsdf_eval->glossy*shadow;
L->direct_transmission += throughput*bsdf_eval->transmission*shadow;
L->direct_subsurface += throughput*bsdf_eval->subsurface*shadow;
+ L->direct_scatter += throughput*bsdf_eval->scatter*shadow;
if(is_lamp) {
L->shadow.x += shadow.x*shadow_fac;
@@ -250,7 +270,7 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 through
}
else {
/* indirectly visible lighting after BSDF bounce */
- float3 sum = bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->subsurface;
+ float3 sum = bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->subsurface + bsdf_eval->scatter;
L->indirect += throughput*sum*shadow;
}
}
@@ -291,12 +311,14 @@ ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L)
L->direct_glossy += L->path_glossy*L->direct_emission;
L->direct_transmission += L->path_transmission*L->direct_emission;
L->direct_subsurface += L->path_subsurface*L->direct_emission;
+ L->direct_scatter += L->path_scatter*L->direct_emission;
L->indirect = safe_divide_color(L->indirect, L->direct_throughput);
L->indirect_diffuse += L->path_diffuse*L->indirect;
L->indirect_glossy += L->path_glossy*L->indirect;
L->indirect_transmission += L->path_transmission*L->indirect;
L->indirect_subsurface += L->path_subsurface*L->indirect;
+ L->indirect_scatter += L->path_scatter*L->indirect;
}
#endif
}
@@ -309,6 +331,7 @@ ccl_device_inline void path_radiance_reset_indirect(PathRadiance *L)
L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
L->path_transmission = make_float3(0.0f, 0.0f, 0.0f);
L->path_subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->path_scatter = make_float3(0.0f, 0.0f, 0.0f);
L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
L->indirect = make_float3(0.0f, 0.0f, 0.0f);
@@ -327,8 +350,8 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
if(L->use_light_pass) {
path_radiance_sum_indirect(L);
- L_direct = L->direct_diffuse + L->direct_glossy + L->direct_transmission + L->direct_subsurface + L->emission;
- L_indirect = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission + L->indirect_subsurface;
+ L_direct = L->direct_diffuse + L->direct_glossy + L->direct_transmission + L->direct_subsurface + L->direct_scatter + L->emission;
+ L_indirect = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission + L->indirect_subsurface + L->indirect_scatter;
if(!kernel_data.background.transparent)
L_direct += L->background;
@@ -344,11 +367,13 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_scatter = make_float3(0.0f, 0.0f, 0.0f);
L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect_scatter = make_float3(0.0f, 0.0f, 0.0f);
L->emission = make_float3(0.0f, 0.0f, 0.0f);
}
@@ -368,6 +393,7 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
L->direct_glossy *= scale;
L->direct_transmission *= scale;
L->direct_subsurface *= scale;
+ L->direct_scatter *= scale;
L->emission *= scale;
L->background *= scale;
}
@@ -382,6 +408,7 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
L->indirect_glossy *= scale;
L->indirect_transmission *= scale;
L->indirect_subsurface *= scale;
+ L->indirect_scatter *= scale;
}
/* Sum again, after clamping */
@@ -416,11 +443,13 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance
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->emission += L_sample->emission*fac;
L->background += L_sample->background*fac;
diff --git a/intern/cycles/kernel/kernel_avx.cpp b/intern/cycles/kernel/kernel_avx.cpp
index d612a82b785..e7ff21a6f09 100644
--- a/intern/cycles/kernel/kernel_avx.cpp
+++ b/intern/cycles/kernel/kernel_avx.cpp
@@ -68,10 +68,10 @@ void kernel_cpu_avx_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, float
/* Shader Evaluate */
-void kernel_cpu_avx_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i, int sample)
+void kernel_cpu_avx_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i, int offset, int sample)
{
if(type >= SHADER_EVAL_BAKE)
- kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, i, sample);
+ kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, i, offset, sample);
else
kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, i, sample);
}
diff --git a/intern/cycles/kernel/kernel_avx2.cpp b/intern/cycles/kernel/kernel_avx2.cpp
index 339421a002b..cb1662bbfbe 100644
--- a/intern/cycles/kernel/kernel_avx2.cpp
+++ b/intern/cycles/kernel/kernel_avx2.cpp
@@ -69,10 +69,10 @@ void kernel_cpu_avx2_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, floa
/* Shader Evaluate */
-void kernel_cpu_avx2_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i, int sample)
+void kernel_cpu_avx2_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i, int offset, int sample)
{
if(type >= SHADER_EVAL_BAKE)
- kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, i, sample);
+ kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, i, offset, sample);
else
kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, i, sample);
}
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index c2d14b7f835..dfbb49db7e6 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -172,7 +172,8 @@ ccl_device_inline float bake_clamp_mirror_repeat(float u)
}
#endif
-ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, ccl_global float4 *output, ShaderEvalType type, int i, int sample)
+ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, ccl_global float4 *output,
+ ShaderEvalType type, int i, int offset, int sample)
{
ShaderData sd;
uint4 in = input[i * 2];
@@ -197,7 +198,7 @@ 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(i, 0);
+ RNG rng = cmj_hash(offset + i, 0);
#if 0
uint rng_state = cmj_hash(i, 0);
@@ -215,7 +216,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
int shader;
float3 P, Ng;
- triangle_point_normal(kg, prim, u, v, &P, &Ng, &shader);
+ triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader);
/* dummy initilizations copied from SHADER_EVAL_DISPLACE */
float3 I = Ng;
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index 6b03abe9708..5c83358a56d 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -21,16 +21,22 @@ CCL_NAMESPACE_BEGIN
ccl_device float2 camera_sample_aperture(KernelGlobals *kg, float u, float v)
{
float blades = kernel_data.cam.blades;
+ float2 bokeh;
if(blades == 0.0f) {
/* sample disk */
- return concentric_sample_disk(u, v);
+ bokeh = concentric_sample_disk(u, v);
}
else {
/* sample polygon */
float rotation = kernel_data.cam.bladesrotation;
- return regular_polygon_sample(blades, rotation, u, v);
+ bokeh = regular_polygon_sample(blades, rotation, u, v);
}
+
+ /* anamorphic lens bokeh */
+ bokeh.x *= kernel_data.cam.inv_aperture_ratio;
+
+ return bokeh;
}
ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, Ray *ray)
@@ -183,7 +189,8 @@ ccl_device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float
/* calculate orthonormal coordinates perpendicular to D */
float3 U, V;
- make_orthonormals(D, &U, &V);
+ U = normalize(make_float3(1.0f, 0.0f, 0.0f) - D.x * D);
+ V = normalize(cross(D, U));
/* update ray for effect of lens */
ray->P = U * lensuv.x + V * lensuv.y;
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index bda98b84da8..4b2bb723ab6 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -108,6 +108,8 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd,
eval->glossy = make_float3(0.0f, 0.0f, 0.0f);
if(ls->shader & SHADER_EXCLUDE_TRANSMIT)
eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
+ if(ls->shader & SHADER_EXCLUDE_SCATTER)
+ eval->scatter = make_float3(0.0f, 0.0f, 0.0f);
}
#endif
@@ -187,7 +189,8 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, PathState *st
if(ls.shader & SHADER_EXCLUDE_ANY) {
if(((ls.shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) ||
((ls.shader & SHADER_EXCLUDE_GLOSSY) && (state->flag & PATH_RAY_GLOSSY)) ||
- ((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)))
+ ((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)) ||
+ ((ls.shader & SHADER_EXCLUDE_SCATTER) && (state->flag & PATH_RAY_VOLUME_SCATTER)))
continue;
}
#endif
@@ -231,7 +234,8 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg, PathState *sta
if(((shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) ||
((shader & SHADER_EXCLUDE_GLOSSY) && (state->flag & PATH_RAY_GLOSSY)) ||
((shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)) ||
- ((shader & SHADER_EXCLUDE_CAMERA) && (state->flag & PATH_RAY_CAMERA)))
+ ((shader & SHADER_EXCLUDE_CAMERA) && (state->flag & PATH_RAY_CAMERA)) ||
+ ((shader & SHADER_EXCLUDE_SCATTER) && (state->flag & PATH_RAY_VOLUME_SCATTER)))
return make_float3(0.0f, 0.0f, 0.0f);
}
diff --git a/intern/cycles/kernel/kernel_jitter.h b/intern/cycles/kernel/kernel_jitter.h
index 7a850844bf2..2a5b7689e57 100644
--- a/intern/cycles/kernel/kernel_jitter.h
+++ b/intern/cycles/kernel/kernel_jitter.h
@@ -14,6 +14,8 @@
* limitations under the License
*/
+/* TODO(sergey): Consider moving portable ctz/clz stuff to util. */
+
CCL_NAMESPACE_BEGIN
/* "Correlated Multi-Jittered Sampling"
@@ -35,8 +37,16 @@ ccl_device_inline int cmj_fast_mod_pow2(int a, int b)
/* a must be > 0 and b must be > 1 */
ccl_device_inline int cmj_fast_div_pow2(int a, int b)
{
-#if defined(__KERNEL_SSE2__) && !defined(_MSC_VER)
+ kernel_assert(a > 0);
+ kernel_assert(b > 1);
+#if defined(__KERNEL_SSE2__)
+# ifdef _MSC_VER
+ unsigned long ctz;
+ _BitScanForward(&ctz, b);
+ return a >> ctz;
+# else
return a >> __builtin_ctz(b);
+# endif
#else
return a/b;
#endif
@@ -44,8 +54,15 @@ ccl_device_inline int cmj_fast_div_pow2(int a, int b)
ccl_device_inline uint cmj_w_mask(uint w)
{
-#if defined(__KERNEL_SSE2__) && !defined(_MSC_VER)
+ kernel_assert(w > 1);
+#if defined(__KERNEL_SSE2__)
+# ifdef _MSC_VER
+ unsigned long leading_zero;
+ _BitScanReverse(&leading_zero, w);
+ return ((1 << (1 + leading_zero)) - 1);
+# else
return ((1 << (32 - __builtin_clz(w))) - 1);
+# endif
#else
w |= w >> 1;
w |= w >> 2;
@@ -165,7 +182,8 @@ ccl_device void cmj_sample_2D(int s, int N, int p, float *fx, float *fy)
smodm = cmj_fast_mod_pow2(s, m);
}
else {
- sdivm = float_to_int(s * invm);
+ /* Doing s*inmv gives precision issues here. */
+ sdivm = s / m;
smodm = s - sdivm*m;
}
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 0adf9ed4666..e7f62f230f8 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -27,7 +27,7 @@ typedef struct LightSample {
float pdf; /* light sampling probability density function */
float eval_fac; /* intensity multiplier */
int object; /* object id for triangle/curve lights */
- int prim; /* primitive id for triangle/curve ligths */
+ int prim; /* primitive id for triangle/curve lights */
int shader; /* shader id */
int lamp; /* lamp id */
LightType type; /* type of light */
@@ -208,8 +208,8 @@ ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3
return t*t/cos_pi;
}
-ccl_device bool lamp_light_sample(KernelGlobals *kg, int lamp,
- float randu, float randv, float3 P, LightSample *ls, bool for_volume)
+ccl_device void lamp_light_sample(KernelGlobals *kg, int lamp,
+ float randu, float randv, float3 P, LightSample *ls)
{
float4 data0 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 0);
float4 data1 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 1);
@@ -224,11 +224,6 @@ ccl_device bool lamp_light_sample(KernelGlobals *kg, int lamp,
ls->v = randv;
if(type == LIGHT_DISTANT) {
-#ifdef __VOLUME__
- if(for_volume)
- return false;
-#endif
-
/* distant light */
float3 lightD = make_float3(data0.y, data0.z, data0.w);
float3 D = lightD;
@@ -249,11 +244,6 @@ ccl_device bool lamp_light_sample(KernelGlobals *kg, int lamp,
}
#ifdef __BACKGROUND_MIS__
else if(type == LIGHT_BACKGROUND) {
-#ifdef __VOLUME__
- if(for_volume)
- return false;
-#endif
-
/* infinite area light (e.g. light dome or env light) */
float3 D = background_light_sample(kg, randu, randv, &ls->pdf);
@@ -309,8 +299,6 @@ ccl_device bool lamp_light_sample(KernelGlobals *kg, int lamp,
ls->eval_fac *= kernel_data.integrator.inv_pdf_lights;
ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
}
-
- return true;
}
ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, float t, LightSample *ls)
@@ -469,7 +457,7 @@ ccl_device void triangle_light_sample(KernelGlobals *kg, int prim, int object,
v = randv*randu;
/* triangle, so get position, normal, shader */
- triangle_point_normal(kg, prim, u, v, &ls->P, &ls->Ng, &ls->shader);
+ triangle_point_normal(kg, object, prim, u, v, &ls->P, &ls->Ng, &ls->shader);
ls->object = object;
ls->prim = prim;
ls->lamp = LAMP_NONE;
@@ -526,7 +514,7 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float randt)
/* Generic Light */
-ccl_device bool light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, LightSample *ls, bool for_volume)
+ccl_device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, LightSample *ls)
{
/* sample index */
int index = light_distribution_sample(kg, randt);
@@ -545,12 +533,10 @@ ccl_device bool light_sample(KernelGlobals *kg, float randt, float randu, float
ls->D = normalize_len(ls->P - P, &ls->t);
ls->pdf = triangle_light_pdf(kg, ls->Ng, -ls->D, ls->t);
ls->shader |= shader_flag;
-
- return true;
}
else {
int lamp = -prim-1;
- return lamp_light_sample(kg, lamp, randu, randv, P, ls, for_volume);
+ lamp_light_sample(kg, lamp, randu, randv, P, ls);
}
}
@@ -560,11 +546,6 @@ ccl_device int light_select_num_samples(KernelGlobals *kg, int index)
return __float_as_int(data3.x);
}
-ccl_device bool light_select(KernelGlobals *kg, int index, float randu, float randv, float3 P, LightSample *ls, bool for_volume)
-{
- return lamp_light_sample(kg, index, randu, randv, P, ls, for_volume);
-}
-
ccl_device int lamp_light_eval_sample(KernelGlobals *kg, float randt)
{
/* sample index */
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 0c033f6234c..515854b6e9c 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -89,6 +89,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray,
volume_ray.t = (hit)? isect.t: FLT_MAX;
bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack);
+
+#ifdef __VOLUME_DECOUPLED__
int sampling_method = volume_stack_sampling_method(kg, state.volume_stack);
bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, false, sampling_method);
@@ -135,28 +137,32 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray,
kernel_volume_decoupled_free(kg, &volume_segment);
if(result == VOLUME_PATH_SCATTERED) {
- if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, L, &ray, 1.0f))
+ if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, L, &ray))
continue;
else
break;
}
}
- else {
+ else
+#endif
+ {
/* integrate along volume segment with distance sampling */
ShaderData volume_sd;
VolumeIntegrateResult result = kernel_volume_integrate(
- kg, &state, &volume_sd, &volume_ray, L, &throughput, rng);
+ kg, &state, &volume_sd, &volume_ray, L, &throughput, rng, heterogeneous);
+#ifdef __VOLUME_SCATTER__
if(result == VOLUME_PATH_SCATTERED) {
/* direct lighting */
- kernel_path_volume_connect_light(kg, rng, &volume_sd, throughput, &state, L, 1.0f);
+ kernel_path_volume_connect_light(kg, rng, &volume_sd, throughput, &state, L);
/* indirect light bounce */
- if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, L, &ray, 1.0f))
+ if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, L, &ray))
continue;
else
break;
}
+#endif
}
}
#endif
@@ -470,6 +476,8 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
volume_ray.t = (hit)? isect.t: FLT_MAX;
bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack);
+
+#ifdef __VOLUME_DECOUPLED__
int sampling_method = volume_stack_sampling_method(kg, state.volume_stack);
bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, true, sampling_method);
@@ -516,28 +524,32 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
kernel_volume_decoupled_free(kg, &volume_segment);
if(result == VOLUME_PATH_SCATTERED) {
- if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, &L, &ray, 1.0f))
+ if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, &L, &ray))
continue;
else
break;
}
}
- else {
+ else
+#endif
+ {
/* integrate along volume segment with distance sampling */
ShaderData volume_sd;
VolumeIntegrateResult result = kernel_volume_integrate(
- kg, &state, &volume_sd, &volume_ray, &L, &throughput, rng);
+ kg, &state, &volume_sd, &volume_ray, &L, &throughput, rng, heterogeneous);
+#ifdef __VOLUME_SCATTER__
if(result == VOLUME_PATH_SCATTERED) {
/* direct lighting */
- kernel_path_volume_connect_light(kg, rng, &volume_sd, throughput, &state, &L, 1.0f);
+ kernel_path_volume_connect_light(kg, rng, &volume_sd, throughput, &state, &L);
/* indirect light bounce */
- if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, &L, &ray, 1.0f))
+ if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, &L, &ray))
continue;
else
break;
}
+#endif
}
}
#endif
@@ -803,10 +815,11 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
if(state.volume_stack[0].shader != SHADER_NONE) {
Ray volume_ray = ray;
volume_ray.t = (hit)? isect.t: FLT_MAX;
+
+ bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack);
-#ifdef __KERNEL_CPU__
+#ifdef __VOLUME_DECOUPLED__
/* decoupled ray marching only supported on CPU */
- bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack);
/* cache steps along volume for repeated sampling */
VolumeSegment volume_segment;
@@ -850,16 +863,17 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
&ps, &pray, &volume_sd, &tp, rphase, rscatter, &volume_segment, NULL, false);
+
+ (void)result;
+ kernel_assert(result == VOLUME_PATH_SCATTERED);
- if(result == VOLUME_PATH_SCATTERED) {
- if(kernel_path_volume_bounce(kg, rng, &volume_sd, &tp, &ps, &L, &pray, num_samples_inv)) {
- kernel_path_indirect(kg, rng, pray, tp*num_samples_inv, num_samples, ps, &L);
+ if(kernel_path_volume_bounce(kg, rng, &volume_sd, &tp, &ps, &L, &pray)) {
+ kernel_path_indirect(kg, rng, pray, tp*num_samples_inv, num_samples, ps, &L);
- /* for render passes, sum and reset indirect light pass variables
- * for the next samples */
- path_radiance_sum_indirect(&L);
- path_radiance_reset_indirect(&L);
- }
+ /* for render passes, sum and reset indirect light pass variables
+ * for the next samples */
+ path_radiance_sum_indirect(&L);
+ path_radiance_reset_indirect(&L);
}
}
}
@@ -883,21 +897,22 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
PathState ps = state;
Ray pray = ray;
ShaderData volume_sd;
- float3 tp = throughput;
+ float3 tp = throughput * num_samples_inv;
/* branch RNG state */
path_state_branch(&ps, j, num_samples);
VolumeIntegrateResult result = kernel_volume_integrate(
- kg, &ps, &volume_sd, &volume_ray, &L, &tp, rng);
+ kg, &ps, &volume_sd, &volume_ray, &L, &tp, rng, 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, &volume_sd, throughput, &state, &L, num_samples_inv);
+ kernel_path_volume_connect_light(kg, rng, &volume_sd, tp, &state, &L);
- if(kernel_path_volume_bounce(kg, rng, &volume_sd, &tp, &ps, &L, &pray, num_samples_inv)) {
- kernel_path_indirect(kg, rng, pray, tp*num_samples_inv, num_samples, ps, &L);
+ if(kernel_path_volume_bounce(kg, rng, &volume_sd, &tp, &ps, &L, &pray)) {
+ kernel_path_indirect(kg, rng, pray, tp, num_samples, ps, &L);
/* for render passes, sum and reset indirect light pass variables
* for the next samples */
@@ -905,6 +920,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
path_radiance_reset_indirect(&L);
}
}
+#endif
}
/* todo: avoid this calculation using decoupled ray marching */
@@ -941,7 +957,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
/* holdout */
#ifdef __HOLDOUT__
- if((sd.flag & (SD_HOLDOUT|SD_HOLDOUT_MASK))) {
+ if(sd.flag & (SD_HOLDOUT|SD_HOLDOUT_MASK)) {
if(kernel_data.background.transparent) {
float3 holdout_weight;
@@ -1031,6 +1047,13 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
ray.P = ray_offset(sd.P, -sd.Ng);
ray.t -= sd.ray_length; /* clipping works through transparent */
+
+#ifdef __RAY_DIFFERENTIALS__
+ ray.dP = sd.dP;
+ ray.dD.dx = -sd.dI.dx;
+ ray.dD.dy = -sd.dI.dy;
+#endif
+
#ifdef __VOLUME__
/* enter/exit volume */
kernel_volume_stack_enter_exit(kg, &sd, state.volume_stack);
diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h
index 7700abfbdae..9553c2da0df 100644
--- a/intern/cycles/kernel/kernel_path_surface.h
+++ b/intern/cycles/kernel/kernel_path_surface.h
@@ -50,7 +50,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN
path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
LightSample ls;
- light_select(kg, i, light_u, light_v, sd->P, &ls, false);
+ lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls);
if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
/* trace shadow ray */
@@ -82,7 +82,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN
light_t = 0.5f*light_t;
LightSample ls;
- light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls, false);
+ light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
/* trace shadow ray */
@@ -103,7 +103,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN
path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
LightSample ls;
- light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls, false);
+ light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
/* sample random light */
if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
@@ -200,7 +200,7 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG
#endif
LightSample ls;
- light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls, false);
+ light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
/* trace shadow ray */
diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h
index 8453b79de45..da2d5e6eca8 100644
--- a/intern/cycles/kernel/kernel_path_volume.h
+++ b/intern/cycles/kernel/kernel_path_volume.h
@@ -16,11 +16,10 @@
CCL_NAMESPACE_BEGIN
-#ifdef __VOLUME__
+#ifdef __VOLUME_SCATTER__
ccl_device void kernel_path_volume_connect_light(KernelGlobals *kg, RNG *rng,
- ShaderData *sd, float3 throughput, PathState *state, PathRadiance *L,
- float num_samples_adjust)
+ ShaderData *sd, float3 throughput, PathState *state, PathRadiance *L)
{
#ifdef __EMISSION__
if(!kernel_data.integrator.use_direct_light)
@@ -41,9 +40,8 @@ ccl_device void kernel_path_volume_connect_light(KernelGlobals *kg, RNG *rng,
light_ray.time = sd->time;
#endif
- if(!light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls, true))
- return;
- else if(ls.pdf == 0.0f)
+ light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
+ if(ls.pdf == 0.0f)
return;
if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
@@ -52,15 +50,14 @@ ccl_device void kernel_path_volume_connect_light(KernelGlobals *kg, RNG *rng,
if(!shadow_blocked(kg, state, &light_ray, &shadow)) {
/* accumulate */
- path_radiance_accum_light(L, throughput * num_samples_adjust, &L_light, shadow, 1.0f, state->bounce, is_lamp);
+ path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp);
}
}
#endif
}
ccl_device bool kernel_path_volume_bounce(KernelGlobals *kg, RNG *rng,
- ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray,
- float num_samples_adjust)
+ ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray)
{
/* sample phase function */
float phase_pdf;
@@ -135,26 +132,22 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
LightSample ls;
- if(!light_select(kg, i, light_u, light_v, ray->P, &ls, true))
- continue;
+ lamp_light_sample(kg, i, light_u, light_v, ray->P, &ls);
float3 tp = throughput;
/* sample position on volume segment */
- if(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, rng, state, j, num_samples, PRNG_PHASE);
+ float rscatter = path_branched_rng_1D_for_decision(kg, rng, 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);
+ VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
+ state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
+
+ (void)result;
+ kernel_assert(result == VOLUME_PATH_SCATTERED);
- if(result != VOLUME_PATH_SCATTERED)
- continue;
-
- /* todo: split up light_sample so we don't have to call it again with new position */
- if(!light_select(kg, i, light_u, light_v, sd->P, &ls, true))
- continue;
- }
+ /* todo: split up light_sample so we don't have to call it again with new position */
+ lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls);
if(ls.pdf == 0.0f)
continue;
@@ -190,26 +183,22 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
light_t = 0.5f*light_t;
LightSample ls;
- if(!light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls, true))
- continue;
+ light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls);
float3 tp = throughput;
/* sample position on volume segment */
- if(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, rng, state, j, num_samples, PRNG_PHASE);
+ float rscatter = path_branched_rng_1D_for_decision(kg, rng, 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);
+ VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
+ state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
+
+ (void)result;
+ kernel_assert(result == VOLUME_PATH_SCATTERED);
- if(result != VOLUME_PATH_SCATTERED)
- continue;
-
- /* 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, &ls, true))
- continue;
- }
+ /* todo: split up light_sample so we don't have to call it again with new position */
+ light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
if(ls.pdf == 0.0f)
continue;
@@ -233,26 +222,22 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
LightSample ls;
- if(!light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls, true))
- return;
+ light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls);
float3 tp = throughput;
/* sample position on volume segment */
- if(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, rng, state, PRNG_PHASE);
+ float rscatter = path_state_rng_1D_for_decision(kg, rng, 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);
+ VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
+ state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
+
+ (void)result;
+ kernel_assert(result == VOLUME_PATH_SCATTERED);
- if(result != VOLUME_PATH_SCATTERED)
- return;
-
- /* 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, &ls, true))
- return;
- }
+ /* todo: split up light_sample so we don't have to call it again with new position */
+ light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
if(ls.pdf == 0.0f)
return;
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 842b9f68840..fc61f1a9c2c 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -86,7 +86,7 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
#endif
if(sd->type & PRIMITIVE_TRIANGLE) {
/* static triangle */
- float3 Ng = triangle_normal(kg, sd->prim);
+ float3 Ng = triangle_normal(kg, sd);
sd->shader = __float_as_int(kernel_tex_fetch(__tri_shader, sd->prim));
/* vectors */
@@ -165,7 +165,7 @@ ccl_device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderDat
/* fetch triangle data */
if(sd->type == PRIMITIVE_TRIANGLE) {
- float3 Ng = triangle_normal(kg, sd->prim);
+ float3 Ng = triangle_normal(kg, sd);
sd->shader = __float_as_int(kernel_tex_fetch(__tri_shader, sd->prim));
/* static triangle */
@@ -340,7 +340,7 @@ ccl_device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
float3 P, Ng, I = make_float3(0.0f, 0.0f, 0.0f);
int shader;
- triangle_point_normal(kg, prim, u, v, &P, &Ng, &shader);
+ triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader);
/* force smooth shading for displacement */
shader |= SHADER_SMOOTH_NORMAL;
diff --git a/intern/cycles/kernel/kernel_sse2.cpp b/intern/cycles/kernel/kernel_sse2.cpp
index 67bd0943b1b..740998e8c92 100644
--- a/intern/cycles/kernel/kernel_sse2.cpp
+++ b/intern/cycles/kernel/kernel_sse2.cpp
@@ -64,10 +64,10 @@ void kernel_cpu_sse2_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, floa
/* Shader Evaluate */
-void kernel_cpu_sse2_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i, int sample)
+void kernel_cpu_sse2_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i, int offset, int sample)
{
if(type >= SHADER_EVAL_BAKE)
- kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, i, sample);
+ kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, i, offset, sample);
else
kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, i, sample);
}
diff --git a/intern/cycles/kernel/kernel_sse3.cpp b/intern/cycles/kernel/kernel_sse3.cpp
index 40d621b66f6..da73a3a1c97 100644
--- a/intern/cycles/kernel/kernel_sse3.cpp
+++ b/intern/cycles/kernel/kernel_sse3.cpp
@@ -66,10 +66,10 @@ void kernel_cpu_sse3_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, floa
/* Shader Evaluate */
-void kernel_cpu_sse3_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i, int sample)
+void kernel_cpu_sse3_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i, int offset, int sample)
{
if(type >= SHADER_EVAL_BAKE)
- kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, i, sample);
+ kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, i, offset, sample);
else
kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, i, sample);
}
diff --git a/intern/cycles/kernel/kernel_sse41.cpp b/intern/cycles/kernel/kernel_sse41.cpp
index 4b48d10b020..5704f60e138 100644
--- a/intern/cycles/kernel/kernel_sse41.cpp
+++ b/intern/cycles/kernel/kernel_sse41.cpp
@@ -67,10 +67,10 @@ void kernel_cpu_sse41_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, flo
/* Shader Evaluate */
-void kernel_cpu_sse41_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i, int sample)
+void kernel_cpu_sse41_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i, int offset, int sample)
{
if(type >= SHADER_EVAL_BAKE)
- kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, i, sample);
+ kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, i, offset, sample);
else
kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, i, sample);
}
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index d81909a623a..933202ea498 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -66,6 +66,8 @@ CCL_NAMESPACE_BEGIN
#define __SUBSURFACE__
#define __CMJ__
#define __VOLUME__
+#define __VOLUME_DECOUPLED__
+#define __VOLUME_SCATTER__
#define __SHADOW_RECORD_ALL__
#endif
@@ -73,10 +75,15 @@ CCL_NAMESPACE_BEGIN
#define __KERNEL_SHADING__
#define __KERNEL_ADV_SHADING__
#define __BRANCHED_PATH__
+#define __VOLUME__
+#define __VOLUME_SCATTER__
/* Experimental on GPU */
-//#define __VOLUME__
-//#define __SUBSURFACE__
+#ifdef __KERNEL_CUDA_EXPERIMENTAL__
+#define __SUBSURFACE__
+#define __CMJ__
+#endif
+
#endif
#ifdef __KERNEL_OPENCL__
@@ -103,7 +110,6 @@ CCL_NAMESPACE_BEGIN
#define __BACKGROUND_MIS__
#define __LAMP_MIS__
#define __AO__
-#define __ANISOTROPIC__
//#define __CAMERA_MOTION__
//#define __OBJECT_MOTION__
//#define __HAIR__
@@ -134,11 +140,9 @@ CCL_NAMESPACE_BEGIN
#ifdef __KERNEL_SHADING__
#define __SVM__
#define __EMISSION__
-#define __PROCEDURAL_TEXTURES__
-#define __IMAGE_TEXTURES__
+#define __TEXTURES__
#define __EXTRA_NODES__
#define __HOLDOUT__
-#define __NORMAL_MAP__
#endif
#ifdef __KERNEL_ADV_SHADING__
@@ -148,7 +152,6 @@ CCL_NAMESPACE_BEGIN
#define __BACKGROUND_MIS__
#define __LAMP_MIS__
#define __AO__
-#define __ANISOTROPIC__
#define __CAMERA_MOTION__
#define __OBJECT_MOTION__
#define __HAIR__
@@ -223,10 +226,9 @@ enum PathTraceDimension {
PRNG_PHASE_V = 9,
PRNG_PHASE = 10,
PRNG_SCATTER_DISTANCE = 11,
- PRNG_BOUNCE_NUM = 12,
-#else
- PRNG_BOUNCE_NUM = 8,
#endif
+
+ PRNG_BOUNCE_NUM = 12,
};
enum SamplingPattern {
@@ -252,17 +254,17 @@ enum PathRayFlag {
PATH_RAY_SHADOW_TRANSPARENT = 256,
PATH_RAY_SHADOW = (PATH_RAY_SHADOW_OPAQUE|PATH_RAY_SHADOW_TRANSPARENT),
- PATH_RAY_CURVE = 512, /* visibility flag to define curve segments*/
+ PATH_RAY_CURVE = 512, /* visibility flag to define curve segments */
+ PATH_RAY_VOLUME_SCATTER = 1024, /* volume scattering */
/* note that these can use maximum 12 bits, the other are for layers */
- PATH_RAY_ALL_VISIBILITY = (1|2|4|8|16|32|64|128|256|512),
+ PATH_RAY_ALL_VISIBILITY = (1|2|4|8|16|32|64|128|256|512|1024),
- PATH_RAY_MIS_SKIP = 1024,
- PATH_RAY_DIFFUSE_ANCESTOR = 2048,
- PATH_RAY_GLOSSY_ANCESTOR = 4096,
- PATH_RAY_BSSRDF_ANCESTOR = 8192,
- PATH_RAY_SINGLE_PASS_DONE = 16384,
- PATH_RAY_VOLUME_SCATTER = 32768,
+ PATH_RAY_MIS_SKIP = 2048,
+ PATH_RAY_DIFFUSE_ANCESTOR = 4096,
+ PATH_RAY_GLOSSY_ANCESTOR = 8192,
+ PATH_RAY_BSSRDF_ANCESTOR = 16384,
+ PATH_RAY_SINGLE_PASS_DONE = 32768,
/* we need layer member flags to be the 20 upper bits */
PATH_RAY_LAYER_SHIFT = (32-20)
@@ -332,21 +334,25 @@ typedef struct PathRadiance {
float3 color_glossy;
float3 color_transmission;
float3 color_subsurface;
+ float3 color_scatter;
float3 direct_diffuse;
float3 direct_glossy;
float3 direct_transmission;
float3 direct_subsurface;
+ float3 direct_scatter;
float3 indirect_diffuse;
float3 indirect_glossy;
float3 indirect_transmission;
float3 indirect_subsurface;
+ float3 indirect_scatter;
float3 path_diffuse;
float3 path_glossy;
float3 path_transmission;
float3 path_subsurface;
+ float3 path_scatter;
float4 shadow;
float mist;
@@ -360,6 +366,7 @@ typedef struct BsdfEval {
float3 transmission;
float3 transparent;
float3 subsurface;
+ float3 scatter;
} BsdfEval;
#else
@@ -380,7 +387,8 @@ typedef enum ShaderFlag {
SHADER_EXCLUDE_GLOSSY = (1 << 26),
SHADER_EXCLUDE_TRANSMIT = (1 << 25),
SHADER_EXCLUDE_CAMERA = (1 << 24),
- SHADER_EXCLUDE_ANY = (SHADER_EXCLUDE_DIFFUSE|SHADER_EXCLUDE_GLOSSY|SHADER_EXCLUDE_TRANSMIT|SHADER_EXCLUDE_CAMERA),
+ SHADER_EXCLUDE_SCATTER = (1 << 23),
+ SHADER_EXCLUDE_ANY = (SHADER_EXCLUDE_DIFFUSE|SHADER_EXCLUDE_GLOSSY|SHADER_EXCLUDE_TRANSMIT|SHADER_EXCLUDE_CAMERA|SHADER_EXCLUDE_SCATTER),
SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT|SHADER_USE_MIS|SHADER_EXCLUDE_ANY)
} ShaderFlag;
@@ -392,10 +400,8 @@ typedef enum LightType {
LIGHT_DISTANT,
LIGHT_BACKGROUND,
LIGHT_AREA,
- LIGHT_AO,
LIGHT_SPOT,
- LIGHT_TRIANGLE,
- LIGHT_STRAND
+ LIGHT_TRIANGLE
} LightType;
/* Camera Type */
@@ -526,17 +532,15 @@ typedef struct ShaderClosure {
ClosureType type;
float3 weight;
- float sample_weight;
-
float data0;
float data1;
+ float data2;
float3 N;
-#if defined(__ANISOTROPIC__) || defined(__SUBSURFACE__) || defined(__HAIR__)
float3 T;
-#endif
+
+ float sample_weight;
- float data2;
#ifdef __OSL__
void *prim;
#endif
@@ -596,7 +600,8 @@ enum ShaderDataFlag {
/* object flags */
SD_HOLDOUT_MASK = 524288, /* holdout for camera rays */
SD_OBJECT_MOTION = 1048576, /* has object motion blur */
- SD_TRANSFORM_APPLIED = 2097152, /* vertices have transform applied */
+ SD_TRANSFORM_APPLIED = 2097152, /* vertices have transform applied */
+ SD_NEGATIVE_SCALE_APPLIED = 4194304, /* vertices have negative scale applied */
SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED)
};
@@ -762,9 +767,12 @@ typedef struct KernelCamera {
/* render size */
float width, height;
int resolution;
+
+ /* anamorphic lens bokeh */
+ float inv_aperture_ratio;
+
int pad1;
int pad2;
- int pad3;
/* more matrices */
Transform screentoworld;
@@ -866,7 +874,8 @@ typedef struct KernelIntegrator {
int transparent_shadows;
/* caustics */
- int no_caustics;
+ int caustics_reflective;
+ int caustics_refractive;
float filter_glossy;
/* seed */
@@ -927,7 +936,6 @@ typedef enum CurveFlag {
} CurveFlag;
typedef struct KernelCurves {
- /* strand intersect and normal parameters - many can be changed to flags */
int curveflags;
int subdivisions;
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index cc4b2e3edf1..ea02ede10cd 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -176,6 +176,8 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, PathState
/* compute extinction at the start */
float t = 0.0f;
+ float3 sum = make_float3(0.0f, 0.0f, 0.0f);
+
for(int i = 0; i < max_steps; i++) {
/* advance to new position */
float new_t = min(ray->t, (i+1) * step);
@@ -190,20 +192,26 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, PathState
/* compute attenuation over segment */
if(volume_shader_extinction_sample(kg, sd, state, new_P, &sigma_t)) {
- /* todo: we could avoid computing expf() for each step by summing,
- * because exp(a)*exp(b) = exp(a+b), but we still want a quick
- * tp_eps check too */
- tp *= volume_color_transmittance(sigma_t, new_t - t);
-
- /* stop if nearly all light blocked */
- if(tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps)
- break;
+ /* Compute expf() only for every Nth step, to save some calculations
+ * because exp(a)*exp(b) = exp(a+b), also do a quick tp_eps check then. */
+
+ sum += (-sigma_t * (new_t - t));
+ if((i & 0x07) == 0) { /* ToDo: Other interval? */
+ tp = *throughput * make_float3(expf(sum.x), expf(sum.y), expf(sum.z));
+
+ /* stop if nearly all light is blocked */
+ if(tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps)
+ break;
+ }
}
/* stop if at the end of the volume */
t = new_t;
- if(t == ray->t)
+ if(t == ray->t) {
+ /* Update throughput in case we haven't done it above */
+ tp = *throughput * make_float3(expf(sum.x), expf(sum.y), expf(sum.z));
break;
+ }
}
*throughput = tp;
@@ -326,6 +334,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
float t = ray->t;
float3 new_tp;
+#ifdef __VOLUME_SCATTER__
/* randomly scatter, and if we do t is shortened */
if(closure_flag & SD_SCATTER) {
/* extinction coefficient */
@@ -379,7 +388,9 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
new_tp = *throughput * transmittance / pdf;
}
}
- else if(closure_flag & SD_ABSORPTION) {
+ else
+#endif
+ if(closure_flag & SD_ABSORPTION) {
/* absorption only, no sampling needed */
float3 transmittance = volume_color_transmittance(coeff.sigma_a, t);
new_tp = *throughput * transmittance;
@@ -456,6 +467,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
bool scatter = false;
/* distance sampling */
+#ifdef __VOLUME_SCATTER__
if((closure_flag & SD_SCATTER) || (has_scatter && (closure_flag & SD_ABSORPTION))) {
has_scatter = true;
@@ -491,7 +503,9 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
xi = 1.0f - (1.0f - xi)/sample_transmittance;
}
}
- else if(closure_flag & SD_ABSORPTION) {
+ else
+#endif
+ if(closure_flag & SD_ABSORPTION) {
/* absorption only, no sampling needed */
float3 sigma_a = coeff.sigma_a;
@@ -546,13 +560,12 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
* between the endpoints. distance sampling is used to decide if we will
* scatter or not. */
ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(KernelGlobals *kg,
- PathState *state, ShaderData *sd, Ray *ray, PathRadiance *L, float3 *throughput, RNG *rng)
+ PathState *state, ShaderData *sd, Ray *ray, PathRadiance *L, float3 *throughput, RNG *rng, bool heterogeneous)
{
/* workaround to fix correlation bug in T38710, can find better solution
* in random number generator later, for now this is done here to not impact
* performance of rendering without volumes */
RNG tmp_rng = cmj_hash(*rng, state->rng_offset);
- bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack);
shader_setup_from_volume(kg, sd, ray, state->bounce, state->transparent_bounce);
@@ -724,16 +737,15 @@ ccl_device void kernel_volume_decoupled_free(KernelGlobals *kg, VolumeSegment *s
* scattering, they always scatter if there is any non-zero scattering
* coefficient.
*
- * these also do not do emission or modify throughput. */
+ * these also do not do emission or modify throughput.
+ *
+ * function is expected to return VOLUME_PATH_SCATTERED when probalistic_scatter is false */
ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
KernelGlobals *kg, PathState *state, Ray *ray, ShaderData *sd,
float3 *throughput, float rphase, float rscatter,
const VolumeSegment *segment, const float3 *light_P, bool probalistic_scatter)
{
- int closure_flag = segment->closure_flag;
-
- if(!(closure_flag & SD_SCATTER))
- return VOLUME_PATH_MISSED;
+ kernel_assert(segment->closure_flag & SD_SCATTER);
/* pick random color channel, we use the Veach one-sample
* model with balance heuristic for the channels */
@@ -845,15 +857,33 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
float3 step_pdf_distance = make_float3(1.0f, 1.0f, 1.0f);
if(segment->numsteps > 1) {
- /* todo: optimize using binary search */
float3 prev_cdf_distance = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < segment->numsteps-1; i++, step++) {
- if(sample_t < step->t)
+ int numsteps = segment->numsteps;
+ int high = numsteps - 1;
+ int low = 0;
+ int mid;
+
+ while(low < high) {
+ mid = (low + high) >> 1;
+
+ if(sample_t < step[mid].t)
+ high = mid;
+ else if(sample_t >= step[mid + 1].t)
+ low = mid + 1;
+ else {
+ /* found our interval in step[mid] .. step[mid+1] */
+ prev_t = step[mid].t;
+ prev_cdf_distance = step[mid].cdf_distance;
+ step += mid+1;
break;
+ }
+ }
- prev_t = step->t;
- prev_cdf_distance = step->cdf_distance;
+ if(low >= numsteps - 1) {
+ prev_t = step[numsteps - 1].t;
+ prev_cdf_distance = step[numsteps-1].cdf_distance;
+ step += numsteps - 1;
}
/* pdf for picking step with distance sampling */
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp
index 94337290d20..84ef85e089d 100644
--- a/intern/cycles/kernel/osl/osl_bssrdf.cpp
+++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp
@@ -66,18 +66,6 @@ ClosureParam *closure_bssrdf_cubic_params()
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, sc.N),
CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, radius),
- //CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.data1),
- CLOSURE_STRING_KEYPARAM("label"),
- CLOSURE_FINISH_PARAM(CubicBSSRDFClosure)
- };
- return params;
-}
-
-ClosureParam *closure_bssrdf_cubic_extended_params()
-{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, sc.N),
- CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, radius),
CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.data1),
CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.T.x),
CLOSURE_STRING_KEYPARAM("label"),
@@ -107,18 +95,6 @@ ClosureParam *closure_bssrdf_gaussian_params()
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, sc.N),
CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, radius),
- //CLOSURE_FLOAT_PARAM(GaussianBSSRDFClosure, sc.data1),
- CLOSURE_STRING_KEYPARAM("label"),
- CLOSURE_FINISH_PARAM(GaussianBSSRDFClosure)
- };
- return params;
-}
-
-ClosureParam *closure_bssrdf_gaussian_extended_params()
-{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, sc.N),
- CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, radius),
CLOSURE_FLOAT_PARAM(GaussianBSSRDFClosure, sc.data1),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(GaussianBSSRDFClosure)
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index 2d716103b85..d7789edcfff 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -105,7 +105,7 @@ BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, ashikhmin_velvet, LA
CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet)
-BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley, ashikhmin_shirley_aniso, ashikhmin_shirley, LABEL_GLOSSY)
+BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley, ashikhmin_shirley_aniso, ashikhmin_shirley, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, sc.N),
CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, sc.T),
CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, sc.data0),
@@ -124,37 +124,37 @@ BSDF_CLOSURE_CLASS_BEGIN(GlossyToon, glossy_toon, glossy_toon, LABEL_GLOSSY)
CLOSURE_FLOAT_PARAM(GlossyToonClosure, sc.data1),
BSDF_CLOSURE_CLASS_END(GlossyToon, glossy_toon)
-BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, microfacet_ggx, microfacet_ggx, LABEL_GLOSSY)
+BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, microfacet_ggx, microfacet_ggx, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx)
-BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXAniso, microfacet_ggx_aniso, microfacet_ggx, LABEL_GLOSSY)
+BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXAniso, microfacet_ggx_aniso, microfacet_ggx, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, sc.N),
CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, sc.T),
CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, sc.data1),
BSDF_CLOSURE_CLASS_END(MicrofacetGGXAniso, microfacet_ggx_aniso)
-BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, microfacet_beckmann, microfacet_beckmann, LABEL_GLOSSY)
+BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, microfacet_beckmann, microfacet_beckmann, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann)
-BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannAniso, microfacet_beckmann_aniso, microfacet_beckmann, LABEL_GLOSSY)
+BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannAniso, microfacet_beckmann_aniso, microfacet_beckmann, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, sc.N),
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, sc.T),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, sc.data1),
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannAniso, microfacet_beckmann_aniso)
-BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction, microfacet_ggx, LABEL_GLOSSY)
+BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction, microfacet_ggx, LABEL_GLOSSY|LABEL_TRANSMIT)
CLOSURE_FLOAT3_PARAM(MicrofacetGGXRefractionClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data2),
BSDF_CLOSURE_CLASS_END(MicrofacetGGXRefraction, microfacet_ggx_refraction)
-BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction, microfacet_beckmann, LABEL_GLOSSY)
+BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction, microfacet_beckmann, LABEL_GLOSSY|LABEL_TRANSMIT)
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannRefractionClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data2),
@@ -244,8 +244,6 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
bsdf_diffuse_toon_params(), bsdf_diffuse_toon_prepare);
register_closure(ss, "glossy_toon", id++,
bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare);
- register_closure(ss, "specular_toon", id++,
- bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare);
register_closure(ss, "westin_backscatter", id++,
bsdf_westin_backscatter_params(), bsdf_westin_backscatter_prepare);
register_closure(ss, "westin_sheen", id++,
@@ -267,10 +265,6 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
closure_bssrdf_cubic_params(), closure_bssrdf_cubic_prepare);
register_closure(ss, "bssrdf_gaussian", id++,
closure_bssrdf_gaussian_params(), closure_bssrdf_gaussian_prepare);
- register_closure(ss, "bssrdf_cubic", id++,
- closure_bssrdf_cubic_extended_params(), closure_bssrdf_cubic_prepare);
- register_closure(ss, "bssrdf_gaussian", id++,
- closure_bssrdf_gaussian_extended_params(), closure_bssrdf_gaussian_prepare);
register_closure(ss, "hair_reflection", id++,
bsdf_hair_reflection_params(), bsdf_hair_reflection_prepare);
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index a543907e884..58d215295dc 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -52,8 +52,6 @@ OSL::ClosureParam *closure_westin_backscatter_params();
OSL::ClosureParam *closure_westin_sheen_params();
OSL::ClosureParam *closure_bssrdf_cubic_params();
OSL::ClosureParam *closure_bssrdf_gaussian_params();
-OSL::ClosureParam *closure_bssrdf_cubic_extended_params();
-OSL::ClosureParam *closure_bssrdf_gaussian_extended_params();
OSL::ClosureParam *closure_henyey_greenstein_volume_params();
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 6a59a381f48..38cb5061346 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -126,7 +126,7 @@ void OSLRenderServices::thread_init(KernelGlobals *kernel_globals_, OSL::Texture
osl_ts = osl_ts_;
}
-bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time)
+bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform, float time)
{
/* this is only used for shader and object space, we don't really have
* a concept of shader space, so we just use object space for both. */
@@ -156,7 +156,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr
return false;
}
-bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time)
+bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform, float time)
{
/* this is only used for shader and object space, we don't really have
* a concept of shader space, so we just use object space for both. */
@@ -186,7 +186,7 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform
return false;
}
-bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from, float time)
+bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from, float time)
{
KernelGlobals *kg = kernel_globals;
@@ -218,7 +218,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from, float ti
return false;
}
-bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time)
+bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring to, float time)
{
KernelGlobals *kg = kernel_globals;
@@ -250,7 +250,7 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, fl
return false;
}
-bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform)
+bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform)
{
/* this is only used for shader and object space, we don't really have
* a concept of shader space, so we just use object space for both. */
@@ -275,7 +275,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr
return false;
}
-bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform)
+bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform)
{
/* this is only used for shader and object space, we don't really have
* a concept of shader space, so we just use object space for both. */
@@ -300,7 +300,7 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform
return false;
}
-bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from)
+bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from)
{
KernelGlobals *kg = kernel_globals;
@@ -328,7 +328,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from)
return false;
}
-bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to)
+bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring to)
{
KernelGlobals *kg = kernel_globals;
@@ -356,7 +356,7 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to)
return false;
}
-bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives,
+bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals *sg, bool derivatives,
ustring object, TypeDesc type, ustring name,
int index, void *val)
{
@@ -479,7 +479,7 @@ static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val)
static bool set_attribute_string(ustring str, TypeDesc type, bool derivatives, void *val)
{
- if(type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) {
+ if(type.basetype == TypeDesc::STRING && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) {
ustring *sval = (ustring *)val;
sval[0] = str;
@@ -751,13 +751,19 @@ bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData *
return false;
}
-bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustring object_name,
+bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg, bool derivatives, ustring object_name,
TypeDesc type, ustring name, void *val)
{
- if (renderstate == NULL)
+ if (sg->renderstate == NULL)
return false;
- ShaderData *sd = (ShaderData *)renderstate;
+ ShaderData *sd = (ShaderData *)(sg->renderstate);
+ return get_attribute(sd, derivatives, object_name, type, name, val);
+}
+
+bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring object_name,
+ TypeDesc type, ustring name, void *val)
+{
KernelGlobals *kg = sd->osl_globals;
bool is_curve;
int object;
@@ -815,12 +821,12 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
}
bool OSLRenderServices::get_userdata(bool derivatives, ustring name, TypeDesc type,
- void *renderstate, void *val)
+ OSL::ShaderGlobals *sg, void *val)
{
return false; /* disabled by lockgeom */
}
-bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, void *renderstate)
+bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, OSL::ShaderGlobals *sg)
{
return false; /* never called by OSL */
}
@@ -969,7 +975,7 @@ bool OSLRenderServices::environment(ustring filename, TextureOpt &options,
return status;
}
-bool OSLRenderServices::get_texture_info(ustring filename, int subimage,
+bool OSLRenderServices::get_texture_info(OSL::ShaderGlobals *sg, ustring filename, int subimage,
ustring dataname,
TypeDesc datatype, void *data)
{
diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h
index 069722d81b6..6f928a0d103 100644
--- a/intern/cycles/kernel/osl/osl_services.h
+++ b/intern/cycles/kernel/osl/osl_services.h
@@ -49,27 +49,29 @@ public:
void thread_init(KernelGlobals *kernel_globals, OSL::TextureSystem *ts);
- bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time);
- bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time);
+ bool get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform, float time);
+ bool get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform, float time);
- bool get_matrix(OSL::Matrix44 &result, ustring from, float time);
- bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time);
+ bool get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from, float time);
+ bool get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring to, float time);
- bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform);
- bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform);
+ bool get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform);
+ bool get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform);
- bool get_matrix(OSL::Matrix44 &result, ustring from);
- bool get_inverse_matrix(OSL::Matrix44 &result, ustring from);
+ bool get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from);
+ bool get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from);
- bool get_array_attribute(void *renderstate, bool derivatives,
+ bool get_array_attribute(OSL::ShaderGlobals *sg, bool derivatives,
ustring object, TypeDesc type, ustring name,
int index, void *val);
- bool get_attribute(void *renderstate, bool derivatives, ustring object,
+ bool get_attribute(OSL::ShaderGlobals *sg, bool derivatives, ustring object,
+ TypeDesc type, ustring name, void *val);
+ bool get_attribute(ShaderData *sd, bool derivatives, ustring object_name,
TypeDesc type, ustring name, void *val);
bool get_userdata(bool derivatives, ustring name, TypeDesc type,
- void *renderstate, void *val);
- bool has_userdata(ustring name, TypeDesc type, void *renderstate);
+ OSL::ShaderGlobals *sg, void *val);
+ bool has_userdata(ustring name, TypeDesc type, OSL::ShaderGlobals *sg);
int pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 &center,
float radius, int max_points, bool sort, size_t *out_indices,
@@ -106,7 +108,7 @@ public:
OSL::ShaderGlobals *sg, const OSL::Vec3 &R,
const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, float *result);
- bool get_texture_info(ustring filename, int subimage,
+ bool get_texture_info(OSL::ShaderGlobals *sg, ustring filename, int subimage,
ustring dataname, TypeDesc datatype, void *data);
static bool get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name,
@@ -157,6 +159,70 @@ public:
static ustring u_v;
static ustring u_empty;
+#if OSL_LIBRARY_VERSION_CODE < 10500
+ bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time) {
+ return get_matrix(NULL, result, xform, time);
+ }
+
+ bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time) {
+ return get_inverse_matrix(NULL, result, xform, time);
+ }
+
+ bool get_matrix(OSL::Matrix44 &result, ustring from, float time) {
+ return get_matrix(NULL, result, from, time);
+ }
+
+ bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time) {
+ return get_inverse_matrix(NULL, result, to, time);
+ }
+
+ bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform) {
+ return get_matrix(NULL, result, xform);
+ }
+
+ bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform) {
+ return get_inverse_matrix(NULL, result, xform);
+ }
+
+ bool get_matrix(OSL::Matrix44 &result, ustring from) {
+ return get_matrix(NULL, result, from);
+ }
+
+ bool get_inverse_matrix(OSL::Matrix44 &result, ustring to) {
+ return get_inverse_matrix(NULL, result, to);
+ }
+
+ bool get_array_attribute(void *renderstate, bool derivatives,
+ ustring object, TypeDesc type, ustring name,
+ int index, void *val) {
+ OSL::ShaderGlobals sg;
+ sg.renderstate = renderstate;
+ return get_array_attribute(&sg, derivatives,
+ object, type, name,
+ index, val);
+ }
+
+ bool get_attribute(void *renderstate, bool derivatives, ustring object_name,
+ TypeDesc type, ustring name, void *val) {
+ OSL::ShaderGlobals sg;
+ sg.renderstate = renderstate;
+ return get_attribute(&sg, derivatives, object_name, type, name, val);
+ }
+
+ bool has_userdata(ustring name, TypeDesc type, void *renderstate) {
+ return has_userdata(name, type, (OSL::ShaderGlobals *) renderstate);
+ }
+
+ bool get_userdata(bool derivatives, ustring name, TypeDesc type,
+ void *renderstate, void *val) {
+ return get_userdata(derivatives, name, type, (OSL::ShaderGlobals *) renderstate, val);
+ }
+
+ bool get_texture_info(ustring filename, int subimage,
+ ustring dataname, TypeDesc datatype, void *data) {
+ return get_texture_info(NULL, filename, subimage, dataname, datatype, data);
+ }
+#endif
private:
KernelGlobals *kernel_globals;
OSL::TextureSystem *osl_ts;
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 28135784db9..48498116874 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -164,11 +164,14 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
CBSDFClosure *bsdf = (CBSDFClosure *)prim;
int scattering = bsdf->scattering();
- /* no caustics option */
- if(scattering == LABEL_GLOSSY && (path_flag & PATH_RAY_DIFFUSE)) {
+ /* caustic options */
+ if((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
KernelGlobals *kg = sd->osl_globals;
- if(kernel_data.integrator.no_caustics)
+
+ if((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) ||
+ (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT))) {
return;
+ }
}
/* sample weight */
diff --git a/intern/cycles/kernel/shaders/node_fresnel.h b/intern/cycles/kernel/shaders/node_fresnel.h
index 447a84255ef..9f10ba8023e 100644
--- a/intern/cycles/kernel/shaders/node_fresnel.h
+++ b/intern/cycles/kernel/shaders/node_fresnel.h
@@ -34,3 +34,16 @@ float fresnel_dielectric_cos(float cosi, float eta)
return result;
}
+color fresnel_conductor(float cosi, color eta, color k)
+{
+ color cosi2 = color(cosi*cosi);
+ color one = color(1, 1, 1);
+ color tmp_f = eta * eta + k * k;
+ color tmp = tmp_f * cosi2;
+ color Rparl2 = (tmp - (2.0 * eta * cosi) + one) /
+ (tmp + (2.0 * eta * cosi) + one);
+ color Rperp2 = (tmp_f - (2.0 * eta * cosi) + cosi2) /
+ (tmp_f + (2.0 * eta * cosi) + cosi2);
+ return (Rparl2 + Rperp2) * 0.5;
+}
+
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index e39db8097f2..f8e5fd510ee 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -507,12 +507,8 @@ closure color hair_transmission(normal N, float roughnessu, float roughnessv, ve
closure color henyey_greenstein(float g) BUILTIN;
closure color absorption() BUILTIN;
-// Backwards compatibility
-closure color bssrdf_cubic(normal N, vector radius) BUILTIN;
-closure color bssrdf_gaussian(normal N, vector radius) BUILTIN;
-closure color specular_toon(normal N, float size, float smooth) BUILTIN;
-
// Renderer state
+int backfacing () BUILTIN;
int raytype (string typename) BUILTIN;
// the individual 'isFOOray' functions are deprecated
int iscameraray () { return raytype("camera"); }
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index d6663aae9db..c13eae813d6 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -236,7 +236,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
if(stack_load_float(stack, node.z) == 1.0f)
offset += node.y;
break;
-#ifdef __IMAGE_TEXTURES__
+#ifdef __TEXTURES__
case NODE_TEX_IMAGE:
svm_node_tex_image(kg, sd, stack, node);
break;
@@ -246,8 +246,6 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_TEX_ENVIRONMENT:
svm_node_tex_environment(kg, sd, stack, node);
break;
-#endif
-#ifdef __PROCEDURAL_TEXTURES__
case NODE_TEX_SKY:
svm_node_tex_sky(kg, sd, stack, node, &offset);
break;
@@ -420,17 +418,13 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_LIGHT_FALLOFF:
svm_node_light_falloff(sd, stack, node);
break;
-#endif
-#ifdef __ANISOTROPIC__
+#endif
case NODE_TANGENT:
svm_node_tangent(kg, sd, stack, node);
break;
-#endif
-#ifdef __NORMAL_MAP__
case NODE_NORMAL_MAP:
svm_node_normal_map(kg, sd, stack, node);
- break;
-#endif
+ break;
case NODE_END:
default:
return;
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 5fcc44e478b..30110db3ef9 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -179,7 +179,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: {
#ifdef __CAUSTICS_TRICKS__
- if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
+ if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
@@ -207,7 +207,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
#ifdef __CAUSTICS_TRICKS__
- if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
+ if(!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
@@ -244,8 +244,10 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: {
#ifdef __CAUSTICS_TRICKS__
- if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
+ if(!kernel_data.integrator.caustics_reflective &&
+ !kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE)) {
break;
+ }
#endif
/* index of refraction */
float eta = fmaxf(param2, 1e-5f);
@@ -262,12 +264,21 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float sample_weight = sc->sample_weight;
sc = svm_node_closure_get_bsdf(sd, mix_weight*fresnel);
-
- if(sc) {
- sc->N = N;
- svm_node_glass_setup(sd, sc, type, eta, roughness, false);
+#ifdef __CAUSTICS_TRICKS__
+ if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
+#endif
+ {
+ if(sc) {
+ sc->N = N;
+ svm_node_glass_setup(sd, sc, type, eta, roughness, false);
+ }
}
+#ifdef __CAUSTICS_TRICKS__
+ if(!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
+ break;
+#endif
+
/* refraction */
sc = &sd->closure[sd->num_closure];
sc->weight = weight;
@@ -286,7 +297,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID: {
#ifdef __CAUSTICS_TRICKS__
- if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
+ if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
@@ -294,7 +305,6 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(sc) {
sc->N = N;
-#ifdef __ANISOTROPIC__
sc->T = stack_load_float3(stack, data_node.y);
/* rotate tangent */
@@ -324,9 +334,6 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sd->flag |= bsdf_microfacet_ggx_aniso_setup(sc);
else
sd->flag |= bsdf_ashikhmin_shirley_aniso_setup(sc);
-#else
- sd->flag |= bsdf_diffuse_setup(sc);
-#endif
}
break;
}
@@ -371,7 +378,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(sc) {
/* todo: giving a fixed weight here will cause issues when
- * mixing multiple BSDFS. energey will not be conserved and
+ * mixing multiple BSDFS. energy will not be conserved and
* the throughput can blow up after multiple bounces. we
* better figure out a way to skip backfaces from rays
* spawned by transmission from the front */
diff --git a/intern/cycles/kernel/svm/svm_convert.h b/intern/cycles/kernel/svm/svm_convert.h
index 2503912c5c6..b221e0728ec 100644
--- a/intern/cycles/kernel/svm/svm_convert.h
+++ b/intern/cycles/kernel/svm/svm_convert.h
@@ -45,13 +45,13 @@ ccl_device void svm_node_convert(ShaderData *sd, float *stack, uint type, uint f
}
case NODE_CONVERT_VF: {
float3 f = stack_load_float3(stack, from);
- float g = (f.x + f.y + f.z)*(1.0f/3.0f);
+ float g = average(f);
stack_store_float(stack, to, g);
break;
}
case NODE_CONVERT_VI: {
float3 f = stack_load_float3(stack, from);
- int i = (int)((f.x + f.y + f.z)*(1.0f/3.0f));
+ int i = (int)average(f);
stack_store_int(stack, to, i);
break;
}
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp
index a877c52fbed..3926ecb99d6 100644
--- a/intern/cycles/render/background.cpp
+++ b/intern/cycles/render/background.cpp
@@ -78,6 +78,8 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene
kbackground->surface_shader |= SHADER_EXCLUDE_GLOSSY;
if(!(visibility & PATH_RAY_TRANSMIT))
kbackground->surface_shader |= SHADER_EXCLUDE_TRANSMIT;
+ if(!(visibility & PATH_RAY_VOLUME_SCATTER))
+ kbackground->surface_shader |= SHADER_EXCLUDE_SCATTER;
if(!(visibility & PATH_RAY_CAMERA))
kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA;
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index c68f6e1f08e..5723a22dd84 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -19,7 +19,7 @@
CCL_NAMESPACE_BEGIN
-BakeData::BakeData(const int object, const int tri_offset, const int num_pixels):
+BakeData::BakeData(const int object, const size_t tri_offset, const size_t num_pixels):
m_object(object),
m_tri_offset(tri_offset),
m_num_pixels(num_pixels)
@@ -60,7 +60,7 @@ int BakeData::object()
return m_object;
}
-int BakeData::size()
+size_t BakeData::size()
{
return m_num_pixels;
}
@@ -95,6 +95,7 @@ BakeManager::BakeManager()
m_bake_data = NULL;
m_is_baking = false;
need_update = true;
+ m_shader_limit = 512 * 512;
}
BakeManager::~BakeManager()
@@ -113,76 +114,105 @@ void BakeManager::set_baking(const bool value)
m_is_baking = value;
}
-BakeData *BakeManager::init(const int object, const int tri_offset, const int num_pixels)
+BakeData *BakeManager::init(const int object, const size_t tri_offset, const size_t num_pixels)
{
m_bake_data = new BakeData(object, tri_offset, num_pixels);
return m_bake_data;
}
+void BakeManager::set_shader_limit(const size_t x, const size_t y)
+{
+ m_shader_limit = x * y;
+ m_shader_limit = (size_t)pow(2, ceil(log(m_shader_limit)/log(2)));
+}
+
bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, BakeData *bake_data, float result[])
{
- size_t limit = bake_data->size();
+ size_t num_pixels = bake_data->size();
- /* setup input for device task */
- device_vector<uint4> d_input;
- uint4 *d_input_data = d_input.resize(limit * 2);
- size_t d_input_size = 0;
+ progress.reset_sample();
+ this->num_parts = 0;
- for(size_t i = 0; i < limit; i++) {
- d_input_data[d_input_size++] = bake_data->data(i);
- d_input_data[d_input_size++] = bake_data->differentials(i);
+ /* calculate the total parts for the progress bar */
+ for(size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
+ size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
+
+ DeviceTask task(DeviceTask::SHADER);
+ task.shader_w = shader_size;
+
+ this->num_parts += device->get_split_task_count(task);
}
- if(d_input_size == 0)
- return false;
+ this->num_samples = is_aa_pass(shader_type)? scene->integrator->aa_samples : 1;
- /* run device task */
- device_vector<float4> d_output;
- d_output.resize(limit);
+ for(size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
+ size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
- /* needs to be up to data for attribute access */
- device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
+ /* setup input for device task */
+ device_vector<uint4> d_input;
+ uint4 *d_input_data = d_input.resize(shader_size * 2);
+ size_t d_input_size = 0;
- device->mem_alloc(d_input, MEM_READ_ONLY);
- device->mem_copy_to(d_input);
- device->mem_alloc(d_output, MEM_WRITE_ONLY);
+ for(size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
+ d_input_data[d_input_size++] = bake_data->data(i);
+ d_input_data[d_input_size++] = bake_data->differentials(i);
+ }
- DeviceTask task(DeviceTask::SHADER);
- task.shader_input = d_input.device_pointer;
- task.shader_output = d_output.device_pointer;
- task.shader_eval_type = shader_type;
- task.shader_x = 0;
- task.shader_w = d_output.size();
- task.num_samples = is_aa_pass(shader_type)? scene->integrator->aa_samples: 1;
- task.get_cancel = function_bind(&Progress::get_cancel, &progress);
+ if(d_input_size == 0) {
+ m_is_baking = false;
+ return false;
+ }
- device->task_add(task);
- device->task_wait();
+ /* run device task */
+ device_vector<float4> d_output;
+ d_output.resize(shader_size);
+
+ /* needs to be up to data for attribute access */
+ device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
+
+ device->mem_alloc(d_input, MEM_READ_ONLY);
+ device->mem_copy_to(d_input);
+ device->mem_alloc(d_output, MEM_WRITE_ONLY);
+
+ DeviceTask task(DeviceTask::SHADER);
+ task.shader_input = d_input.device_pointer;
+ task.shader_output = d_output.device_pointer;
+ task.shader_eval_type = shader_type;
+ task.shader_x = 0;
+ task.offset = shader_offset;
+ task.shader_w = d_output.size();
+ task.num_samples = this->num_samples;
+ task.get_cancel = function_bind(&Progress::get_cancel, &progress);
+ task.update_progress_sample = function_bind(&Progress::increment_sample_update, &progress);
+
+ device->task_add(task);
+ device->task_wait();
+
+ if(progress.get_cancel()) {
+ device->mem_free(d_input);
+ device->mem_free(d_output);
+ m_is_baking = false;
+ return false;
+ }
- if(progress.get_cancel()) {
+ device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float4));
device->mem_free(d_input);
device->mem_free(d_output);
- m_is_baking = false;
- return false;
- }
-
- device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float4));
- device->mem_free(d_input);
- device->mem_free(d_output);
- /* read result */
- int k = 0;
+ /* read result */
+ int k = 0;
- float4 *offset = (float4*)d_output.data_pointer;
+ float4 *offset = (float4*)d_output.data_pointer;
- size_t depth = 4;
- for(size_t i = 0; i < limit; i++) {
- size_t index = i * depth;
- float4 out = offset[k++];
+ size_t depth = 4;
+ for(size_t i=shader_offset; i < (shader_offset + shader_size); i++) {
+ size_t index = i * depth;
+ float4 out = offset[k++];
- if(bake_data->is_valid(i)) {
- for(size_t j=0; j < 4; j++) {
- result[index + j] = out[j];
+ if(bake_data->is_valid(i)) {
+ for(size_t j=0; j < 4; j++) {
+ result[index + j] = out[j];
+ }
}
}
}
diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h
index f91ba589b8b..186fbbeea4d 100644
--- a/intern/cycles/render/bake.h
+++ b/intern/cycles/render/bake.h
@@ -27,20 +27,20 @@ CCL_NAMESPACE_BEGIN
class BakeData {
public:
- BakeData(const int object, const int tri_offset, const int num_pixels);
+ BakeData(const int object, const size_t tri_offset, const size_t num_pixels);
~BakeData();
void set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy);
int object();
- int size();
+ size_t size();
uint4 data(int i);
uint4 differentials(int i);
bool is_valid(int i);
private:
int m_object;
- int m_tri_offset;
- int m_num_pixels;
+ size_t m_tri_offset;
+ size_t m_num_pixels;
vector<int>m_primitive;
vector<float>m_u;
vector<float>m_v;
@@ -58,7 +58,9 @@ public:
bool get_baking();
void set_baking(const bool value);
- BakeData *init(const int object, const int tri_offset, const int num_pixels);
+ BakeData *init(const int object, const size_t tri_offset, const size_t num_pixels);
+
+ void set_shader_limit(const size_t x, const size_t y);
bool bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, BakeData *bake_data, float result[]);
@@ -70,9 +72,13 @@ public:
bool need_update;
+ int num_samples;
+ int num_parts;
+
private:
BakeData *m_bake_data;
bool m_is_baking;
+ size_t m_shader_limit;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 8659fe4f7a3..bb0fec759a9 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -38,6 +38,8 @@ Camera::Camera()
motion.post = transform_identity();
use_motion = false;
+ aperture_ratio = 1.0f;
+
type = CAMERA_PERSPECTIVE;
panorama_type = PANORAMA_EQUIRECTANGULAR;
fisheye_fov = M_PI_F;
@@ -241,6 +243,9 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
/* type */
kcam->type = type;
+ /* anamorphic lens bokeh */
+ kcam->inv_aperture_ratio = 1.0f / aperture_ratio;
+
/* panorama */
kcam->panorama_type = panorama_type;
kcam->fisheye_fov = fisheye_fov;
@@ -291,6 +296,7 @@ bool Camera::modified(const Camera& cam)
(viewplane == cam.viewplane) &&
(border == cam.border) &&
(matrix == cam.matrix) &&
+ (aperture_ratio == cam.aperture_ratio) &&
(panorama_type == cam.panorama_type) &&
(fisheye_fov == cam.fisheye_fov) &&
(fisheye_lens == cam.fisheye_lens));
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index c28670bc55f..50889968a90 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -54,6 +54,9 @@ public:
float fisheye_fov;
float fisheye_lens;
+ /* anamorphic lens bokeh */
+ float aperture_ratio;
+
/* sensor */
float sensorwidth;
float sensorheight;
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index c1aefbcfbbc..09973e8bc86 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -80,22 +80,13 @@ void Pass::add(PassType type, vector<Pass>& passes)
pass.components = 1;
break;
case PASS_OBJECT_ID:
- pass.components = 1;
- pass.filter = false;
- break;
case PASS_MATERIAL_ID:
pass.components = 1;
pass.filter = false;
break;
case PASS_DIFFUSE_COLOR:
- pass.components = 4;
- break;
case PASS_GLOSSY_COLOR:
- pass.components = 4;
- break;
case PASS_TRANSMISSION_COLOR:
- pass.components = 4;
- break;
case PASS_SUBSURFACE_COLOR:
pass.components = 4;
break;
@@ -141,9 +132,6 @@ void Pass::add(PassType type, vector<Pass>& passes)
break;
case PASS_EMISSION:
- pass.components = 4;
- pass.exposure = true;
- break;
case PASS_BACKGROUND:
pass.components = 4;
pass.exposure = true;
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 8369df5e137..076cc3d8b63 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -135,6 +135,7 @@ bool ImageManager::is_float_image(const string& filename, void *builtin_data, bo
(colorspace == "" &&
(strcmp(in->format_name(), "png") == 0 ||
strcmp(in->format_name(), "tiff") == 0 ||
+ strcmp(in->format_name(), "dpx") == 0 ||
strcmp(in->format_name(), "jpeg2000") == 0)));
}
else {
@@ -313,6 +314,32 @@ void ImageManager::remove_image(const string& filename, void *builtin_data, Inte
}
}
+/* TODO(sergey): Deduplicate with the iteration above, but make it pretty,
+ * without bunch of arguments passing around making code readability even
+ * more cluttered.
+ */
+void ImageManager::tag_reload_image(const string& filename, void *builtin_data, InterpolationType interpolation)
+{
+ size_t slot;
+
+ for(slot = 0; slot < images.size(); slot++) {
+ if(images[slot] && image_equals(images[slot], filename, builtin_data, interpolation)) {
+ images[slot]->need_load = true;
+ break;
+ }
+ }
+
+ if(slot == images.size()) {
+ /* see if it's in a float texture slot */
+ for(slot = 0; slot < float_images.size(); slot++) {
+ if(float_images[slot] && image_equals(float_images[slot], filename, builtin_data, interpolation)) {
+ float_images[slot]->need_load = true;
+ break;
+ }
+ }
+ }
+}
+
bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
{
if(img->filename == "")
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 50ea346c034..535f0ff156d 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -59,6 +59,7 @@ public:
bool& is_float, bool& is_linear, InterpolationType interpolation, bool use_alpha);
void remove_image(int slot);
void remove_image(const string& filename, void *builtin_data, InterpolationType interpolation);
+ void tag_reload_image(const string& filename, void *builtin_data, InterpolationType interpolation);
bool is_float_image(const string& filename, void *builtin_data, bool& is_linear);
void device_update(Device *device, DeviceScene *dscene, Progress& progress);
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index 4a8b490b1ad..b7a87ac14da 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -43,7 +43,8 @@ Integrator::Integrator()
volume_max_steps = 1024;
volume_step_size = 0.1f;
- no_caustics = false;
+ caustics_reflective = true;
+ caustics_refractive = true;
filter_glossy = 0.0f;
seed = 0;
layer_flag = ~0;
@@ -86,11 +87,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->max_diffuse_bounce = max_diffuse_bounce + 1;
kintegrator->max_glossy_bounce = max_glossy_bounce + 1;
kintegrator->max_transmission_bounce = max_transmission_bounce + 1;
-
- if(kintegrator->use_volumes)
- kintegrator->max_volume_bounce = max_volume_bounce + 1;
- else
- kintegrator->max_volume_bounce = 1;
+ kintegrator->max_volume_bounce = max_volume_bounce + 1;
kintegrator->transparent_max_bounce = transparent_max_bounce + 1;
kintegrator->transparent_min_bounce = transparent_min_bounce + 1;
@@ -104,7 +101,8 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->volume_max_steps = volume_max_steps;
kintegrator->volume_step_size = volume_step_size;
- kintegrator->no_caustics = no_caustics;
+ kintegrator->caustics_reflective = caustics_reflective;
+ kintegrator->caustics_refractive = caustics_refractive;
kintegrator->filter_glossy = (filter_glossy == 0.0f)? FLT_MAX: 1.0f/filter_glossy;
kintegrator->seed = hash_int(seed);
@@ -183,7 +181,8 @@ bool Integrator::modified(const Integrator& integrator)
volume_homogeneous_sampling == integrator.volume_homogeneous_sampling &&
volume_max_steps == integrator.volume_max_steps &&
volume_step_size == integrator.volume_step_size &&
- no_caustics == integrator.no_caustics &&
+ caustics_reflective == integrator.caustics_reflective &&
+ caustics_refractive == integrator.caustics_refractive &&
filter_glossy == integrator.filter_glossy &&
layer_flag == integrator.layer_flag &&
seed == integrator.seed &&
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index 380c1a65722..13c10e8ca94 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -43,7 +43,8 @@ public:
int volume_max_steps;
float volume_step_size;
- bool no_caustics;
+ bool caustics_reflective;
+ bool caustics_refractive;
float filter_glossy;
int seed;
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 9a0a7ead696..1f006637e67 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -121,6 +121,7 @@ Light::Light()
use_diffuse = true;
use_glossy = true;
use_transmission = true;
+ use_scatter = true;
shader = 0;
samples = 1;
@@ -206,8 +207,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
}
/* skip motion blurred deforming meshes, not supported yet */
- if(mesh->has_motion_blur())
+ if(mesh->has_motion_blur()) {
+ j++;
continue;
+ }
/* skip if we have no emission shaders */
foreach(uint sindex, mesh->used_shaders) {
@@ -241,6 +244,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
shader_flag |= SHADER_EXCLUDE_TRANSMIT;
use_light_visibility = true;
}
+ if(!(object->visibility & PATH_RAY_VOLUME_SCATTER)) {
+ shader_flag |= SHADER_EXCLUDE_SCATTER;
+ use_light_visibility = true;
+ }
for(size_t i = 0; i < mesh->triangles.size(); i++) {
Shader *shader = scene->shaders[mesh->shader[i]];
@@ -498,6 +505,10 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
shader_id |= SHADER_EXCLUDE_TRANSMIT;
use_light_visibility = true;
}
+ if(!light->use_scatter) {
+ shader_id |= SHADER_EXCLUDE_SCATTER;
+ use_light_visibility = true;
+ }
if(light->type == LIGHT_POINT) {
shader_id &= ~SHADER_AREA_LIGHT;
@@ -552,6 +563,10 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
shader_id |= SHADER_EXCLUDE_TRANSMIT;
use_light_visibility = true;
}
+ if(!(visibility & PATH_RAY_VOLUME_SCATTER)) {
+ shader_id |= SHADER_EXCLUDE_SCATTER;
+ use_light_visibility = true;
+ }
light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f);
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index 82308cf3e88..89091bb5f9e 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -54,6 +54,7 @@ public:
bool use_diffuse;
bool use_glossy;
bool use_transmission;
+ bool use_scatter;
int shader;
int samples;
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 273443034c5..8299cd02fef 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -132,6 +132,7 @@ void Mesh::clear()
transform_applied = false;
transform_negative_scaled = false;
transform_normal = transform_identity();
+ geometry_synced = false;
}
int Mesh::split_vertex(int vertex)
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 5ee774bacc1..d45905611fa 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -71,6 +71,9 @@ public:
ustring name;
/* Mesh Data */
+ bool geometry_synced; /* used to distinguish meshes with no verts
+ and meshed for which geometry is not created */
+
vector<float3> verts;
vector<Triangle> triangles;
vector<uint> shader;
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 027bfd71931..1f148d34ea6 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -449,6 +449,8 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, u
}
object_flag[i] |= SD_TRANSFORM_APPLIED;
+ if(object->mesh->transform_negative_scaled)
+ object_flag[i] |= SD_NEGATIVE_SCALE_APPLIED;
}
else
have_instancing = true;
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 94866102f60..f57e16471a1 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -248,20 +248,27 @@ void OSLShaderManager::shading_system_free()
bool OSLShaderManager::osl_compile(const string& inputfile, const string& outputfile)
{
- vector<string> options;
+#if OSL_LIBRARY_VERSION_CODE < 10500
+ typedef string string_view;
+#endif
+
+ vector<string_view> options;
string stdosl_path;
+ string shader_path = path_get("shader");
/* specify output file name */
options.push_back("-o");
options.push_back(outputfile);
/* specify standard include path */
- options.push_back("-I" + path_get("shader"));
+ options.push_back("-I");
+ options.push_back(shader_path);
+
stdosl_path = path_get("shader/stdosl.h");
/* compile */
OSL::OSLCompiler *compiler = OSL::OSLCompiler::create();
- bool ok = compiler->compile(inputfile, options, stdosl_path);
+ bool ok = compiler->compile(string_view(inputfile), options, string_view(stdosl_path));
delete compiler;
return ok;
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index cf0f0bc1055..796007b64a8 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -141,7 +141,7 @@ void Scene::device_update(Device *device_, Progress& progress)
* the different managers, using data computed by previous managers.
*
* - Image manager uploads images used by shaders.
- * - Camera may be used for adapative subdivison.
+ * - Camera may be used for adaptive subdivision.
* - Displacement shader must have all shader data available.
* - Light manager needs lookup tables and final mesh data to compute emission CDF.
* - Film needs light manager to run for use_light_visibility
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 576c176759c..13c63d9420c 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -363,14 +363,17 @@ bool SVMCompiler::node_skip_input(ShaderNode *node, ShaderInput *input)
return false;
}
-void SVMCompiler::find_dependencies(set<ShaderNode*>& dependencies, const set<ShaderNode*>& done, ShaderInput *input)
+void SVMCompiler::find_dependencies(set<ShaderNode*>& dependencies,
+ const set<ShaderNode*>& done,
+ ShaderInput *input,
+ ShaderNode *skip_node)
{
ShaderNode *node = (input->link)? input->link->parent: NULL;
- if(node && done.find(node) == done.end()) {
+ if(node && done.find(node) == done.end() && node != skip_node) {
foreach(ShaderInput *in, node->inputs)
if(!node_skip_input(node, in))
- find_dependencies(dependencies, done, in);
+ find_dependencies(dependencies, done, in, skip_node);
dependencies.insert(node);
}
@@ -459,20 +462,28 @@ void SVMCompiler::generate_closure_node(ShaderNode *node, set<ShaderNode*>& done
}
}
-void SVMCompiler::generated_shared_closure_nodes(ShaderNode *node, set<ShaderNode*>& done, set<ShaderNode*>& closure_done, const set<ShaderNode*>& shared)
+void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
+ ShaderNode *node,
+ set<ShaderNode*>& done,
+ set<ShaderNode*>& closure_done,
+ const set<ShaderNode*>& shared)
{
if(shared.find(node) != shared.end()) {
- generate_multi_closure(node, done, closure_done);
+ generate_multi_closure(root_node, node, done, closure_done);
}
else {
foreach(ShaderInput *in, node->inputs) {
if(in->type == SHADER_SOCKET_CLOSURE && in->link)
- generated_shared_closure_nodes(in->link->parent, done, closure_done, shared);
+ generated_shared_closure_nodes(root_node, in->link->parent,
+ done, closure_done, shared);
}
}
}
-void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, set<ShaderNode*>& closure_done)
+void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
+ ShaderNode *node,
+ set<ShaderNode*>& done,
+ set<ShaderNode*>& closure_done)
{
/* only generate once */
if(closure_done.find(node) != closure_done.end())
@@ -509,12 +520,33 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
set_intersection(cl1deps.begin(), cl1deps.end(),
cl2deps.begin(), cl2deps.end(),
std::inserter(shareddeps, shareddeps.begin()));
-
+
+ /* it's possible some nodes are not shared between this mix node
+ * inputs, but still needed to be always executed, this mainly
+ * happens when a node of current subbranch is used by a parent
+ * node or so */
+ if(root_node != node) {
+ foreach(ShaderInput *in, root_node->inputs) {
+ set<ShaderNode*> rootdeps;
+ find_dependencies(rootdeps, done, in, node);
+ set_intersection(rootdeps.begin(), rootdeps.end(),
+ cl1deps.begin(), cl1deps.end(),
+ std::inserter(shareddeps, shareddeps.begin()));
+ set_intersection(rootdeps.begin(), rootdeps.end(),
+ cl2deps.begin(), cl2deps.end(),
+ std::inserter(shareddeps, shareddeps.begin()));
+ }
+ }
+
if(!shareddeps.empty()) {
- if(cl1in->link)
- generated_shared_closure_nodes(cl1in->link->parent, done, closure_done, shareddeps);
- if(cl2in->link)
- generated_shared_closure_nodes(cl2in->link->parent, done, closure_done, shareddeps);
+ if(cl1in->link) {
+ generated_shared_closure_nodes(root_node, cl1in->link->parent,
+ done, closure_done, shareddeps);
+ }
+ if(cl2in->link) {
+ generated_shared_closure_nodes(root_node, cl2in->link->parent,
+ done, closure_done, shareddeps);
+ }
generate_svm_nodes(shareddeps, done);
}
@@ -525,7 +557,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
svm_nodes.push_back(make_int4(NODE_JUMP_IF_ONE, 0, facin->stack_offset, 0));
int node_jump_skip_index = svm_nodes.size() - 1;
- generate_multi_closure(cl1in->link->parent, done, closure_done);
+ generate_multi_closure(root_node, cl1in->link->parent, done, closure_done);
/* fill in jump instruction location to be after closure */
svm_nodes[node_jump_skip_index].y = svm_nodes.size() - node_jump_skip_index - 1;
@@ -537,7 +569,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
svm_nodes.push_back(make_int4(NODE_JUMP_IF_ZERO, 0, facin->stack_offset, 0));
int node_jump_skip_index = svm_nodes.size() - 1;
- generate_multi_closure(cl2in->link->parent, done, closure_done);
+ generate_multi_closure(root_node, cl2in->link->parent, done, closure_done);
/* fill in jump instruction location to be after closure */
svm_nodes[node_jump_skip_index].y = svm_nodes.size() - node_jump_skip_index - 1;
@@ -551,9 +583,9 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
* to skip closures here because was already optimized due to
* fixed weight or add closure that always needs both */
if(cl1in->link)
- generate_multi_closure(cl1in->link->parent, done, closure_done);
+ generate_multi_closure(root_node, cl1in->link->parent, done, closure_done);
if(cl2in->link)
- generate_multi_closure(cl2in->link->parent, done, closure_done);
+ generate_multi_closure(root_node, cl2in->link->parent, done, closure_done);
}
}
else {
@@ -638,7 +670,8 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
if(generate) {
set<ShaderNode*> done, closure_done;
- generate_multi_closure(clin->link->parent, done, closure_done);
+ generate_multi_closure(clin->link->parent, clin->link->parent,
+ done, closure_done);
}
}
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index 45aa4d26926..c1dd96e4d80 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -123,15 +123,21 @@ protected:
/* single closure */
void find_dependencies(set<ShaderNode*>& dependencies,
- const set<ShaderNode*>& done, ShaderInput *input);
+ const set<ShaderNode*>& done,
+ ShaderInput *input,
+ ShaderNode *skip_node = NULL);
void generate_node(ShaderNode *node, set<ShaderNode*>& done);
void generate_closure_node(ShaderNode *node, set<ShaderNode*>& done);
- void generated_shared_closure_nodes(ShaderNode *node, set<ShaderNode*>& done,
+ void generated_shared_closure_nodes(ShaderNode *root_node, ShaderNode *node,
+ set<ShaderNode*>& done,
set<ShaderNode*>& closure_done, const set<ShaderNode*>& shared);
void generate_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNode*>& done);
/* multi closure */
- void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, set<ShaderNode*>& closure_done);
+ void generate_multi_closure(ShaderNode *root_node,
+ ShaderNode *node,
+ set<ShaderNode*>& done,
+ set<ShaderNode*>& closure_done);
/* compile */
void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index 701ba313c79..7b3301e8abe 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -10,10 +10,8 @@ set(INC_SYS
set(SRC
util_cache.cpp
- util_cuda.cpp
util_dynlib.cpp
util_md5.cpp
- util_opencl.cpp
util_path.cpp
util_string.cpp
util_simd.cpp
@@ -34,7 +32,6 @@ set(SRC_HEADERS
util_args.h
util_boundbox.h
util_cache.h
- util_cuda.h
util_debug.h
util_dynlib.h
util_foreach.h
@@ -46,7 +43,6 @@ set(SRC_HEADERS
util_map.h
util_math.h
util_md5.h
- util_opencl.h
util_opengl.h
util_optimization.h
util_param.h
diff --git a/intern/cycles/util/util_cache.h b/intern/cycles/util/util_cache.h
index 417f4a869b6..bfb2877a22b 100644
--- a/intern/cycles/util/util_cache.h
+++ b/intern/cycles/util/util_cache.h
@@ -25,7 +25,7 @@
* again into the appropriate data structures.
*
* This way we do not need to accurately track changes, compare dates and
- * invalidate cache entries, at the cost of exta computation. If everything
+ * invalidate cache entries, at the cost of extra computation. If everything
* is stored in a global cache, computations can perhaps even be shared between
* different scenes where it may be hard to detect duplicate work.
*/
@@ -96,54 +96,70 @@ public:
buffers.push_back(buffer);
}
- template<typename T> void read(array<T>& data)
+ template<typename T> bool read(array<T>& data)
{
size_t size;
if(!fread(&size, sizeof(size), 1, f)) {
fprintf(stderr, "Failed to read vector size from cache.\n");
- return;
+ return false;
}
if(!size)
- return;
+ return false;
data.resize(size/sizeof(T));
if(!fread(&data[0], size, 1, f)) {
fprintf(stderr, "Failed to read vector data from cache (%lu).\n", (unsigned long)size);
- return;
+ return false;
}
+ return true;
}
- void read(int& data)
+ bool read(int& data)
{
size_t size;
- if(!fread(&size, sizeof(size), 1, f))
+ if(!fread(&size, sizeof(size), 1, f)) {
fprintf(stderr, "Failed to read int size from cache.\n");
- if(!fread(&data, sizeof(data), 1, f))
+ return false;
+ }
+ if(!fread(&data, sizeof(data), 1, f)) {
fprintf(stderr, "Failed to read int from cache.\n");
+ return false;
+ }
+ return true;
}
- void read(float& data)
+ bool read(float& data)
{
size_t size;
- if(!fread(&size, sizeof(size), 1, f))
+ if(!fread(&size, sizeof(size), 1, f)) {
fprintf(stderr, "Failed to read float size from cache.\n");
- if(!fread(&data, sizeof(data), 1, f))
+ return false;
+ }
+ if(!fread(&data, sizeof(data), 1, f)) {
fprintf(stderr, "Failed to read float from cache.\n");
+ return false;
+ }
+ return true;
}
- void read(size_t& data)
+ bool read(size_t& data)
{
size_t size;
- if(!fread(&size, sizeof(size), 1, f))
+ if(!fread(&size, sizeof(size), 1, f)) {
fprintf(stderr, "Failed to read size_t size from cache.\n");
- if(!fread(&data, sizeof(data), 1, f))
+ return false;
+ }
+ if(!fread(&data, sizeof(data), 1, f)) {
fprintf(stderr, "Failed to read size_t from cache.\n");
+ return false;
+ }
+ return true;
}
};
diff --git a/intern/cycles/util/util_cuda.cpp b/intern/cycles/util/util_cuda.cpp
deleted file mode 100644
index 9404f45d9a6..00000000000
--- a/intern/cycles/util/util_cuda.cpp
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * Copyright 2011-2013 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * 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 <iostream>
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "util_cuda.h"
-#include "util_debug.h"
-#include "util_dynlib.h"
-#include "util_path.h"
-#include "util_string.h"
-
-#ifdef _WIN32
-#define popen _popen
-#define pclose _pclose
-#endif
-
-/* function defininitions */
-
-tcuInit *cuInit;
-tcuDriverGetVersion *cuDriverGetVersion;
-tcuDeviceGet *cuDeviceGet;
-tcuDeviceGetCount *cuDeviceGetCount;
-tcuDeviceGetName *cuDeviceGetName;
-tcuDeviceComputeCapability *cuDeviceComputeCapability;
-tcuDeviceTotalMem *cuDeviceTotalMem;
-tcuDeviceGetProperties *cuDeviceGetProperties;
-tcuDeviceGetAttribute *cuDeviceGetAttribute;
-tcuCtxCreate *cuCtxCreate;
-tcuCtxDestroy *cuCtxDestroy;
-tcuCtxAttach *cuCtxAttach;
-tcuCtxDetach *cuCtxDetach;
-tcuCtxPushCurrent *cuCtxPushCurrent;
-tcuCtxPopCurrent *cuCtxPopCurrent;
-tcuCtxGetDevice *cuCtxGetDevice;
-tcuCtxSynchronize *cuCtxSynchronize;
-tcuModuleLoad *cuModuleLoad;
-tcuModuleLoadData *cuModuleLoadData;
-tcuModuleLoadDataEx *cuModuleLoadDataEx;
-tcuModuleLoadFatBinary *cuModuleLoadFatBinary;
-tcuModuleUnload *cuModuleUnload;
-tcuModuleGetFunction *cuModuleGetFunction;
-tcuModuleGetGlobal *cuModuleGetGlobal;
-tcuModuleGetTexRef *cuModuleGetTexRef;
-tcuModuleGetSurfRef *cuModuleGetSurfRef;
-tcuMemGetInfo *cuMemGetInfo;
-tcuMemAlloc *cuMemAlloc;
-tcuMemAllocPitch *cuMemAllocPitch;
-tcuMemFree *cuMemFree;
-tcuMemGetAddressRange *cuMemGetAddressRange;
-tcuMemAllocHost *cuMemAllocHost;
-tcuMemFreeHost *cuMemFreeHost;
-tcuMemHostAlloc *cuMemHostAlloc;
-tcuMemHostGetDevicePointer *cuMemHostGetDevicePointer;
-tcuMemHostGetFlags *cuMemHostGetFlags;
-tcuMemcpyHtoD *cuMemcpyHtoD;
-tcuMemcpyDtoH *cuMemcpyDtoH;
-tcuMemcpyDtoD *cuMemcpyDtoD;
-tcuMemcpyDtoA *cuMemcpyDtoA;
-tcuMemcpyAtoD *cuMemcpyAtoD;
-tcuMemcpyHtoA *cuMemcpyHtoA;
-tcuMemcpyAtoH *cuMemcpyAtoH;
-tcuMemcpyAtoA *cuMemcpyAtoA;
-tcuMemcpy2D *cuMemcpy2D;
-tcuMemcpy2DUnaligned *cuMemcpy2DUnaligned;
-tcuMemcpy3D *cuMemcpy3D;
-tcuMemcpyHtoDAsync *cuMemcpyHtoDAsync;
-tcuMemcpyDtoHAsync *cuMemcpyDtoHAsync;
-tcuMemcpyDtoDAsync *cuMemcpyDtoDAsync;
-tcuMemcpyHtoAAsync *cuMemcpyHtoAAsync;
-tcuMemcpyAtoHAsync *cuMemcpyAtoHAsync;
-tcuMemcpy2DAsync *cuMemcpy2DAsync;
-tcuMemcpy3DAsync *cuMemcpy3DAsync;
-tcuMemsetD8 *cuMemsetD8;
-tcuMemsetD16 *cuMemsetD16;
-tcuMemsetD32 *cuMemsetD32;
-tcuMemsetD2D8 *cuMemsetD2D8;
-tcuMemsetD2D16 *cuMemsetD2D16;
-tcuMemsetD2D32 *cuMemsetD2D32;
-tcuFuncSetBlockShape *cuFuncSetBlockShape;
-tcuFuncSetSharedSize *cuFuncSetSharedSize;
-tcuFuncGetAttribute *cuFuncGetAttribute;
-tcuFuncSetCacheConfig *cuFuncSetCacheConfig;
-tcuArrayCreate *cuArrayCreate;
-tcuArrayGetDescriptor *cuArrayGetDescriptor;
-tcuArrayDestroy *cuArrayDestroy;
-tcuArray3DCreate *cuArray3DCreate;
-tcuArray3DGetDescriptor *cuArray3DGetDescriptor;
-tcuTexRefCreate *cuTexRefCreate;
-tcuTexRefDestroy *cuTexRefDestroy;
-tcuTexRefSetArray *cuTexRefSetArray;
-tcuTexRefSetAddress *cuTexRefSetAddress;
-tcuTexRefSetAddress2D *cuTexRefSetAddress2D;
-tcuTexRefSetFormat *cuTexRefSetFormat;
-tcuTexRefSetAddressMode *cuTexRefSetAddressMode;
-tcuTexRefSetFilterMode *cuTexRefSetFilterMode;
-tcuTexRefSetFlags *cuTexRefSetFlags;
-tcuTexRefGetAddress *cuTexRefGetAddress;
-tcuTexRefGetArray *cuTexRefGetArray;
-tcuTexRefGetAddressMode *cuTexRefGetAddressMode;
-tcuTexRefGetFilterMode *cuTexRefGetFilterMode;
-tcuTexRefGetFormat *cuTexRefGetFormat;
-tcuTexRefGetFlags *cuTexRefGetFlags;
-tcuSurfRefSetArray *cuSurfRefSetArray;
-tcuSurfRefGetArray *cuSurfRefGetArray;
-tcuParamSetSize *cuParamSetSize;
-tcuParamSeti *cuParamSeti;
-tcuParamSetf *cuParamSetf;
-tcuParamSetv *cuParamSetv;
-tcuParamSetTexRef *cuParamSetTexRef;
-tcuLaunch *cuLaunch;
-tcuLaunchGrid *cuLaunchGrid;
-tcuLaunchGridAsync *cuLaunchGridAsync;
-tcuEventCreate *cuEventCreate;
-tcuEventRecord *cuEventRecord;
-tcuEventQuery *cuEventQuery;
-tcuEventSynchronize *cuEventSynchronize;
-tcuEventDestroy *cuEventDestroy;
-tcuEventElapsedTime *cuEventElapsedTime;
-tcuStreamCreate *cuStreamCreate;
-tcuStreamQuery *cuStreamQuery;
-tcuStreamSynchronize *cuStreamSynchronize;
-tcuStreamDestroy *cuStreamDestroy;
-tcuGraphicsUnregisterResource *cuGraphicsUnregisterResource;
-tcuGraphicsSubResourceGetMappedArray *cuGraphicsSubResourceGetMappedArray;
-tcuGraphicsResourceGetMappedPointer *cuGraphicsResourceGetMappedPointer;
-tcuGraphicsResourceSetMapFlags *cuGraphicsResourceSetMapFlags;
-tcuGraphicsMapResources *cuGraphicsMapResources;
-tcuGraphicsUnmapResources *cuGraphicsUnmapResources;
-tcuGetExportTable *cuGetExportTable;
-tcuCtxSetLimit *cuCtxSetLimit;
-tcuCtxGetLimit *cuCtxGetLimit;
-tcuGLCtxCreate *cuGLCtxCreate;
-tcuGraphicsGLRegisterBuffer *cuGraphicsGLRegisterBuffer;
-tcuGraphicsGLRegisterImage *cuGraphicsGLRegisterImage;
-tcuCtxSetCurrent *cuCtxSetCurrent;
-
-CCL_NAMESPACE_BEGIN
-
-/* utility macros */
-#define CUDA_LIBRARY_FIND_CHECKED(name) \
- name = (t##name*)dynamic_library_find(lib, #name);
-
-#define CUDA_LIBRARY_FIND(name) \
- name = (t##name*)dynamic_library_find(lib, #name); \
- assert(name);
-
-#define CUDA_LIBRARY_FIND_V2(name) \
- name = (t##name*)dynamic_library_find(lib, #name "_v2"); \
- assert(name);
-
-/* initialization function */
-
-bool cuLibraryInit()
-{
- static bool initialized = false;
- static bool result = false;
-
- if(initialized)
- return result;
-
- initialized = true;
-
- /* library paths */
-#ifdef _WIN32
- /* expected in c:/windows/system or similar, no path needed */
- const char *path = "nvcuda.dll";
- const char *alternative_path = NULL;
-#elif defined(__APPLE__)
- /* default installation path */
- const char *path = "/usr/local/cuda/lib/libcuda.dylib";
- const char *alternative_path = NULL;
-#else
- const char *path = "libcuda.so";
- const char *alternative_path = "libcuda.so.1";
-#endif
-
- /* load library */
- DynamicLibrary *lib = dynamic_library_open(path);
-
- if(lib == NULL && alternative_path)
- lib = dynamic_library_open(alternative_path);
-
- if(lib == NULL)
- return false;
-
- /* detect driver version */
- int driver_version = 1000;
-
- CUDA_LIBRARY_FIND_CHECKED(cuDriverGetVersion);
- if(cuDriverGetVersion)
- cuDriverGetVersion(&driver_version);
-
- /* we require version 4.0 */
- if(driver_version < 4000)
- return false;
-
- /* fetch all function pointers */
- CUDA_LIBRARY_FIND(cuInit);
- CUDA_LIBRARY_FIND(cuDeviceGet);
- CUDA_LIBRARY_FIND(cuDeviceGetCount);
- CUDA_LIBRARY_FIND(cuDeviceGetName);
- CUDA_LIBRARY_FIND(cuDeviceComputeCapability);
- CUDA_LIBRARY_FIND(cuDeviceTotalMem);
- CUDA_LIBRARY_FIND(cuDeviceGetProperties);
- CUDA_LIBRARY_FIND(cuDeviceGetAttribute);
- CUDA_LIBRARY_FIND(cuCtxCreate);
- CUDA_LIBRARY_FIND(cuCtxDestroy);
- CUDA_LIBRARY_FIND(cuCtxAttach);
- CUDA_LIBRARY_FIND(cuCtxDetach);
- CUDA_LIBRARY_FIND(cuCtxPushCurrent);
- CUDA_LIBRARY_FIND(cuCtxPopCurrent);
- CUDA_LIBRARY_FIND(cuCtxGetDevice);
- CUDA_LIBRARY_FIND(cuCtxSynchronize);
- CUDA_LIBRARY_FIND(cuModuleLoad);
- CUDA_LIBRARY_FIND(cuModuleLoadData);
- CUDA_LIBRARY_FIND(cuModuleUnload);
- CUDA_LIBRARY_FIND(cuModuleGetFunction);
- CUDA_LIBRARY_FIND(cuModuleGetGlobal);
- CUDA_LIBRARY_FIND(cuModuleGetTexRef);
- CUDA_LIBRARY_FIND(cuMemGetInfo);
- CUDA_LIBRARY_FIND(cuMemAlloc);
- CUDA_LIBRARY_FIND(cuMemAllocPitch);
- CUDA_LIBRARY_FIND(cuMemFree);
- CUDA_LIBRARY_FIND(cuMemGetAddressRange);
- CUDA_LIBRARY_FIND(cuMemAllocHost);
- CUDA_LIBRARY_FIND(cuMemFreeHost);
- CUDA_LIBRARY_FIND(cuMemHostAlloc);
- CUDA_LIBRARY_FIND(cuMemHostGetDevicePointer);
- CUDA_LIBRARY_FIND(cuMemcpyHtoD);
- CUDA_LIBRARY_FIND(cuMemcpyDtoH);
- CUDA_LIBRARY_FIND(cuMemcpyDtoD);
- CUDA_LIBRARY_FIND(cuMemcpyDtoA);
- CUDA_LIBRARY_FIND(cuMemcpyAtoD);
- CUDA_LIBRARY_FIND(cuMemcpyHtoA);
- CUDA_LIBRARY_FIND(cuMemcpyAtoH);
- CUDA_LIBRARY_FIND(cuMemcpyAtoA);
- CUDA_LIBRARY_FIND(cuMemcpy2D);
- CUDA_LIBRARY_FIND(cuMemcpy2DUnaligned);
- CUDA_LIBRARY_FIND(cuMemcpy3D);
- CUDA_LIBRARY_FIND(cuMemcpyHtoDAsync);
- CUDA_LIBRARY_FIND(cuMemcpyDtoHAsync);
- CUDA_LIBRARY_FIND(cuMemcpyHtoAAsync);
- CUDA_LIBRARY_FIND(cuMemcpyAtoHAsync);
- CUDA_LIBRARY_FIND(cuMemcpy2DAsync);
- CUDA_LIBRARY_FIND(cuMemcpy3DAsync);
- CUDA_LIBRARY_FIND(cuMemsetD8);
- CUDA_LIBRARY_FIND(cuMemsetD16);
- CUDA_LIBRARY_FIND(cuMemsetD32);
- CUDA_LIBRARY_FIND(cuMemsetD2D8);
- CUDA_LIBRARY_FIND(cuMemsetD2D16);
- CUDA_LIBRARY_FIND(cuMemsetD2D32);
- CUDA_LIBRARY_FIND(cuFuncSetBlockShape);
- CUDA_LIBRARY_FIND(cuFuncSetSharedSize);
- CUDA_LIBRARY_FIND(cuFuncGetAttribute);
- CUDA_LIBRARY_FIND(cuArrayCreate);
- CUDA_LIBRARY_FIND(cuArrayGetDescriptor);
- CUDA_LIBRARY_FIND(cuArrayDestroy);
- CUDA_LIBRARY_FIND(cuArray3DCreate);
- CUDA_LIBRARY_FIND(cuArray3DGetDescriptor);
- CUDA_LIBRARY_FIND(cuTexRefCreate);
- CUDA_LIBRARY_FIND(cuTexRefDestroy);
- CUDA_LIBRARY_FIND(cuTexRefSetArray);
- CUDA_LIBRARY_FIND(cuTexRefSetAddress);
- CUDA_LIBRARY_FIND(cuTexRefSetAddress2D);
- CUDA_LIBRARY_FIND(cuTexRefSetFormat);
- CUDA_LIBRARY_FIND(cuTexRefSetAddressMode);
- CUDA_LIBRARY_FIND(cuTexRefSetFilterMode);
- CUDA_LIBRARY_FIND(cuTexRefSetFlags);
- CUDA_LIBRARY_FIND(cuTexRefGetAddress);
- CUDA_LIBRARY_FIND(cuTexRefGetArray);
- CUDA_LIBRARY_FIND(cuTexRefGetAddressMode);
- CUDA_LIBRARY_FIND(cuTexRefGetFilterMode);
- CUDA_LIBRARY_FIND(cuTexRefGetFormat);
- CUDA_LIBRARY_FIND(cuTexRefGetFlags);
- CUDA_LIBRARY_FIND(cuParamSetSize);
- CUDA_LIBRARY_FIND(cuParamSeti);
- CUDA_LIBRARY_FIND(cuParamSetf);
- CUDA_LIBRARY_FIND(cuParamSetv);
- CUDA_LIBRARY_FIND(cuParamSetTexRef);
- CUDA_LIBRARY_FIND(cuLaunch);
- CUDA_LIBRARY_FIND(cuLaunchGrid);
- CUDA_LIBRARY_FIND(cuLaunchGridAsync);
- CUDA_LIBRARY_FIND(cuEventCreate);
- CUDA_LIBRARY_FIND(cuEventRecord);
- CUDA_LIBRARY_FIND(cuEventQuery);
- CUDA_LIBRARY_FIND(cuEventSynchronize);
- CUDA_LIBRARY_FIND(cuEventDestroy);
- CUDA_LIBRARY_FIND(cuEventElapsedTime);
- CUDA_LIBRARY_FIND(cuStreamCreate);
- CUDA_LIBRARY_FIND(cuStreamQuery);
- CUDA_LIBRARY_FIND(cuStreamSynchronize);
- CUDA_LIBRARY_FIND(cuStreamDestroy);
-
- /* cuda 2.1 */
- CUDA_LIBRARY_FIND(cuModuleLoadDataEx);
- CUDA_LIBRARY_FIND(cuModuleLoadFatBinary);
- CUDA_LIBRARY_FIND(cuGLCtxCreate);
- CUDA_LIBRARY_FIND(cuGraphicsGLRegisterBuffer);
- CUDA_LIBRARY_FIND(cuGraphicsGLRegisterImage);
-
- /* cuda 2.3 */
- CUDA_LIBRARY_FIND(cuMemHostGetFlags);
- CUDA_LIBRARY_FIND(cuGraphicsGLRegisterBuffer);
- CUDA_LIBRARY_FIND(cuGraphicsGLRegisterImage);
-
- /* cuda 3.0 */
- CUDA_LIBRARY_FIND(cuMemcpyDtoDAsync);
- CUDA_LIBRARY_FIND(cuFuncSetCacheConfig);
- CUDA_LIBRARY_FIND(cuGraphicsUnregisterResource);
- CUDA_LIBRARY_FIND(cuGraphicsSubResourceGetMappedArray);
- CUDA_LIBRARY_FIND(cuGraphicsResourceGetMappedPointer);
- CUDA_LIBRARY_FIND(cuGraphicsResourceSetMapFlags);
- CUDA_LIBRARY_FIND(cuGraphicsMapResources);
- CUDA_LIBRARY_FIND(cuGraphicsUnmapResources);
- CUDA_LIBRARY_FIND(cuGetExportTable);
-
- /* cuda 3.1 */
- CUDA_LIBRARY_FIND(cuModuleGetSurfRef);
- CUDA_LIBRARY_FIND(cuSurfRefSetArray);
- CUDA_LIBRARY_FIND(cuSurfRefGetArray);
- CUDA_LIBRARY_FIND(cuCtxSetLimit);
- CUDA_LIBRARY_FIND(cuCtxGetLimit);
-
- /* functions which changed 3.1 -> 3.2 for 64 bit stuff, the cuda library
- * has both the old ones for compatibility and new ones with _v2 postfix,
- * we load the _v2 ones here. */
- CUDA_LIBRARY_FIND_V2(cuDeviceTotalMem);
- CUDA_LIBRARY_FIND_V2(cuCtxCreate);
- CUDA_LIBRARY_FIND_V2(cuModuleGetGlobal);
- CUDA_LIBRARY_FIND_V2(cuMemGetInfo);
- CUDA_LIBRARY_FIND_V2(cuMemAlloc);
- CUDA_LIBRARY_FIND_V2(cuMemAllocPitch);
- CUDA_LIBRARY_FIND_V2(cuMemFree);
- CUDA_LIBRARY_FIND_V2(cuMemGetAddressRange);
- CUDA_LIBRARY_FIND_V2(cuMemAllocHost);
- CUDA_LIBRARY_FIND_V2(cuMemHostGetDevicePointer);
- CUDA_LIBRARY_FIND_V2(cuMemcpyHtoD);
- CUDA_LIBRARY_FIND_V2(cuMemcpyDtoH);
- CUDA_LIBRARY_FIND_V2(cuMemcpyDtoD);
- CUDA_LIBRARY_FIND_V2(cuMemcpyDtoA);
- CUDA_LIBRARY_FIND_V2(cuMemcpyAtoD);
- CUDA_LIBRARY_FIND_V2(cuMemcpyHtoA);
- CUDA_LIBRARY_FIND_V2(cuMemcpyAtoH);
- CUDA_LIBRARY_FIND_V2(cuMemcpyAtoA);
- CUDA_LIBRARY_FIND_V2(cuMemcpyHtoAAsync);
- CUDA_LIBRARY_FIND_V2(cuMemcpyAtoHAsync);
- CUDA_LIBRARY_FIND_V2(cuMemcpy2D);
- CUDA_LIBRARY_FIND_V2(cuMemcpy2DUnaligned);
- CUDA_LIBRARY_FIND_V2(cuMemcpy3D);
- CUDA_LIBRARY_FIND_V2(cuMemcpyHtoDAsync);
- CUDA_LIBRARY_FIND_V2(cuMemcpyDtoHAsync);
- CUDA_LIBRARY_FIND_V2(cuMemcpyDtoDAsync);
- CUDA_LIBRARY_FIND_V2(cuMemcpy2DAsync);
- CUDA_LIBRARY_FIND_V2(cuMemcpy3DAsync);
- CUDA_LIBRARY_FIND_V2(cuMemsetD8);
- CUDA_LIBRARY_FIND_V2(cuMemsetD16);
- CUDA_LIBRARY_FIND_V2(cuMemsetD32);
- CUDA_LIBRARY_FIND_V2(cuMemsetD2D8);
- CUDA_LIBRARY_FIND_V2(cuMemsetD2D16);
- CUDA_LIBRARY_FIND_V2(cuMemsetD2D32);
- CUDA_LIBRARY_FIND_V2(cuArrayCreate);
- CUDA_LIBRARY_FIND_V2(cuArrayGetDescriptor);
- CUDA_LIBRARY_FIND_V2(cuArray3DCreate);
- CUDA_LIBRARY_FIND_V2(cuArray3DGetDescriptor);
- CUDA_LIBRARY_FIND_V2(cuTexRefSetAddress);
- CUDA_LIBRARY_FIND_V2(cuTexRefSetAddress2D);
- CUDA_LIBRARY_FIND_V2(cuTexRefGetAddress);
- CUDA_LIBRARY_FIND_V2(cuGraphicsResourceGetMappedPointer);
- CUDA_LIBRARY_FIND_V2(cuGLCtxCreate);
-
- /* cuda 4.0 */
- CUDA_LIBRARY_FIND(cuCtxSetCurrent);
-
- if(cuHavePrecompiledKernels())
- result = true;
-#ifndef _WIN32
- else if(cuCompilerPath() != "")
- result = true;
-#endif
-
- return result;
-}
-
-bool cuHavePrecompiledKernels()
-{
- string cubins_path = path_get("lib");
-
- return path_exists(cubins_path);
-}
-
-string cuCompilerPath()
-{
-#ifdef _WIN32
- const char *defaultpaths[] = {"C:/CUDA/bin", NULL};
- const char *executable = "nvcc.exe";
-#else
- const char *defaultpaths[] = {
- "/Developer/NVIDIA/CUDA-5.0/bin",
- "/usr/local/cuda-5.0/bin",
- "/usr/local/cuda/bin",
- "/Developer/NVIDIA/CUDA-6.0/bin",
- "/usr/local/cuda-6.0/bin",
- "/Developer/NVIDIA/CUDA-5.5/bin",
- "/usr/local/cuda-5.5/bin",
- NULL};
- const char *executable = "nvcc";
-#endif
-
- const char *binpath = getenv("CUDA_BIN_PATH");
-
- string nvcc;
-
- if(binpath) {
- nvcc = path_join(binpath, executable);
- if(path_exists(nvcc))
- return nvcc;
- }
-
- for(int i = 0; defaultpaths[i]; i++) {
- nvcc = path_join(defaultpaths[i], executable);
- if(path_exists(nvcc))
- return nvcc;
- }
-
-#ifndef _WIN32
- {
- FILE *handle = popen("which nvcc", "r");
- if(handle) {
- char buffer[4096] = {0};
- int len = fread(buffer, 1, sizeof(buffer) - 1, handle);
- buffer[len] = '\0';
- pclose(handle);
-
- if(buffer[0])
- return "nvcc";
- }
- }
-#endif
-
- return "";
-}
-
-int cuCompilerVersion()
-{
- string path = cuCompilerPath();
- if(path == "")
- return 0;
-
- /* get --version output */
- FILE *pipe = popen((path + " --version").c_str(), "r");
- if(!pipe) {
- fprintf(stderr, "CUDA: failed to run compiler to retrieve version");
- return 0;
- }
-
- char buf[128];
- string output = "";
-
- while(!feof(pipe))
- if(fgets(buf, 128, pipe) != NULL)
- output += buf;
-
- pclose(pipe);
-
- /* parse version number */
- string marker = "Cuda compilation tools, release ";
- size_t offset = output.find(marker);
- if(offset == string::npos) {
- fprintf(stderr, "CUDA: failed to find version number in:\n\n%s\n", output.c_str());
- return 0;
- }
-
- string versionstr = output.substr(offset + marker.size(), string::npos);
- int major, minor;
-
- if(sscanf(versionstr.c_str(), "%d.%d", &major, &minor) < 2) {
- fprintf(stderr, "CUDA: failed to parse version number from:\n\n%s\n", output.c_str());
- return 0;
- }
-
- return 10*major + minor;
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/util/util_cuda.h b/intern/cycles/util/util_cuda.h
deleted file mode 100644
index b5e9c7188cd..00000000000
--- a/intern/cycles/util/util_cuda.h
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * Copyright 2011-2013 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * 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_CUDA_H__
-#define __UTIL_CUDA_H__
-
-#include <stdlib.h>
-#include "util_opengl.h"
-#include "util_string.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* CUDA is linked in dynamically at runtime, so we can start the application
- * without requiring a CUDA installation. Code adapted from the example
- * matrixMulDynlinkJIT in the CUDA SDK. */
-
-bool cuLibraryInit();
-bool cuHavePrecompiledKernels();
-string cuCompilerPath();
-int cuCompilerVersion();
-
-CCL_NAMESPACE_END
-
-/* defines, structs, enums */
-
-#define CUDA_VERSION 3020
-
-#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined(__LP64__)
-typedef unsigned long long CUdeviceptr;
-#else
-typedef unsigned int CUdeviceptr;
-#endif
-
-typedef int CUdevice;
-typedef struct CUctx_st *CUcontext;
-typedef struct CUmod_st *CUmodule;
-typedef struct CUfunc_st *CUfunction;
-typedef struct CUarray_st *CUarray;
-typedef struct CUtexref_st *CUtexref;
-typedef struct CUsurfref_st *CUsurfref;
-typedef struct CUevent_st *CUevent;
-typedef struct CUstream_st *CUstream;
-typedef struct CUgraphicsResource_st *CUgraphicsResource;
-
-typedef struct CUuuid_st {
- char bytes[16];
-} CUuuid;
-
-typedef enum CUctx_flags_enum {
- CU_CTX_SCHED_AUTO = 0,
- CU_CTX_SCHED_SPIN = 1,
- CU_CTX_SCHED_YIELD = 2,
- CU_CTX_SCHED_MASK = 0x3,
- CU_CTX_BLOCKING_SYNC = 4,
- CU_CTX_MAP_HOST = 8,
- CU_CTX_LMEM_RESIZE_TO_MAX = 16,
- CU_CTX_FLAGS_MASK = 0x1f
-} CUctx_flags;
-
-typedef enum CUevent_flags_enum {
- CU_EVENT_DEFAULT = 0,
- CU_EVENT_BLOCKING_SYNC = 1,
- CU_EVENT_DISABLE_TIMING = 2
-} CUevent_flags;
-
-typedef enum CUarray_format_enum {
- CU_AD_FORMAT_UNSIGNED_INT8 = 0x01,
- CU_AD_FORMAT_UNSIGNED_INT16 = 0x02,
- CU_AD_FORMAT_UNSIGNED_INT32 = 0x03,
- CU_AD_FORMAT_SIGNED_INT8 = 0x08,
- CU_AD_FORMAT_SIGNED_INT16 = 0x09,
- CU_AD_FORMAT_SIGNED_INT32 = 0x0a,
- CU_AD_FORMAT_HALF = 0x10,
- CU_AD_FORMAT_FLOAT = 0x20
-} CUarray_format;
-
-typedef enum CUaddress_mode_enum {
- CU_TR_ADDRESS_MODE_WRAP = 0,
- CU_TR_ADDRESS_MODE_CLAMP = 1,
- CU_TR_ADDRESS_MODE_MIRROR = 2,
- CU_TR_ADDRESS_MODE_BORDER = 3
-} CUaddress_mode;
-
-typedef enum CUfilter_mode_enum {
- CU_TR_FILTER_MODE_POINT = 0,
- CU_TR_FILTER_MODE_LINEAR = 1
-} CUfilter_mode;
-
-typedef enum CUdevice_attribute_enum {
- CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK = 1,
- CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_X = 2,
- CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_Y = 3,
- CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_Z = 4,
- CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_X = 5,
- CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_Y = 6,
- CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_Z = 7,
- CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_BLOCK = 8,
- CU_DEVICE_ATTRIBUTE_SHARED_MEMORY_PER_BLOCK = 8,
- CU_DEVICE_ATTRIBUTE_TOTAL_CONSTANT_MEMORY = 9,
- CU_DEVICE_ATTRIBUTE_WARP_SIZE = 10,
- CU_DEVICE_ATTRIBUTE_MAX_PITCH = 11,
- CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_BLOCK = 12,
- CU_DEVICE_ATTRIBUTE_REGISTERS_PER_BLOCK = 12,
- CU_DEVICE_ATTRIBUTE_CLOCK_RATE = 13,
- CU_DEVICE_ATTRIBUTE_TEXTURE_ALIGNMENT = 14,
- CU_DEVICE_ATTRIBUTE_GPU_OVERLAP = 15,
- CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT = 16,
- CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT = 17,
- CU_DEVICE_ATTRIBUTE_INTEGRATED = 18,
- CU_DEVICE_ATTRIBUTE_CAN_MAP_HOST_MEMORY = 19,
- CU_DEVICE_ATTRIBUTE_COMPUTE_MODE = 20,
- CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE1D_WIDTH = 21,
- CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_WIDTH = 22,
- CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_HEIGHT = 23,
- CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_WIDTH = 24,
- CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_HEIGHT = 25,
- CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE3D_DEPTH = 26,
- CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_ARRAY_WIDTH = 27,
- CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_ARRAY_HEIGHT = 28,
- CU_DEVICE_ATTRIBUTE_MAXIMUM_TEXTURE2D_ARRAY_NUMSLICES = 29,
- CU_DEVICE_ATTRIBUTE_SURFACE_ALIGNMENT = 30,
- CU_DEVICE_ATTRIBUTE_CONCURRENT_KERNELS = 31,
- CU_DEVICE_ATTRIBUTE_ECC_ENABLED = 32,
- CU_DEVICE_ATTRIBUTE_PCI_BUS_ID = 33,
- CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID = 34,
- CU_DEVICE_ATTRIBUTE_TCC_DRIVER = 35
-} CUdevice_attribute;
-
-typedef struct CUdevprop_st {
- int maxThreadsPerBlock;
- int maxThreadsDim[3];
- int maxGridSize[3];
- int sharedMemPerBlock;
- int totalConstantMemory;
- int SIMDWidth;
- int memPitch;
- int regsPerBlock;
- int clockRate;
- int textureAlign;
-} CUdevprop;
-
-typedef enum CUfunction_attribute_enum {
- CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK = 0,
- CU_FUNC_ATTRIBUTE_SHARED_SIZE_BYTES = 1,
- CU_FUNC_ATTRIBUTE_CONST_SIZE_BYTES = 2,
- CU_FUNC_ATTRIBUTE_LOCAL_SIZE_BYTES = 3,
- CU_FUNC_ATTRIBUTE_NUM_REGS = 4,
- CU_FUNC_ATTRIBUTE_PTX_VERSION = 5,
- CU_FUNC_ATTRIBUTE_BINARY_VERSION = 6,
- CU_FUNC_ATTRIBUTE_MAX
-} CUfunction_attribute;
-
-typedef enum CUfunc_cache_enum {
- CU_FUNC_CACHE_PREFER_NONE = 0x00,
- CU_FUNC_CACHE_PREFER_SHARED = 0x01,
- CU_FUNC_CACHE_PREFER_L1 = 0x02
-} CUfunc_cache;
-
-typedef enum CUmemorytype_enum {
- CU_MEMORYTYPE_HOST = 0x01,
- CU_MEMORYTYPE_DEVICE = 0x02,
- CU_MEMORYTYPE_ARRAY = 0x03
-} CUmemorytype;
-
-typedef enum CUcomputemode_enum {
- CU_COMPUTEMODE_DEFAULT = 0,
- CU_COMPUTEMODE_EXCLUSIVE = 1,
- CU_COMPUTEMODE_PROHIBITED = 2
-} CUcomputemode;
-
-typedef enum CUjit_option_enum
-{
- CU_JIT_MAX_REGISTERS = 0,
- CU_JIT_THREADS_PER_BLOCK,
- CU_JIT_WALL_TIME,
- CU_JIT_INFO_LOG_BUFFER,
- CU_JIT_INFO_LOG_BUFFER_SIZE_BYTES,
- CU_JIT_ERROR_LOG_BUFFER,
- CU_JIT_ERROR_LOG_BUFFER_SIZE_BYTES,
- CU_JIT_OPTIMIZATION_LEVEL,
- CU_JIT_TARGET_FROM_CUCONTEXT,
- CU_JIT_TARGET,
- CU_JIT_FALLBACK_STRATEGY
-
-} CUjit_option;
-
-typedef enum CUjit_target_enum
-{
- CU_TARGET_COMPUTE_10 = 0,
- CU_TARGET_COMPUTE_11,
- CU_TARGET_COMPUTE_12,
- CU_TARGET_COMPUTE_13,
- CU_TARGET_COMPUTE_20,
- CU_TARGET_COMPUTE_21,
- CU_TARGET_COMPUTE_30,
- CU_TARGET_COMPUTE_35,
- CU_TARGET_COMPUTE_50
-} CUjit_target;
-
-typedef enum CUjit_fallback_enum
-{
- CU_PREFER_PTX = 0,
- CU_PREFER_BINARY
-
-} CUjit_fallback;
-
-typedef enum CUgraphicsRegisterFlags_enum {
- CU_GRAPHICS_REGISTER_FLAGS_NONE = 0x00
-} CUgraphicsRegisterFlags;
-
-typedef enum CUgraphicsMapResourceFlags_enum {
- CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE = 0x00,
- CU_GRAPHICS_MAP_RESOURCE_FLAGS_READ_ONLY = 0x01,
- CU_GRAPHICS_MAP_RESOURCE_FLAGS_WRITE_DISCARD = 0x02
-} CUgraphicsMapResourceFlags;
-
-typedef enum CUarray_cubemap_face_enum {
- CU_CUBEMAP_FACE_POSITIVE_X = 0x00,
- CU_CUBEMAP_FACE_NEGATIVE_X = 0x01,
- CU_CUBEMAP_FACE_POSITIVE_Y = 0x02,
- CU_CUBEMAP_FACE_NEGATIVE_Y = 0x03,
- CU_CUBEMAP_FACE_POSITIVE_Z = 0x04,
- CU_CUBEMAP_FACE_NEGATIVE_Z = 0x05
-} CUarray_cubemap_face;
-
-typedef enum CUlimit_enum {
- CU_LIMIT_STACK_SIZE = 0x00,
- CU_LIMIT_PRINTF_FIFO_SIZE = 0x01,
- CU_LIMIT_MALLOC_HEAP_SIZE = 0x02
-} CUlimit;
-
-typedef enum cudaError_enum {
- CUDA_SUCCESS = 0,
- CUDA_ERROR_INVALID_VALUE = 1,
- CUDA_ERROR_OUT_OF_MEMORY = 2,
- CUDA_ERROR_NOT_INITIALIZED = 3,
- CUDA_ERROR_DEINITIALIZED = 4,
- CUDA_ERROR_NO_DEVICE = 100,
- CUDA_ERROR_INVALID_DEVICE = 101,
- CUDA_ERROR_INVALID_IMAGE = 200,
- CUDA_ERROR_INVALID_CONTEXT = 201,
- CUDA_ERROR_MAP_FAILED = 205,
- CUDA_ERROR_UNMAP_FAILED = 206,
- CUDA_ERROR_ARRAY_IS_MAPPED = 207,
- CUDA_ERROR_ALREADY_MAPPED = 208,
- CUDA_ERROR_NO_BINARY_FOR_GPU = 209,
- CUDA_ERROR_ALREADY_ACQUIRED = 210,
- CUDA_ERROR_NOT_MAPPED = 211,
- CUDA_ERROR_NOT_MAPPED_AS_ARRAY = 212,
- CUDA_ERROR_NOT_MAPPED_AS_POINTER = 213,
- CUDA_ERROR_ECC_UNCORRECTABLE = 214,
- CUDA_ERROR_UNSUPPORTED_LIMIT = 215,
- CUDA_ERROR_CONTEXT_ALREADY_IN_USE = 216,
- CUDA_ERROR_PEER_ACCESS_UNSUPPORTED = 217,
- CUDA_ERROR_INVALID_PTX = 218,
- CUDA_ERROR_INVALID_SOURCE = 300,
- CUDA_ERROR_FILE_NOT_FOUND = 301,
- CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND = 302,
- CUDA_ERROR_SHARED_OBJECT_INIT_FAILED = 303,
- CUDA_ERROR_OPERATING_SYSTEM = 304,
- CUDA_ERROR_INVALID_HANDLE = 400,
- CUDA_ERROR_NOT_FOUND = 500,
- CUDA_ERROR_NOT_READY = 600,
- CUDA_ERROR_ILLEGAL_ADDRESS = 700,
- CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES = 701,
- CUDA_ERROR_LAUNCH_TIMEOUT = 702,
- CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING = 703,
- CUDA_ERROR_HARDWARE_STACK_ERROR = 714,
- CUDA_ERROR_ILLEGAL_INSTRUCTION = 715,
- CUDA_ERROR_MISALIGNED_ADDRESS = 716,
- CUDA_ERROR_INVALID_ADDRESS_SPACE = 717,
- CUDA_ERROR_INVALID_PC = 718,
- CUDA_ERROR_LAUNCH_FAILED = 719,
- CUDA_ERROR_NOT_PERMITTED = 800,
- CUDA_ERROR_NOT_SUPPORTED = 801,
- CUDA_ERROR_UNKNOWN = 999
-} CUresult;
-
-#define CU_MEMHOSTALLOC_PORTABLE 0x01
-#define CU_MEMHOSTALLOC_DEVICEMAP 0x02
-#define CU_MEMHOSTALLOC_WRITECOMBINED 0x04
-
-typedef struct CUDA_MEMCPY2D_st {
- size_t srcXInBytes;
- size_t srcY;
-
- CUmemorytype srcMemoryType;
- const void *srcHost;
- CUdeviceptr srcDevice;
- CUarray srcArray;
- size_t srcPitch;
-
- size_t dstXInBytes;
- size_t dstY;
-
- CUmemorytype dstMemoryType;
- void *dstHost;
- CUdeviceptr dstDevice;
- CUarray dstArray;
- size_t dstPitch;
-
- size_t WidthInBytes;
- size_t Height;
-} CUDA_MEMCPY2D;
-
-typedef struct CUDA_MEMCPY3D_st {
- size_t srcXInBytes;
- size_t srcY;
- size_t srcZ;
- size_t srcLOD;
- CUmemorytype srcMemoryType;
- const void *srcHost;
- CUdeviceptr srcDevice;
- CUarray srcArray;
- void *reserved0;
- size_t srcPitch;
- size_t srcHeight;
-
- size_t dstXInBytes;
- size_t dstY;
- size_t dstZ;
- size_t dstLOD;
- CUmemorytype dstMemoryType;
- void *dstHost;
- CUdeviceptr dstDevice;
- CUarray dstArray;
- void *reserved1;
- size_t dstPitch;
- size_t dstHeight;
-
- size_t WidthInBytes;
- size_t Height;
- size_t Depth;
-} CUDA_MEMCPY3D;
-
-typedef struct CUDA_ARRAY_DESCRIPTOR_st
-{
- size_t Width;
- size_t Height;
-
- CUarray_format Format;
- unsigned int NumChannels;
-} CUDA_ARRAY_DESCRIPTOR;
-
-typedef struct CUDA_ARRAY3D_DESCRIPTOR_st
-{
- size_t Width;
- size_t Height;
- size_t Depth;
-
- CUarray_format Format;
- unsigned int NumChannels;
- unsigned int Flags;
-} CUDA_ARRAY3D_DESCRIPTOR;
-
-#define CUDA_ARRAY3D_2DARRAY 0x01
-#define CUDA_ARRAY3D_SURFACE_LDST 0x02
-#define CU_TRSA_OVERRIDE_FORMAT 0x01
-#define CU_TRSF_READ_AS_INTEGER 0x01
-#define CU_TRSF_NORMALIZED_COORDINATES 0x02
-#define CU_TRSF_SRGB 0x10
-#define CU_PARAM_TR_DEFAULT -1
-
-#ifdef _WIN32
-#define CUDAAPI __stdcall
-#else
-#define CUDAAPI
-#endif
-
-/* function types */
-
-typedef CUresult CUDAAPI tcuInit(unsigned int Flags);
-typedef CUresult CUDAAPI tcuDriverGetVersion(int *driverVersion);
-typedef CUresult CUDAAPI tcuDeviceGet(CUdevice *device, int ordinal);
-typedef CUresult CUDAAPI tcuDeviceGetCount(int *count);
-typedef CUresult CUDAAPI tcuDeviceGetName(char *name, int len, CUdevice dev);
-typedef CUresult CUDAAPI tcuDeviceComputeCapability(int *major, int *minor, CUdevice dev);
-typedef CUresult CUDAAPI tcuDeviceTotalMem(size_t *bytes, CUdevice dev);
-typedef CUresult CUDAAPI tcuDeviceGetProperties(CUdevprop *prop, CUdevice dev);
-typedef CUresult CUDAAPI tcuDeviceGetAttribute(int *pi, CUdevice_attribute attrib, CUdevice dev);
-typedef CUresult CUDAAPI tcuCtxCreate(CUcontext *pctx, unsigned int flags, CUdevice dev);
-typedef CUresult CUDAAPI tcuCtxDestroy(CUcontext ctx);
-typedef CUresult CUDAAPI tcuCtxAttach(CUcontext *pctx, unsigned int flags);
-typedef CUresult CUDAAPI tcuCtxDetach(CUcontext ctx);
-typedef CUresult CUDAAPI tcuCtxPushCurrent(CUcontext ctx );
-typedef CUresult CUDAAPI tcuCtxPopCurrent(CUcontext *pctx);
-typedef CUresult CUDAAPI tcuCtxGetDevice(CUdevice *device);
-typedef CUresult CUDAAPI tcuCtxSynchronize(void);
-typedef CUresult CUDAAPI tcuCtxSetLimit(CUlimit limit, size_t value);
-typedef CUresult CUDAAPI tcuCtxGetLimit(size_t *pvalue, CUlimit limit);
-typedef CUresult CUDAAPI tcuCtxGetCacheConfig(CUfunc_cache *pconfig);
-typedef CUresult CUDAAPI tcuCtxSetCacheConfig(CUfunc_cache config);
-typedef CUresult CUDAAPI tcuCtxGetApiVersion(CUcontext ctx, unsigned int *version);
-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 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(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 tcuMemGetInfo(size_t *free, size_t *total);
-typedef CUresult CUDAAPI tcuMemAlloc(CUdeviceptr *dptr, size_t bytesize);
-typedef CUresult CUDAAPI tcuMemAllocPitch(CUdeviceptr *dptr, size_t *pPitch, size_t WidthInBytes, size_t Height, unsigned int ElementSizeBytes);
-typedef CUresult CUDAAPI tcuMemFree(CUdeviceptr dptr);
-typedef CUresult CUDAAPI tcuMemGetAddressRange(CUdeviceptr *pbase, size_t *psize, CUdeviceptr dptr);
-typedef CUresult CUDAAPI tcuMemAllocHost(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 tcuMemHostGetDevicePointer(CUdeviceptr *pdptr, void *p, unsigned int Flags);
-typedef CUresult CUDAAPI tcuMemHostGetFlags(unsigned int *pFlags, void *p);
-typedef CUresult CUDAAPI tcuMemcpyHtoD(CUdeviceptr dstDevice, const void *srcHost, size_t ByteCount);
-typedef CUresult CUDAAPI tcuMemcpyDtoH(void *dstHost, CUdeviceptr srcDevice, size_t ByteCount);
-typedef CUresult CUDAAPI tcuMemcpyDtoD(CUdeviceptr dstDevice, CUdeviceptr srcDevice, size_t ByteCount);
-typedef CUresult CUDAAPI tcuMemcpyDtoA(CUarray dstArray, size_t dstOffset, CUdeviceptr srcDevice, size_t ByteCount);
-typedef CUresult CUDAAPI tcuMemcpyAtoD(CUdeviceptr dstDevice, CUarray srcArray, size_t srcOffset, size_t ByteCount);
-typedef CUresult CUDAAPI tcuMemcpyHtoA(CUarray dstArray, size_t dstOffset, const void *srcHost, size_t ByteCount);
-typedef CUresult CUDAAPI tcuMemcpyAtoH(void *dstHost, CUarray srcArray, size_t srcOffset, size_t ByteCount);
-typedef CUresult CUDAAPI tcuMemcpyAtoA(CUarray dstArray, size_t dstOffset, CUarray srcArray, size_t srcOffset, size_t ByteCount);
-typedef CUresult CUDAAPI tcuMemcpy2D(const CUDA_MEMCPY2D *pCopy);
-typedef CUresult CUDAAPI tcuMemcpy2DUnaligned(const CUDA_MEMCPY2D *pCopy);
-typedef CUresult CUDAAPI tcuMemcpy3D(const CUDA_MEMCPY3D *pCopy);
-typedef CUresult CUDAAPI tcuMemcpyHtoDAsync(CUdeviceptr dstDevice, const void *srcHost, size_t ByteCount, CUstream hStream);
-typedef CUresult CUDAAPI tcuMemcpyDtoHAsync(void *dstHost, CUdeviceptr srcDevice, size_t ByteCount, CUstream hStream);
-typedef CUresult CUDAAPI tcuMemcpyDtoDAsync(CUdeviceptr dstDevice, CUdeviceptr srcDevice, size_t ByteCount, CUstream hStream);
-typedef CUresult CUDAAPI tcuMemcpyHtoAAsync(CUarray dstArray, size_t dstOffset, const void *srcHost, size_t ByteCount, CUstream hStream);
-typedef CUresult CUDAAPI tcuMemcpyAtoHAsync(void *dstHost, CUarray srcArray, size_t srcOffset, size_t ByteCount, CUstream hStream);
-typedef CUresult CUDAAPI tcuMemcpy2DAsync(const CUDA_MEMCPY2D *pCopy, CUstream hStream);
-typedef CUresult CUDAAPI tcuMemcpy3DAsync(const CUDA_MEMCPY3D *pCopy, CUstream hStream);
-typedef CUresult CUDAAPI tcuMemsetD8(CUdeviceptr dstDevice, unsigned char uc, size_t N);
-typedef CUresult CUDAAPI tcuMemsetD16(CUdeviceptr dstDevice, unsigned short us, size_t N);
-typedef CUresult CUDAAPI tcuMemsetD32(CUdeviceptr dstDevice, unsigned int ui, size_t N);
-typedef CUresult CUDAAPI tcuMemsetD2D8(CUdeviceptr dstDevice, size_t dstPitch, unsigned char uc, size_t Width, size_t Height);
-typedef CUresult CUDAAPI tcuMemsetD2D16(CUdeviceptr dstDevice, size_t dstPitch, unsigned short us, size_t Width, size_t Height);
-typedef CUresult CUDAAPI tcuMemsetD2D32(CUdeviceptr dstDevice, size_t dstPitch, unsigned int ui, size_t Width, size_t Height);
-typedef CUresult CUDAAPI tcuMemsetD8Async(CUdeviceptr dstDevice, unsigned char uc, size_t N, CUstream hStream);
-typedef CUresult CUDAAPI tcuMemsetD16Async(CUdeviceptr dstDevice, unsigned short us, size_t N, CUstream hStream);
-typedef CUresult CUDAAPI tcuMemsetD32Async(CUdeviceptr dstDevice, unsigned int ui, size_t N, CUstream hStream);
-typedef CUresult CUDAAPI tcuMemsetD2D8Async(CUdeviceptr dstDevice, size_t dstPitch, unsigned char uc, size_t Width, size_t Height, CUstream hStream);
-typedef CUresult CUDAAPI tcuMemsetD2D16Async(CUdeviceptr dstDevice, size_t dstPitch, unsigned short us, size_t Width, size_t Height, CUstream hStream);
-typedef CUresult CUDAAPI tcuMemsetD2D32Async(CUdeviceptr dstDevice, size_t dstPitch, unsigned int ui, size_t Width, size_t Height, CUstream hStream);
-typedef CUresult CUDAAPI tcuArrayCreate(CUarray *pHandle, const CUDA_ARRAY_DESCRIPTOR *pAllocateArray);
-typedef CUresult CUDAAPI tcuArrayGetDescriptor(CUDA_ARRAY_DESCRIPTOR *pArrayDescriptor, CUarray hArray);
-typedef CUresult CUDAAPI tcuArrayDestroy(CUarray hArray);
-typedef CUresult CUDAAPI tcuArray3DCreate(CUarray *pHandle, const CUDA_ARRAY3D_DESCRIPTOR *pAllocateArray);
-typedef CUresult CUDAAPI tcuArray3DGetDescriptor(CUDA_ARRAY3D_DESCRIPTOR *pArrayDescriptor, CUarray hArray);
-typedef CUresult CUDAAPI tcuStreamCreate(CUstream *phStream, unsigned int Flags);
-typedef CUresult CUDAAPI tcuStreamWaitEvent(CUstream hStream, CUevent hEvent, unsigned int Flags);
-typedef CUresult CUDAAPI tcuStreamQuery(CUstream hStream);
-typedef CUresult CUDAAPI tcuStreamSynchronize(CUstream hStream);
-typedef CUresult CUDAAPI tcuStreamDestroy(CUstream hStream);
-typedef CUresult CUDAAPI tcuEventCreate(CUevent *phEvent, unsigned int Flags);
-typedef CUresult CUDAAPI tcuEventRecord(CUevent hEvent, CUstream hStream);
-typedef CUresult CUDAAPI tcuEventQuery(CUevent hEvent);
-typedef CUresult CUDAAPI tcuEventSynchronize(CUevent hEvent);
-typedef CUresult CUDAAPI tcuEventDestroy(CUevent hEvent);
-typedef CUresult CUDAAPI tcuEventElapsedTime(float *pMilliseconds, CUevent hStart, CUevent hEnd);
-typedef CUresult CUDAAPI tcuFuncSetBlockShape(CUfunction hfunc, int x, int y, int z);
-typedef CUresult CUDAAPI tcuFuncSetSharedSize(CUfunction hfunc, unsigned int bytes);
-typedef CUresult CUDAAPI tcuFuncGetAttribute(int *pi, CUfunction_attribute attrib, CUfunction hfunc);
-typedef CUresult CUDAAPI tcuFuncSetCacheConfig(CUfunction hfunc, CUfunc_cache config);
-typedef CUresult CUDAAPI tcuParamSetSize(CUfunction hfunc, unsigned int numbytes);
-typedef CUresult CUDAAPI tcuParamSeti(CUfunction hfunc, int offset, unsigned int value);
-typedef CUresult CUDAAPI tcuParamSetf(CUfunction hfunc, int offset, float value);
-typedef CUresult CUDAAPI tcuParamSetv(CUfunction hfunc, int offset, void *ptr, unsigned int numbytes);
-typedef CUresult CUDAAPI tcuLaunch(CUfunction f);
-typedef CUresult CUDAAPI tcuLaunchGrid(CUfunction f, int grid_width, int grid_height);
-typedef CUresult CUDAAPI tcuLaunchGridAsync(CUfunction f, int grid_width, int grid_height, CUstream hStream);
-typedef CUresult CUDAAPI tcuParamSetTexRef(CUfunction hfunc, int texunit, CUtexref hTexRef);
-typedef CUresult CUDAAPI tcuTexRefSetArray(CUtexref hTexRef, CUarray hArray, unsigned int Flags);
-typedef CUresult CUDAAPI tcuTexRefSetAddress(size_t *ByteOffset, CUtexref hTexRef, CUdeviceptr dptr, size_t bytes);
-typedef CUresult CUDAAPI tcuTexRefSetAddress2D(CUtexref hTexRef, const CUDA_ARRAY_DESCRIPTOR *desc, CUdeviceptr dptr, size_t Pitch);
-typedef CUresult CUDAAPI tcuTexRefSetFormat(CUtexref hTexRef, CUarray_format fmt, int NumPackedComponents);
-typedef CUresult CUDAAPI tcuTexRefSetAddressMode(CUtexref hTexRef, int dim, CUaddress_mode am);
-typedef CUresult CUDAAPI tcuTexRefSetFilterMode(CUtexref hTexRef, CUfilter_mode fm);
-typedef CUresult CUDAAPI tcuTexRefSetFlags(CUtexref hTexRef, unsigned int Flags);
-typedef CUresult CUDAAPI tcuTexRefGetAddress(CUdeviceptr *pdptr, CUtexref hTexRef);
-typedef CUresult CUDAAPI tcuTexRefGetArray(CUarray *phArray, CUtexref hTexRef);
-typedef CUresult CUDAAPI tcuTexRefGetAddressMode(CUaddress_mode *pam, CUtexref hTexRef, int dim);
-typedef CUresult CUDAAPI tcuTexRefGetFilterMode(CUfilter_mode *pfm, CUtexref hTexRef);
-typedef CUresult CUDAAPI tcuTexRefGetFormat(CUarray_format *pFormat, int *pNumChannels, CUtexref hTexRef);
-typedef CUresult CUDAAPI tcuTexRefGetFlags(unsigned int *pFlags, CUtexref hTexRef);
-typedef CUresult CUDAAPI tcuTexRefCreate(CUtexref *pTexRef);
-typedef CUresult CUDAAPI tcuTexRefDestroy(CUtexref hTexRef);
-typedef CUresult CUDAAPI tcuSurfRefSetArray(CUsurfref hSurfRef, CUarray hArray, unsigned int Flags);
-typedef CUresult CUDAAPI tcuSurfRefGetArray(CUarray *phArray, CUsurfref hSurfRef);
-typedef CUresult CUDAAPI tcuGraphicsUnregisterResource(CUgraphicsResource resource);
-typedef CUresult CUDAAPI tcuGraphicsSubResourceGetMappedArray(CUarray *pArray, CUgraphicsResource resource, unsigned int arrayIndex, unsigned int mipLevel);
-typedef CUresult CUDAAPI tcuGraphicsResourceGetMappedPointer(CUdeviceptr *pDevPtr, size_t *pSize, CUgraphicsResource resource);
-typedef CUresult CUDAAPI tcuGraphicsResourceSetMapFlags(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 tcuGLCtxCreate(CUcontext *pCtx, unsigned int Flags, CUdevice device );
-typedef CUresult CUDAAPI tcuGraphicsGLRegisterBuffer(CUgraphicsResource *pCudaResource, GLuint buffer, unsigned int Flags);
-typedef CUresult CUDAAPI tcuGraphicsGLRegisterImage(CUgraphicsResource *pCudaResource, GLuint image, GLenum target, unsigned int Flags);
-typedef CUresult CUDAAPI tcuCtxSetCurrent(CUcontext ctx);
-
-/* function declarations */
-
-extern tcuInit *cuInit;
-extern tcuDriverGetVersion *cuDriverGetVersion;
-extern tcuDeviceGet *cuDeviceGet;
-extern tcuDeviceGetCount *cuDeviceGetCount;
-extern tcuDeviceGetName *cuDeviceGetName;
-extern tcuDeviceComputeCapability *cuDeviceComputeCapability;
-extern tcuDeviceTotalMem *cuDeviceTotalMem;
-extern tcuDeviceGetProperties *cuDeviceGetProperties;
-extern tcuDeviceGetAttribute *cuDeviceGetAttribute;
-extern tcuCtxCreate *cuCtxCreate;
-extern tcuCtxDestroy *cuCtxDestroy;
-extern tcuCtxAttach *cuCtxAttach;
-extern tcuCtxDetach *cuCtxDetach;
-extern tcuCtxPushCurrent *cuCtxPushCurrent;
-extern tcuCtxPopCurrent *cuCtxPopCurrent;
-extern tcuCtxGetDevice *cuCtxGetDevice;
-extern tcuCtxSynchronize *cuCtxSynchronize;
-extern tcuModuleLoad *cuModuleLoad;
-extern tcuModuleLoadData *cuModuleLoadData;
-extern tcuModuleLoadDataEx *cuModuleLoadDataEx;
-extern tcuModuleLoadFatBinary *cuModuleLoadFatBinary;
-extern tcuModuleUnload *cuModuleUnload;
-extern tcuModuleGetFunction *cuModuleGetFunction;
-extern tcuModuleGetGlobal *cuModuleGetGlobal;
-extern tcuModuleGetTexRef *cuModuleGetTexRef;
-extern tcuModuleGetSurfRef *cuModuleGetSurfRef;
-extern tcuMemGetInfo *cuMemGetInfo;
-extern tcuMemAlloc *cuMemAlloc;
-extern tcuMemAllocPitch *cuMemAllocPitch;
-extern tcuMemFree *cuMemFree;
-extern tcuMemGetAddressRange *cuMemGetAddressRange;
-extern tcuMemAllocHost *cuMemAllocHost;
-extern tcuMemFreeHost *cuMemFreeHost;
-extern tcuMemHostAlloc *cuMemHostAlloc;
-extern tcuMemHostGetDevicePointer *cuMemHostGetDevicePointer;
-extern tcuMemHostGetFlags *cuMemHostGetFlags;
-extern tcuMemcpyHtoD *cuMemcpyHtoD;
-extern tcuMemcpyDtoH *cuMemcpyDtoH;
-extern tcuMemcpyDtoD *cuMemcpyDtoD;
-extern tcuMemcpyDtoA *cuMemcpyDtoA;
-extern tcuMemcpyAtoD *cuMemcpyAtoD;
-extern tcuMemcpyHtoA *cuMemcpyHtoA;
-extern tcuMemcpyAtoH *cuMemcpyAtoH;
-extern tcuMemcpyAtoA *cuMemcpyAtoA;
-extern tcuMemcpy2D *cuMemcpy2D;
-extern tcuMemcpy2DUnaligned *cuMemcpy2DUnaligned;
-extern tcuMemcpy3D *cuMemcpy3D;
-extern tcuMemcpyHtoDAsync *cuMemcpyHtoDAsync;
-extern tcuMemcpyDtoHAsync *cuMemcpyDtoHAsync;
-extern tcuMemcpyDtoDAsync *cuMemcpyDtoDAsync;
-extern tcuMemcpyHtoAAsync *cuMemcpyHtoAAsync;
-extern tcuMemcpyAtoHAsync *cuMemcpyAtoHAsync;
-extern tcuMemcpy2DAsync *cuMemcpy2DAsync;
-extern tcuMemcpy3DAsync *cuMemcpy3DAsync;
-extern tcuMemsetD8 *cuMemsetD8;
-extern tcuMemsetD16 *cuMemsetD16;
-extern tcuMemsetD32 *cuMemsetD32;
-extern tcuMemsetD2D8 *cuMemsetD2D8;
-extern tcuMemsetD2D16 *cuMemsetD2D16;
-extern tcuMemsetD2D32 *cuMemsetD2D32;
-extern tcuFuncSetBlockShape *cuFuncSetBlockShape;
-extern tcuFuncSetSharedSize *cuFuncSetSharedSize;
-extern tcuFuncGetAttribute *cuFuncGetAttribute;
-extern tcuFuncSetCacheConfig *cuFuncSetCacheConfig;
-extern tcuArrayCreate *cuArrayCreate;
-extern tcuArrayGetDescriptor *cuArrayGetDescriptor;
-extern tcuArrayDestroy *cuArrayDestroy;
-extern tcuArray3DCreate *cuArray3DCreate;
-extern tcuArray3DGetDescriptor *cuArray3DGetDescriptor;
-extern tcuTexRefCreate *cuTexRefCreate;
-extern tcuTexRefDestroy *cuTexRefDestroy;
-extern tcuTexRefSetArray *cuTexRefSetArray;
-extern tcuTexRefSetAddress *cuTexRefSetAddress;
-extern tcuTexRefSetAddress2D *cuTexRefSetAddress2D;
-extern tcuTexRefSetFormat *cuTexRefSetFormat;
-extern tcuTexRefSetAddressMode *cuTexRefSetAddressMode;
-extern tcuTexRefSetFilterMode *cuTexRefSetFilterMode;
-extern tcuTexRefSetFlags *cuTexRefSetFlags;
-extern tcuTexRefGetAddress *cuTexRefGetAddress;
-extern tcuTexRefGetArray *cuTexRefGetArray;
-extern tcuTexRefGetAddressMode *cuTexRefGetAddressMode;
-extern tcuTexRefGetFilterMode *cuTexRefGetFilterMode;
-extern tcuTexRefGetFormat *cuTexRefGetFormat;
-extern tcuTexRefGetFlags *cuTexRefGetFlags;
-extern tcuSurfRefSetArray *cuSurfRefSetArray;
-extern tcuSurfRefGetArray *cuSurfRefGetArray;
-extern tcuParamSetSize *cuParamSetSize;
-extern tcuParamSeti *cuParamSeti;
-extern tcuParamSetf *cuParamSetf;
-extern tcuParamSetv *cuParamSetv;
-extern tcuParamSetTexRef *cuParamSetTexRef;
-extern tcuLaunch *cuLaunch;
-extern tcuLaunchGrid *cuLaunchGrid;
-extern tcuLaunchGridAsync *cuLaunchGridAsync;
-extern tcuEventCreate *cuEventCreate;
-extern tcuEventRecord *cuEventRecord;
-extern tcuEventQuery *cuEventQuery;
-extern tcuEventSynchronize *cuEventSynchronize;
-extern tcuEventDestroy *cuEventDestroy;
-extern tcuEventElapsedTime *cuEventElapsedTime;
-extern tcuStreamCreate *cuStreamCreate;
-extern tcuStreamQuery *cuStreamQuery;
-extern tcuStreamSynchronize *cuStreamSynchronize;
-extern tcuStreamDestroy *cuStreamDestroy;
-extern tcuGraphicsUnregisterResource *cuGraphicsUnregisterResource;
-extern tcuGraphicsSubResourceGetMappedArray *cuGraphicsSubResourceGetMappedArray;
-extern tcuGraphicsResourceGetMappedPointer *cuGraphicsResourceGetMappedPointer;
-extern tcuGraphicsResourceSetMapFlags *cuGraphicsResourceSetMapFlags;
-extern tcuGraphicsMapResources *cuGraphicsMapResources;
-extern tcuGraphicsUnmapResources *cuGraphicsUnmapResources;
-extern tcuGetExportTable *cuGetExportTable;
-extern tcuCtxSetLimit *cuCtxSetLimit;
-extern tcuCtxGetLimit *cuCtxGetLimit;
-extern tcuGLCtxCreate *cuGLCtxCreate;
-extern tcuGraphicsGLRegisterBuffer *cuGraphicsGLRegisterBuffer;
-extern tcuGraphicsGLRegisterImage *cuGraphicsGLRegisterImage;
-extern tcuCtxSetCurrent *cuCtxSetCurrent;
-
-#endif /* __UTIL_CUDA_H__ */
-
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index fc6827573f8..1cd8883a5c7 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -76,17 +76,6 @@ CCL_NAMESPACE_BEGIN
#ifdef _WIN32
-#ifndef __KERNEL_GPU__
-
-#if defined(_MSC_VER) && (_MSC_VER < 1800)
-# define copysignf(x, y) ((float)_copysign(x, y))
-# define hypotf(x, y) _hypotf(x, y)
-# define isnan(x) _isnan(x)
-# define isfinite(x) _finite(x)
-#endif
-
-#endif
-
#ifndef __KERNEL_OPENCL__
ccl_device_inline float fmaxf(float a, float b)
@@ -853,7 +842,6 @@ ccl_device_inline float4 max(float4 a, float4 b)
ccl_device_inline float4 select(const int4& mask, const float4& a, const float4& b)
{
#ifdef __KERNEL_SSE__
- /* blendv is sse4, and apparently broken on vs2008 */
return _mm_or_ps(_mm_and_ps(_mm_cvtepi32_ps(mask), a), _mm_andnot_ps(_mm_cvtepi32_ps(mask), b)); /* todo: avoid cvt */
#else
return make_float4((mask.x)? a.x: b.x, (mask.y)? a.y: b.y, (mask.z)? a.z: b.z, (mask.w)? a.w: b.w);
@@ -1425,6 +1413,23 @@ ccl_device bool ray_quad_intersect(
return false;
}
+/* projections */
+ccl_device bool map_to_sphere(float *r_u, float *r_v,
+ const float x, const float y, const float z)
+{
+ float len = sqrtf(x * x + y * y + z * z);
+ if (len > 0.0f) {
+ if (x == 0.0f && y == 0.0f) *r_u = 0.0f; /* othwise domain error */
+ else *r_u = (1.0f - atan2f(x, y) / (float)M_PI) / 2.0f;
+ *r_v = 1.0f - safe_acosf(z / len) / (float)M_PI;
+ return true;
+ }
+ else {
+ *r_v = *r_u = 0.0f; /* to avoid un-initialized variables */
+ return false;
+ }
+}
+
CCL_NAMESPACE_END
#endif /* __UTIL_MATH_H__ */
diff --git a/intern/cycles/util/util_opencl.cpp b/intern/cycles/util/util_opencl.cpp
deleted file mode 100644
index c2d6bc66dc1..00000000000
--- a/intern/cycles/util/util_opencl.cpp
+++ /dev/null
@@ -1,337 +0,0 @@
-//////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2009 Organic Vectory B.V.
-// Written by George van Venrooij
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file doc/license/Boost.txt)
-// Extracted from the CLCC project - http://clcc.sourceforge.net/
-//////////////////////////////////////////////////////////////////////////
-
-#include <stdlib.h>
-
-#include "util_opencl.h"
-
-#ifndef CLCC_GENERATE_DOCUMENTATION
-#ifdef _WIN32
-# define WIN32_LEAN_AND_MEAN
-# define VC_EXTRALEAN
-# include <windows.h>
-
- typedef HMODULE CLCC_DYNLIB_HANDLE;
-
-# define CLCC_DYNLIB_OPEN LoadLibrary
-# define CLCC_DYNLIB_CLOSE FreeLibrary
-# define CLCC_DYNLIB_IMPORT GetProcAddress
-#else
-# include <dlfcn.h>
-
- typedef void* CLCC_DYNLIB_HANDLE;
-
-# define CLCC_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL)
-# define CLCC_DYNLIB_CLOSE dlclose
-# define CLCC_DYNLIB_IMPORT dlsym
-#endif
-#else
-// typedef implementation_defined CLCC_DYNLIB_HANDLE;
-//# define CLCC_DYNLIB_OPEN(path) implementation_defined
-//# define CLCC_DYNLIB_CLOSE implementation_defined
-//# define CLCC_DYNLIB_IMPORT implementation_defined
-#endif
-
-CCL_NAMESPACE_BEGIN
-
-//! \brief module handle
-static CLCC_DYNLIB_HANDLE module = NULL;
-
-// Variables holding function entry points
-#ifndef CLCC_GENERATE_DOCUMENTATION
-PFNCLGETPLATFORMIDS __clewGetPlatformIDs = NULL;
-PFNCLGETPLATFORMINFO __clewGetPlatformInfo = NULL;
-PFNCLGETDEVICEIDS __clewGetDeviceIDs = NULL;
-PFNCLGETDEVICEINFO __clewGetDeviceInfo = NULL;
-PFNCLCREATECONTEXT __clewCreateContext = NULL;
-PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType = NULL;
-PFNCLRETAINCONTEXT __clewRetainContext = NULL;
-PFNCLRELEASECONTEXT __clewReleaseContext = NULL;
-PFNCLGETCONTEXTINFO __clewGetContextInfo = NULL;
-PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue = NULL;
-PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue = NULL;
-PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue = NULL;
-PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo = NULL;
-PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty = NULL;
-PFNCLCREATEBUFFER __clewCreateBuffer = NULL;
-PFNCLCREATEIMAGE2D __clewCreateImage2D = NULL;
-PFNCLCREATEIMAGE3D __clewCreateImage3D = NULL;
-PFNCLRETAINMEMOBJECT __clewRetainMemObject = NULL;
-PFNCLRELEASEMEMOBJECT __clewReleaseMemObject = NULL;
-PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats = NULL;
-PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo = NULL;
-PFNCLGETIMAGEINFO __clewGetImageInfo = NULL;
-PFNCLCREATESAMPLER __clewCreateSampler = NULL;
-PFNCLRETAINSAMPLER __clewRetainSampler = NULL;
-PFNCLRELEASESAMPLER __clewReleaseSampler = NULL;
-PFNCLGETSAMPLERINFO __clewGetSamplerInfo = NULL;
-PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource = NULL;
-PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary = NULL;
-PFNCLRETAINPROGRAM __clewRetainProgram = NULL;
-PFNCLRELEASEPROGRAM __clewReleaseProgram = NULL;
-PFNCLBUILDPROGRAM __clewBuildProgram = NULL;
-PFNCLUNLOADCOMPILER __clewUnloadCompiler = NULL;
-PFNCLGETPROGRAMINFO __clewGetProgramInfo = NULL;
-PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo = NULL;
-PFNCLCREATEKERNEL __clewCreateKernel = NULL;
-PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram = NULL;
-PFNCLRETAINKERNEL __clewRetainKernel = NULL;
-PFNCLRELEASEKERNEL __clewReleaseKernel = NULL;
-PFNCLSETKERNELARG __clewSetKernelArg = NULL;
-PFNCLGETKERNELINFO __clewGetKernelInfo = NULL;
-PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo = NULL;
-PFNCLWAITFOREVENTS __clewWaitForEvents = NULL;
-PFNCLGETEVENTINFO __clewGetEventInfo = NULL;
-PFNCLRETAINEVENT __clewRetainEvent = NULL;
-PFNCLRELEASEEVENT __clewReleaseEvent = NULL;
-PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo = NULL;
-PFNCLFLUSH __clewFlush = NULL;
-PFNCLFINISH __clewFinish = NULL;
-PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer = NULL;
-PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer = NULL;
-PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer = NULL;
-PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage = NULL;
-PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage = NULL;
-PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage = NULL;
-PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer = NULL;
-PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage = NULL;
-PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer = NULL;
-PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage = NULL;
-PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject = NULL;
-PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel = NULL;
-PFNCLENQUEUETASK __clewEnqueueTask = NULL;
-PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel = NULL;
-PFNCLENQUEUEMARKER __clewEnqueueMarker = NULL;
-PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents = NULL;
-PFNCLENQUEUEBARRIER __clewEnqueueBarrier = NULL;
-PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress = NULL;
-#endif // CLCC_GENERATE_DOCUMENTATION
-
-
-#if 0
-//! \brief Unloads OpenCL dynamic library, should not be called directly
-static void clewExit(void)
-{
- if (module != NULL)
- {
- // Ignore errors
- CLCC_DYNLIB_CLOSE(module);
- module = NULL;
- }
-}
-#endif
-
-//! \param path path to dynamic library to load
-//! \return CLEW_ERROR_OPEN_FAILED if the library could not be opened
-//! CLEW_ERROR_ATEXIT_FAILED if atexit(clewExit) failed
-//! CLEW_SUCCESS when the library was succesfully loaded
-int clLibraryInit()
-{
-#ifdef _WIN32
- const char *path = "OpenCL.dll";
-#elif defined(__APPLE__)
- const char *path = "/Library/Frameworks/OpenCL.framework/OpenCL";
-#else
- const char *path = "libOpenCL.so";
-#endif
-
- // OpenCL disabled for now, only works with this environment variable set
- if(!getenv("CYCLES_OPENCL_TEST"))
- return 0;
-
- // Check if already initialized
- if (module != NULL)
- {
- return 1;
- }
-
- // Load library
- module = CLCC_DYNLIB_OPEN(path);
-
- // Check for errors
- if (module == NULL)
- {
- return 0;
- }
-
- // Disabled because we retain OpenCL context and it's difficult to ensure
- // this will exit after releasing the context
-#if 0
- // Set unloading
- int error = atexit(clewExit);
-
- if (error)
- {
- // Failure queing atexit, shutdown with error
- CLCC_DYNLIB_CLOSE(module);
- module = NULL;
-
- return 0;
- }
-#endif
-
- // Determine function entry-points
- __clewGetPlatformIDs = (PFNCLGETPLATFORMIDS )CLCC_DYNLIB_IMPORT(module, "clGetPlatformIDs");
- __clewGetPlatformInfo = (PFNCLGETPLATFORMINFO )CLCC_DYNLIB_IMPORT(module, "clGetPlatformInfo");
- __clewGetDeviceIDs = (PFNCLGETDEVICEIDS )CLCC_DYNLIB_IMPORT(module, "clGetDeviceIDs");
- __clewGetDeviceInfo = (PFNCLGETDEVICEINFO )CLCC_DYNLIB_IMPORT(module, "clGetDeviceInfo");
- __clewCreateContext = (PFNCLCREATECONTEXT )CLCC_DYNLIB_IMPORT(module, "clCreateContext");
- __clewCreateContextFromType = (PFNCLCREATECONTEXTFROMTYPE )CLCC_DYNLIB_IMPORT(module, "clCreateContextFromType");
- __clewRetainContext = (PFNCLRETAINCONTEXT )CLCC_DYNLIB_IMPORT(module, "clRetainContext");
- __clewReleaseContext = (PFNCLRELEASECONTEXT )CLCC_DYNLIB_IMPORT(module, "clReleaseContext");
- __clewGetContextInfo = (PFNCLGETCONTEXTINFO )CLCC_DYNLIB_IMPORT(module, "clGetContextInfo");
- __clewCreateCommandQueue = (PFNCLCREATECOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clCreateCommandQueue");
- __clewRetainCommandQueue = (PFNCLRETAINCOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clRetainCommandQueue");
- __clewReleaseCommandQueue = (PFNCLRELEASECOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clReleaseCommandQueue");
- __clewGetCommandQueueInfo = (PFNCLGETCOMMANDQUEUEINFO )CLCC_DYNLIB_IMPORT(module, "clGetCommandQueueInfo");
- __clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY )CLCC_DYNLIB_IMPORT(module, "clSetCommandQueueProperty");
- __clewCreateBuffer = (PFNCLCREATEBUFFER )CLCC_DYNLIB_IMPORT(module, "clCreateBuffer");
- __clewCreateImage2D = (PFNCLCREATEIMAGE2D )CLCC_DYNLIB_IMPORT(module, "clCreateImage2D");
- __clewCreateImage3D = (PFNCLCREATEIMAGE3D )CLCC_DYNLIB_IMPORT(module, "clCreateImage3D");
- __clewRetainMemObject = (PFNCLRETAINMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clRetainMemObject");
- __clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clReleaseMemObject");
- __clewGetSupportedImageFormats = (PFNCLGETSUPPORTEDIMAGEFORMATS )CLCC_DYNLIB_IMPORT(module, "clGetSupportedImageFormats");
- __clewGetMemObjectInfo = (PFNCLGETMEMOBJECTINFO )CLCC_DYNLIB_IMPORT(module, "clGetMemObjectInfo");
- __clewGetImageInfo = (PFNCLGETIMAGEINFO )CLCC_DYNLIB_IMPORT(module, "clGetImageInfo");
- __clewCreateSampler = (PFNCLCREATESAMPLER )CLCC_DYNLIB_IMPORT(module, "clCreateSampler");
- __clewRetainSampler = (PFNCLRETAINSAMPLER )CLCC_DYNLIB_IMPORT(module, "clRetainSampler");
- __clewReleaseSampler = (PFNCLRELEASESAMPLER )CLCC_DYNLIB_IMPORT(module, "clReleaseSampler");
- __clewGetSamplerInfo = (PFNCLGETSAMPLERINFO )CLCC_DYNLIB_IMPORT(module, "clGetSamplerInfo");
- __clewCreateProgramWithSource = (PFNCLCREATEPROGRAMWITHSOURCE )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithSource");
- __clewCreateProgramWithBinary = (PFNCLCREATEPROGRAMWITHBINARY )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithBinary");
- __clewRetainProgram = (PFNCLRETAINPROGRAM )CLCC_DYNLIB_IMPORT(module, "clRetainProgram");
- __clewReleaseProgram = (PFNCLRELEASEPROGRAM )CLCC_DYNLIB_IMPORT(module, "clReleaseProgram");
- __clewBuildProgram = (PFNCLBUILDPROGRAM )CLCC_DYNLIB_IMPORT(module, "clBuildProgram");
- __clewUnloadCompiler = (PFNCLUNLOADCOMPILER )CLCC_DYNLIB_IMPORT(module, "clUnloadCompiler");
- __clewGetProgramInfo = (PFNCLGETPROGRAMINFO )CLCC_DYNLIB_IMPORT(module, "clGetProgramInfo");
- __clewGetProgramBuildInfo = (PFNCLGETPROGRAMBUILDINFO )CLCC_DYNLIB_IMPORT(module, "clGetProgramBuildInfo");
- __clewCreateKernel = (PFNCLCREATEKERNEL )CLCC_DYNLIB_IMPORT(module, "clCreateKernel");
- __clewCreateKernelsInProgram = (PFNCLCREATEKERNELSINPROGRAM )CLCC_DYNLIB_IMPORT(module, "clCreateKernelsInProgram");
- __clewRetainKernel = (PFNCLRETAINKERNEL )CLCC_DYNLIB_IMPORT(module, "clRetainKernel");
- __clewReleaseKernel = (PFNCLRELEASEKERNEL )CLCC_DYNLIB_IMPORT(module, "clReleaseKernel");
- __clewSetKernelArg = (PFNCLSETKERNELARG )CLCC_DYNLIB_IMPORT(module, "clSetKernelArg");
- __clewGetKernelInfo = (PFNCLGETKERNELINFO )CLCC_DYNLIB_IMPORT(module, "clGetKernelInfo");
- __clewGetKernelWorkGroupInfo = (PFNCLGETKERNELWORKGROUPINFO )CLCC_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo");
- __clewWaitForEvents = (PFNCLWAITFOREVENTS )CLCC_DYNLIB_IMPORT(module, "clWaitForEvents");
- __clewGetEventInfo = (PFNCLGETEVENTINFO )CLCC_DYNLIB_IMPORT(module, "clGetEventInfo");
- __clewRetainEvent = (PFNCLRETAINEVENT )CLCC_DYNLIB_IMPORT(module, "clRetainEvent");
- __clewReleaseEvent = (PFNCLRELEASEEVENT )CLCC_DYNLIB_IMPORT(module, "clReleaseEvent");
- __clewGetEventProfilingInfo = (PFNCLGETEVENTPROFILINGINFO )CLCC_DYNLIB_IMPORT(module, "clGetEventProfilingInfo");
- __clewFlush = (PFNCLFLUSH )CLCC_DYNLIB_IMPORT(module, "clFlush");
- __clewFinish = (PFNCLFINISH )CLCC_DYNLIB_IMPORT(module, "clFinish");
- __clewEnqueueReadBuffer = (PFNCLENQUEUEREADBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadBuffer");
- __clewEnqueueWriteBuffer = (PFNCLENQUEUEWRITEBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer");
- __clewEnqueueCopyBuffer = (PFNCLENQUEUECOPYBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer");
- __clewEnqueueReadImage = (PFNCLENQUEUEREADIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadImage");
- __clewEnqueueWriteImage = (PFNCLENQUEUEWRITEIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteImage");
- __clewEnqueueCopyImage = (PFNCLENQUEUECOPYIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImage");
- __clewEnqueueCopyImageToBuffer = (PFNCLENQUEUECOPYIMAGETOBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer");
- __clewEnqueueCopyBufferToImage = (PFNCLENQUEUECOPYBUFFERTOIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage");
- __clewEnqueueMapBuffer = (PFNCLENQUEUEMAPBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapBuffer");
- __clewEnqueueMapImage = (PFNCLENQUEUEMAPIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapImage");
- __clewEnqueueUnmapMemObject = (PFNCLENQUEUEUNMAPMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject");
- __clewEnqueueNDRangeKernel = (PFNCLENQUEUENDRANGEKERNEL )CLCC_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel");
- __clewEnqueueTask = (PFNCLENQUEUETASK )CLCC_DYNLIB_IMPORT(module, "clEnqueueTask");
- __clewEnqueueNativeKernel = (PFNCLENQUEUENATIVEKERNEL )CLCC_DYNLIB_IMPORT(module, "clEnqueueNativeKernel");
- __clewEnqueueMarker = (PFNCLENQUEUEMARKER )CLCC_DYNLIB_IMPORT(module, "clEnqueueMarker");
- __clewEnqueueWaitForEvents = (PFNCLENQUEUEWAITFOREVENTS )CLCC_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents");
- __clewEnqueueBarrier = (PFNCLENQUEUEBARRIER )CLCC_DYNLIB_IMPORT(module, "clEnqueueBarrier");
- __clewGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS )CLCC_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress");
-
- if(__clewGetPlatformIDs == NULL) return 0;
- if(__clewGetPlatformInfo == NULL) return 0;
- if(__clewGetDeviceIDs == NULL) return 0;
- if(__clewGetDeviceInfo == NULL) return 0;
-
- return 1;
-}
-
-//! \param error CL error code
-//! \return a string representation of the error code
-const char *clErrorString(cl_int error)
-{
- static const char* strings[] =
- {
- // Error Codes
- "CL_SUCCESS" // 0
- , "CL_DEVICE_NOT_FOUND" // -1
- , "CL_DEVICE_NOT_AVAILABLE" // -2
- , "CL_COMPILER_NOT_AVAILABLE" // -3
- , "CL_MEM_OBJECT_ALLOCATION_FAILURE" // -4
- , "CL_OUT_OF_RESOURCES" // -5
- , "CL_OUT_OF_HOST_MEMORY" // -6
- , "CL_PROFILING_INFO_NOT_AVAILABLE" // -7
- , "CL_MEM_COPY_OVERLAP" // -8
- , "CL_IMAGE_FORMAT_MISMATCH" // -9
- , "CL_IMAGE_FORMAT_NOT_SUPPORTED" // -10
- , "CL_BUILD_PROGRAM_FAILURE" // -11
- , "CL_MAP_FAILURE" // -12
-
- , "" // -13
- , "" // -14
- , "" // -15
- , "" // -16
- , "" // -17
- , "" // -18
- , "" // -19
-
- , "" // -20
- , "" // -21
- , "" // -22
- , "" // -23
- , "" // -24
- , "" // -25
- , "" // -26
- , "" // -27
- , "" // -28
- , "" // -29
-
- , "CL_INVALID_VALUE" // -30
- , "CL_INVALID_DEVICE_TYPE" // -31
- , "CL_INVALID_PLATFORM" // -32
- , "CL_INVALID_DEVICE" // -33
- , "CL_INVALID_CONTEXT" // -34
- , "CL_INVALID_QUEUE_PROPERTIES" // -35
- , "CL_INVALID_COMMAND_QUEUE" // -36
- , "CL_INVALID_HOST_PTR" // -37
- , "CL_INVALID_MEM_OBJECT" // -38
- , "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" // -39
- , "CL_INVALID_IMAGE_SIZE" // -40
- , "CL_INVALID_SAMPLER" // -41
- , "CL_INVALID_BINARY" // -42
- , "CL_INVALID_BUILD_OPTIONS" // -43
- , "CL_INVALID_PROGRAM" // -44
- , "CL_INVALID_PROGRAM_EXECUTABLE" // -45
- , "CL_INVALID_KERNEL_NAME" // -46
- , "CL_INVALID_KERNEL_DEFINITION" // -47
- , "CL_INVALID_KERNEL" // -48
- , "CL_INVALID_ARG_INDEX" // -49
- , "CL_INVALID_ARG_VALUE" // -50
- , "CL_INVALID_ARG_SIZE" // -51
- , "CL_INVALID_KERNEL_ARGS" // -52
- , "CL_INVALID_WORK_DIMENSION" // -53
- , "CL_INVALID_WORK_GROUP_SIZE" // -54
- , "CL_INVALID_WORK_ITEM_SIZE" // -55
- , "CL_INVALID_GLOBAL_OFFSET" // -56
- , "CL_INVALID_EVENT_WAIT_LIST" // -57
- , "CL_INVALID_EVENT" // -58
- , "CL_INVALID_OPERATION" // -59
- , "CL_INVALID_GL_OBJECT" // -60
- , "CL_INVALID_BUFFER_SIZE" // -61
- , "CL_INVALID_MIP_LEVEL" // -62
- , "CL_INVALID_GLOBAL_WORK_SIZE" // -63
- };
-
- return strings[-error];
-}
-
-CCL_NAMESPACE_END
-
-#ifdef CLCC_DYNLIB_CLOSE
-#endif
diff --git a/intern/cycles/util/util_opencl.h b/intern/cycles/util/util_opencl.h
deleted file mode 100644
index 141c5e38273..00000000000
--- a/intern/cycles/util/util_opencl.h
+++ /dev/null
@@ -1,1313 +0,0 @@
-//////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2009 Organic Vectory B.V.
-// Written by George van Venrooij
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file doc/license/Boost.txt)
-// Extracted from the CLCC project - http://clcc.sourceforge.net/
-//////////////////////////////////////////////////////////////////////////
-
-#ifndef __UTIL_OPENCL_H__
-#define __UTIL_OPENCL_H__
-
-CCL_NAMESPACE_BEGIN
-
-//! This file contains a copy of the contents of CL.H and CL_PLATFORM.H from the
-//! official OpenCL spec. The purpose of this code is to load the OpenCL dynamic
-//! library at run-time and thus allow the executable to function on many
-//! platforms regardless of the vendor of the OpenCL driver actually installed.
-//! Some of the techniques used here were inspired by work done in the GLEW
-//! library (http://glew.sourceforge.net/)
-
-// Run-time dynamic linking functionality based on concepts used in GLEW
-#ifdef __OPENCL_CL_H
-#error cl.h included before clew.h
-#endif
-
-#ifdef __OPENCL_CL_PLATFORM_H
-#error cl_platform.h included before clew.h
-#endif
-
-#ifndef CLCC_GENERATE_DOCUMENTATION
-// Prevent cl.h inclusion
-#define __OPENCL_CL_H
-// Prevent cl_platform.h inclusion
-#define __CL_PLATFORM_H
-#endif // CLCC_GENERATE_DOCUMENTATION
-
-/*******************************************************************************
- * Copyright (c) 2008-2009 The Khronos Group Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and/or associated documentation files (the
- * "Materials"), to deal in the Materials without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Materials, and to
- * permit persons to whom the Materials are furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Materials.
- *
- * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
- ******************************************************************************/
-
-#ifndef CLCC_GENERATE_DOCUMENTATION
-
-#if defined(_WIN32)
-#define CL_API_ENTRY
-#define CL_API_CALL __stdcall
-#else
-#define CL_API_ENTRY
-#define CL_API_CALL
-#endif
-
-#define CL_API_SUFFIX__VERSION_1_0
-
-#if defined(_WIN32) && defined(_MSC_VER)
-
-/* scalar types */
-typedef signed __int8 cl_char;
-typedef unsigned __int8 cl_uchar;
-typedef signed __int16 cl_short;
-typedef unsigned __int16 cl_ushort;
-typedef signed __int32 cl_int;
-typedef unsigned __int32 cl_uint;
-typedef signed __int64 cl_long;
-typedef unsigned __int64 cl_ulong;
-
-typedef unsigned __int16 cl_half;
-typedef float cl_float;
-typedef double cl_double;
-
-
-/*
- * Vector types
- *
- * Note: OpenCL requires that all types be naturally aligned.
- * This means that vector types must be naturally aligned.
- * For example, a vector of four floats must be aligned to
- * a 16 byte boundary (calculated as 4 * the natural 4-byte
- * alignment of the float). The alignment qualifiers here
- * will only function properly if your compiler supports them
- * and if you don't actively work to defeat them. For example,
- * in order for a cl_float4 to be 16 byte aligned in a struct,
- * the start of the struct must itself be 16-byte aligned.
- *
- * Maintaining proper alignment is the user's responsibility.
- */
-typedef signed __int8 cl_char2[2];
-typedef signed __int8 cl_char4[4];
-typedef signed __int8 cl_char8[8];
-typedef signed __int8 cl_char16[16];
-typedef unsigned __int8 cl_uchar2[2];
-typedef unsigned __int8 cl_uchar4[4];
-typedef unsigned __int8 cl_uchar8[8];
-typedef unsigned __int8 cl_uchar16[16];
-
-typedef signed __int16 cl_short2[2];
-typedef signed __int16 cl_short4[4];
-typedef signed __int16 cl_short8[8];
-typedef signed __int16 cl_short16[16];
-typedef unsigned __int16 cl_ushort2[2];
-typedef unsigned __int16 cl_ushort4[4];
-typedef unsigned __int16 cl_ushort8[8];
-typedef unsigned __int16 cl_ushort16[16];
-
-typedef signed __int32 cl_int2[2];
-typedef signed __int32 cl_int4[4];
-typedef signed __int32 cl_int8[8];
-typedef signed __int32 cl_int16[16];
-typedef unsigned __int32 cl_uint2[2];
-typedef unsigned __int32 cl_uint4[4];
-typedef unsigned __int32 cl_uint8[8];
-typedef unsigned __int32 cl_uint16[16];
-
-typedef signed __int64 cl_long2[2];
-typedef signed __int64 cl_long4[4];
-typedef signed __int64 cl_long8[8];
-typedef signed __int64 cl_long16[16];
-typedef unsigned __int64 cl_ulong2[2];
-typedef unsigned __int64 cl_ulong4[4];
-typedef unsigned __int64 cl_ulong8[8];
-typedef unsigned __int64 cl_ulong16[16];
-
-typedef float cl_float2[2];
-typedef float cl_float4[4];
-typedef float cl_float8[8];
-typedef float cl_float16[16];
-
-typedef double cl_double2[2];
-typedef double cl_double4[4];
-typedef double cl_double8[8];
-typedef double cl_double16[16];
-/* There are no vector types for half */
-
-#else
-
-#include <stdint.h>
-
-/* scalar types */
-typedef int8_t cl_char;
-typedef uint8_t cl_uchar;
-typedef int16_t cl_short __attribute__((aligned(2)));
-typedef uint16_t cl_ushort __attribute__((aligned(2)));
-typedef int32_t cl_int __attribute__((aligned(4)));
-typedef uint32_t cl_uint __attribute__((aligned(4)));
-typedef int64_t cl_long __attribute__((aligned(8)));
-typedef uint64_t cl_ulong __attribute__((aligned(8)));
-
-typedef uint16_t cl_half __attribute__((aligned(2)));
-typedef float cl_float __attribute__((aligned(4)));
-typedef double cl_double __attribute__((aligned(8)));
-
-/*
- * Vector types
- *
- * Note: OpenCL requires that all types be naturally aligned.
- * This means that vector types must be naturally aligned.
- * For example, a vector of four floats must be aligned to
- * a 16 byte boundary (calculated as 4 * the natural 4-byte
- * alignment of the float). The alignment qualifiers here
- * will only function properly if your compiler supports them
- * and if you don't actively work to defeat them. For example,
- * in order for a cl_float4 to be 16 byte aligned in a struct,
- * the start of the struct must itself be 16-byte aligned.
- *
- * Maintaining proper alignment is the user's responsibility.
- */
-typedef int8_t cl_char2[2] __attribute__((aligned(2)));
-typedef int8_t cl_char4[4] __attribute__((aligned(4)));
-typedef int8_t cl_char8[8] __attribute__((aligned(8)));
-typedef int8_t cl_char16[16] __attribute__((aligned(16)));
-typedef uint8_t cl_uchar2[2] __attribute__((aligned(2)));
-typedef uint8_t cl_uchar4[4] __attribute__((aligned(4)));
-typedef uint8_t cl_uchar8[8] __attribute__((aligned(8)));
-typedef uint8_t cl_uchar16[16] __attribute__((aligned(16)));
-
-typedef int16_t cl_short2[2] __attribute__((aligned(4)));
-typedef int16_t cl_short4[4] __attribute__((aligned(8)));
-typedef int16_t cl_short8[8] __attribute__((aligned(16)));
-typedef int16_t cl_short16[16] __attribute__((aligned(32)));
-typedef uint16_t cl_ushort2[2] __attribute__((aligned(4)));
-typedef uint16_t cl_ushort4[4] __attribute__((aligned(8)));
-typedef uint16_t cl_ushort8[8] __attribute__((aligned(16)));
-typedef uint16_t cl_ushort16[16] __attribute__((aligned(32)));
-
-typedef int32_t cl_int2[2] __attribute__((aligned(8)));
-typedef int32_t cl_int4[4] __attribute__((aligned(16)));
-typedef int32_t cl_int8[8] __attribute__((aligned(32)));
-typedef int32_t cl_int16[16] __attribute__((aligned(64)));
-typedef uint32_t cl_uint2[2] __attribute__((aligned(8)));
-typedef uint32_t cl_uint4[4] __attribute__((aligned(16)));
-typedef uint32_t cl_uint8[8] __attribute__((aligned(32)));
-typedef uint32_t cl_uint16[16] __attribute__((aligned(64)));
-
-typedef int64_t cl_long2[2] __attribute__((aligned(16)));
-typedef int64_t cl_long4[4] __attribute__((aligned(32)));
-typedef int64_t cl_long8[8] __attribute__((aligned(64)));
-typedef int64_t cl_long16[16] __attribute__((aligned(128)));
-typedef uint64_t cl_ulong2[2] __attribute__((aligned(16)));
-typedef uint64_t cl_ulong4[4] __attribute__((aligned(32)));
-typedef uint64_t cl_ulong8[8] __attribute__((aligned(64)));
-typedef uint64_t cl_ulong16[16] __attribute__((aligned(128)));
-
-typedef float cl_float2[2] __attribute__((aligned(8)));
-typedef float cl_float4[4] __attribute__((aligned(16)));
-typedef float cl_float8[8] __attribute__((aligned(32)));
-typedef float cl_float16[16] __attribute__((aligned(64)));
-
-typedef double cl_double2[2] __attribute__((aligned(16)));
-typedef double cl_double4[4] __attribute__((aligned(32)));
-typedef double cl_double8[8] __attribute__((aligned(64)));
-typedef double cl_double16[16] __attribute__((aligned(128)));
-
-/* There are no vector types for half */
-
-#endif
-
-/******************************************************************************/
-
-// Macro names and corresponding values defined by OpenCL
-
-#define CL_CHAR_BIT 8
-#define CL_SCHAR_MAX 127
-#define CL_SCHAR_MIN (-127-1)
-#define CL_CHAR_MAX CL_SCHAR_MAX
-#define CL_CHAR_MIN CL_SCHAR_MIN
-#define CL_UCHAR_MAX 255
-#define CL_SHRT_MAX 32767
-#define CL_SHRT_MIN (-32767-1)
-#define CL_USHRT_MAX 65535
-#define CL_INT_MAX 2147483647
-#define CL_INT_MIN (-2147483647-1)
-#define CL_UINT_MAX 0xffffffffU
-#define CL_LONG_MAX ((cl_long) 0x7FFFFFFFFFFFFFFFLL)
-#define CL_LONG_MIN ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL)
-#define CL_ULONG_MAX ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL)
-
-#define CL_FLT_DIG 6
-#define CL_FLT_MANT_DIG 24
-#define CL_FLT_MAX_10_EXP +38
-#define CL_FLT_MAX_EXP +128
-#define CL_FLT_MIN_10_EXP -37
-#define CL_FLT_MIN_EXP -125
-#define CL_FLT_RADIX 2
-#if defined(_MSC_VER)
-// MSVC doesn't understand hex floats
-#define CL_FLT_MAX 3.402823466e+38F
-#define CL_FLT_MIN 1.175494351e-38F
-#define CL_FLT_EPSILON 1.192092896e-07F
-#else
-#define CL_FLT_MAX 0x1.fffffep127f
-#define CL_FLT_MIN 0x1.0p-126f
-#define CL_FLT_EPSILON 0x1.0p-23f
-#endif
-
-#define CL_DBL_DIG 15
-#define CL_DBL_MANT_DIG 53
-#define CL_DBL_MAX_10_EXP +308
-#define CL_DBL_MAX_EXP +1024
-#define CL_DBL_MIN_10_EXP -307
-#define CL_DBL_MIN_EXP -1021
-#define CL_DBL_RADIX 2
-#if defined(_MSC_VER)
-// MSVC doesn't understand hex floats
-#define CL_DBL_MAX 1.7976931348623158e+308
-#define CL_DBL_MIN 2.2250738585072014e-308
-#define CL_DBL_EPSILON 2.2204460492503131e-016
-#else
-#define CL_DBL_MAX 0x1.fffffffffffffp1023
-#define CL_DBL_MIN 0x1.0p-1022
-#define CL_DBL_EPSILON 0x1.0p-52
-#endif
-
-#include <stddef.h>
-
-
-// CL.h contents
-/******************************************************************************/
-
-typedef struct _cl_platform_id * cl_platform_id;
-typedef struct _cl_device_id * cl_device_id;
-typedef struct _cl_context * cl_context;
-typedef struct _cl_command_queue * cl_command_queue;
-typedef struct _cl_mem * cl_mem;
-typedef struct _cl_program * cl_program;
-typedef struct _cl_kernel * cl_kernel;
-typedef struct _cl_event * cl_event;
-typedef struct _cl_sampler * cl_sampler;
-
-/* WARNING! Unlike cl_ types in cl_platform.h,
- * cl_bool is not guaranteed to be the same size as the bool in kernels. */
-typedef cl_uint cl_bool;
-typedef cl_ulong cl_bitfield;
-typedef cl_bitfield cl_device_type;
-typedef cl_uint cl_platform_info;
-typedef cl_uint cl_device_info;
-typedef cl_bitfield cl_device_address_info;
-typedef cl_bitfield cl_device_fp_config;
-typedef cl_uint cl_device_mem_cache_type;
-typedef cl_uint cl_device_local_mem_type;
-typedef cl_bitfield cl_device_exec_capabilities;
-typedef cl_bitfield cl_command_queue_properties;
-
-typedef intptr_t cl_context_properties;
-typedef cl_uint cl_context_info;
-typedef cl_uint cl_command_queue_info;
-typedef cl_uint cl_channel_order;
-typedef cl_uint cl_channel_type;
-typedef cl_bitfield cl_mem_flags;
-typedef cl_uint cl_mem_object_type;
-typedef cl_uint cl_mem_info;
-typedef cl_uint cl_image_info;
-typedef cl_uint cl_addressing_mode;
-typedef cl_uint cl_filter_mode;
-typedef cl_uint cl_sampler_info;
-typedef cl_bitfield cl_map_flags;
-typedef cl_uint cl_program_info;
-typedef cl_uint cl_program_build_info;
-typedef cl_int cl_build_status;
-typedef cl_uint cl_kernel_info;
-typedef cl_uint cl_kernel_work_group_info;
-typedef cl_uint cl_event_info;
-typedef cl_uint cl_command_type;
-typedef cl_uint cl_profiling_info;
-
-typedef struct _cl_image_format {
- cl_channel_order image_channel_order;
- cl_channel_type image_channel_data_type;
-} cl_image_format;
-
-
-
-/******************************************************************************/
-
-// Error Codes
-#define CL_SUCCESS 0
-#define CL_DEVICE_NOT_FOUND -1
-#define CL_DEVICE_NOT_AVAILABLE -2
-#define CL_COMPILER_NOT_AVAILABLE -3
-#define CL_MEM_OBJECT_ALLOCATION_FAILURE -4
-#define CL_OUT_OF_RESOURCES -5
-#define CL_OUT_OF_HOST_MEMORY -6
-#define CL_PROFILING_INFO_NOT_AVAILABLE -7
-#define CL_MEM_COPY_OVERLAP -8
-#define CL_IMAGE_FORMAT_MISMATCH -9
-#define CL_IMAGE_FORMAT_NOT_SUPPORTED -10
-#define CL_BUILD_PROGRAM_FAILURE -11
-#define CL_MAP_FAILURE -12
-
-#define CL_INVALID_VALUE -30
-#define CL_INVALID_DEVICE_TYPE -31
-#define CL_INVALID_PLATFORM -32
-#define CL_INVALID_DEVICE -33
-#define CL_INVALID_CONTEXT -34
-#define CL_INVALID_QUEUE_PROPERTIES -35
-#define CL_INVALID_COMMAND_QUEUE -36
-#define CL_INVALID_HOST_PTR -37
-#define CL_INVALID_MEM_OBJECT -38
-#define CL_INVALID_IMAGE_FORMAT_DESCRIPTOR -39
-#define CL_INVALID_IMAGE_SIZE -40
-#define CL_INVALID_SAMPLER -41
-#define CL_INVALID_BINARY -42
-#define CL_INVALID_BUILD_OPTIONS -43
-#define CL_INVALID_PROGRAM -44
-#define CL_INVALID_PROGRAM_EXECUTABLE -45
-#define CL_INVALID_KERNEL_NAME -46
-#define CL_INVALID_KERNEL_DEFINITION -47
-#define CL_INVALID_KERNEL -48
-#define CL_INVALID_ARG_INDEX -49
-#define CL_INVALID_ARG_VALUE -50
-#define CL_INVALID_ARG_SIZE -51
-#define CL_INVALID_KERNEL_ARGS -52
-#define CL_INVALID_WORK_DIMENSION -53
-#define CL_INVALID_WORK_GROUP_SIZE -54
-#define CL_INVALID_WORK_ITEM_SIZE -55
-#define CL_INVALID_GLOBAL_OFFSET -56
-#define CL_INVALID_EVENT_WAIT_LIST -57
-#define CL_INVALID_EVENT -58
-#define CL_INVALID_OPERATION -59
-#define CL_INVALID_GL_OBJECT -60
-#define CL_INVALID_BUFFER_SIZE -61
-#define CL_INVALID_MIP_LEVEL -62
-#define CL_INVALID_GLOBAL_WORK_SIZE -63
-
-// OpenCL Version
-#define CL_VERSION_1_0 1
-
-// cl_bool
-#define CL_FALSE 0
-#define CL_TRUE 1
-
-// cl_platform_info
-#define CL_PLATFORM_PROFILE 0x0900
-#define CL_PLATFORM_VERSION 0x0901
-#define CL_PLATFORM_NAME 0x0902
-#define CL_PLATFORM_VENDOR 0x0903
-#define CL_PLATFORM_EXTENSIONS 0x0904
-
-// cl_device_type - bitfield
-#define CL_DEVICE_TYPE_DEFAULT (1 << 0)
-#define CL_DEVICE_TYPE_CPU (1 << 1)
-#define CL_DEVICE_TYPE_GPU (1 << 2)
-#define CL_DEVICE_TYPE_ACCELERATOR (1 << 3)
-#define CL_DEVICE_TYPE_ALL 0xFFFFFFFF
-
-// cl_device_info
-#define CL_DEVICE_TYPE 0x1000
-#define CL_DEVICE_VENDOR_ID 0x1001
-#define CL_DEVICE_MAX_COMPUTE_UNITS 0x1002
-#define CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS 0x1003
-#define CL_DEVICE_MAX_WORK_GROUP_SIZE 0x1004
-#define CL_DEVICE_MAX_WORK_ITEM_SIZES 0x1005
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR 0x1006
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT 0x1007
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT 0x1008
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG 0x1009
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT 0x100A
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE 0x100B
-#define CL_DEVICE_MAX_CLOCK_FREQUENCY 0x100C
-#define CL_DEVICE_ADDRESS_BITS 0x100D
-#define CL_DEVICE_MAX_READ_IMAGE_ARGS 0x100E
-#define CL_DEVICE_MAX_WRITE_IMAGE_ARGS 0x100F
-#define CL_DEVICE_MAX_MEM_ALLOC_SIZE 0x1010
-#define CL_DEVICE_IMAGE2D_MAX_WIDTH 0x1011
-#define CL_DEVICE_IMAGE2D_MAX_HEIGHT 0x1012
-#define CL_DEVICE_IMAGE3D_MAX_WIDTH 0x1013
-#define CL_DEVICE_IMAGE3D_MAX_HEIGHT 0x1014
-#define CL_DEVICE_IMAGE3D_MAX_DEPTH 0x1015
-#define CL_DEVICE_IMAGE_SUPPORT 0x1016
-#define CL_DEVICE_MAX_PARAMETER_SIZE 0x1017
-#define CL_DEVICE_MAX_SAMPLERS 0x1018
-#define CL_DEVICE_MEM_BASE_ADDR_ALIGN 0x1019
-#define CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE 0x101A
-#define CL_DEVICE_SINGLE_FP_CONFIG 0x101B
-#define CL_DEVICE_GLOBAL_MEM_CACHE_TYPE 0x101C
-#define CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE 0x101D
-#define CL_DEVICE_GLOBAL_MEM_CACHE_SIZE 0x101E
-#define CL_DEVICE_GLOBAL_MEM_SIZE 0x101F
-#define CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE 0x1020
-#define CL_DEVICE_MAX_CONSTANT_ARGS 0x1021
-#define CL_DEVICE_LOCAL_MEM_TYPE 0x1022
-#define CL_DEVICE_LOCAL_MEM_SIZE 0x1023
-#define CL_DEVICE_ERROR_CORRECTION_SUPPORT 0x1024
-#define CL_DEVICE_PROFILING_TIMER_RESOLUTION 0x1025
-#define CL_DEVICE_ENDIAN_LITTLE 0x1026
-#define CL_DEVICE_AVAILABLE 0x1027
-#define CL_DEVICE_COMPILER_AVAILABLE 0x1028
-#define CL_DEVICE_EXECUTION_CAPABILITIES 0x1029
-#define CL_DEVICE_QUEUE_PROPERTIES 0x102A
-#define CL_DEVICE_NAME 0x102B
-#define CL_DEVICE_VENDOR 0x102C
-#define CL_DRIVER_VERSION 0x102D
-#define CL_DEVICE_PROFILE 0x102E
-#define CL_DEVICE_VERSION 0x102F
-#define CL_DEVICE_EXTENSIONS 0x1030
-#define CL_DEVICE_PLATFORM 0x1031
-/* 0x1032 reserved for CL_DEVICE_DOUBLE_FP_CONFIG */
-/* 0x1033 reserved for CL_DEVICE_HALF_FP_CONFIG */
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF 0x1034
-#define CL_DEVICE_HOST_UNIFIED_MEMORY 0x1035
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR 0x1036
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT 0x1037
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_INT 0x1038
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG 0x1039
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT 0x103A
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE 0x103B
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF 0x103C
-#define CL_DEVICE_OPENCL_C_VERSION 0x103D
-
-// cl_device_fp_config - bitfield
-#define CL_FP_DENORM (1 << 0)
-#define CL_FP_INF_NAN (1 << 1)
-#define CL_FP_ROUND_TO_NEAREST (1 << 2)
-#define CL_FP_ROUND_TO_ZERO (1 << 3)
-#define CL_FP_ROUND_TO_INF (1 << 4)
-#define CL_FP_FMA (1 << 5)
-
-// cl_device_mem_cache_type
-#define CL_NONE 0x0
-#define CL_READ_ONLY_CACHE 0x1
-#define CL_READ_WRITE_CACHE 0x2
-
-// cl_device_local_mem_type
-#define CL_LOCAL 0x1
-#define CL_GLOBAL 0x2
-
-// cl_device_exec_capabilities - bitfield
-#define CL_EXEC_KERNEL (1 << 0)
-#define CL_EXEC_NATIVE_KERNEL (1 << 1)
-
-// cl_command_queue_properties - bitfield
-#define CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE (1 << 0)
-#define CL_QUEUE_PROFILING_ENABLE (1 << 1)
-
-// cl_context_info
-#define CL_CONTEXT_REFERENCE_COUNT 0x1080
-#define CL_CONTEXT_DEVICES 0x1081
-#define CL_CONTEXT_PROPERTIES 0x1082
-
-// cl_context_properties
-#define CL_CONTEXT_PLATFORM 0x1084
-
-// cl_command_queue_info
-#define CL_QUEUE_CONTEXT 0x1090
-#define CL_QUEUE_DEVICE 0x1091
-#define CL_QUEUE_REFERENCE_COUNT 0x1092
-#define CL_QUEUE_PROPERTIES 0x1093
-
-// cl_mem_flags - bitfield
-#define CL_MEM_READ_WRITE (1 << 0)
-#define CL_MEM_WRITE_ONLY (1 << 1)
-#define CL_MEM_READ_ONLY (1 << 2)
-#define CL_MEM_USE_HOST_PTR (1 << 3)
-#define CL_MEM_ALLOC_HOST_PTR (1 << 4)
-#define CL_MEM_COPY_HOST_PTR (1 << 5)
-
-// cl_channel_order
-#define CL_R 0x10B0
-#define CL_A 0x10B1
-#define CL_RG 0x10B2
-#define CL_RA 0x10B3
-#define CL_RGB 0x10B4
-#define CL_RGBA 0x10B5
-#define CL_BGRA 0x10B6
-#define CL_ARGB 0x10B7
-#define CL_INTENSITY 0x10B8
-#define CL_LUMINANCE 0x10B9
-
-// cl_channel_type
-#define CL_SNORM_INT8 0x10D0
-#define CL_SNORM_INT16 0x10D1
-#define CL_UNORM_INT8 0x10D2
-#define CL_UNORM_INT16 0x10D3
-#define CL_UNORM_SHORT_565 0x10D4
-#define CL_UNORM_SHORT_555 0x10D5
-#define CL_UNORM_INT_101010 0x10D6
-#define CL_SIGNED_INT8 0x10D7
-#define CL_SIGNED_INT16 0x10D8
-#define CL_SIGNED_INT32 0x10D9
-#define CL_UNSIGNED_INT8 0x10DA
-#define CL_UNSIGNED_INT16 0x10DB
-#define CL_UNSIGNED_INT32 0x10DC
-#define CL_HALF_FLOAT 0x10DD
-#define CL_FLOAT 0x10DE
-
-// cl_mem_object_type
-#define CL_MEM_OBJECT_BUFFER 0x10F0
-#define CL_MEM_OBJECT_IMAGE2D 0x10F1
-#define CL_MEM_OBJECT_IMAGE3D 0x10F2
-
-// cl_mem_info
-#define CL_MEM_TYPE 0x1100
-#define CL_MEM_FLAGS 0x1101
-#define CL_MEM_SIZE 0x1102
-#define CL_MEM_HOST_PTR 0x1103
-#define CL_MEM_MAP_COUNT 0x1104
-#define CL_MEM_REFERENCE_COUNT 0x1105
-#define CL_MEM_CONTEXT 0x1106
-
-// cl_image_info
-#define CL_IMAGE_FORMAT 0x1110
-#define CL_IMAGE_ELEMENT_SIZE 0x1111
-#define CL_IMAGE_ROW_PITCH 0x1112
-#define CL_IMAGE_SLICE_PITCH 0x1113
-#define CL_IMAGE_WIDTH 0x1114
-#define CL_IMAGE_HEIGHT 0x1115
-#define CL_IMAGE_DEPTH 0x1116
-
-// cl_addressing_mode
-#define CL_ADDRESS_NONE 0x1130
-#define CL_ADDRESS_CLAMP_TO_EDGE 0x1131
-#define CL_ADDRESS_CLAMP 0x1132
-#define CL_ADDRESS_REPEAT 0x1133
-
-// cl_filter_mode
-#define CL_FILTER_NEAREST 0x1140
-#define CL_FILTER_LINEAR 0x1141
-
-// cl_sampler_info
-#define CL_SAMPLER_REFERENCE_COUNT 0x1150
-#define CL_SAMPLER_CONTEXT 0x1151
-#define CL_SAMPLER_NORMALIZED_COORDS 0x1152
-#define CL_SAMPLER_ADDRESSING_MODE 0x1153
-#define CL_SAMPLER_FILTER_MODE 0x1154
-
-// cl_map_flags - bitfield
-#define CL_MAP_READ (1 << 0)
-#define CL_MAP_WRITE (1 << 1)
-
-// cl_program_info
-#define CL_PROGRAM_REFERENCE_COUNT 0x1160
-#define CL_PROGRAM_CONTEXT 0x1161
-#define CL_PROGRAM_NUM_DEVICES 0x1162
-#define CL_PROGRAM_DEVICES 0x1163
-#define CL_PROGRAM_SOURCE 0x1164
-#define CL_PROGRAM_BINARY_SIZES 0x1165
-#define CL_PROGRAM_BINARIES 0x1166
-
-// cl_program_build_info
-#define CL_PROGRAM_BUILD_STATUS 0x1181
-#define CL_PROGRAM_BUILD_OPTIONS 0x1182
-#define CL_PROGRAM_BUILD_LOG 0x1183
-
-// cl_build_status
-#define CL_BUILD_SUCCESS 0
-#define CL_BUILD_NONE -1
-#define CL_BUILD_ERROR -2
-#define CL_BUILD_IN_PROGRESS -3
-
-// cl_kernel_info
-#define CL_KERNEL_FUNCTION_NAME 0x1190
-#define CL_KERNEL_NUM_ARGS 0x1191
-#define CL_KERNEL_REFERENCE_COUNT 0x1192
-#define CL_KERNEL_CONTEXT 0x1193
-#define CL_KERNEL_PROGRAM 0x1194
-
-// cl_kernel_work_group_info
-#define CL_KERNEL_WORK_GROUP_SIZE 0x11B0
-#define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1
-#define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2
-
-// cl_event_info
-#define CL_EVENT_COMMAND_QUEUE 0x11D0
-#define CL_EVENT_COMMAND_TYPE 0x11D1
-#define CL_EVENT_REFERENCE_COUNT 0x11D2
-#define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3
-
-// cl_command_type
-#define CL_COMMAND_NDRANGE_KERNEL 0x11F0
-#define CL_COMMAND_TASK 0x11F1
-#define CL_COMMAND_NATIVE_KERNEL 0x11F2
-#define CL_COMMAND_READ_BUFFER 0x11F3
-#define CL_COMMAND_WRITE_BUFFER 0x11F4
-#define CL_COMMAND_COPY_BUFFER 0x11F5
-#define CL_COMMAND_READ_IMAGE 0x11F6
-#define CL_COMMAND_WRITE_IMAGE 0x11F7
-#define CL_COMMAND_COPY_IMAGE 0x11F8
-#define CL_COMMAND_COPY_IMAGE_TO_BUFFER 0x11F9
-#define CL_COMMAND_COPY_BUFFER_TO_IMAGE 0x11FA
-#define CL_COMMAND_MAP_BUFFER 0x11FB
-#define CL_COMMAND_MAP_IMAGE 0x11FC
-#define CL_COMMAND_UNMAP_MEM_OBJECT 0x11FD
-#define CL_COMMAND_MARKER 0x11FE
-#define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x11FF
-#define CL_COMMAND_RELEASE_GL_OBJECTS 0x1200
-
-// command execution status
-#define CL_COMPLETE 0x0
-#define CL_RUNNING 0x1
-#define CL_SUBMITTED 0x2
-#define CL_QUEUED 0x3
-
-// cl_profiling_info
-#define CL_PROFILING_COMMAND_QUEUED 0x1280
-#define CL_PROFILING_COMMAND_SUBMIT 0x1281
-#define CL_PROFILING_COMMAND_START 0x1282
-#define CL_PROFILING_COMMAND_END 0x1283
-
-/********************************************************************************************************/
-
-/********************************************************************************************************/
-
-// Function signature typedef's
-
-// Platform API
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETPLATFORMIDS)(cl_uint /* num_entries */,
- cl_platform_id * /* platforms */,
- cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETPLATFORMINFO)(cl_platform_id /* platform */,
- cl_platform_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Device APIs
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETDEVICEIDS)(cl_platform_id /* platform */,
- cl_device_type /* device_type */,
- cl_uint /* num_entries */,
- cl_device_id * /* devices */,
- cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETDEVICEINFO)(cl_device_id /* device */,
- cl_device_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Context APIs
-typedef CL_API_ENTRY cl_context (CL_API_CALL *
-PFNCLCREATECONTEXT)(const cl_context_properties * /* properties */,
- cl_uint /* num_devices */,
- const cl_device_id * /* devices */,
- void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */,
- void * /* user_data */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_context (CL_API_CALL *
-PFNCLCREATECONTEXTFROMTYPE)(const cl_context_properties * /* properties */,
- cl_device_type /* device_type */,
- void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */,
- void * /* user_data */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINCONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASECONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETCONTEXTINFO)(cl_context /* context */,
- cl_context_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Command Queue APIs
-typedef CL_API_ENTRY cl_command_queue (CL_API_CALL *
-PFNCLCREATECOMMANDQUEUE)(cl_context /* context */,
- cl_device_id /* device */,
- cl_command_queue_properties /* properties */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINCOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASECOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETCOMMANDQUEUEINFO)(cl_command_queue /* command_queue */,
- cl_command_queue_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLSETCOMMANDQUEUEPROPERTY)(cl_command_queue /* command_queue */,
- cl_command_queue_properties /* properties */,
- cl_bool /* enable */,
- cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0;
-
-// Memory Object APIs
-typedef CL_API_ENTRY cl_mem (CL_API_CALL *
-PFNCLCREATEBUFFER)(cl_context /* context */,
- cl_mem_flags /* flags */,
- size_t /* size */,
- void * /* host_ptr */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_mem (CL_API_CALL *
-PFNCLCREATEIMAGE2D)(cl_context /* context */,
- cl_mem_flags /* flags */,
- const cl_image_format * /* image_format */,
- size_t /* image_width */,
- size_t /* image_height */,
- size_t /* image_row_pitch */,
- void * /* host_ptr */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_mem (CL_API_CALL *
-PFNCLCREATEIMAGE3D)(cl_context /* context */,
- cl_mem_flags /* flags */,
- const cl_image_format * /* image_format */,
- size_t /* image_width */,
- size_t /* image_height */,
- size_t /* image_depth */,
- size_t /* image_row_pitch */,
- size_t /* image_slice_pitch */,
- void * /* host_ptr */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASEMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETSUPPORTEDIMAGEFORMATS)(cl_context /* context */,
- cl_mem_flags /* flags */,
- cl_mem_object_type /* image_type */,
- cl_uint /* num_entries */,
- cl_image_format * /* image_formats */,
- cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETMEMOBJECTINFO)(cl_mem /* memobj */,
- cl_mem_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETIMAGEINFO)(cl_mem /* image */,
- cl_image_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Sampler APIs
-typedef CL_API_ENTRY cl_sampler (CL_API_CALL *
-PFNCLCREATESAMPLER)(cl_context /* context */,
- cl_bool /* normalized_coords */,
- cl_addressing_mode /* addressing_mode */,
- cl_filter_mode /* filter_mode */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINSAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASESAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETSAMPLERINFO)(cl_sampler /* sampler */,
- cl_sampler_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Program Object APIs
-typedef CL_API_ENTRY cl_program (CL_API_CALL *
-PFNCLCREATEPROGRAMWITHSOURCE)(cl_context /* context */,
- cl_uint /* count */,
- const char ** /* strings */,
- const size_t * /* lengths */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_program (CL_API_CALL *
-PFNCLCREATEPROGRAMWITHBINARY)(cl_context /* context */,
- cl_uint /* num_devices */,
- const cl_device_id * /* device_list */,
- const size_t * /* lengths */,
- const unsigned char ** /* binaries */,
- cl_int * /* binary_status */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASEPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLBUILDPROGRAM)(cl_program /* program */,
- cl_uint /* num_devices */,
- const cl_device_id * /* device_list */,
- const char * /* options */,
- void (*pfn_notify)(cl_program /* program */, void * /* user_data */),
- void * /* user_data */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLUNLOADCOMPILER)(void) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETPROGRAMINFO)(cl_program /* program */,
- cl_program_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETPROGRAMBUILDINFO)(cl_program /* program */,
- cl_device_id /* device */,
- cl_program_build_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Kernel Object APIs
-typedef CL_API_ENTRY cl_kernel (CL_API_CALL *
-PFNCLCREATEKERNEL)(cl_program /* program */,
- const char * /* kernel_name */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLCREATEKERNELSINPROGRAM)(cl_program /* program */,
- cl_uint /* num_kernels */,
- cl_kernel * /* kernels */,
- cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASEKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLSETKERNELARG)(cl_kernel /* kernel */,
- cl_uint /* arg_index */,
- size_t /* arg_size */,
- const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETKERNELINFO)(cl_kernel /* kernel */,
- cl_kernel_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETKERNELWORKGROUPINFO)(cl_kernel /* kernel */,
- cl_device_id /* device */,
- cl_kernel_work_group_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Event Object APIs
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLWAITFOREVENTS)(cl_uint /* num_events */,
- const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETEVENTINFO)(cl_event /* event */,
- cl_event_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASEEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-// Profiling APIs
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETEVENTPROFILINGINFO)(cl_event /* event */,
- cl_profiling_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Flush and Finish APIs
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLFLUSH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLFINISH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-// Enqueued Commands APIs
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEREADBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_read */,
- size_t /* offset */,
- size_t /* cb */,
- void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEWRITEBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_write */,
- size_t /* offset */,
- size_t /* cb */,
- const void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* src_buffer */,
- cl_mem /* dst_buffer */,
- size_t /* src_offset */,
- size_t /* dst_offset */,
- size_t /* cb */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEREADIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* image */,
- cl_bool /* blocking_read */,
- const size_t * /* origin[3] */,
- const size_t * /* region[3] */,
- size_t /* row_pitch */,
- size_t /* slice_pitch */,
- void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEWRITEIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* image */,
- cl_bool /* blocking_write */,
- const size_t * /* origin[3] */,
- const size_t * /* region[3] */,
- size_t /* input_row_pitch */,
- size_t /* input_slice_pitch */,
- const void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* src_image */,
- cl_mem /* dst_image */,
- const size_t * /* src_origin[3] */,
- const size_t * /* dst_origin[3] */,
- const size_t * /* region[3] */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYIMAGETOBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* src_image */,
- cl_mem /* dst_buffer */,
- const size_t * /* src_origin[3] */,
- const size_t * /* region[3] */,
- size_t /* dst_offset */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYBUFFERTOIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* src_buffer */,
- cl_mem /* dst_image */,
- size_t /* src_offset */,
- const size_t * /* dst_origin[3] */,
- const size_t * /* region[3] */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY void * (CL_API_CALL *
-PFNCLENQUEUEMAPBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_map */,
- cl_map_flags /* map_flags */,
- size_t /* offset */,
- size_t /* cb */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY void * (CL_API_CALL *
-PFNCLENQUEUEMAPIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* image */,
- cl_bool /* blocking_map */,
- cl_map_flags /* map_flags */,
- const size_t * /* origin[3] */,
- const size_t * /* region[3] */,
- size_t * /* image_row_pitch */,
- size_t * /* image_slice_pitch */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEUNMAPMEMOBJECT)(cl_command_queue /* command_queue */,
- cl_mem /* memobj */,
- void * /* mapped_ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUENDRANGEKERNEL)(cl_command_queue /* command_queue */,
- cl_kernel /* kernel */,
- cl_uint /* work_dim */,
- const size_t * /* global_work_offset */,
- const size_t * /* global_work_size */,
- const size_t * /* local_work_size */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUETASK)(cl_command_queue /* command_queue */,
- cl_kernel /* kernel */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUENATIVEKERNEL)(cl_command_queue /* command_queue */,
- void (*user_func)(void *),
- void * /* args */,
- size_t /* cb_args */,
- cl_uint /* num_mem_objects */,
- const cl_mem * /* mem_list */,
- const void ** /* args_mem_loc */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEMARKER)(cl_command_queue /* command_queue */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEWAITFOREVENTS)(cl_command_queue /* command_queue */,
- cl_uint /* num_events */,
- const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEBARRIER)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-// Extension function access
-//
-// Returns the extension function address for the given function name,
-// or NULL if a valid function can not be found. The client must
-// check to make sure the address is not NULL, before using or
-// calling the returned function address.
-//
-typedef CL_API_ENTRY void * (CL_API_CALL * PFNCLGETEXTENSIONFUNCTIONADDRESS)(const char * /* func_name */) CL_API_SUFFIX__VERSION_1_0;
-
-
-#define CLEW_STATIC
-
-#ifdef CLEW_STATIC
-# define CLEWAPI extern
-#else
-# ifdef CLEW_BUILD
-# define CLEWAPI extern __declspec(dllexport)
-# else
-# define CLEWAPI extern __declspec(dllimport)
-# endif
-#endif
-
-#if defined(_WIN32)
-#define CLEW_FUN_EXPORT extern
-#else
-#define CLEW_FUN_EXPORT CLEWAPI
-#endif
-
-#define CLEW_GET_FUN(x) x
-
-
-// Variables holding function entry points
-CLEW_FUN_EXPORT PFNCLGETPLATFORMIDS __clewGetPlatformIDs ;
-CLEW_FUN_EXPORT PFNCLGETPLATFORMINFO __clewGetPlatformInfo ;
-CLEW_FUN_EXPORT PFNCLGETDEVICEIDS __clewGetDeviceIDs ;
-CLEW_FUN_EXPORT PFNCLGETDEVICEINFO __clewGetDeviceInfo ;
-CLEW_FUN_EXPORT PFNCLCREATECONTEXT __clewCreateContext ;
-CLEW_FUN_EXPORT PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType ;
-CLEW_FUN_EXPORT PFNCLRETAINCONTEXT __clewRetainContext ;
-CLEW_FUN_EXPORT PFNCLRELEASECONTEXT __clewReleaseContext ;
-CLEW_FUN_EXPORT PFNCLGETCONTEXTINFO __clewGetContextInfo ;
-CLEW_FUN_EXPORT PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue ;
-CLEW_FUN_EXPORT PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue ;
-CLEW_FUN_EXPORT PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue ;
-CLEW_FUN_EXPORT PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo ;
-CLEW_FUN_EXPORT PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty ;
-CLEW_FUN_EXPORT PFNCLCREATEBUFFER __clewCreateBuffer ;
-CLEW_FUN_EXPORT PFNCLCREATEIMAGE2D __clewCreateImage2D ;
-CLEW_FUN_EXPORT PFNCLCREATEIMAGE3D __clewCreateImage3D ;
-CLEW_FUN_EXPORT PFNCLRETAINMEMOBJECT __clewRetainMemObject ;
-CLEW_FUN_EXPORT PFNCLRELEASEMEMOBJECT __clewReleaseMemObject ;
-CLEW_FUN_EXPORT PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats ;
-CLEW_FUN_EXPORT PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo ;
-CLEW_FUN_EXPORT PFNCLGETIMAGEINFO __clewGetImageInfo ;
-CLEW_FUN_EXPORT PFNCLCREATESAMPLER __clewCreateSampler ;
-CLEW_FUN_EXPORT PFNCLRETAINSAMPLER __clewRetainSampler ;
-CLEW_FUN_EXPORT PFNCLRELEASESAMPLER __clewReleaseSampler ;
-CLEW_FUN_EXPORT PFNCLGETSAMPLERINFO __clewGetSamplerInfo ;
-CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource ;
-CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary ;
-CLEW_FUN_EXPORT PFNCLRETAINPROGRAM __clewRetainProgram ;
-CLEW_FUN_EXPORT PFNCLRELEASEPROGRAM __clewReleaseProgram ;
-CLEW_FUN_EXPORT PFNCLBUILDPROGRAM __clewBuildProgram ;
-CLEW_FUN_EXPORT PFNCLUNLOADCOMPILER __clewUnloadCompiler ;
-CLEW_FUN_EXPORT PFNCLGETPROGRAMINFO __clewGetProgramInfo ;
-CLEW_FUN_EXPORT PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo ;
-CLEW_FUN_EXPORT PFNCLCREATEKERNEL __clewCreateKernel ;
-CLEW_FUN_EXPORT PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram ;
-CLEW_FUN_EXPORT PFNCLRETAINKERNEL __clewRetainKernel ;
-CLEW_FUN_EXPORT PFNCLRELEASEKERNEL __clewReleaseKernel ;
-CLEW_FUN_EXPORT PFNCLSETKERNELARG __clewSetKernelArg ;
-CLEW_FUN_EXPORT PFNCLGETKERNELINFO __clewGetKernelInfo ;
-CLEW_FUN_EXPORT PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo ;
-CLEW_FUN_EXPORT PFNCLWAITFOREVENTS __clewWaitForEvents ;
-CLEW_FUN_EXPORT PFNCLGETEVENTINFO __clewGetEventInfo ;
-CLEW_FUN_EXPORT PFNCLRETAINEVENT __clewRetainEvent ;
-CLEW_FUN_EXPORT PFNCLRELEASEEVENT __clewReleaseEvent ;
-CLEW_FUN_EXPORT PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo ;
-CLEW_FUN_EXPORT PFNCLFLUSH __clewFlush ;
-CLEW_FUN_EXPORT PFNCLFINISH __clewFinish ;
-CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject ;
-CLEW_FUN_EXPORT PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel ;
-CLEW_FUN_EXPORT PFNCLENQUEUETASK __clewEnqueueTask ;
-CLEW_FUN_EXPORT PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel ;
-CLEW_FUN_EXPORT PFNCLENQUEUEMARKER __clewEnqueueMarker ;
-CLEW_FUN_EXPORT PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents ;
-CLEW_FUN_EXPORT PFNCLENQUEUEBARRIER __clewEnqueueBarrier ;
-CLEW_FUN_EXPORT PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress ;
-
-
-#define clGetPlatformIDs CLEW_GET_FUN(__clewGetPlatformIDs )
-#define clGetPlatformInfo CLEW_GET_FUN(__clewGetPlatformInfo )
-#define clGetDeviceIDs CLEW_GET_FUN(__clewGetDeviceIDs )
-#define clGetDeviceInfo CLEW_GET_FUN(__clewGetDeviceInfo )
-#define clCreateContext CLEW_GET_FUN(__clewCreateContext )
-#define clCreateContextFromType CLEW_GET_FUN(__clewCreateContextFromType )
-#define clRetainContext CLEW_GET_FUN(__clewRetainContext )
-#define clReleaseContext CLEW_GET_FUN(__clewReleaseContext )
-#define clGetContextInfo CLEW_GET_FUN(__clewGetContextInfo )
-#define clCreateCommandQueue CLEW_GET_FUN(__clewCreateCommandQueue )
-#define clRetainCommandQueue CLEW_GET_FUN(__clewRetainCommandQueue )
-#define clReleaseCommandQueue CLEW_GET_FUN(__clewReleaseCommandQueue )
-#define clGetCommandQueueInfo CLEW_GET_FUN(__clewGetCommandQueueInfo )
-#define clSetCommandQueueProperty CLEW_GET_FUN(__clewSetCommandQueueProperty )
-#define clCreateBuffer CLEW_GET_FUN(__clewCreateBuffer )
-#define clCreateImage2D CLEW_GET_FUN(__clewCreateImage2D )
-#define clCreateImage3D CLEW_GET_FUN(__clewCreateImage3D )
-#define clRetainMemObject CLEW_GET_FUN(__clewRetainMemObject )
-#define clReleaseMemObject CLEW_GET_FUN(__clewReleaseMemObject )
-#define clGetSupportedImageFormats CLEW_GET_FUN(__clewGetSupportedImageFormats )
-#define clGetMemObjectInfo CLEW_GET_FUN(__clewGetMemObjectInfo )
-#define clGetImageInfo CLEW_GET_FUN(__clewGetImageInfo )
-#define clCreateSampler CLEW_GET_FUN(__clewCreateSampler )
-#define clRetainSampler CLEW_GET_FUN(__clewRetainSampler )
-#define clReleaseSampler CLEW_GET_FUN(__clewReleaseSampler )
-#define clGetSamplerInfo CLEW_GET_FUN(__clewGetSamplerInfo )
-#define clCreateProgramWithSource CLEW_GET_FUN(__clewCreateProgramWithSource )
-#define clCreateProgramWithBinary CLEW_GET_FUN(__clewCreateProgramWithBinary )
-#define clRetainProgram CLEW_GET_FUN(__clewRetainProgram )
-#define clReleaseProgram CLEW_GET_FUN(__clewReleaseProgram )
-#define clBuildProgram CLEW_GET_FUN(__clewBuildProgram )
-#define clUnloadCompiler CLEW_GET_FUN(__clewUnloadCompiler )
-#define clGetProgramInfo CLEW_GET_FUN(__clewGetProgramInfo )
-#define clGetProgramBuildInfo CLEW_GET_FUN(__clewGetProgramBuildInfo )
-#define clCreateKernel CLEW_GET_FUN(__clewCreateKernel )
-#define clCreateKernelsInProgram CLEW_GET_FUN(__clewCreateKernelsInProgram )
-#define clRetainKernel CLEW_GET_FUN(__clewRetainKernel )
-#define clReleaseKernel CLEW_GET_FUN(__clewReleaseKernel )
-#define clSetKernelArg CLEW_GET_FUN(__clewSetKernelArg )
-#define clGetKernelInfo CLEW_GET_FUN(__clewGetKernelInfo )
-#define clGetKernelWorkGroupInfo CLEW_GET_FUN(__clewGetKernelWorkGroupInfo )
-#define clWaitForEvents CLEW_GET_FUN(__clewWaitForEvents )
-#define clGetEventInfo CLEW_GET_FUN(__clewGetEventInfo )
-#define clRetainEvent CLEW_GET_FUN(__clewRetainEvent )
-#define clReleaseEvent CLEW_GET_FUN(__clewReleaseEvent )
-#define clGetEventProfilingInfo CLEW_GET_FUN(__clewGetEventProfilingInfo )
-#define clFlush CLEW_GET_FUN(__clewFlush )
-#define clFinish CLEW_GET_FUN(__clewFinish )
-#define clEnqueueReadBuffer CLEW_GET_FUN(__clewEnqueueReadBuffer )
-#define clEnqueueWriteBuffer CLEW_GET_FUN(__clewEnqueueWriteBuffer )
-#define clEnqueueCopyBuffer CLEW_GET_FUN(__clewEnqueueCopyBuffer )
-#define clEnqueueReadImage CLEW_GET_FUN(__clewEnqueueReadImage )
-#define clEnqueueWriteImage CLEW_GET_FUN(__clewEnqueueWriteImage )
-#define clEnqueueCopyImage CLEW_GET_FUN(__clewEnqueueCopyImage )
-#define clEnqueueCopyImageToBuffer CLEW_GET_FUN(__clewEnqueueCopyImageToBuffer )
-#define clEnqueueCopyBufferToImage CLEW_GET_FUN(__clewEnqueueCopyBufferToImage )
-#define clEnqueueMapBuffer CLEW_GET_FUN(__clewEnqueueMapBuffer )
-#define clEnqueueMapImage CLEW_GET_FUN(__clewEnqueueMapImage )
-#define clEnqueueUnmapMemObject CLEW_GET_FUN(__clewEnqueueUnmapMemObject )
-#define clEnqueueNDRangeKernel CLEW_GET_FUN(__clewEnqueueNDRangeKernel )
-#define clEnqueueTask CLEW_GET_FUN(__clewEnqueueTask )
-#define clEnqueueNativeKernel CLEW_GET_FUN(__clewEnqueueNativeKernel )
-#define clEnqueueMarker CLEW_GET_FUN(__clewEnqueueMarker )
-#define clEnqueueWaitForEvents CLEW_GET_FUN(__clewEnqueueWaitForEvents )
-#define clEnqueueBarrier CLEW_GET_FUN(__clewEnqueueBarrier )
-#define clGetExtensionFunctionAddress CLEW_GET_FUN(__clewGetExtensionFunctionAddress )
-
-#endif // CLCC_GENERATE_DOCUMENTATION
-
-#define CLEW_SUCCESS 0 //!< Success error code
-#define CLEW_ERROR_OPEN_FAILED -1 //!< Error code for failing to open the dynamic library
-#define CLEW_ERROR_ATEXIT_FAILED -2 //!< Error code for failing to queue the closing of the dynamic library to atexit()
-
-int clLibraryInit(void);
-const char *clErrorString(cl_int error);
-
-CCL_NAMESPACE_END
-
-#endif /* __UTIL_OPENCL_H__ */
-
diff --git a/intern/cycles/util/util_optimization.h b/intern/cycles/util/util_optimization.h
index 5d0fea34761..2feb3d6ab7e 100644
--- a/intern/cycles/util/util_optimization.h
+++ b/intern/cycles/util/util_optimization.h
@@ -69,13 +69,6 @@
#define WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
#endif
-/* MSVC 2008, no SSE41 (broken blendv intrinsic) and no AVX support */
-#if defined(_MSC_VER) && (_MSC_VER < 1700)
-#undef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
-#undef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
-#undef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
-#endif
-
#endif
/* SSE Experiment
diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h
index 5d1219bfef3..e721a3f5047 100644
--- a/intern/cycles/util/util_progress.h
+++ b/intern/cycles/util/util_progress.h
@@ -149,6 +149,12 @@ public:
sample++;
}
+ void increment_sample_update()
+ {
+ increment_sample();
+ set_update();
+ }
+
int get_sample()
{
return sample;
diff --git a/intern/cycles/util/util_stats.h b/intern/cycles/util/util_stats.h
index 62b1f1760d7..8758b823084 100644
--- a/intern/cycles/util/util_stats.h
+++ b/intern/cycles/util/util_stats.h
@@ -30,6 +30,7 @@ public:
}
void mem_free(size_t size) {
+ assert(mem_used >= size);
mem_used -= size;
}
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index 98d70786d44..d7d80e2cffd 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -474,14 +474,14 @@ enum InterpolationType {
* ... the compiler optimizes away the temp var */
#ifdef __GNUC__
#define CHECK_TYPE(var, type) { \
- __typeof(var) *__tmp; \
+ 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; \
+ typeof(var_a) *__tmp; \
+ __tmp = (typeof(var_b) *)NULL; \
(void)__tmp; \
} (void)0
#else
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index b678d52c481..0f4fd47d306 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -151,7 +151,7 @@ extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
/**
* Returns the dimensions of all displays combine
* (the current workspace).
- * No need to worrky about overlapping monitors.
+ * No need to worry about overlapping monitors.
* \param systemhandle The handle to the system
* \param width A pointer the width gets put in
* \param height A pointer the height gets put in
@@ -401,7 +401,7 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
* do this automatically.
* \param windowhandle The handle to the window
* \param mode The new grab state of the cursor.
- * \param bounds The grab ragion (optional) - left,top,right,bottom
+ * \param bounds The grab region (optional) - left,top,right,bottom
* \param mouse_ungrab_xy XY for new mouse location (optional) - x,y
* \return Indication of success.
*/
@@ -758,7 +758,7 @@ extern GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehand
/**
* Returns whether this rectangle is valid.
- * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, emapty rectangles are valid.
+ * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, empty rectangles are valid.
* \param rectanglehandle The handle to the rectangle
* \return intean value (true == valid rectangle)
*/
@@ -852,7 +852,7 @@ extern GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle,
GHOST_RectangleHandle anotherrectanglehandle);
/**
- * Return the data from the clipboad
+ * Return the data from the clipboard
* \param selection Boolean to return the selection instead, X11 only feature.
* \return clipboard data
*/
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 137926b033c..19f36319949 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -48,7 +48,7 @@ class GHOST_IEventConsumer;
*
* GHOST is yet another acronym. It stands for "Generic Handy Operating System
* Toolkit". It has been created to replace the OpenGL utility tool kit
- * <a href="http://www.opengl.org/developers/documentation/glut.html">GLUT</a>.
+ * <a href="http://www.opengl.org/resources/libraries/glut/">GLUT</a>.
* GLUT was used in <a href="http://www.blender3d.com">Blender</a> until the
* point that Blender needed to be ported to Apple's Mac OSX. Blender needed a
* number of modifications in GLUT to work but the GLUT sources for OSX were
@@ -60,31 +60,29 @@ class GHOST_IEventConsumer;
* In short: everything that Blender needed from GLUT to run on all it's supported
* operating systems and some extra's.
* This includes :
- * <ul>
- * <li> Time(r) management.</li>
- * <li> Display/window management (windows are only created on the main display).
- * <li> Event management.</li>
- * <li> Cursor shape management (no custom cursors for now).</li>
- * <li> Access to the state of the mouse buttons and the keyboard.</li>
- * <li> Menus for windows with events generated when they are accessed (this is
- * work in progress).</li>
- * <li> Video mode switching.</li>
- * <li> Copy/Paste buffers.</li>
- * <li> System paths.</li>
- * </ul>
+ *
+ * - Time(r) management.
+ * - Display/window management (windows are only created on the main display).
+ * - Event management.
+ * - Cursor shape management (no custom cursors for now).
+ * - Access to the state of the mouse buttons and the keyboard.
+ * - Menus for windows with events generated when they are accessed (this is
+ * work in progress).
+ * - Video mode switching.
+ * - Copy/Paste buffers.
+ * - System paths.
+ *
* Font management has been moved to a separate library.
*
* \section platforms Platforms
*
* GHOST supports the following platforms:
- * <ul>
- * <li> OSX Cocoa.</li>
- * <li> OSX Carbon.</li>
- * <li> Windows.</li>
- * <li> X11.</li>
- * <li> SDL1.3 (experimental).</li>
- * <li> NULL (headless mode).</li>
- * </ul>
+ *
+ * - OSX Cocoa.
+ * - Windows.
+ * - X11.
+ * - SDL2 (experimental).
+ * - NULL (headless mode).
*
* \section Building GHOST
*
@@ -92,23 +90,23 @@ class GHOST_IEventConsumer;
*
* \section interface Interface
* GHOST has two programming interfaces:
- * <ul>
- * <li>The C-API. For programs written in C.</li>
- * <li>The C++-API. For programs written in C++.</li>
- * </ul>
- * GHOST itself is writtem in C++ and the C-API is a wrapper around the C++
+ *
+ * - The C-API. For programs written in C.
+ * - The C++-API. For programs written in C++.
+ *
+ * GHOST itself is written in C++ and the C-API is a wrapper around the C++
* API.
*
* \subsection cplusplus_api The C++ API consists of the following files:
- * <ul>
- * <li>GHOST_IEvent.h</li>
- * <li>GHOST_IEventConsumer.h</li>
- * <li>GHOST_ISystem.h</li>
- * <li>GHOST_ITimerTask.h</li>
- * <li>GHOST_IWindow.h</li>
- * <li>GHOST_Rect.h</li>
- * <li>GHOST_Types.h</li>
- * </ul>
+ *
+ * - GHOST_IEvent.h
+ * - GHOST_IEventConsumer.h
+ * - GHOST_ISystem.h
+ * - GHOST_ITimerTask.h
+ * - GHOST_IWindow.h
+ * - GHOST_Rect.h
+ * - GHOST_Types.h
+ *
* For an example of using the C++-API, have a look at the GHOST_C-Test.cpp
* program in the ?/ghost/test/gears/ directory.
*
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index ba3797a77e7..5fde53e397b 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -46,13 +46,12 @@
* \see GHOST_ISystem#createWindow
*
* There are two coordinate systems:
- * <ul>
- * <li>The screen coordinate system. The origin of the screen is located in the
- * upper left corner of the screen.</li>
- * <li>The client rectangle coordinate system. The client rectangle of a window
- * is the area that is drawable by the application (excluding title bars etc.).
- * </li>
- * </ul>
+ *
+ * - The screen coordinate system. The origin of the screen is located in the
+ * upper left corner of the screen.</li>
+ * - The client rectangle coordinate system. The client rectangle of a window
+ * is the area that is drawable by the application (excluding title bars etc.).
+ *
* \author Maarten Gribnau
* \date May 31, 2001
*/
diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h
index a055b6f7f0d..c2ea8db0a66 100644
--- a/intern/ghost/GHOST_Rect.h
+++ b/intern/ghost/GHOST_Rect.h
@@ -102,7 +102,7 @@ public:
/**
* Returns whether this rectangle is valid.
- * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, emapty rectangles are valid.
+ * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, empty rectangles are valid.
* \return boolean value (true==valid rectangle)
*/
virtual inline bool isValid() const;
diff --git a/intern/ghost/intern/GHOST_Context.cpp b/intern/ghost/intern/GHOST_Context.cpp
index 211c712cde2..c3483d7d7c9 100644
--- a/intern/ghost/intern/GHOST_Context.cpp
+++ b/intern/ghost/intern/GHOST_Context.cpp
@@ -37,7 +37,7 @@
-const char* get_glew_error_message_string(GLenum error)
+static const char* get_glew_error_message_string(GLenum error)
{
switch (error) {
case GLEW_OK: /* also GLEW_NO_ERROR */
@@ -52,7 +52,7 @@ const char* get_glew_error_message_string(GLenum error)
case GLEW_ERROR_GLX_VERSION_11_ONLY:
return "GLX 1.2 or later is required.";
-#if WITH_GLEW_ES
+#ifdef WITH_GLEW_ES
case GLEW_ERROR_NOT_GLES_VERSION:
return "OpenGL ES is required.";
@@ -73,7 +73,7 @@ const char* get_glew_error_message_string(GLenum error)
-const char* get_glew_error_enum_string(GLenum error)
+static const char* get_glew_error_enum_string(GLenum error)
{
switch (error) {
case GLEW_OK: /* also GLEW_NO_ERROR */
@@ -88,7 +88,7 @@ const char* get_glew_error_enum_string(GLenum error)
case GLEW_ERROR_GLX_VERSION_11_ONLY:
return "GLEW_ERROR_GLX_VERSION_11_ONLY";
-#if WITH_GLEW_ES
+#ifdef WITH_GLEW_ES
case GLEW_ERROR_NOT_GLES_VERSION:
return "GLEW_ERROR_NOT_GLES_VERSION";
diff --git a/intern/ghost/intern/GHOST_DisplayManager.cpp b/intern/ghost/intern/GHOST_DisplayManager.cpp
index 7ca4c8182b9..9f0b32148f6 100644
--- a/intern/ghost/intern/GHOST_DisplayManager.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManager.cpp
@@ -40,9 +40,8 @@
#include "GHOST_Debug.h"
-GHOST_DisplayManager::GHOST_DisplayManager(
- void)
- : m_settingsInitialized(false)
+GHOST_DisplayManager::GHOST_DisplayManager(void)
+ : m_settingsInitialized(false)
{
}
diff --git a/intern/ghost/intern/GHOST_DisplayManager.h b/intern/ghost/intern/GHOST_DisplayManager.h
index 7dc0cf2ca04..afdb11543e9 100644
--- a/intern/ghost/intern/GHOST_DisplayManager.h
+++ b/intern/ghost/intern/GHOST_DisplayManager.h
@@ -100,7 +100,7 @@ public:
/**
* Changes the current setting for this display device.
- * The setting given to this method is matched againts the available diplay settings.
+ * The setting given to this method is matched against the available display settings.
* The best match is activated (@see findMatch()).
* \param display The index of the display to query with 0 <= display < getNumDisplays().
* \param setting The setting of the display device to be matched and activated.
diff --git a/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp b/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
index fa92adf87f0..cdba8cdb4bb 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
@@ -35,8 +35,7 @@
#include "GHOST_WindowManager.h"
GHOST_DisplayManagerSDL::GHOST_DisplayManagerSDL(GHOST_SystemSDL *system)
- :
- GHOST_DisplayManager(),
+ : GHOST_DisplayManager(),
m_system(system)
{
memset(&m_mode, 0, sizeof(m_mode));
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
index 0bfc67a9126..65d5e650251 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
@@ -56,7 +56,7 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(GHOST_TUns8& numDisplay
return numDisplays > 0 ? GHOST_kSuccess : GHOST_kFailure;
}
-static BOOL get_dd(DWORD d, DISPLAY_DEVICE* dd)
+static BOOL get_dd(DWORD d, DISPLAY_DEVICE *dd)
{
dd->cb = sizeof(DISPLAY_DEVICE);
return ::EnumDisplayDevices(NULL, d, dd, 0);
@@ -161,8 +161,7 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(GHOST_TUns8 d
LONG status = ::ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
#ifdef GHOST_DEBUG
- switch (status)
- {
+ switch (status) {
case DISP_CHANGE_SUCCESSFUL:
printf("display change: The settings change was successful.\n");
break;
@@ -173,7 +172,8 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(GHOST_TUns8 d
printf("display change: An invalid set of flags was passed in.\n");
break;
case DISP_CHANGE_BADPARAM:
- printf("display change: An invalid parameter was passed in. This can include an invalid flag or combination of flags.\n");
+ printf("display change: An invalid parameter was passed in. "
+ "This can include an invalid flag or combination of flags.\n");
break;
case DISP_CHANGE_FAILED:
printf("display change: The display driver failed the specified graphics mode.\n");
diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
index f63a93eebb8..24289e6b006 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
@@ -42,10 +42,9 @@
GHOST_DisplayManagerX11::
GHOST_DisplayManagerX11(
- GHOST_SystemX11 *system
- ) :
- GHOST_DisplayManager(),
- m_system(system)
+ GHOST_SystemX11 *system)
+ : GHOST_DisplayManager(),
+ m_system(system)
{
/* nothing to do. */
}
@@ -195,7 +194,7 @@ setCurrentDisplaySetting(
fprintf(stderr, "Error: XF86VidMode extension missing!\n");
return GHOST_kFailure;
}
-# ifdef _DEBUG
+# ifdef DEBUG
printf("Using XFree86-VidModeExtension Version %d.%d\n",
majorVersion, minorVersion);
# endif
@@ -241,7 +240,7 @@ setCurrentDisplaySetting(
}
if (best_fit != -1) {
-# ifdef _DEBUG
+# ifdef DEBUG
printf("Switching to video mode %dx%d %dx%d %d\n",
vidmodes[best_fit]->hdisplay, vidmodes[best_fit]->vdisplay,
vidmodes[best_fit]->htotal, vidmodes[best_fit]->vtotal,
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
index 5288b77a3c6..fd9abce96b7 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
@@ -43,10 +43,11 @@ void printLastError(void);
#endif // GHOST_DEBUG
-GHOST_DropTargetWin32::GHOST_DropTargetWin32(GHOST_WindowWin32 *window, GHOST_SystemWin32 *system)
- :
- m_window(window),
- m_system(system)
+GHOST_DropTargetWin32::GHOST_DropTargetWin32(
+ GHOST_WindowWin32 *window,
+ GHOST_SystemWin32 *system)
+ : m_window(window),
+ m_system(system)
{
m_cRef = 1;
m_hWnd = window->getHWND();
@@ -68,8 +69,7 @@ HRESULT __stdcall GHOST_DropTargetWin32::QueryInterface(REFIID riid, void **ppvO
return E_INVALIDARG;
*ppvObj = NULL;
- if (riid == IID_IUnknown || riid == IID_IDropTarget)
- {
+ if (riid == IID_IUnknown || riid == IID_IDropTarget) {
AddRef();
*ppvObj = (void *)this;
return S_OK;
@@ -186,7 +186,7 @@ DWORD GHOST_DropTargetWin32::allowedDropEffect(DWORD dwAllowed)
GHOST_TDragnDropTypes GHOST_DropTargetWin32::getGhostType(IDataObject *pDataObject)
{
/* Text
- * Note: Unicode text is aviable as CF_TEXT too, the system can do the
+ * Note: Unicode text is available as CF_TEXT too, the system can do the
* conversion, but we do the conversion ourself with WC_NO_BEST_FIT_CHARS.
*/
FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
@@ -208,8 +208,7 @@ GHOST_TDragnDropTypes GHOST_DropTargetWin32::getGhostType(IDataObject *pDataObje
void *GHOST_DropTargetWin32::getGhostData(IDataObject *pDataObject)
{
GHOST_TDragnDropTypes type = getGhostType(pDataObject);
- switch (type)
- {
+ switch (type) {
case GHOST_kDragnDropTypeFilenames:
return getDropDataAsFilenames(pDataObject);
break;
@@ -241,15 +240,12 @@ void *GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject *pDataObject)
// Check if dataobject supplies the format we want.
// Double checking here, first in getGhostType.
- if (pDataObject->QueryGetData(&fmtetc) == S_OK)
- {
- if (pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
- {
+ if (pDataObject->QueryGetData(&fmtetc) == S_OK) {
+ if (pDataObject->GetData(&fmtetc, &stgmed) == S_OK) {
hdrop = (HDROP) ::GlobalLock(stgmed.hGlobal);
totfiles = ::DragQueryFileW(hdrop, -1, NULL, 0);
- if (!totfiles)
- {
+ if (!totfiles) {
::GlobalUnlock(stgmed.hGlobal);
return NULL;
}
@@ -258,14 +254,11 @@ void *GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject *pDataObject)
strArray->count = 0;
strArray->strings = (GHOST_TUns8 **) ::malloc(totfiles * sizeof(GHOST_TUns8 *));
- for (UINT nfile = 0; nfile < totfiles; nfile++)
- {
- if (::DragQueryFileW(hdrop, nfile, fpath, MAX_PATH) > 0)
- {
- if (!(temp_path = alloc_utf_8_from_16(fpath, 0)) )
- {
+ for (UINT nfile = 0; nfile < totfiles; nfile++) {
+ if (::DragQueryFileW(hdrop, nfile, fpath, MAX_PATH) > 0) {
+ if (!(temp_path = alloc_utf_8_from_16(fpath, 0)) ) {
continue;
- }
+ }
// Just ignore paths that could not be converted verbatim.
strArray->strings[nvalid] = (GHOST_TUns8 *) temp_path;
@@ -291,13 +284,10 @@ void *GHOST_DropTargetWin32::getDropDataAsString(IDataObject *pDataObject)
// Try unicode first.
// Check if dataobject supplies the format we want.
- if (pDataObject->QueryGetData(&fmtetc) == S_OK)
- {
- if (pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
- {
+ if (pDataObject->QueryGetData(&fmtetc) == S_OK) {
+ if (pDataObject->GetData(&fmtetc, &stgmed) == S_OK) {
LPCWSTR wstr = (LPCWSTR) ::GlobalLock(stgmed.hGlobal);
- if (!(tmp_string = alloc_utf_8_from_16((wchar_t *)wstr, 0)) )
- {
+ if (!(tmp_string = alloc_utf_8_from_16((wchar_t *)wstr, 0)) ) {
::GlobalUnlock(stgmed.hGlobal);
return NULL;
}
@@ -313,21 +303,17 @@ void *GHOST_DropTargetWin32::getDropDataAsString(IDataObject *pDataObject)
fmtetc.cfFormat = CF_TEXT;
- if (pDataObject->QueryGetData(&fmtetc) == S_OK)
- {
- if (pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
- {
+ if (pDataObject->QueryGetData(&fmtetc) == S_OK) {
+ if (pDataObject->GetData(&fmtetc, &stgmed) == S_OK) {
char *str = (char *)::GlobalLock(stgmed.hGlobal);
tmp_string = (char *)::malloc(::strlen(str) + 1);
- if (!tmp_string)
- {
+ if (!tmp_string) {
::GlobalUnlock(stgmed.hGlobal);
return NULL;
}
- if (!::strcpy(tmp_string, str) )
- {
+ if (!::strcpy(tmp_string, str) ) {
::free(tmp_string);
::GlobalUnlock(stgmed.hGlobal);
return NULL;
@@ -358,8 +344,7 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char * &out)
NULL, NULL
);
- if (!size)
- {
+ if (!size) {
#ifdef GHOST_DEBUG
::printLastError();
#endif // GHOST_DEBUG
@@ -367,8 +352,7 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char * &out)
}
out = (char *)::malloc(size);
- if (!out)
- {
+ if (!out) {
::printf("\nmalloc failed!!!");
return 0;
}
@@ -382,8 +366,7 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char * &out)
NULL, NULL
);
- if (!size)
- {
+ if (!size) {
#ifdef GHOST_DEBUG
::printLastError();
#endif //GHOST_DEBUG
@@ -407,8 +390,7 @@ void printLastError(void)
0,
(LPTSTR)&s,
0,
- NULL)
- )
+ NULL))
{
printf("\nLastError: (%d) %s\n", (int)err, s);
LocalFree(s);
diff --git a/intern/ghost/intern/GHOST_DropTargetX11.h b/intern/ghost/intern/GHOST_DropTargetX11.h
index 0254139bcd8..e2968844ff0 100644
--- a/intern/ghost/intern/GHOST_DropTargetX11.h
+++ b/intern/ghost/intern/GHOST_DropTargetX11.h
@@ -73,12 +73,12 @@ private:
/* Internal helper functions */
/**
- * Initiailize XDND and all related X atoms
+ * Initialize XDND and all related X atoms
*/
void Initialize(void);
/**
- * Uninitiailize XDND and all related X atoms
+ * Uninitialize XDND and all related X atoms
*/
void Uninitialize(void);
@@ -101,7 +101,7 @@ private:
/**
* Fully decode file URL (i.e. converts "file:///a%20b/test" to "/a b/test")
* \param fileUrl - file path URL to be fully decoded
- * \return decoded file path (resutl shold be free-d)
+ * \return decoded file path (resutl should be free-d)
*/
char *FileUrlDecode(char *fileUrl);
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index c99680641c3..9bd6226d5c2 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -189,18 +189,18 @@ static const NDOF_ButtonT Generic_HID_map[] = {
static const int genericButtonCount = sizeof(Generic_HID_map) / sizeof(NDOF_ButtonT);
-GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys)
- : m_system(sys)
- , m_deviceType(NDOF_UnknownDevice) // each platform has its own device detection code
- , m_buttonCount(genericButtonCount)
- , m_buttonMask(0)
- , m_hidMap(Generic_HID_map)
- , m_buttons(0)
- , m_motionTime(0)
- , m_prevMotionTime(0)
- , m_motionState(GHOST_kNotStarted)
- , m_motionEventPending(false)
- , m_deadZone(0.f)
+GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys)
+ : m_system(sys),
+ m_deviceType(NDOF_UnknownDevice), /* each platform has its own device detection code */
+ m_buttonCount(genericButtonCount),
+ m_buttonMask(0),
+ m_hidMap(Generic_HID_map),
+ m_buttons(0),
+ m_motionTime(0),
+ m_prevMotionTime(0),
+ m_motionState(GHOST_kNotStarted),
+ m_motionEventPending(false),
+ m_deadZone(0.0f)
{
// to avoid the rare situation where one triple is updated and
// the other is not, initialize them both here:
diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h
index 98aebfa4f30..0b2080e36a9 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.h
+++ b/intern/ghost/intern/GHOST_NDOFManager.h
@@ -105,7 +105,7 @@ typedef enum {
class GHOST_NDOFManager
{
public:
- GHOST_NDOFManager(GHOST_System&);
+ GHOST_NDOFManager(GHOST_System &);
virtual ~GHOST_NDOFManager() {}
diff --git a/intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c b/intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c
index 9df9a56f8b8..01e301f927e 100644
--- a/intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c
+++ b/intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c
@@ -30,14 +30,14 @@
/* It is to be noted that these implementations are linked in as
* 'extern "C"' calls from GHOST_NDOFManagerCocoa.
-
+ *
* This is done in order to
* preserve weak linking capability (which as of clang-3.3 and xcode5
* breaks weak linking when there is name mangling of c++ libraries.)
*
* We need to have the weak linked file as pure C. Therefore we build a
* compiled bridge from the real weak linked calls and the calls within C++
-
+ *
*/
OSErr GHOST_NDOFManager3Dconnexion_available(void)
diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm
index 1a029257f09..6eedaafb2d1 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm
+++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm
@@ -30,7 +30,7 @@
extern "C" {
#include <ConnexionClientAPI.h>
#include <stdio.h>
- }
+}
// static functions need to talk to these objects:
diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
index 939e1272434..6c1627905e0 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp
@@ -28,7 +28,7 @@
GHOST_NDOFManagerWin32::GHOST_NDOFManagerWin32(GHOST_System& sys)
- : GHOST_NDOFManager(sys)
+ : GHOST_NDOFManager(sys)
{
setDeadZone(0.1f);
}
diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp
index 77e09e7ef49..8e6f9994e51 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp
@@ -30,9 +30,8 @@
GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys)
- :
- GHOST_NDOFManager(sys),
- m_available(false)
+ : GHOST_NDOFManager(sys),
+ m_available(false)
{
setDeadZone(0.1f); /* how to calibrate on Linux? throw away slight motion! */
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index 023c5958c4f..d1f2d5d87c8 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -45,13 +45,13 @@
GHOST_System::GHOST_System()
- : m_nativePixel(false),
- m_displayManager(NULL),
- m_timerManager(NULL),
- m_windowManager(NULL),
- m_eventManager(NULL)
+ : m_nativePixel(false),
+ m_displayManager(NULL),
+ m_timerManager(NULL),
+ m_windowManager(NULL),
+ m_eventManager(NULL)
#ifdef WITH_INPUT_NDOF
- , m_ndofManager(0)
+ , m_ndofManager(0)
#endif
{
}
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index 57aa0a31c94..79230b0f505 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -250,27 +250,23 @@ public:
virtual GHOST_TSuccess pushEvent(GHOST_IEvent *event);
/**
- * Returns the timer manager.
* \return The timer manager.
*/
inline virtual GHOST_TimerManager *getTimerManager() const;
/**
- * Returns a pointer to our event manager.
* \return A pointer to our event manager.
*/
virtual inline GHOST_EventManager *getEventManager() const;
/**
- * Returns a pointer to our window manager.
* \return A pointer to our window manager.
*/
virtual inline GHOST_WindowManager *getWindowManager() const;
#ifdef WITH_INPUT_NDOF
/**
- * Returns a pointer to our n-degree of freedeom manager.
- * \return A pointer to our n-degree of freedeom manager.
+ * \return A pointer to our n-degree of freedom manager.
*/
virtual inline GHOST_NDOFManager *getNDOFManager() const;
#endif
@@ -333,7 +329,7 @@ protected:
virtual GHOST_TSuccess createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0);
- /** The display manager (platform dependant). */
+ /** The display manager (platform dependent). */
GHOST_DisplayManager *m_displayManager;
/** The timer manager. */
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index 7d58c58b90e..9b30abe75d5 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -265,7 +265,7 @@ public:
protected:
/**
* Initializes the system.
- * For now, it justs registers the window class (WNDCLASS).
+ * For now, it just registers the window class (WNDCLASS).
* \return A success value.
*/
virtual GHOST_TSuccess init();
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 1d4c6d5e10b..a2e26574530 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -700,10 +700,10 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
handleKeyEvent(event);
}
else {
- // For some reason NSApp is swallowing the key up events when command
+ // For some reason NSApp is swallowing the key up events when modifier
// key is pressed, even if there seems to be no apparent reason to do
// so, as a workaround we always handle these up events.
- if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask))
+ if ([event type] == NSKeyUp && (([event modifierFlags] & NSCommandKeyMask) || ([event modifierFlags] & NSAlternateKeyMask)))
handleKeyEvent(event);
[NSApp sendEvent:event];
diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
index 3a313c792d0..2bd380050f1 100644
--- a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
@@ -37,7 +37,7 @@
#include <shlobj.h>
#include "utfconv.h"
-#if defined(__MINGW32__) || defined(__CYGWIN__)
+#ifdef __MINGW32__
#if !defined(SHARD_PIDL)
#define SHARD_PIDL 0x00000001L
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index ac0d5f3fadf..c53c6a1082d 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -46,6 +46,8 @@
#include <shlobj.h>
#include <tlhelp32.h>
+#include <Psapi.h>
+#include <windowsx.h>
#include "utfconv.h"
@@ -114,6 +116,17 @@
#define VK_MEDIA_PLAY_PAUSE 0xB3
#endif // VK_MEDIA_PLAY_PAUSE
+/* Workaround for some laptop touchpads, some of which seems to
+ * have driver issues which makes it so window function receives
+ * the message, but PeekMessage doesn't pick those messages for
+ * some reason.
+ *
+ * We send a dummy WM_USER message to force PeekMessage to receive
+ * something, making it so blender's window manager sees the new
+ * messages coming in.
+ */
+#define BROKEN_PEEK_TOUCHPAD
+
static void initRawInput()
{
#ifdef WITH_INPUT_NDOF
@@ -201,23 +214,34 @@ GHOST_TUns8 GHOST_SystemWin32::getNumDisplays() const
}
-void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
+void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
{
width = ::GetSystemMetrics(SM_CXSCREEN);
height = ::GetSystemMetrics(SM_CYSCREEN);
}
-void GHOST_SystemWin32::getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
+void GHOST_SystemWin32::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
{
width = ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
height = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
}
GHOST_IWindow *GHOST_SystemWin32::createWindow(
+<<<<<<< HEAD
const STR_String& title,
GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height,
GHOST_TWindowState state, GHOST_TDrawingContextType type,
bool wantStereoVisual, const bool exclusive, const GHOST_TUns16 wantNumOfAASamples, const GHOST_TEmbedderWindowID parentWindow)
+=======
+ const STR_String &title,
+ GHOST_TInt32 left, GHOST_TInt32 top,
+ GHOST_TUns32 width, GHOST_TUns32 height,
+ GHOST_TWindowState state, GHOST_TDrawingContextType type,
+ bool stereoVisual,
+ const bool exclusive,
+ const GHOST_TUns16 numOfAASamples,
+ const GHOST_TEmbedderWindowID parentWindow)
+>>>>>>> master
{
GHOST_Window *window =
new GHOST_WindowWin32(
@@ -294,7 +318,7 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
}
-GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
+GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const
{
POINT point;
if (::GetCursorPos(&point)) {
@@ -308,13 +332,13 @@ GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt3
GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
{
- if (!GetActiveWindow())
+ if (!::GetActiveWindow())
return GHOST_kFailure;
return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
}
-GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) const
+GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys &keys) const
{
bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
keys.set(GHOST_kModifierKeyLeftShift, down);
@@ -341,7 +365,7 @@ GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) cons
}
-GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons& buttons) const
+GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons &buttons) const
{
/* Check for swapped buttons (left-handed mouse buttons)
* GetAsyncKeyState() will give back the state of the physical mouse buttons.
@@ -417,7 +441,7 @@ GHOST_TSuccess GHOST_SystemWin32::exit()
return GHOST_System::exit();
}
-GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int *keyDown, char *vk)
+GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const &raw, int *keyDown, char *vk)
{
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
GHOST_TKey key = GHOST_kKeyUnknown;
@@ -432,8 +456,7 @@ GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const& raw
key = this->convertKey(window, raw.data.keyboard.VKey, raw.data.keyboard.MakeCode, (raw.data.keyboard.Flags & (RI_KEY_E1 | RI_KEY_E0)));
// extra handling of modifier keys: don't send repeats out from GHOST
- if (key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt)
- {
+ if (key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt) {
bool changed = false;
GHOST_TModifierKeyMask modifier;
switch (key) {
@@ -441,43 +464,43 @@ GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const& raw
{
changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown);
modifier = GHOST_kModifierKeyLeftShift;
+ break;
}
- break;
case GHOST_kKeyRightShift:
{
changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown);
modifier = GHOST_kModifierKeyRightShift;
+ break;
}
- break;
case GHOST_kKeyLeftControl:
{
changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown);
modifier = GHOST_kModifierKeyLeftControl;
+ break;
}
- break;
case GHOST_kKeyRightControl:
{
changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown);
modifier = GHOST_kModifierKeyRightControl;
+ break;
}
- break;
case GHOST_kKeyLeftAlt:
{
changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown);
modifier = GHOST_kModifierKeyLeftAlt;
+ break;
}
- break;
case GHOST_kKeyRightAlt:
{
changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown);
modifier = GHOST_kModifierKeyRightAlt;
+ break;
}
- break;
- default: break;
+ default:
+ break;
}
- if (changed)
- {
+ if (changed) {
modifiers.set(modifier, (bool)*keyDown);
system->storeModifierKeys(modifiers);
}
@@ -629,7 +652,10 @@ GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, short vKey, shor
return key;
}
-GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask)
+GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(
+ GHOST_TEventType type,
+ GHOST_IWindow *window,
+ GHOST_TButtonMask mask)
{
return new GHOST_EventButton(getSystem()->getMilliSeconds(), type, window, mask);
}
@@ -706,7 +732,7 @@ GHOST_EventWheel *GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WP
}
-GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw)
+GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINPUT const &raw)
{
int keyDown = 0;
char vk;
@@ -724,7 +750,7 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP
GetKeyboardState((PBYTE)state);
// don't call ToUnicodeEx on dead keys as it clears the buffer and so won't allow diacritical composition.
- if (MapVirtualKeyW(vk,2) != 0) {
+ if (MapVirtualKeyW(vk, 2) != 0) {
// todo: ToUnicodeEx can respond with up to 4 utf16 chars (only 2 here). Could be up to 24 utf8 bytes.
if ((r = ToUnicodeEx(vk, raw.data.keyboard.MakeCode, state, utf16, 2, 0, system->m_keylayout))) {
if ((r > 0 && r < 3)) {
@@ -764,17 +790,18 @@ GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_
if (type == GHOST_kEventWindowActivate) {
system->getWindowManager()->setActiveWindow(window);
- ((GHOST_WindowWin32*)window)->bringTabletContextToFront();
+ ((GHOST_WindowWin32 *)window)->bringTabletContextToFront();
}
return new GHOST_Event(system->getMilliSeconds(), type, window);
}
-GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType,
- GHOST_TDragnDropTypes draggedObjectType,
- GHOST_IWindow *window,
- int mouseX, int mouseY,
- void *data)
+GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(
+ GHOST_TEventType eventType,
+ GHOST_TDragnDropTypes draggedObjectType,
+ GHOST_IWindow *window,
+ int mouseX, int mouseY,
+ void *data)
{
GHOST_SystemWin32 *system = ((GHOST_SystemWin32 *)getSystem());
return system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
@@ -791,7 +818,7 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax)
}
#ifdef WITH_INPUT_NDOF
-bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw)
+bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
{
bool eventSent = false;
GHOST_TUns64 now = getMilliSeconds();
@@ -837,8 +864,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw)
#endif
BYTE packetType = data[0];
- switch (packetType)
- {
+ switch (packetType) {
case 1: // translation
{
const short *axis = (short *)(data + 1);
@@ -846,8 +872,8 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw)
const short t[3] = {axis[0], -axis[2], axis[1]};
m_ndofManager->updateTranslation(t, now);
- if (raw.data.hid.dwSizeHid == 13)
- { // this report also includes rotation
+ if (raw.data.hid.dwSizeHid == 13) {
+ // this report also includes rotation
const short r[3] = {-axis[3], axis[5], -axis[4]};
m_ndofManager->updateRotation(r, now);
@@ -909,8 +935,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER));
- switch (raw.header.dwType)
- {
+ switch (raw.header.dwType) {
case RIM_TYPEKEYBOARD:
event = processKeyEvent(window, raw);
if (!event) {
@@ -970,8 +995,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* maximize, minimize or close the window are triggered. Also it is sent when ALT
* button is press for menu. To prevent this we must return preventing DefWindowProc.
*/
- if (wParam == SC_KEYMENU)
- {
+ if (wParam == SC_KEYMENU) {
eventHandled = true;
}
break;
@@ -1034,6 +1058,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
event = processCursorEvent(GHOST_kEventCursorMove, window);
break;
case WM_MOUSEWHEEL:
+ {
/* The WM_MOUSEWHEEL message is sent to the focus window
* when the mouse wheel is rotated. The DefWindowProc
* function propagates the message to the window's parent.
@@ -1041,8 +1066,28 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* since DefWindowProc propagates it up the parent chain
* until it finds a window that processes it.
*/
- event = processWheelEvent(window, wParam, lParam);
+
+ /* Get the winow under the mouse and send event to it's queue. */
+ POINT mouse_pos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
+ HWND mouse_hwnd = WindowFromPoint(mouse_pos);
+ GHOST_WindowWin32 *mouse_window = (GHOST_WindowWin32 *)::GetWindowLongPtr(mouse_hwnd, GWLP_USERDATA);
+ if (mouse_window != NULL) {
+ event = processWheelEvent(mouse_window, wParam, lParam);
+ }
+ else {
+ /* If it happened so window under the mouse is not found (which i'm not
+ * really sure might happen), then we add event to the focused window
+ * in order to avoid some possible negative side effects.
+ * - sergey -
+ */
+ event = processWheelEvent(window, wParam, lParam);
+ }
+
+#ifdef BROKEN_PEEK_TOUCHPAD
+ PostMessage(hwnd, WM_USER, 0, 0);
+#endif
break;
+ }
case WM_SETCURSOR:
/* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor
* to move within a window and mouse input is not captured.
@@ -1099,7 +1144,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
/* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
* will not be dispatched to OUR active window if we minimize one of OUR windows. */
- if (LOWORD(wParam)==WA_INACTIVE)
+ if (LOWORD(wParam) == WA_INACTIVE)
window->lostMouseCapture();
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
@@ -1222,8 +1267,8 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
case WM_KILLFOCUS:
/* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus.
* We want to prevent this if a window is still active and it loses focus to nowhere*/
- if (!wParam && hwnd == GetActiveWindow())
- SetFocus(hwnd);
+ if (!wParam && hwnd == ::GetActiveWindow())
+ ::SetFocus(hwnd);
case WM_SHOWWINDOW:
/* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */
case WM_WINDOWPOSCHANGING:
@@ -1373,16 +1418,63 @@ void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const
}
}
+static DWORD GetParentProcessID(void)
+{
+ HANDLE snapshot;
+ PROCESSENTRY32 pe32 = {0};
+ DWORD ppid = 0, pid = GetCurrentProcessId();
+ snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
+ if (snapshot == INVALID_HANDLE_VALUE) {
+ return -1;
+ }
+ pe32.dwSize = sizeof( pe32 );
+ if (!Process32First(snapshot, &pe32)) {
+ CloseHandle(snapshot);
+ return -1;
+ }
+ do {
+ if (pe32.th32ProcessID == pid) {
+ ppid = pe32.th32ParentProcessID;
+ break;
+ }
+ } while (Process32Next(snapshot, &pe32));
+ CloseHandle(snapshot);
+ return ppid;
+}
+
+static bool getProcessName(int pid, char *buffer, int max_len)
+{
+ bool result = false;
+ HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+ FALSE, pid);
+ if (handle) {
+ GetModuleFileNameEx(handle, 0, buffer, max_len);
+ result = true;
+ }
+ CloseHandle(handle);
+ return result;
+}
+
static bool isStartedFromCommandPrompt()
{
HWND hwnd = GetConsoleWindow();
if (hwnd) {
DWORD pid = (DWORD)-1;
+ DWORD ppid = GetParentProcessID();
+ char parent_name[MAX_PATH];
+ bool start_from_launcher = false;
GetWindowThreadProcessId(hwnd, &pid);
+ if (getProcessName(ppid, parent_name, sizeof(parent_name))) {
+ char *filename = strrchr(parent_name, '\\');
+ if (filename != NULL) {
+ start_from_launcher = strstr(filename, "blender.exe") != NULL;
+ }
+ }
- if (pid == GetCurrentProcessId())
+ /* When we're starting from a wrapper we need to compare with parent process ID. */
+ if (pid == (start_from_launcher ? ppid : GetCurrentProcessId()))
return true;
}
@@ -1413,8 +1505,7 @@ int GHOST_SystemWin32::toggleConsole(int action)
ShowWindow(GetConsoleWindow(), m_consoleStatus ? SW_HIDE : SW_SHOW);
m_consoleStatus = !m_consoleStatus;
break;
-
- };
+ }
return m_consoleStatus;
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 18aadfbdca6..79fed06c6a5 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -215,7 +215,7 @@ public:
protected:
/**
* Initializes the system.
- * For now, it justs registers the window class (WNDCLASS).
+ * For now, it just registers the window class (WNDCLASS).
* \return A success value.
*/
virtual GHOST_TSuccess init();
@@ -231,7 +231,7 @@ protected:
* \param window-> The window for this handling
* \param vKey The virtual key from hardKey
* \param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1)
- * \param extend Flag if key is not primerly (left or right)
+ * \param extend Flag if key is not primly (left or right)
* \return The GHOST key (GHOST_kKeyUnknown if no match).
*/
virtual GHOST_TKey convertKey(GHOST_IWindow *window, short vKey, short ScanCode, short extend) const;
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 9b6d48c5993..75a9223d6a3 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -86,9 +86,9 @@ using namespace std;
GHOST_SystemX11::
GHOST_SystemX11(
- ) :
- GHOST_System(),
- m_start_time(0)
+ )
+ : GHOST_System(),
+ m_start_time(0)
{
m_display = XOpenDisplay(NULL);
@@ -141,6 +141,8 @@ GHOST_SystemX11(
#undef GHOST_INTERN_ATOM
m_last_warp = 0;
+ m_last_release_keycode = 0;
+ m_last_release_time = 0;
/* compute the initial time */
timeval tv;
@@ -244,7 +246,7 @@ getMainDisplayDimensions(
{
if (m_display) {
/* note, for this to work as documented,
- * we would need to use Xinerama check r54370 for code that did thia,
+ * we would need to use Xinerama check r54370 for code that did this,
* we've since removed since its not worth the extra dep - campbell */
getAllDisplayDimensions(width, height);
}
@@ -526,6 +528,16 @@ processEvents(
continue;
}
#endif
+ /* when using autorepeat, some keypress events can actually come *after* the
+ * last keyrelease. The next code takes care of that */
+ if (xevent.type == KeyRelease) {
+ m_last_release_keycode = xevent.xkey.keycode;
+ m_last_release_time = xevent.xkey.time;
+ }
+ else if (xevent.type == KeyPress) {
+ if ((xevent.xkey.keycode == m_last_release_keycode) && ((xevent.xkey.time <= m_last_release_time)))
+ continue;
+ }
processEvent(&xevent);
anyProcessed = true;
@@ -659,7 +671,7 @@ GHOST_SystemX11::processEvent(XEvent *xe)
#ifdef WITH_X11_XINPUT
/* Proximity-Out Events are not reliable, if the tablet is active - check on each event
* this adds a little overhead but only while the tablet is in use.
- * in the futire we could have a ghost call window->CheckTabletProximity()
+ * in the future we could have a ghost call window->CheckTabletProximity()
* but for now enough parts of the code are checking 'Active'
* - campbell */
if (window->GetTabletData()->Active != GHOST_kTabletModeNone) {
@@ -1240,7 +1252,7 @@ getModifierKeys(
XQueryKeymap(m_display, (char *)m_keyboard_vector);
- /* now translate key symobols into keycodes and
+ /* now translate key symbols into keycodes and
* test with vector. */
const static KeyCode shift_l = XKeysymToKeycode(m_display, XK_Shift_L);
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index 1a055725aac..be149cbb773 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -355,6 +355,10 @@ private:
* and stop accumulating all events generated before that */
Time m_last_warp;
+ /* detect autorepeat glitch */
+ unsigned int m_last_release_keycode;
+ Time m_last_release_time;
+
/**
* Return the ghost window associated with the
* X11 window xwind
diff --git a/intern/ghost/intern/GHOST_TaskbarWin32.h b/intern/ghost/intern/GHOST_TaskbarWin32.h
index 4351b387e48..04196701fe9 100644
--- a/intern/ghost/intern/GHOST_TaskbarWin32.h
+++ b/intern/ghost/intern/GHOST_TaskbarWin32.h
@@ -21,8 +21,11 @@
// GHOST_WindowWin32
#ifndef __ITaskbarList_INTERFACE_DEFINED__
#define __ITaskbarList_INTERFACE_DEFINED__
-extern "C" {const GUID CLSID_TaskbarList = {0x56FDF344, 0xFD6D, 0x11D0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90} };
- const GUID IID_ITaskbarList = {0x56FDF342, 0xFD6D, 0x11D0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90} }; }
+extern "C" {
+ const GUID CLSID_TaskbarList = {0x56FDF344, 0xFD6D, 0x11D0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90}};
+ const GUID IID_ITaskbarList = {0x56FDF342, 0xFD6D, 0x11D0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90}};
+}
+
class ITaskbarList : public IUnknown
{
public:
@@ -36,7 +39,9 @@ public:
#ifndef __ITaskbarList2_INTERFACE_DEFINED__
#define __ITaskbarList2_INTERFACE_DEFINED__
-extern "C" {const GUID IID_ITaskbarList2 = {0x602D4995, 0xB13A, 0x429b, {0xA6, 0x6E, 0x19, 0x35, 0xE4, 0x4F, 0x43, 0x17} }; }
+extern "C" {
+ const GUID IID_ITaskbarList2 = {0x602D4995, 0xB13A, 0x429b, {0xA6, 0x6E, 0x19, 0x35, 0xE4, 0x4F, 0x43, 0x17}};
+}
class ITaskbarList2 : public ITaskbarList
{
public:
@@ -46,12 +51,46 @@ public:
#ifndef __ITaskbarList3_INTERFACE_DEFINED__
#define __ITaskbarList3_INTERFACE_DEFINED__
-typedef enum THUMBBUTTONFLAGS {THBF_ENABLED = 0, THBF_DISABLED = 0x1, THBF_DISMISSONCLICK = 0x2, THBF_NOBACKGROUND = 0x4, THBF_HIDDEN = 0x8, THBF_NONINTERACTIVE = 0x10} THUMBBUTTONFLAGS;
-typedef enum THUMBBUTTONMASK {THB_BITMAP = 0x1, THB_ICON = 0x2, THB_TOOLTIP = 0x4, THB_FLAGS = 0x8} THUMBBUTTONMASK;
-typedef struct THUMBBUTTON {THUMBBUTTONMASK dwMask; UINT iId; UINT iBitmap; HICON hIcon; WCHAR szTip[260]; THUMBBUTTONFLAGS dwFlags; } THUMBBUTTON;
-typedef enum TBPFLAG {TBPF_NOPROGRESS = 0, TBPF_INDETERMINATE = 0x1, TBPF_NORMAL = 0x2, TBPF_ERROR = 0x4, TBPF_PAUSED = 0x8 } TBPFLAG;
+typedef enum THUMBBUTTONFLAGS {
+ THBF_ENABLED = 0,
+ THBF_DISABLED = 0x1,
+ THBF_DISMISSONCLICK = 0x2,
+ THBF_NOBACKGROUND = 0x4,
+ THBF_HIDDEN = 0x8,
+ THBF_NONINTERACTIVE = 0x10,
+}
+THUMBBUTTONFLAGS;
+
+typedef enum THUMBBUTTONMASK {
+ THB_BITMAP = 0x1,
+ THB_ICON = 0x2,
+ THB_TOOLTIP = 0x4,
+ THB_FLAGS = 0x8,
+}
+THUMBBUTTONMASK;
+
+typedef struct THUMBBUTTON {
+ THUMBBUTTONMASK dwMask;
+ UINT iId;
+ UINT iBitmap;
+ HICON hIcon;
+ WCHAR szTip[260];
+ THUMBBUTTONFLAGS dwFlags;
+} THUMBBUTTON;
+
+typedef enum TBPFLAG {
+ TBPF_NOPROGRESS = 0,
+ TBPF_INDETERMINATE = 0x1,
+ TBPF_NORMAL = 0x2,
+ TBPF_ERROR = 0x4,
+ TBPF_PAUSED = 0x8,
+} TBPFLAG;
+
#define THBN_CLICKED 0x1800
-extern "C" {const GUID IID_ITaskList3 = { 0xEA1AFB91, 0x9E28, 0x4B86, {0x90, 0xE9, 0x9E, 0x9F, 0x8A, 0x5E, 0xEF, 0xAF} }; }
+
+extern "C" {
+ const GUID IID_ITaskList3 = {0xEA1AFB91, 0x9E28, 0x4B86, {0x90, 0xE9, 0x9E, 0x9F, 0x8A, 0x5E, 0xEF, 0xAF}};
+}
class ITaskbarList3 : public ITaskbarList2
{
diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h
index 5a24c56ef10..b94175e9ff8 100644
--- a/intern/ghost/intern/GHOST_TimerManager.h
+++ b/intern/ghost/intern/GHOST_TimerManager.h
@@ -67,7 +67,7 @@ public:
virtual GHOST_TUns32 getNumTimers();
/**
- * Returns whther this timer task ins in our list.
+ * Returns whether this timer task ins in our list.
* \return Indication of presence.
*/
virtual bool getTimerFound(GHOST_TimerTask *timer);
diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h
index e8f5ecd9fbb..e33788ec826 100644
--- a/intern/ghost/intern/GHOST_TimerTask.h
+++ b/intern/ghost/intern/GHOST_TimerTask.h
@@ -48,7 +48,7 @@ public:
* Constructor.
* \param start The timer start time.
* \param interval The interval between calls to the timerProc
- * \param timerProc The callbak invoked when the interval expires.
+ * \param timerProc The callback invoked when the interval expires.
* \param data The timer user data.
*/
GHOST_TimerTask(GHOST_TUns64 start,
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h
index a11e78d0085..ce35110dcdf 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -129,7 +129,7 @@ public:
/**
* Returns the client rectangle dimensions.
* The left and top members of the rectangle are always zero.
- * \param bounds The bounding rectangle of the cleient area of the window.
+ * \param bounds The bounding rectangle of the client area of the window.
*/
virtual void getClientBounds(GHOST_Rect& bounds) const;
diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h
index ecf0cb30860..8297e4d24d2 100644
--- a/intern/ghost/intern/GHOST_WindowManager.h
+++ b/intern/ghost/intern/GHOST_WindowManager.h
@@ -87,7 +87,7 @@ public:
/**
* Returns pointer to the full-screen window.
- * \return The fll-screen window (0 if not in full-screen).
+ * \return The full-screen window (NULL if not in full-screen).
*/
virtual GHOST_IWindow *getFullScreenWindow(void) const;
@@ -121,7 +121,7 @@ public:
/**
* Set this window to be inactive (not receiving events).
- * \param window The window to decativate.
+ * \param window The window to deactivate.
*/
virtual void setWindowInactive(const GHOST_IWindow *window);
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 8e52fe8e133..11ddc478d6c 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -55,6 +55,51 @@
const wchar_t *GHOST_WindowWin32::s_windowClassName = L"GHOST_WindowClass";
const int GHOST_WindowWin32::s_maxTitleLength = 128;
+<<<<<<< HEAD
+=======
+static int WeightPixelFormat(PIXELFORMATDESCRIPTOR &pfd);
+static int EnumPixelFormats(HDC hdc);
+
+/*
+ * Color and depth bit values are not to be trusted.
+ * For instance, on TNT2:
+ * When the screen color depth is set to 16 bit, we get 5 color bits
+ * and 16 depth bits.
+ * When the screen color depth is set to 32 bit, we get 8 color bits
+ * and 24 depth bits.
+ * Just to be safe, we request high quality settings.
+ */
+static PIXELFORMATDESCRIPTOR sPreferredFormat = {
+ sizeof(PIXELFORMATDESCRIPTOR), /* size */
+ 1, /* version */
+ PFD_SUPPORT_OPENGL |
+ PFD_DRAW_TO_WINDOW |
+ PFD_SWAP_COPY | /* support swap copy */
+ PFD_DOUBLEBUFFER, /* support double-buffering */
+ PFD_TYPE_RGBA, /* color type */
+ 32, /* prefered color depth */
+ 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
+ 0, /* no alpha buffer */
+ 0, /* alpha bits (ignored) */
+ 0, /* no accumulation buffer */
+ 0, 0, 0, 0, /* accum bits (ignored) */
+ 32, /* depth buffer */
+ 0, /* no stencil buffer */
+ 0, /* no auxiliary buffers */
+ PFD_MAIN_PLANE, /* main layer */
+ 0, /* reserved */
+ 0, 0, 0 /* no layer, visible, damage masks */
+};
+
+/* Intel videocards don't work fine with multiple contexts and
+ * have to share the same context for all windows.
+ * But if we just share context for all windows it could work incorrect
+ * with multiple videocards configuration. Suppose, that Intel videocards
+ * can't be in multiple-devices configuration. */
+static int is_crappy_intel_card(void)
+{
+ static short is_crappy = -1;
+>>>>>>> master
@@ -64,6 +109,7 @@ extern "C" {
}
GHOST_WindowWin32::GHOST_WindowWin32(
+<<<<<<< HEAD
GHOST_SystemWin32 *system,
const STR_String& title,
GHOST_TInt32 left,
@@ -90,6 +136,48 @@ GHOST_WindowWin32::GHOST_WindowWin32(
m_maxPressure(0),
m_normal_state(GHOST_kWindowStateNormal),
m_parentWindowHwnd(parentwindowhwnd)
+=======
+ GHOST_SystemWin32 *system,
+ const STR_String &title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ const bool stereoVisual,
+ const GHOST_TUns16 numOfAASamples,
+ GHOST_TEmbedderWindowID parentwindowhwnd,
+ GHOST_TSuccess msEnabled,
+ int msPixelFormat)
+ : GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone,
+ stereoVisual, false, numOfAASamples),
+ m_inLiveResize(false),
+ m_system(system),
+ m_hDC(0),
+ m_hGlRc(0),
+ m_hasMouseCaptured(false),
+ m_hasGrabMouse(false),
+ m_nPressedButtons(0),
+ m_customCursor(0),
+ m_wintab(NULL),
+ m_tabletData(NULL),
+ m_tablet(0),
+ m_maxPressure(0),
+ m_multisample(numOfAASamples),
+ m_multisampleEnabled(msEnabled),
+ m_msPixelFormat(msPixelFormat),
+ //For recreation
+ m_title(title),
+ m_left(left),
+ m_top(top),
+ m_width(width),
+ m_height(height),
+ m_normal_state(GHOST_kWindowStateNormal),
+ m_stereo(stereoVisual),
+ m_nextWindow(NULL),
+ m_parentWindowHwnd(parentwindowhwnd)
+>>>>>>> master
{
OSVERSIONINFOEX versionInfo;
bool hasMinVersionForTaskbar = false;
@@ -101,13 +189,17 @@ GHOST_WindowWin32::GHOST_WindowWin32(
if (!GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
- if ((versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1) || versionInfo.dwMajorVersion >= 7) {
+ if ((versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1) ||
+ (versionInfo.dwMajorVersion >= 7))
+ {
hasMinVersionForTaskbar = true;
}
}
}
else {
- if ((versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1) || versionInfo.dwMajorVersion >= 7) {
+ if ((versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1) ||
+ (versionInfo.dwMajorVersion >= 7))
+ {
hasMinVersionForTaskbar = true;
}
}
@@ -117,7 +209,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(
MONITORINFO monitor;
GHOST_TUns32 tw, th;
-#if !defined(_MSC_VER) || _MSC_VER < 1700
+#ifndef _MSC_VER
int cxsizeframe = GetSystemMetrics(SM_CXSIZEFRAME);
int cysizeframe = GetSystemMetrics(SM_CYSIZEFRAME);
#else
@@ -147,8 +239,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(
th = monitor.rcWork.bottom - monitor.rcWork.top;
tw = monitor.rcWork.right - monitor.rcWork.left;
- if (tw < width)
- {
+ if (tw < width) {
width = tw;
left = monitor.rcWork.left;
}
@@ -157,8 +248,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(
else if (left < monitor.rcWork.left)
left = monitor.rcWork.left;
- if (th < height)
- {
+ if (th < height) {
height = th;
top = monitor.rcWork.top;
}
@@ -168,8 +258,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(
top = monitor.rcWork.top;
int wintype = WS_OVERLAPPEDWINDOW;
- if (m_parentWindowHwnd != 0)
- {
+ if (m_parentWindowHwnd != 0) {
wintype = WS_CHILD;
GetWindowRect((HWND)m_parentWindowHwnd, &rect);
left = 0;
@@ -242,6 +331,10 @@ GHOST_WindowWin32::GHOST_WindowWin32(
break;
}
+<<<<<<< HEAD
+=======
+ if (success) {
+>>>>>>> master
::ShowWindow(m_hWnd, nCmdShow);
// Force an initial paint of the window
@@ -273,7 +366,8 @@ GHOST_WindowWin32::GHOST_WindowWin32(
if (fpWTInfo && fpWTInfo(0, 0, NULL)) {
// Now init the tablet
LOGCONTEXT lc;
- AXIS TabletX, TabletY, Pressure, Orientation[3]; /* The maximum tablet size, pressure and orientation (tilt) */
+ /* The maximum tablet size, pressure and orientation (tilt) */
+ AXIS TabletX, TabletY, Pressure, Orientation[3];
// Open a Wintab context
@@ -350,8 +444,20 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
m_customCursor = NULL;
}
+<<<<<<< HEAD
if (m_hWnd != NULL && m_hDC != NULL && releaseNativeHandles())
::ReleaseDC(m_hWnd, m_hDC);
+=======
+ ::wglMakeCurrent(NULL, NULL);
+ m_multisampleEnabled = GHOST_kFailure;
+ m_multisample = 0;
+ setDrawingContextType(GHOST_kDrawingContextTypeNone);
+
+ if (m_hDC && m_hDC != s_firstHDC) {
+ ::ReleaseDC(m_hWnd, m_hDC);
+ m_hDC = 0;
+ }
+>>>>>>> master
if (m_hWnd) {
if (m_dropTarget) {
@@ -376,7 +482,7 @@ HWND GHOST_WindowWin32::getHWND() const
return m_hWnd;
}
-void GHOST_WindowWin32::setTitle(const STR_String& title)
+void GHOST_WindowWin32::setTitle(const STR_String &title)
{
wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
::SetWindowTextW(m_hWnd, (wchar_t *)title_16);
@@ -384,7 +490,7 @@ void GHOST_WindowWin32::setTitle(const STR_String& title)
}
-void GHOST_WindowWin32::getTitle(STR_String& title) const
+void GHOST_WindowWin32::getTitle(STR_String &title) const
{
char buf[s_maxTitleLength]; /*CHANGE + never used yet*/
::GetWindowText(m_hWnd, buf, s_maxTitleLength);
@@ -393,7 +499,7 @@ void GHOST_WindowWin32::getTitle(STR_String& title) const
}
-void GHOST_WindowWin32::getWindowBounds(GHOST_Rect& bounds) const
+void GHOST_WindowWin32::getWindowBounds(GHOST_Rect &bounds) const
{
RECT rect;
::GetWindowRect(m_hWnd, &rect);
@@ -404,7 +510,7 @@ void GHOST_WindowWin32::getWindowBounds(GHOST_Rect& bounds) const
}
-void GHOST_WindowWin32::getClientBounds(GHOST_Rect& bounds) const
+void GHOST_WindowWin32::getClientBounds(GHOST_Rect &bounds) const
{
RECT rect;
POINT coord;
@@ -495,6 +601,7 @@ GHOST_TWindowState GHOST_WindowWin32::getState() const
state = GHOST_kWindowStateEmbedded;
return state;
}
+
if (::IsIconic(m_hWnd)) {
state = GHOST_kWindowStateMinimized;
}
@@ -512,18 +619,22 @@ GHOST_TWindowState GHOST_WindowWin32::getState() const
}
-void GHOST_WindowWin32::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
+void GHOST_WindowWin32::screenToClient(
+ GHOST_TInt32 inX, GHOST_TInt32 inY,
+ GHOST_TInt32 &outX, GHOST_TInt32 &outY) const
{
- POINT point = { inX, inY };
+ POINT point = {inX, inY};
::ScreenToClient(m_hWnd, &point);
outX = point.x;
outY = point.y;
}
-void GHOST_WindowWin32::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
+void GHOST_WindowWin32::clientToScreen(
+ GHOST_TInt32 inX, GHOST_TInt32 inY,
+ GHOST_TInt32 &outX, GHOST_TInt32 &outY) const
{
- POINT point = { inX, inY };
+ POINT point = {inX, inY};
::ClientToScreen(m_hWnd, &point);
outX = point.x;
outY = point.y;
@@ -539,13 +650,14 @@ GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
if (state == GHOST_kWindowStateNormal)
state = m_normal_state;
+
switch (state) {
case GHOST_kWindowStateMinimized:
wp.showCmd = SW_SHOWMINIMIZED;
break;
case GHOST_kWindowStateMaximized:
wp.showCmd = SW_SHOWMAXIMIZED;
- SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
+ ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
break;
case GHOST_kWindowStateFullScreen:
if (curstate != state && curstate != GHOST_kWindowStateMinimized)
@@ -553,18 +665,20 @@ GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
wp.showCmd = SW_SHOWMAXIMIZED;
wp.ptMaxPosition.x = 0;
wp.ptMaxPosition.y = 0;
- SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_POPUP | WS_MAXIMIZE);
+ ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_POPUP | WS_MAXIMIZE);
break;
case GHOST_kWindowStateEmbedded:
- SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_CHILD);
+ ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_CHILD);
break;
case GHOST_kWindowStateNormal:
default:
wp.showCmd = SW_SHOWNORMAL;
- SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
+ ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
break;
}
- SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); /*Clears window cache for SetWindowLongPtr */
+ /* Clears window cache for SetWindowLongPtr */
+ ::SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+
return ::SetWindowPlacement(m_hWnd, &wp) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
}
@@ -581,9 +695,11 @@ GHOST_TSuccess GHOST_WindowWin32::setOrder(GHOST_TWindowOrder order)
hWndInsertAfter = HWND_TOP;
hWndToRaise = NULL;
}
+
if (::SetWindowPos(m_hWnd, hWndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) == FALSE) {
return GHOST_kFailure;
}
+
if (hWndToRaise && ::SetWindowPos(hWndToRaise, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) == FALSE) {
return GHOST_kFailure;
}
@@ -683,6 +799,7 @@ GHOST_Context* GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
#error
#endif
+<<<<<<< HEAD
#else
#error
#endif
@@ -690,6 +807,11 @@ GHOST_Context* GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
return context;
else
delete context;
+=======
+ if (!wglChoosePixelFormatARB) {
+ m_multisampleEnabled = GHOST_kFailure;
+ return GHOST_kFailure;
+>>>>>>> master
}
return NULL;
@@ -700,8 +822,13 @@ GHOST_Context* GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
void GHOST_WindowWin32::lostMouseCapture()
{
if (m_hasMouseCaptured) {
+<<<<<<< HEAD
m_hasGrabMouse = false;
m_nPressedButtons = 0;
+=======
+ m_hasGrabMouse = false;
+ m_nPressedButtons = 0;
+>>>>>>> master
m_hasMouseCaptured = false;
}
}
@@ -709,21 +836,18 @@ void GHOST_WindowWin32::lostMouseCapture()
void GHOST_WindowWin32::registerMouseClickEvent(int press)
{
- switch (press)
- {
+ switch (press) {
case 0: m_nPressedButtons++; break;
case 1: if (m_nPressedButtons) m_nPressedButtons--; break;
case 2: m_hasGrabMouse = true; break;
case 3: m_hasGrabMouse = false; break;
}
- if (!m_nPressedButtons && !m_hasGrabMouse && m_hasMouseCaptured)
- {
+ if (!m_nPressedButtons && !m_hasGrabMouse && m_hasMouseCaptured) {
::ReleaseCapture();
m_hasMouseCaptured = false;
}
- else if ((m_nPressedButtons || m_hasGrabMouse) && !m_hasMouseCaptured)
- {
+ else if ((m_nPressedButtons || m_hasGrabMouse) && !m_hasMouseCaptured) {
::SetCapture(m_hWnd);
m_hasMouseCaptured = true;
@@ -975,17 +1099,19 @@ static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt)
return shrt;
}
#endif
-GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
- GHOST_TUns8 mask[16][2],
- int hotX, int hotY)
+GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(
+ GHOST_TUns8 bitmap[16][2],
+ GHOST_TUns8 mask[16][2],
+ int hotX, int hotY)
{
return setWindowCustomCursorShape((GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask,
16, 16, hotX, hotY, 0, 1);
}
-GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask, int sizeX, int sizeY, int hotX, int hotY,
- int fg_color, int bg_color)
+GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(
+ GHOST_TUns8 *bitmap,
+ GHOST_TUns8 *mask, int sizeX, int sizeY, int hotX, int hotY,
+ int fg_color, int bg_color)
{
GHOST_TUns32 andData[32];
GHOST_TUns32 xorData[32];
@@ -1046,3 +1172,96 @@ GHOST_TSuccess GHOST_WindowWin32::endProgressBar()
return GHOST_kFailure;
}
+<<<<<<< HEAD
+=======
+/* Ron Fosner's code for weighting pixel formats and forcing software.
+ * See http://www.opengl.org/resources/faq/technical/weight.cpp */
+
+static int WeightPixelFormat(PIXELFORMATDESCRIPTOR &pfd)
+{
+ int weight = 0;
+
+ /* assume desktop color depth is 32 bits per pixel */
+
+ /* cull unusable pixel formats */
+ /* if no formats can be found, can we determine why it was rejected? */
+ if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL) ||
+ !(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
+ !(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this */
+ (pfd.cDepthBits <= 8) ||
+ !(pfd.iPixelType == PFD_TYPE_RGBA))
+ {
+ return 0;
+ }
+
+ weight = 1; /* it's usable */
+
+ /* the bigger the depth buffer the better */
+ /* give no weight to a 16-bit depth buffer, because those are crap */
+ weight += pfd.cDepthBits - 16;
+
+ weight += pfd.cColorBits - 8;
+
+#ifdef GHOST_OPENGL_ALPHA
+ if (pfd.cAlphaBits > 0)
+ weight ++;
+#endif
+
+ /* want swap copy capability -- it matters a lot */
+ if (pfd.dwFlags & PFD_SWAP_COPY) weight += 16;
+
+ /* but if it's a generic (not accelerated) view, it's really bad */
+ if (pfd.dwFlags & PFD_GENERIC_FORMAT) weight /= 10;
+
+ return weight;
+}
+
+/* A modification of Ron Fosner's replacement for ChoosePixelFormat */
+/* returns 0 on error, else returns the pixel format number to be used */
+static int EnumPixelFormats(HDC hdc)
+{
+ int iPixelFormat;
+ int i, n, w, weight = 0;
+ PIXELFORMATDESCRIPTOR pfd;
+
+ /* we need a device context to do anything */
+ if (!hdc) return 0;
+
+ iPixelFormat = 1; /* careful! PFD numbers are 1 based, not zero based */
+
+ /* obtain detailed information about
+ * the device context's first pixel format */
+ n = 1 + ::DescribePixelFormat(hdc, iPixelFormat,
+ sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+
+ /* choose a pixel format using the useless Windows function in case
+ * we come up empty handed */
+ iPixelFormat = ::ChoosePixelFormat(hdc, &sPreferredFormat);
+
+ if (!iPixelFormat) return 0; /* couldn't find one to use */
+
+ for (i = 1; i <= n; i++) { /* not the idiom, but it's right */
+ ::DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+ w = WeightPixelFormat(pfd);
+ // be strict on stereo
+ if (!((sPreferredFormat.dwFlags ^ pfd.dwFlags) & PFD_STEREO)) {
+ if (w > weight) {
+ weight = w;
+ iPixelFormat = i;
+ }
+ }
+ }
+ if (weight == 0) {
+ // we could find the correct stereo setting, just find any suitable format
+ for (i = 1; i <= n; i++) { /* not the idiom, but it's right */
+ ::DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+ w = WeightPixelFormat(pfd);
+ if (w > weight) {
+ weight = w;
+ iPixelFormat = i;
+ }
+ }
+ }
+ return iPixelFormat;
+}
+>>>>>>> master
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index 12dca5f3fee..b5e8157dd62 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -138,7 +138,7 @@ public:
/**
* Returns the client rectangle dimensions.
* The left and top members of the rectangle are always zero.
- * \param bounds The bounding rectangle of the cleient area of the window.
+ * \param bounds The bounding rectangle of the client area of the window.
*/
virtual void getClientBounds(GHOST_Rect& bounds) const;
@@ -318,7 +318,7 @@ private:
/** Flag for if window has captured the mouse */
bool m_hasMouseCaptured;
/** Flag if an operator grabs the mouse with WM_cursor_grab_enable/ungrab()
- * Multiple grabs must be realesed with a single ungrab*/
+ * Multiple grabs must be released with a single ungrab */
bool m_hasGrabMouse;
/** Count of number of pressed buttons */
int m_nPressedButtons;
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index ade76f2a12a..821cc1076fe 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -61,7 +61,7 @@
#include <algorithm>
#include <string>
-/* For obscure full screen mode stuuf
+/* For obscure full screen mode stuff
* lifted verbatim from blut. */
typedef struct {
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index 8d7cf3a4d44..92d2b8e17d3 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -246,7 +246,7 @@ protected:
/**
* Sets the cursor grab on the window using
* native window system calls.
- * \param warp Only used when grab is enabled, hides the mouse and allows gragging outside the screen.
+ * \param warp Only used when grab is enabled, hides the mouse and allows dragging outside the screen.
*/
GHOST_TSuccess
setWindowCursorGrab(
diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp
index 78e5257be1f..a81aaa85ecf 100644
--- a/intern/ghost/test/gears/GHOST_Test.cpp
+++ b/intern/ghost/test/gears/GHOST_Test.cpp
@@ -262,7 +262,8 @@ static void View(GHOST_IWindow *window, bool stereo, int eye = 0)
window->activateDrawingContext();
GHOST_Rect bnds;
int noOfScanlines = 0, lowerScanline = 0;
- int verticalBlankingInterval = 32; // hard coded for testing purposes, display device dependant
+ /* hard coded for testing purposes, display device dependent */
+ int verticalBlankingInterval = 32;
float left, right, bottom, top;
float nearplane, farplane, zeroPlane, distance;
float eyeSeparation = 0.62f;
diff --git a/intern/glew-mx/glew-mx.h b/intern/glew-mx/glew-mx.h
index ea3dd3f2da7..49ba0bb0e47 100644
--- a/intern/glew-mx/glew-mx.h
+++ b/intern/glew-mx/glew-mx.h
@@ -48,7 +48,7 @@ extern "C" {
extern GLEWContext* _glewContext;
void glewSetContext(GLEWContext* ctx);
-GLEWContext* glewCreateContext();
+GLEWContext* glewCreateContext(void);
void glewDestroyContext(GLEWContext* ctx);
#ifdef __cplusplus
diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h
index 176fdd8d188..f1ff6f432e8 100644
--- a/intern/guardedalloc/MEM_guardedalloc.h
+++ b/intern/guardedalloc/MEM_guardedalloc.h
@@ -84,7 +84,7 @@ extern "C" {
extern size_t (*MEM_allocN_len)(const void *vmemh) ATTR_WARN_UNUSED_RESULT;
/**
- * Release memory previously allocatred by this module.
+ * Release memory previously allocated by this module.
*/
extern void (*MEM_freeN)(void *vmemh);
diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.c b/intern/guardedalloc/intern/mallocn_guarded_impl.c
index 6e32844e2e7..10781a9cc54 100644
--- a/intern/guardedalloc/intern/mallocn_guarded_impl.c
+++ b/intern/guardedalloc/intern/mallocn_guarded_impl.c
@@ -231,7 +231,7 @@ __attribute__ ((format(printf, 1, 2)))
#endif
static void print_error(const char *str, ...)
{
- char buf[512];
+ char buf[1024];
va_list ap;
va_start(ap, str);
@@ -239,7 +239,10 @@ static void print_error(const char *str, ...)
va_end(ap);
buf[sizeof(buf) - 1] = '\0';
- if (error_callback) error_callback(buf);
+ if (error_callback)
+ error_callback(buf);
+ else
+ fputs(buf, stderr);
}
static void mem_lock_thread(void)
@@ -794,11 +797,10 @@ static void MEM_guarded_printmemlist_internal(int pydict)
}
while (membl) {
if (pydict) {
- fprintf(stderr,
- " {'len':" SIZET_FORMAT ", "
- "'name':'''%s''', "
- "'pointer':'%p'},\n",
- SIZET_ARG(membl->len), membl->name, (void *)(membl + 1));
+ print_error(" {'len':" SIZET_FORMAT ", "
+ "'name':'''%s''', "
+ "'pointer':'%p'},\n",
+ SIZET_ARG(membl->len), membl->name, (void *)(membl + 1));
}
else {
#ifdef DEBUG_MEMCOUNTER
@@ -818,8 +820,8 @@ static void MEM_guarded_printmemlist_internal(int pydict)
else break;
}
if (pydict) {
- fprintf(stderr, "]\n\n");
- fprintf(stderr, mem_printmemlist_pydict_script);
+ print_error("]\n\n");
+ print_error(mem_printmemlist_pydict_script);
}
mem_unlock_thread();
diff --git a/intern/itasc/Armature.cpp b/intern/itasc/Armature.cpp
index 0c736566b25..13b471b036d 100644
--- a/intern/itasc/Armature.cpp
+++ b/intern/itasc/Armature.cpp
@@ -15,8 +15,10 @@
namespace iTaSC {
+#if 0
// a joint constraint is characterized by 5 values: tolerance, K, alpha, yd, yddot
static const unsigned int constraintCacheSize = 5;
+#endif
std::string Armature::m_root = "root";
Armature::Armature():
diff --git a/intern/moto/include/MT_Matrix3x3.h b/intern/moto/include/MT_Matrix3x3.h
index 6d709fae662..17dd5335217 100644
--- a/intern/moto/include/MT_Matrix3x3.h
+++ b/intern/moto/include/MT_Matrix3x3.h
@@ -84,11 +84,18 @@ public:
MT_Vector3 getColumn(int i) const {
return MT_Vector3(m_el[0][i], m_el[1][i], m_el[2][i]);
}
+
void setColumn(int i, const MT_Vector3& v) {
m_el[0][i] = v[0];
m_el[1][i] = v[1];
m_el[2][i] = v[2];
}
+
+ void setRow(int i, const MT_Vector3& v) {
+ m_el[i][0] = v[0];
+ m_el[i][1] = v[1];
+ m_el[i][2] = v[2];
+ }
void setValue(const float *m) {
m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m++;
diff --git a/intern/moto/include/MT_Vector3.h b/intern/moto/include/MT_Vector3.h
index 83c53a19d66..b06f345bdaf 100644
--- a/intern/moto/include/MT_Vector3.h
+++ b/intern/moto/include/MT_Vector3.h
@@ -75,7 +75,7 @@ public:
void normalize();
MT_Vector3 normalized() const;
MT_Vector3 safe_normalized() const;
-
+ MT_Vector3 safe_normalized_vec(MT_Vector3 vecnormalized) const;
void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z);
MT_Vector3 scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z) const;
diff --git a/intern/moto/include/MT_Vector3.inl b/intern/moto/include/MT_Vector3.inl
index b17ef47c709..09c92c6ab54 100644
--- a/intern/moto/include/MT_Vector3.inl
+++ b/intern/moto/include/MT_Vector3.inl
@@ -77,6 +77,13 @@ GEN_INLINE MT_Vector3 MT_Vector3::safe_normalized() const {
*this / len;
}
+GEN_INLINE MT_Vector3 MT_Vector3::safe_normalized_vec(MT_Vector3 vecnormalized) const {
+ MT_Scalar len = length();
+ return MT_fuzzyZero(len) ?
+ vecnormalized :
+ *this / len;
+}
+
GEN_INLINE void MT_Vector3::scale(MT_Scalar xx, MT_Scalar yy, MT_Scalar zz) {
m_co[0] *= xx; m_co[1] *= yy; m_co[2] *= zz;
}
diff --git a/intern/opencl/intern/clew.c b/intern/opencl/intern/clew.c
deleted file mode 100644
index 1e31ebced0a..00000000000
--- a/intern/opencl/intern/clew.c
+++ /dev/null
@@ -1,316 +0,0 @@
-//////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2009 Organic Vectory B.V.
-// Written by George van Venrooij
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file license.txt)
-//////////////////////////////////////////////////////////////////////////
-
-#include "clew.h"
-
-//! \file clew.c
-//! \brief OpenCL run-time loader source
-
-#ifndef CLCC_GENERATE_DOCUMENTATION
-#ifdef _WIN32
- #define WIN32_LEAN_AND_MEAN
- #define VC_EXTRALEAN
- #include <windows.h>
-
- typedef HMODULE CLCC_DYNLIB_HANDLE;
-
- #define CLCC_DYNLIB_OPEN LoadLibrary
- #define CLCC_DYNLIB_CLOSE FreeLibrary
- #define CLCC_DYNLIB_IMPORT GetProcAddress
-#else
- #include <dlfcn.h>
-
- typedef void* CLCC_DYNLIB_HANDLE;
-
- #define CLCC_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL)
- #define CLCC_DYNLIB_CLOSE dlclose
- #define CLCC_DYNLIB_IMPORT dlsym
-#endif
-#else
- //typedef implementation_defined CLCC_DYNLIB_HANDLE;
- //#define CLCC_DYNLIB_OPEN(path) implementation_defined
- //#define CLCC_DYNLIB_CLOSE implementation_defined
- //#define CLCC_DYNLIB_IMPORT implementation_defined
-#endif
-
-#include <stdlib.h>
-
-//! \brief module handle
-static CLCC_DYNLIB_HANDLE module = NULL;
-
-// Variables holding function entry points
-#ifndef CLCC_GENERATE_DOCUMENTATION
-PFNCLGETPLATFORMIDS __oclGetPlatformIDs = NULL;
-PFNCLGETPLATFORMINFO __oclGetPlatformInfo = NULL;
-PFNCLGETDEVICEIDS __oclGetDeviceIDs = NULL;
-PFNCLGETDEVICEINFO __oclGetDeviceInfo = NULL;
-PFNCLCREATECONTEXT __oclCreateContext = NULL;
-PFNCLCREATECONTEXTFROMTYPE __oclCreateContextFromType = NULL;
-PFNCLRETAINCONTEXT __oclRetainContext = NULL;
-PFNCLRELEASECONTEXT __oclReleaseContext = NULL;
-PFNCLGETCONTEXTINFO __oclGetContextInfo = NULL;
-PFNCLCREATECOMMANDQUEUE __oclCreateCommandQueue = NULL;
-PFNCLRETAINCOMMANDQUEUE __oclRetainCommandQueue = NULL;
-PFNCLRELEASECOMMANDQUEUE __oclReleaseCommandQueue = NULL;
-PFNCLGETCOMMANDQUEUEINFO __oclGetCommandQueueInfo = NULL;
-PFNCLSETCOMMANDQUEUEPROPERTY __oclSetCommandQueueProperty = NULL;
-PFNCLCREATEBUFFER __oclCreateBuffer = NULL;
-PFNCLCREATEIMAGE2D __oclCreateImage2D = NULL;
-PFNCLCREATEIMAGE3D __oclCreateImage3D = NULL;
-PFNCLRETAINMEMOBJECT __oclRetainMemObject = NULL;
-PFNCLRELEASEMEMOBJECT __oclReleaseMemObject = NULL;
-PFNCLGETSUPPORTEDIMAGEFORMATS __oclGetSupportedImageFormats = NULL;
-PFNCLGETMEMOBJECTINFO __oclGetMemObjectInfo = NULL;
-PFNCLGETIMAGEINFO __oclGetImageInfo = NULL;
-PFNCLCREATESAMPLER __oclCreateSampler = NULL;
-PFNCLRETAINSAMPLER __oclRetainSampler = NULL;
-PFNCLRELEASESAMPLER __oclReleaseSampler = NULL;
-PFNCLGETSAMPLERINFO __oclGetSamplerInfo = NULL;
-PFNCLCREATEPROGRAMWITHSOURCE __oclCreateProgramWithSource = NULL;
-PFNCLCREATEPROGRAMWITHBINARY __oclCreateProgramWithBinary = NULL;
-PFNCLRETAINPROGRAM __oclRetainProgram = NULL;
-PFNCLRELEASEPROGRAM __oclReleaseProgram = NULL;
-PFNCLBUILDPROGRAM __oclBuildProgram = NULL;
-PFNCLUNLOADCOMPILER __oclUnloadCompiler = NULL;
-PFNCLGETPROGRAMINFO __oclGetProgramInfo = NULL;
-PFNCLGETPROGRAMBUILDINFO __oclGetProgramBuildInfo = NULL;
-PFNCLCREATEKERNEL __oclCreateKernel = NULL;
-PFNCLCREATEKERNELSINPROGRAM __oclCreateKernelsInProgram = NULL;
-PFNCLRETAINKERNEL __oclRetainKernel = NULL;
-PFNCLRELEASEKERNEL __oclReleaseKernel = NULL;
-PFNCLSETKERNELARG __oclSetKernelArg = NULL;
-PFNCLGETKERNELINFO __oclGetKernelInfo = NULL;
-PFNCLGETKERNELWORKGROUPINFO __oclGetKernelWorkGroupInfo = NULL;
-PFNCLWAITFOREVENTS __oclWaitForEvents = NULL;
-PFNCLGETEVENTINFO __oclGetEventInfo = NULL;
-PFNCLRETAINEVENT __oclRetainEvent = NULL;
-PFNCLRELEASEEVENT __oclReleaseEvent = NULL;
-PFNCLGETEVENTPROFILINGINFO __oclGetEventProfilingInfo = NULL;
-PFNCLFLUSH __oclFlush = NULL;
-PFNCLFINISH __oclFinish = NULL;
-PFNCLENQUEUEREADBUFFER __oclEnqueueReadBuffer = NULL;
-PFNCLENQUEUEWRITEBUFFER __oclEnqueueWriteBuffer = NULL;
-PFNCLENQUEUECOPYBUFFER __oclEnqueueCopyBuffer = NULL;
-PFNCLENQUEUEREADIMAGE __oclEnqueueReadImage = NULL;
-PFNCLENQUEUEWRITEIMAGE __oclEnqueueWriteImage = NULL;
-PFNCLENQUEUECOPYIMAGE __oclEnqueueCopyImage = NULL;
-PFNCLENQUEUECOPYIMAGETOBUFFER __oclEnqueueCopyImageToBuffer = NULL;
-PFNCLENQUEUECOPYBUFFERTOIMAGE __oclEnqueueCopyBufferToImage = NULL;
-PFNCLENQUEUEMAPBUFFER __oclEnqueueMapBuffer = NULL;
-PFNCLENQUEUEMAPIMAGE __oclEnqueueMapImage = NULL;
-PFNCLENQUEUEUNMAPMEMOBJECT __oclEnqueueUnmapMemObject = NULL;
-PFNCLENQUEUENDRANGEKERNEL __oclEnqueueNDRangeKernel = NULL;
-PFNCLENQUEUETASK __oclEnqueueTask = NULL;
-PFNCLENQUEUENATIVEKERNEL __oclEnqueueNativeKernel = NULL;
-PFNCLENQUEUEMARKER __oclEnqueueMarker = NULL;
-PFNCLENQUEUEWAITFOREVENTS __oclEnqueueWaitForEvents = NULL;
-PFNCLENQUEUEBARRIER __oclEnqueueBarrier = NULL;
-PFNCLGETEXTENSIONFUNCTIONADDRESS __oclGetExtensionFunctionAddress = NULL;
-#endif // CLCC_GENERATE_DOCUMENTATION
-
-
-//! \brief Unloads OpenCL dynamic library, should not be called directly
-static void clewExit(void)
-{
- if (module != NULL)
- {
- // Ignore errors
- CLCC_DYNLIB_CLOSE(module);
- module = NULL;
- }
-}
-
-//! \param path path to dynamic library to load
-//! \return CLEW_ERROR_OPEN_FAILED if the library could not be opened
-//! CLEW_ERROR_ATEXIT_FAILED if atexit(clewExit) failed
-//! CLEW_SUCCESS when the library was succesfully loaded
-int clewInit(const char* path)
-{
- int error = 0;
-
- // Check if already initialized
- if (module != NULL)
- {
- return CLEW_SUCCESS;
- }
-
- // Load library
- module = CLCC_DYNLIB_OPEN(path);
-
- // Check for errors
- if (module == NULL)
- {
- return CLEW_ERROR_OPEN_FAILED;
- }
-
- // Set unloading
- error = atexit(clewExit);
-
- if (error)
- {
- // Failure queing atexit, shutdown with error
- CLCC_DYNLIB_CLOSE(module);
- module = NULL;
-
- return CLEW_ERROR_ATEXIT_FAILED;
- }
-
- // Determine function entry-points
- __oclGetPlatformIDs = (PFNCLGETPLATFORMIDS )CLCC_DYNLIB_IMPORT(module, "clGetPlatformIDs");
- __oclGetPlatformInfo = (PFNCLGETPLATFORMINFO )CLCC_DYNLIB_IMPORT(module, "clGetPlatformInfo");
- __oclGetDeviceIDs = (PFNCLGETDEVICEIDS )CLCC_DYNLIB_IMPORT(module, "clGetDeviceIDs");
- __oclGetDeviceInfo = (PFNCLGETDEVICEINFO )CLCC_DYNLIB_IMPORT(module, "clGetDeviceInfo");
- __oclCreateContext = (PFNCLCREATECONTEXT )CLCC_DYNLIB_IMPORT(module, "clCreateContext");
- __oclCreateContextFromType = (PFNCLCREATECONTEXTFROMTYPE )CLCC_DYNLIB_IMPORT(module, "clCreateContextFromType");
- __oclRetainContext = (PFNCLRETAINCONTEXT )CLCC_DYNLIB_IMPORT(module, "clRetainContext");
- __oclReleaseContext = (PFNCLRELEASECONTEXT )CLCC_DYNLIB_IMPORT(module, "clReleaseContext");
- __oclGetContextInfo = (PFNCLGETCONTEXTINFO )CLCC_DYNLIB_IMPORT(module, "clGetContextInfo");
- __oclCreateCommandQueue = (PFNCLCREATECOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clCreateCommandQueue");
- __oclRetainCommandQueue = (PFNCLRETAINCOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clRetainCommandQueue");
- __oclReleaseCommandQueue = (PFNCLRELEASECOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clReleaseCommandQueue");
- __oclGetCommandQueueInfo = (PFNCLGETCOMMANDQUEUEINFO )CLCC_DYNLIB_IMPORT(module, "clGetCommandQueueInfo");
- __oclSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY )CLCC_DYNLIB_IMPORT(module, "clSetCommandQueueProperty");
- __oclCreateBuffer = (PFNCLCREATEBUFFER )CLCC_DYNLIB_IMPORT(module, "clCreateBuffer");
- __oclCreateImage2D = (PFNCLCREATEIMAGE2D )CLCC_DYNLIB_IMPORT(module, "clCreateImage2D");
- __oclCreateImage3D = (PFNCLCREATEIMAGE3D )CLCC_DYNLIB_IMPORT(module, "clCreateImage3D");
- __oclRetainMemObject = (PFNCLRETAINMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clRetainMemObject");
- __oclReleaseMemObject = (PFNCLRELEASEMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clReleaseMemObject");
- __oclGetSupportedImageFormats = (PFNCLGETSUPPORTEDIMAGEFORMATS )CLCC_DYNLIB_IMPORT(module, "clGetSupportedImageFormats");
- __oclGetMemObjectInfo = (PFNCLGETMEMOBJECTINFO )CLCC_DYNLIB_IMPORT(module, "clGetMemObjectInfo");
- __oclGetImageInfo = (PFNCLGETIMAGEINFO )CLCC_DYNLIB_IMPORT(module, "clGetImageInfo");
- __oclCreateSampler = (PFNCLCREATESAMPLER )CLCC_DYNLIB_IMPORT(module, "clCreateSampler");
- __oclRetainSampler = (PFNCLRETAINSAMPLER )CLCC_DYNLIB_IMPORT(module, "clRetainSampler");
- __oclReleaseSampler = (PFNCLRELEASESAMPLER )CLCC_DYNLIB_IMPORT(module, "clReleaseSampler");
- __oclGetSamplerInfo = (PFNCLGETSAMPLERINFO )CLCC_DYNLIB_IMPORT(module, "clGetSamplerInfo");
- __oclCreateProgramWithSource = (PFNCLCREATEPROGRAMWITHSOURCE )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithSource");
- __oclCreateProgramWithBinary = (PFNCLCREATEPROGRAMWITHBINARY )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithBinary");
- __oclRetainProgram = (PFNCLRETAINPROGRAM )CLCC_DYNLIB_IMPORT(module, "clRetainProgram");
- __oclReleaseProgram = (PFNCLRELEASEPROGRAM )CLCC_DYNLIB_IMPORT(module, "clReleaseProgram");
- __oclBuildProgram = (PFNCLBUILDPROGRAM )CLCC_DYNLIB_IMPORT(module, "clBuildProgram");
- __oclUnloadCompiler = (PFNCLUNLOADCOMPILER )CLCC_DYNLIB_IMPORT(module, "clUnloadCompiler");
- __oclGetProgramInfo = (PFNCLGETPROGRAMINFO )CLCC_DYNLIB_IMPORT(module, "clGetProgramInfo");
- __oclGetProgramBuildInfo = (PFNCLGETPROGRAMBUILDINFO )CLCC_DYNLIB_IMPORT(module, "clGetProgramBuildInfo");
- __oclCreateKernel = (PFNCLCREATEKERNEL )CLCC_DYNLIB_IMPORT(module, "clCreateKernel");
- __oclCreateKernelsInProgram = (PFNCLCREATEKERNELSINPROGRAM )CLCC_DYNLIB_IMPORT(module, "clCreateKernelsInProgram");
- __oclRetainKernel = (PFNCLRETAINKERNEL )CLCC_DYNLIB_IMPORT(module, "clRetainKernel");
- __oclReleaseKernel = (PFNCLRELEASEKERNEL )CLCC_DYNLIB_IMPORT(module, "clReleaseKernel");
- __oclSetKernelArg = (PFNCLSETKERNELARG )CLCC_DYNLIB_IMPORT(module, "clSetKernelArg");
- __oclGetKernelInfo = (PFNCLGETKERNELINFO )CLCC_DYNLIB_IMPORT(module, "clGetKernelInfo");
- __oclGetKernelWorkGroupInfo = (PFNCLGETKERNELWORKGROUPINFO )CLCC_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo");
- __oclWaitForEvents = (PFNCLWAITFOREVENTS )CLCC_DYNLIB_IMPORT(module, "clWaitForEvents");
- __oclGetEventInfo = (PFNCLGETEVENTINFO )CLCC_DYNLIB_IMPORT(module, "clGetEventInfo");
- __oclRetainEvent = (PFNCLRETAINEVENT )CLCC_DYNLIB_IMPORT(module, "clRetainEvent");
- __oclReleaseEvent = (PFNCLRELEASEEVENT )CLCC_DYNLIB_IMPORT(module, "clReleaseEvent");
- __oclGetEventProfilingInfo = (PFNCLGETEVENTPROFILINGINFO )CLCC_DYNLIB_IMPORT(module, "clGetEventProfilingInfo");
- __oclFlush = (PFNCLFLUSH )CLCC_DYNLIB_IMPORT(module, "clFlush");
- __oclFinish = (PFNCLFINISH )CLCC_DYNLIB_IMPORT(module, "clFinish");
- __oclEnqueueReadBuffer = (PFNCLENQUEUEREADBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadBuffer");
- __oclEnqueueWriteBuffer = (PFNCLENQUEUEWRITEBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer");
- __oclEnqueueCopyBuffer = (PFNCLENQUEUECOPYBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer");
- __oclEnqueueReadImage = (PFNCLENQUEUEREADIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadImage");
- __oclEnqueueWriteImage = (PFNCLENQUEUEWRITEIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteImage");
- __oclEnqueueCopyImage = (PFNCLENQUEUECOPYIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImage");
- __oclEnqueueCopyImageToBuffer = (PFNCLENQUEUECOPYIMAGETOBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer");
- __oclEnqueueCopyBufferToImage = (PFNCLENQUEUECOPYBUFFERTOIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage");
- __oclEnqueueMapBuffer = (PFNCLENQUEUEMAPBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapBuffer");
- __oclEnqueueMapImage = (PFNCLENQUEUEMAPIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapImage");
- __oclEnqueueUnmapMemObject = (PFNCLENQUEUEUNMAPMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject");
- __oclEnqueueNDRangeKernel = (PFNCLENQUEUENDRANGEKERNEL )CLCC_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel");
- __oclEnqueueTask = (PFNCLENQUEUETASK )CLCC_DYNLIB_IMPORT(module, "clEnqueueTask");
- __oclEnqueueNativeKernel = (PFNCLENQUEUENATIVEKERNEL )CLCC_DYNLIB_IMPORT(module, "clEnqueueNativeKernel");
- __oclEnqueueMarker = (PFNCLENQUEUEMARKER )CLCC_DYNLIB_IMPORT(module, "clEnqueueMarker");
- __oclEnqueueWaitForEvents = (PFNCLENQUEUEWAITFOREVENTS )CLCC_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents");
- __oclEnqueueBarrier = (PFNCLENQUEUEBARRIER )CLCC_DYNLIB_IMPORT(module, "clEnqueueBarrier");
- __oclGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS )CLCC_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress");
-
- if(__oclGetPlatformIDs == NULL) return CLEW_ERROR_OPEN_FAILED;
- if(__oclGetPlatformInfo == NULL) return CLEW_ERROR_OPEN_FAILED;
- if(__oclGetDeviceIDs == NULL) return CLEW_ERROR_OPEN_FAILED;
- if(__oclGetDeviceInfo == NULL) return CLEW_ERROR_OPEN_FAILED;
-
- return CLEW_SUCCESS;
-}
-
-//! \param error CL error code
-//! \return a string representation of the error code
-const char* clewErrorString(cl_int error)
-{
- static const char* strings[] =
- {
- // Error Codes
- "CL_SUCCESS" // 0
- , "CL_DEVICE_NOT_FOUND" // -1
- , "CL_DEVICE_NOT_AVAILABLE" // -2
- , "CL_COMPILER_NOT_AVAILABLE" // -3
- , "CL_MEM_OBJECT_ALLOCATION_FAILURE" // -4
- , "CL_OUT_OF_RESOURCES" // -5
- , "CL_OUT_OF_HOST_MEMORY" // -6
- , "CL_PROFILING_INFO_NOT_AVAILABLE" // -7
- , "CL_MEM_COPY_OVERLAP" // -8
- , "CL_IMAGE_FORMAT_MISMATCH" // -9
- , "CL_IMAGE_FORMAT_NOT_SUPPORTED" // -10
- , "CL_BUILD_PROGRAM_FAILURE" // -11
- , "CL_MAP_FAILURE" // -12
-
- , "" // -13
- , "" // -14
- , "" // -15
- , "" // -16
- , "" // -17
- , "" // -18
- , "" // -19
-
- , "" // -20
- , "" // -21
- , "" // -22
- , "" // -23
- , "" // -24
- , "" // -25
- , "" // -26
- , "" // -27
- , "" // -28
- , "" // -29
-
- , "CL_INVALID_VALUE" // -30
- , "CL_INVALID_DEVICE_TYPE" // -31
- , "CL_INVALID_PLATFORM" // -32
- , "CL_INVALID_DEVICE" // -33
- , "CL_INVALID_CONTEXT" // -34
- , "CL_INVALID_QUEUE_PROPERTIES" // -35
- , "CL_INVALID_COMMAND_QUEUE" // -36
- , "CL_INVALID_HOST_PTR" // -37
- , "CL_INVALID_MEM_OBJECT" // -38
- , "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" // -39
- , "CL_INVALID_IMAGE_SIZE" // -40
- , "CL_INVALID_SAMPLER" // -41
- , "CL_INVALID_BINARY" // -42
- , "CL_INVALID_BUILD_OPTIONS" // -43
- , "CL_INVALID_PROGRAM" // -44
- , "CL_INVALID_PROGRAM_EXECUTABLE" // -45
- , "CL_INVALID_KERNEL_NAME" // -46
- , "CL_INVALID_KERNEL_DEFINITION" // -47
- , "CL_INVALID_KERNEL" // -48
- , "CL_INVALID_ARG_INDEX" // -49
- , "CL_INVALID_ARG_VALUE" // -50
- , "CL_INVALID_ARG_SIZE" // -51
- , "CL_INVALID_KERNEL_ARGS" // -52
- , "CL_INVALID_WORK_DIMENSION" // -53
- , "CL_INVALID_WORK_GROUP_SIZE" // -54
- , "CL_INVALID_WORK_ITEM_SIZE" // -55
- , "CL_INVALID_GLOBAL_OFFSET" // -56
- , "CL_INVALID_EVENT_WAIT_LIST" // -57
- , "CL_INVALID_EVENT" // -58
- , "CL_INVALID_OPERATION" // -59
- , "CL_INVALID_GL_OBJECT" // -60
- , "CL_INVALID_BUFFER_SIZE" // -61
- , "CL_INVALID_MIP_LEVEL" // -62
- , "CL_INVALID_GLOBAL_WORK_SIZE" // -63
- };
-
- return strings[-error];
-}
diff --git a/intern/opencl/intern/clew.h b/intern/opencl/intern/clew.h
deleted file mode 100644
index bb7e0134dcf..00000000000
--- a/intern/opencl/intern/clew.h
+++ /dev/null
@@ -1,1317 +0,0 @@
-#ifndef CLCC_CLEW_HPP_INCLUDED
-#define CLCC_CLEW_HPP_INCLUDED
-
-//////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2009 Organic Vectory B.V.
-// Written by George van Venrooij
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file license.txt)
-//////////////////////////////////////////////////////////////////////////
-
-//! \file clew.h
-//! \brief OpenCL run-time loader header
-//!
-//! This file contains a copy of the contents of CL.H and CL_PLATFORM.H from the
-//! official OpenCL spec. The purpose of this code is to load the OpenCL dynamic
-//! library at run-time and thus allow the executable to function on many
-//! platforms regardless of the vendor of the OpenCL driver actually installed.
-//! Some of the techniques used here were inspired by work done in the GLEW
-//! library (http://glew.sourceforge.net/)
-
-// Run-time dynamic linking functionality based on concepts used in GLEW
-#ifdef __OPENCL_CL_H
-#error cl.h included before clew.h
-#endif
-
-#ifdef __OPENCL_CL_PLATFORM_H
-#error cl_platform.h included before clew.h
-#endif
-
-#ifndef CLCC_GENERATE_DOCUMENTATION
-// Prevent cl.h inclusion
-#define __OPENCL_CL_H
-// Prevent cl_platform.h inclusion
-#define __CL_PLATFORM_H
-#endif // CLCC_GENERATE_DOCUMENTATION
-
-/*******************************************************************************
-* Copyright (c) 2008-2009 The Khronos Group Inc.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and/or associated documentation files (the
-* "Materials"), to deal in the Materials without restriction, including
-* without limitation the rights to use, copy, modify, merge, publish,
-* distribute, sublicense, and/or sell copies of the Materials, and to
-* permit persons to whom the Materials are furnished to do so, subject to
-* the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Materials.
-*
-* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-******************************************************************************/
-#ifdef __APPLE__
-/* Contains #defines for AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER below */
-#include <AvailabilityMacros.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef CLCC_GENERATE_DOCUMENTATION
-
-#if defined(_WIN32)
-#define CL_API_ENTRY
-#define CL_API_CALL __stdcall
-#else
-#define CL_API_ENTRY
-#define CL_API_CALL
-#endif
-
-#if defined(__APPLE__)
-//JBKK removed for compatibility with blender trunk #define CL_API_SUFFIX__VERSION_1_0 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
-#define CL_API_SUFFIX__VERSION_1_0
-#define CL_EXTENSION_WEAK_LINK __attribute__((weak_import))
-#else
-#define CL_API_SUFFIX__VERSION_1_0
-#define CL_EXTENSION_WEAK_LINK
-#endif
-
-#if defined(_WIN32) && defined(_MSC_VER)
-
-/* scalar types */
-typedef signed __int8 cl_char;
-typedef unsigned __int8 cl_uchar;
-typedef signed __int16 cl_short;
-typedef unsigned __int16 cl_ushort;
-typedef signed __int32 cl_int;
-typedef unsigned __int32 cl_uint;
-typedef signed __int64 cl_long;
-typedef unsigned __int64 cl_ulong;
-
-typedef unsigned __int16 cl_half;
-typedef float cl_float;
-typedef double cl_double;
-
-
-/*
-* Vector types
-*
-* Note: OpenCL requires that all types be naturally aligned.
-* This means that vector types must be naturally aligned.
-* For example, a vector of four floats must be aligned to
-* a 16 byte boundary (calculated as 4 * the natural 4-byte
-* alignment of the float). The alignment qualifiers here
-* will only function properly if your compiler supports them
-* and if you don't actively work to defeat them. For example,
-* in order for a cl_float4 to be 16 byte aligned in a struct,
-* the start of the struct must itself be 16-byte aligned.
-*
-* Maintaining proper alignment is the user's responsibility.
-*/
-typedef signed __int8 cl_char2[2];
-typedef signed __int8 cl_char4[4];
-typedef signed __int8 cl_char8[8];
-typedef signed __int8 cl_char16[16];
-typedef unsigned __int8 cl_uchar2[2];
-typedef unsigned __int8 cl_uchar4[4];
-typedef unsigned __int8 cl_uchar8[8];
-typedef unsigned __int8 cl_uchar16[16];
-
-typedef signed __int16 cl_short2[2];
-typedef signed __int16 cl_short4[4];
-typedef signed __int16 cl_short8[8];
-typedef signed __int16 cl_short16[16];
-typedef unsigned __int16 cl_ushort2[2];
-typedef unsigned __int16 cl_ushort4[4];
-typedef unsigned __int16 cl_ushort8[8];
-typedef unsigned __int16 cl_ushort16[16];
-
-typedef signed __int32 cl_int2[2];
-typedef signed __int32 cl_int4[4];
-typedef signed __int32 cl_int8[8];
-typedef signed __int32 cl_int16[16];
-typedef unsigned __int32 cl_uint2[2];
-typedef unsigned __int32 cl_uint4[4];
-typedef unsigned __int32 cl_uint8[8];
-typedef unsigned __int32 cl_uint16[16];
-
-typedef signed __int64 cl_long2[2];
-typedef signed __int64 cl_long4[4];
-typedef signed __int64 cl_long8[8];
-typedef signed __int64 cl_long16[16];
-typedef unsigned __int64 cl_ulong2[2];
-typedef unsigned __int64 cl_ulong4[4];
-typedef unsigned __int64 cl_ulong8[8];
-typedef unsigned __int64 cl_ulong16[16];
-
-typedef float cl_float2[2];
-typedef float cl_float4[4];
-typedef float cl_float8[8];
-typedef float cl_float16[16];
-
-typedef double cl_double2[2];
-typedef double cl_double4[4];
-typedef double cl_double8[8];
-typedef double cl_double16[16];
-/* There are no vector types for half */
-
-#else
-
-#include <stdint.h>
-
-/* scalar types */
-typedef int8_t cl_char;
-typedef uint8_t cl_uchar;
-typedef int16_t cl_short __attribute__((aligned(2)));
-typedef uint16_t cl_ushort __attribute__((aligned(2)));
-typedef int32_t cl_int __attribute__((aligned(4)));
-typedef uint32_t cl_uint __attribute__((aligned(4)));
-typedef int64_t cl_long __attribute__((aligned(8)));
-typedef uint64_t cl_ulong __attribute__((aligned(8)));
-
-typedef uint16_t cl_half __attribute__((aligned(2)));
-typedef float cl_float __attribute__((aligned(4)));
-typedef double cl_double __attribute__((aligned(8)));
-
-/*
-* Vector types
-*
-* Note: OpenCL requires that all types be naturally aligned.
-* This means that vector types must be naturally aligned.
-* For example, a vector of four floats must be aligned to
-* a 16 byte boundary (calculated as 4 * the natural 4-byte
-* alignment of the float). The alignment qualifiers here
-* will only function properly if your compiler supports them
-* and if you don't actively work to defeat them. For example,
-* in order for a cl_float4 to be 16 byte aligned in a struct,
-* the start of the struct must itself be 16-byte aligned.
-*
-* Maintaining proper alignment is the user's responsibility.
-*/
-typedef int8_t cl_char2[2] __attribute__((aligned(2)));
-typedef int8_t cl_char4[4] __attribute__((aligned(4)));
-typedef int8_t cl_char8[8] __attribute__((aligned(8)));
-typedef int8_t cl_char16[16] __attribute__((aligned(16)));
-typedef uint8_t cl_uchar2[2] __attribute__((aligned(2)));
-typedef uint8_t cl_uchar4[4] __attribute__((aligned(4)));
-typedef uint8_t cl_uchar8[8] __attribute__((aligned(8)));
-typedef uint8_t cl_uchar16[16] __attribute__((aligned(16)));
-
-typedef int16_t cl_short2[2] __attribute__((aligned(4)));
-typedef int16_t cl_short4[4] __attribute__((aligned(8)));
-typedef int16_t cl_short8[8] __attribute__((aligned(16)));
-typedef int16_t cl_short16[16] __attribute__((aligned(32)));
-typedef uint16_t cl_ushort2[2] __attribute__((aligned(4)));
-typedef uint16_t cl_ushort4[4] __attribute__((aligned(8)));
-typedef uint16_t cl_ushort8[8] __attribute__((aligned(16)));
-typedef uint16_t cl_ushort16[16] __attribute__((aligned(32)));
-
-typedef int32_t cl_int2[2] __attribute__((aligned(8)));
-typedef int32_t cl_int4[4] __attribute__((aligned(16)));
-typedef int32_t cl_int8[8] __attribute__((aligned(32)));
-typedef int32_t cl_int16[16] __attribute__((aligned(64)));
-typedef uint32_t cl_uint2[2] __attribute__((aligned(8)));
-typedef uint32_t cl_uint4[4] __attribute__((aligned(16)));
-typedef uint32_t cl_uint8[8] __attribute__((aligned(32)));
-typedef uint32_t cl_uint16[16] __attribute__((aligned(64)));
-
-typedef int64_t cl_long2[2] __attribute__((aligned(16)));
-typedef int64_t cl_long4[4] __attribute__((aligned(32)));
-typedef int64_t cl_long8[8] __attribute__((aligned(64)));
-typedef int64_t cl_long16[16] __attribute__((aligned(128)));
-typedef uint64_t cl_ulong2[2] __attribute__((aligned(16)));
-typedef uint64_t cl_ulong4[4] __attribute__((aligned(32)));
-typedef uint64_t cl_ulong8[8] __attribute__((aligned(64)));
-typedef uint64_t cl_ulong16[16] __attribute__((aligned(128)));
-
-typedef float cl_float2[2] __attribute__((aligned(8)));
-typedef float cl_float4[4] __attribute__((aligned(16)));
-typedef float cl_float8[8] __attribute__((aligned(32)));
-typedef float cl_float16[16] __attribute__((aligned(64)));
-
-typedef double cl_double2[2] __attribute__((aligned(16)));
-typedef double cl_double4[4] __attribute__((aligned(32)));
-typedef double cl_double8[8] __attribute__((aligned(64)));
-typedef double cl_double16[16] __attribute__((aligned(128)));
-
-/* There are no vector types for half */
-
-#endif
-
-/******************************************************************************/
-
-// Macro names and corresponding values defined by OpenCL
-
-#define CL_CHAR_BIT 8
-#define CL_SCHAR_MAX 127
-#define CL_SCHAR_MIN (-127-1)
-#define CL_CHAR_MAX CL_SCHAR_MAX
-#define CL_CHAR_MIN CL_SCHAR_MIN
-#define CL_UCHAR_MAX 255
-#define CL_SHRT_MAX 32767
-#define CL_SHRT_MIN (-32767-1)
-#define CL_USHRT_MAX 65535
-#define CL_INT_MAX 2147483647
-#define CL_INT_MIN (-2147483647-1)
-#define CL_UINT_MAX 0xffffffffU
-#define CL_LONG_MAX ((cl_long) 0x7FFFFFFFFFFFFFFFLL)
-#define CL_LONG_MIN ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL)
-#define CL_ULONG_MAX ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL)
-
-#define CL_FLT_DIG 6
-#define CL_FLT_MANT_DIG 24
-#define CL_FLT_MAX_10_EXP +38
-#define CL_FLT_MAX_EXP +128
-#define CL_FLT_MIN_10_EXP -37
-#define CL_FLT_MIN_EXP -125
-#define CL_FLT_RADIX 2
-#if defined(_MSC_VER)
-// MSVC doesn't understand hex floats
-#define CL_FLT_MAX 3.402823466e+38F
-#define CL_FLT_MIN 1.175494351e-38F
-#define CL_FLT_EPSILON 1.192092896e-07F
-#else
-#define CL_FLT_MAX 0x1.fffffep127f
-#define CL_FLT_MIN 0x1.0p-126f
-#define CL_FLT_EPSILON 0x1.0p-23f
-#endif
-
-#define CL_DBL_DIG 15
-#define CL_DBL_MANT_DIG 53
-#define CL_DBL_MAX_10_EXP +308
-#define CL_DBL_MAX_EXP +1024
-#define CL_DBL_MIN_10_EXP -307
-#define CL_DBL_MIN_EXP -1021
-#define CL_DBL_RADIX 2
-#if defined(_MSC_VER)
-// MSVC doesn't understand hex floats
-#define CL_DBL_MAX 1.7976931348623158e+308
-#define CL_DBL_MIN 2.2250738585072014e-308
-#define CL_DBL_EPSILON 2.2204460492503131e-016
-#else
-#define CL_DBL_MAX 0x1.fffffffffffffp1023
-#define CL_DBL_MIN 0x1.0p-1022
-#define CL_DBL_EPSILON 0x1.0p-52
-#endif
-
-#include <stddef.h>
-
-
-// CL.h contents
-/******************************************************************************/
-
-typedef struct _cl_platform_id * cl_platform_id;
-typedef struct _cl_device_id * cl_device_id;
-typedef struct _cl_context * cl_context;
-typedef struct _cl_command_queue * cl_command_queue;
-typedef struct _cl_mem * cl_mem;
-typedef struct _cl_program * cl_program;
-typedef struct _cl_kernel * cl_kernel;
-typedef struct _cl_event * cl_event;
-typedef struct _cl_sampler * cl_sampler;
-
-typedef cl_uint cl_bool; /* WARNING! Unlike cl_ types in cl_platform.h, cl_bool is not guaranteed to be the same size as the bool in kernels. */
-typedef cl_ulong cl_bitfield;
-typedef cl_bitfield cl_device_type;
-typedef cl_uint cl_platform_info;
-typedef cl_uint cl_device_info;
-typedef cl_bitfield cl_device_address_info;
-typedef cl_bitfield cl_device_fp_config;
-typedef cl_uint cl_device_mem_cache_type;
-typedef cl_uint cl_device_local_mem_type;
-typedef cl_bitfield cl_device_exec_capabilities;
-typedef cl_bitfield cl_command_queue_properties;
-
-typedef intptr_t cl_context_properties;
-typedef cl_uint cl_context_info;
-typedef cl_uint cl_command_queue_info;
-typedef cl_uint cl_channel_order;
-typedef cl_uint cl_channel_type;
-typedef cl_bitfield cl_mem_flags;
-typedef cl_uint cl_mem_object_type;
-typedef cl_uint cl_mem_info;
-typedef cl_uint cl_image_info;
-typedef cl_uint cl_addressing_mode;
-typedef cl_uint cl_filter_mode;
-typedef cl_uint cl_sampler_info;
-typedef cl_bitfield cl_map_flags;
-typedef cl_uint cl_program_info;
-typedef cl_uint cl_program_build_info;
-typedef cl_int cl_build_status;
-typedef cl_uint cl_kernel_info;
-typedef cl_uint cl_kernel_work_group_info;
-typedef cl_uint cl_event_info;
-typedef cl_uint cl_command_type;
-typedef cl_uint cl_profiling_info;
-
-typedef struct _cl_image_format {
- cl_channel_order image_channel_order;
- cl_channel_type image_channel_data_type;
-} cl_image_format;
-
-
-
-/******************************************************************************/
-
-// Error Codes
-#define CL_SUCCESS 0
-#define CL_DEVICE_NOT_FOUND -1
-#define CL_DEVICE_NOT_AVAILABLE -2
-#define CL_COMPILER_NOT_AVAILABLE -3
-#define CL_MEM_OBJECT_ALLOCATION_FAILURE -4
-#define CL_OUT_OF_RESOURCES -5
-#define CL_OUT_OF_HOST_MEMORY -6
-#define CL_PROFILING_INFO_NOT_AVAILABLE -7
-#define CL_MEM_COPY_OVERLAP -8
-#define CL_IMAGE_FORMAT_MISMATCH -9
-#define CL_IMAGE_FORMAT_NOT_SUPPORTED -10
-#define CL_BUILD_PROGRAM_FAILURE -11
-#define CL_MAP_FAILURE -12
-
-#define CL_INVALID_VALUE -30
-#define CL_INVALID_DEVICE_TYPE -31
-#define CL_INVALID_PLATFORM -32
-#define CL_INVALID_DEVICE -33
-#define CL_INVALID_CONTEXT -34
-#define CL_INVALID_QUEUE_PROPERTIES -35
-#define CL_INVALID_COMMAND_QUEUE -36
-#define CL_INVALID_HOST_PTR -37
-#define CL_INVALID_MEM_OBJECT -38
-#define CL_INVALID_IMAGE_FORMAT_DESCRIPTOR -39
-#define CL_INVALID_IMAGE_SIZE -40
-#define CL_INVALID_SAMPLER -41
-#define CL_INVALID_BINARY -42
-#define CL_INVALID_BUILD_OPTIONS -43
-#define CL_INVALID_PROGRAM -44
-#define CL_INVALID_PROGRAM_EXECUTABLE -45
-#define CL_INVALID_KERNEL_NAME -46
-#define CL_INVALID_KERNEL_DEFINITION -47
-#define CL_INVALID_KERNEL -48
-#define CL_INVALID_ARG_INDEX -49
-#define CL_INVALID_ARG_VALUE -50
-#define CL_INVALID_ARG_SIZE -51
-#define CL_INVALID_KERNEL_ARGS -52
-#define CL_INVALID_WORK_DIMENSION -53
-#define CL_INVALID_WORK_GROUP_SIZE -54
-#define CL_INVALID_WORK_ITEM_SIZE -55
-#define CL_INVALID_GLOBAL_OFFSET -56
-#define CL_INVALID_EVENT_WAIT_LIST -57
-#define CL_INVALID_EVENT -58
-#define CL_INVALID_OPERATION -59
-#define CL_INVALID_GL_OBJECT -60
-#define CL_INVALID_BUFFER_SIZE -61
-#define CL_INVALID_MIP_LEVEL -62
-#define CL_INVALID_GLOBAL_WORK_SIZE -63
-
-// OpenCL Version
-#define CL_VERSION_1_0 1
-
-// cl_bool
-#define CL_FALSE 0
-#define CL_TRUE 1
-
-// cl_platform_info
-#define CL_PLATFORM_PROFILE 0x0900
-#define CL_PLATFORM_VERSION 0x0901
-#define CL_PLATFORM_NAME 0x0902
-#define CL_PLATFORM_VENDOR 0x0903
-#define CL_PLATFORM_EXTENSIONS 0x0904
-
-// cl_device_type - bitfield
-#define CL_DEVICE_TYPE_DEFAULT (1 << 0)
-#define CL_DEVICE_TYPE_CPU (1 << 1)
-#define CL_DEVICE_TYPE_GPU (1 << 2)
-#define CL_DEVICE_TYPE_ACCELERATOR (1 << 3)
-#define CL_DEVICE_TYPE_ALL 0xFFFFFFFF
-
-// cl_device_info
-#define CL_DEVICE_TYPE 0x1000
-#define CL_DEVICE_VENDOR_ID 0x1001
-#define CL_DEVICE_MAX_COMPUTE_UNITS 0x1002
-#define CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS 0x1003
-#define CL_DEVICE_MAX_WORK_GROUP_SIZE 0x1004
-#define CL_DEVICE_MAX_WORK_ITEM_SIZES 0x1005
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR 0x1006
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT 0x1007
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT 0x1008
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG 0x1009
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT 0x100A
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE 0x100B
-#define CL_DEVICE_MAX_CLOCK_FREQUENCY 0x100C
-#define CL_DEVICE_ADDRESS_BITS 0x100D
-#define CL_DEVICE_MAX_READ_IMAGE_ARGS 0x100E
-#define CL_DEVICE_MAX_WRITE_IMAGE_ARGS 0x100F
-#define CL_DEVICE_MAX_MEM_ALLOC_SIZE 0x1010
-#define CL_DEVICE_IMAGE2D_MAX_WIDTH 0x1011
-#define CL_DEVICE_IMAGE2D_MAX_HEIGHT 0x1012
-#define CL_DEVICE_IMAGE3D_MAX_WIDTH 0x1013
-#define CL_DEVICE_IMAGE3D_MAX_HEIGHT 0x1014
-#define CL_DEVICE_IMAGE3D_MAX_DEPTH 0x1015
-#define CL_DEVICE_IMAGE_SUPPORT 0x1016
-#define CL_DEVICE_MAX_PARAMETER_SIZE 0x1017
-#define CL_DEVICE_MAX_SAMPLERS 0x1018
-#define CL_DEVICE_MEM_BASE_ADDR_ALIGN 0x1019
-#define CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE 0x101A
-#define CL_DEVICE_SINGLE_FP_CONFIG 0x101B
-#define CL_DEVICE_GLOBAL_MEM_CACHE_TYPE 0x101C
-#define CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE 0x101D
-#define CL_DEVICE_GLOBAL_MEM_CACHE_SIZE 0x101E
-#define CL_DEVICE_GLOBAL_MEM_SIZE 0x101F
-#define CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE 0x1020
-#define CL_DEVICE_MAX_CONSTANT_ARGS 0x1021
-#define CL_DEVICE_LOCAL_MEM_TYPE 0x1022
-#define CL_DEVICE_LOCAL_MEM_SIZE 0x1023
-#define CL_DEVICE_ERROR_CORRECTION_SUPPORT 0x1024
-#define CL_DEVICE_PROFILING_TIMER_RESOLUTION 0x1025
-#define CL_DEVICE_ENDIAN_LITTLE 0x1026
-#define CL_DEVICE_AVAILABLE 0x1027
-#define CL_DEVICE_COMPILER_AVAILABLE 0x1028
-#define CL_DEVICE_EXECUTION_CAPABILITIES 0x1029
-#define CL_DEVICE_QUEUE_PROPERTIES 0x102A
-#define CL_DEVICE_NAME 0x102B
-#define CL_DEVICE_VENDOR 0x102C
-#define CL_DRIVER_VERSION 0x102D
-#define CL_DEVICE_PROFILE 0x102E
-#define CL_DEVICE_VERSION 0x102F
-#define CL_DEVICE_EXTENSIONS 0x1030
-#define CL_DEVICE_PLATFORM 0x1031
-
-// cl_device_fp_config - bitfield
-#define CL_FP_DENORM (1 << 0)
-#define CL_FP_INF_NAN (1 << 1)
-#define CL_FP_ROUND_TO_NEAREST (1 << 2)
-#define CL_FP_ROUND_TO_ZERO (1 << 3)
-#define CL_FP_ROUND_TO_INF (1 << 4)
-#define CL_FP_FMA (1 << 5)
-
-// cl_device_mem_cache_type
-#define CL_NONE 0x0
-#define CL_READ_ONLY_CACHE 0x1
-#define CL_READ_WRITE_CACHE 0x2
-
-// cl_device_local_mem_type
-#define CL_LOCAL 0x1
-#define CL_GLOBAL 0x2
-
-// cl_device_exec_capabilities - bitfield
-#define CL_EXEC_KERNEL (1 << 0)
-#define CL_EXEC_NATIVE_KERNEL (1 << 1)
-
-// cl_command_queue_properties - bitfield
-#define CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE (1 << 0)
-#define CL_QUEUE_PROFILING_ENABLE (1 << 1)
-
-// cl_context_info
-#define CL_CONTEXT_REFERENCE_COUNT 0x1080
-#define CL_CONTEXT_DEVICES 0x1081
-#define CL_CONTEXT_PROPERTIES 0x1082
-
-// cl_context_properties
-#define CL_CONTEXT_PLATFORM 0x1084
-
-// cl_command_queue_info
-#define CL_QUEUE_CONTEXT 0x1090
-#define CL_QUEUE_DEVICE 0x1091
-#define CL_QUEUE_REFERENCE_COUNT 0x1092
-#define CL_QUEUE_PROPERTIES 0x1093
-
-// cl_mem_flags - bitfield
-#define CL_MEM_READ_WRITE (1 << 0)
-#define CL_MEM_WRITE_ONLY (1 << 1)
-#define CL_MEM_READ_ONLY (1 << 2)
-#define CL_MEM_USE_HOST_PTR (1 << 3)
-#define CL_MEM_ALLOC_HOST_PTR (1 << 4)
-#define CL_MEM_COPY_HOST_PTR (1 << 5)
-
-// cl_channel_order
-#define CL_R 0x10B0
-#define CL_A 0x10B1
-#define CL_RG 0x10B2
-#define CL_RA 0x10B3
-#define CL_RGB 0x10B4
-#define CL_RGBA 0x10B5
-#define CL_BGRA 0x10B6
-#define CL_ARGB 0x10B7
-#define CL_INTENSITY 0x10B8
-#define CL_LUMINANCE 0x10B9
-
-// cl_channel_type
-#define CL_SNORM_INT8 0x10D0
-#define CL_SNORM_INT16 0x10D1
-#define CL_UNORM_INT8 0x10D2
-#define CL_UNORM_INT16 0x10D3
-#define CL_UNORM_SHORT_565 0x10D4
-#define CL_UNORM_SHORT_555 0x10D5
-#define CL_UNORM_INT_101010 0x10D6
-#define CL_SIGNED_INT8 0x10D7
-#define CL_SIGNED_INT16 0x10D8
-#define CL_SIGNED_INT32 0x10D9
-#define CL_UNSIGNED_INT8 0x10DA
-#define CL_UNSIGNED_INT16 0x10DB
-#define CL_UNSIGNED_INT32 0x10DC
-#define CL_HALF_FLOAT 0x10DD
-#define CL_FLOAT 0x10DE
-
-// cl_mem_object_type
-#define CL_MEM_OBJECT_BUFFER 0x10F0
-#define CL_MEM_OBJECT_IMAGE2D 0x10F1
-#define CL_MEM_OBJECT_IMAGE3D 0x10F2
-
-// cl_mem_info
-#define CL_MEM_TYPE 0x1100
-#define CL_MEM_FLAGS 0x1101
-#define CL_MEM_SIZE 0x1102
-#define CL_MEM_HOST_PTR 0x1103
-#define CL_MEM_MAP_COUNT 0x1104
-#define CL_MEM_REFERENCE_COUNT 0x1105
-#define CL_MEM_CONTEXT 0x1106
-
-// cl_image_info
-#define CL_IMAGE_FORMAT 0x1110
-#define CL_IMAGE_ELEMENT_SIZE 0x1111
-#define CL_IMAGE_ROW_PITCH 0x1112
-#define CL_IMAGE_SLICE_PITCH 0x1113
-#define CL_IMAGE_WIDTH 0x1114
-#define CL_IMAGE_HEIGHT 0x1115
-#define CL_IMAGE_DEPTH 0x1116
-
-// cl_addressing_mode
-#define CL_ADDRESS_NONE 0x1130
-#define CL_ADDRESS_CLAMP_TO_EDGE 0x1131
-#define CL_ADDRESS_CLAMP 0x1132
-#define CL_ADDRESS_REPEAT 0x1133
-
-// cl_filter_mode
-#define CL_FILTER_NEAREST 0x1140
-#define CL_FILTER_LINEAR 0x1141
-
-// cl_sampler_info
-#define CL_SAMPLER_REFERENCE_COUNT 0x1150
-#define CL_SAMPLER_CONTEXT 0x1151
-#define CL_SAMPLER_NORMALIZED_COORDS 0x1152
-#define CL_SAMPLER_ADDRESSING_MODE 0x1153
-#define CL_SAMPLER_FILTER_MODE 0x1154
-
-// cl_map_flags - bitfield
-#define CL_MAP_READ (1 << 0)
-#define CL_MAP_WRITE (1 << 1)
-
-// cl_program_info
-#define CL_PROGRAM_REFERENCE_COUNT 0x1160
-#define CL_PROGRAM_CONTEXT 0x1161
-#define CL_PROGRAM_NUM_DEVICES 0x1162
-#define CL_PROGRAM_DEVICES 0x1163
-#define CL_PROGRAM_SOURCE 0x1164
-#define CL_PROGRAM_BINARY_SIZES 0x1165
-#define CL_PROGRAM_BINARIES 0x1166
-
-// cl_program_build_info
-#define CL_PROGRAM_BUILD_STATUS 0x1181
-#define CL_PROGRAM_BUILD_OPTIONS 0x1182
-#define CL_PROGRAM_BUILD_LOG 0x1183
-
-// cl_build_status
-#define CL_BUILD_SUCCESS 0
-#define CL_BUILD_NONE -1
-#define CL_BUILD_ERROR -2
-#define CL_BUILD_IN_PROGRESS -3
-
-// cl_kernel_info
-#define CL_KERNEL_FUNCTION_NAME 0x1190
-#define CL_KERNEL_NUM_ARGS 0x1191
-#define CL_KERNEL_REFERENCE_COUNT 0x1192
-#define CL_KERNEL_CONTEXT 0x1193
-#define CL_KERNEL_PROGRAM 0x1194
-
-// cl_kernel_work_group_info
-#define CL_KERNEL_WORK_GROUP_SIZE 0x11B0
-#define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1
-#define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2
-
-// cl_event_info
-#define CL_EVENT_COMMAND_QUEUE 0x11D0
-#define CL_EVENT_COMMAND_TYPE 0x11D1
-#define CL_EVENT_REFERENCE_COUNT 0x11D2
-#define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3
-
-// cl_command_type
-#define CL_COMMAND_NDRANGE_KERNEL 0x11F0
-#define CL_COMMAND_TASK 0x11F1
-#define CL_COMMAND_NATIVE_KERNEL 0x11F2
-#define CL_COMMAND_READ_BUFFER 0x11F3
-#define CL_COMMAND_WRITE_BUFFER 0x11F4
-#define CL_COMMAND_COPY_BUFFER 0x11F5
-#define CL_COMMAND_READ_IMAGE 0x11F6
-#define CL_COMMAND_WRITE_IMAGE 0x11F7
-#define CL_COMMAND_COPY_IMAGE 0x11F8
-#define CL_COMMAND_COPY_IMAGE_TO_BUFFER 0x11F9
-#define CL_COMMAND_COPY_BUFFER_TO_IMAGE 0x11FA
-#define CL_COMMAND_MAP_BUFFER 0x11FB
-#define CL_COMMAND_MAP_IMAGE 0x11FC
-#define CL_COMMAND_UNMAP_MEM_OBJECT 0x11FD
-#define CL_COMMAND_MARKER 0x11FE
-#define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x11FF
-#define CL_COMMAND_RELEASE_GL_OBJECTS 0x1200
-
-// command execution status
-#define CL_COMPLETE 0x0
-#define CL_RUNNING 0x1
-#define CL_SUBMITTED 0x2
-#define CL_QUEUED 0x3
-
-// cl_profiling_info
-#define CL_PROFILING_COMMAND_QUEUED 0x1280
-#define CL_PROFILING_COMMAND_SUBMIT 0x1281
-#define CL_PROFILING_COMMAND_START 0x1282
-#define CL_PROFILING_COMMAND_END 0x1283
-
-/********************************************************************************************************/
-
-/********************************************************************************************************/
-
-// Function signature typedef's
-
-// Platform API
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETPLATFORMIDS)(cl_uint /* num_entries */,
- cl_platform_id * /* platforms */,
- cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETPLATFORMINFO)(cl_platform_id /* platform */,
- cl_platform_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Device APIs
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETDEVICEIDS)(cl_platform_id /* platform */,
- cl_device_type /* device_type */,
- cl_uint /* num_entries */,
- cl_device_id * /* devices */,
- cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETDEVICEINFO)(cl_device_id /* device */,
- cl_device_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Context APIs
-typedef CL_API_ENTRY cl_context (CL_API_CALL *
-PFNCLCREATECONTEXT)(const cl_context_properties * /* properties */,
- cl_uint /* num_devices */,
- const cl_device_id * /* devices */,
- void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */,
- void * /* user_data */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_context (CL_API_CALL *
-PFNCLCREATECONTEXTFROMTYPE)(const cl_context_properties * /* properties */,
- cl_device_type /* device_type */,
- void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */,
- void * /* user_data */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINCONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASECONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETCONTEXTINFO)(cl_context /* context */,
- cl_context_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Command Queue APIs
-typedef CL_API_ENTRY cl_command_queue (CL_API_CALL *
-PFNCLCREATECOMMANDQUEUE)(cl_context /* context */,
- cl_device_id /* device */,
- cl_command_queue_properties /* properties */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINCOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASECOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETCOMMANDQUEUEINFO)(cl_command_queue /* command_queue */,
- cl_command_queue_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLSETCOMMANDQUEUEPROPERTY)(cl_command_queue /* command_queue */,
- cl_command_queue_properties /* properties */,
- cl_bool /* enable */,
- cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0;
-
-// Memory Object APIs
-typedef CL_API_ENTRY cl_mem (CL_API_CALL *
-PFNCLCREATEBUFFER)(cl_context /* context */,
- cl_mem_flags /* flags */,
- size_t /* size */,
- void * /* host_ptr */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_mem (CL_API_CALL *
-PFNCLCREATEIMAGE2D)(cl_context /* context */,
- cl_mem_flags /* flags */,
- const cl_image_format * /* image_format */,
- size_t /* image_width */,
- size_t /* image_height */,
- size_t /* image_row_pitch */,
- void * /* host_ptr */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_mem (CL_API_CALL *
-PFNCLCREATEIMAGE3D)(cl_context /* context */,
- cl_mem_flags /* flags */,
- const cl_image_format * /* image_format */,
- size_t /* image_width */,
- size_t /* image_height */,
- size_t /* image_depth */,
- size_t /* image_row_pitch */,
- size_t /* image_slice_pitch */,
- void * /* host_ptr */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASEMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETSUPPORTEDIMAGEFORMATS)(cl_context /* context */,
- cl_mem_flags /* flags */,
- cl_mem_object_type /* image_type */,
- cl_uint /* num_entries */,
- cl_image_format * /* image_formats */,
- cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETMEMOBJECTINFO)(cl_mem /* memobj */,
- cl_mem_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETIMAGEINFO)(cl_mem /* image */,
- cl_image_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Sampler APIs
-typedef CL_API_ENTRY cl_sampler (CL_API_CALL *
-PFNCLCREATESAMPLER)(cl_context /* context */,
- cl_bool /* normalized_coords */,
- cl_addressing_mode /* addressing_mode */,
- cl_filter_mode /* filter_mode */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINSAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASESAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETSAMPLERINFO)(cl_sampler /* sampler */,
- cl_sampler_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Program Object APIs
-typedef CL_API_ENTRY cl_program (CL_API_CALL *
-PFNCLCREATEPROGRAMWITHSOURCE)(cl_context /* context */,
- cl_uint /* count */,
- const char ** /* strings */,
- const size_t * /* lengths */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_program (CL_API_CALL *
-PFNCLCREATEPROGRAMWITHBINARY)(cl_context /* context */,
- cl_uint /* num_devices */,
- const cl_device_id * /* device_list */,
- const size_t * /* lengths */,
- const unsigned char ** /* binaries */,
- cl_int * /* binary_status */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASEPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLBUILDPROGRAM)(cl_program /* program */,
- cl_uint /* num_devices */,
- const cl_device_id * /* device_list */,
- const char * /* options */,
- void (*pfn_notify)(cl_program /* program */, void * /* user_data */),
- void * /* user_data */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLUNLOADCOMPILER)(void) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETPROGRAMINFO)(cl_program /* program */,
- cl_program_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETPROGRAMBUILDINFO)(cl_program /* program */,
- cl_device_id /* device */,
- cl_program_build_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Kernel Object APIs
-typedef CL_API_ENTRY cl_kernel (CL_API_CALL *
-PFNCLCREATEKERNEL)(cl_program /* program */,
- const char * /* kernel_name */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLCREATEKERNELSINPROGRAM)(cl_program /* program */,
- cl_uint /* num_kernels */,
- cl_kernel * /* kernels */,
- cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASEKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLSETKERNELARG)(cl_kernel /* kernel */,
- cl_uint /* arg_index */,
- size_t /* arg_size */,
- const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETKERNELINFO)(cl_kernel /* kernel */,
- cl_kernel_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETKERNELWORKGROUPINFO)(cl_kernel /* kernel */,
- cl_device_id /* device */,
- cl_kernel_work_group_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Event Object APIs
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLWAITFOREVENTS)(cl_uint /* num_events */,
- const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETEVENTINFO)(cl_event /* event */,
- cl_event_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRETAINEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLRELEASEEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-// Profiling APIs
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLGETEVENTPROFILINGINFO)(cl_event /* event */,
- cl_profiling_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-// Flush and Finish APIs
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLFLUSH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLFINISH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-// Enqueued Commands APIs
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEREADBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_read */,
- size_t /* offset */,
- size_t /* cb */,
- void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEWRITEBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_write */,
- size_t /* offset */,
- size_t /* cb */,
- const void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* src_buffer */,
- cl_mem /* dst_buffer */,
- size_t /* src_offset */,
- size_t /* dst_offset */,
- size_t /* cb */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEREADIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* image */,
- cl_bool /* blocking_read */,
- const size_t * /* origin[3] */,
- const size_t * /* region[3] */,
- size_t /* row_pitch */,
- size_t /* slice_pitch */,
- void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEWRITEIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* image */,
- cl_bool /* blocking_write */,
- const size_t * /* origin[3] */,
- const size_t * /* region[3] */,
- size_t /* input_row_pitch */,
- size_t /* input_slice_pitch */,
- const void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* src_image */,
- cl_mem /* dst_image */,
- const size_t * /* src_origin[3] */,
- const size_t * /* dst_origin[3] */,
- const size_t * /* region[3] */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYIMAGETOBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* src_image */,
- cl_mem /* dst_buffer */,
- const size_t * /* src_origin[3] */,
- const size_t * /* region[3] */,
- size_t /* dst_offset */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUECOPYBUFFERTOIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* src_buffer */,
- cl_mem /* dst_image */,
- size_t /* src_offset */,
- const size_t * /* dst_origin[3] */,
- const size_t * /* region[3] */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY void * (CL_API_CALL *
-PFNCLENQUEUEMAPBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_map */,
- cl_map_flags /* map_flags */,
- size_t /* offset */,
- size_t /* cb */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY void * (CL_API_CALL *
-PFNCLENQUEUEMAPIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* image */,
- cl_bool /* blocking_map */,
- cl_map_flags /* map_flags */,
- const size_t * /* origin[3] */,
- const size_t * /* region[3] */,
- size_t * /* image_row_pitch */,
- size_t * /* image_slice_pitch */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEUNMAPMEMOBJECT)(cl_command_queue /* command_queue */,
- cl_mem /* memobj */,
- void * /* mapped_ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUENDRANGEKERNEL)(cl_command_queue /* command_queue */,
- cl_kernel /* kernel */,
- cl_uint /* work_dim */,
- const size_t * /* global_work_offset */,
- const size_t * /* global_work_size */,
- const size_t * /* local_work_size */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUETASK)(cl_command_queue /* command_queue */,
- cl_kernel /* kernel */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUENATIVEKERNEL)(cl_command_queue /* command_queue */,
- void (*user_func)(void *),
- void * /* args */,
- size_t /* cb_args */,
- cl_uint /* num_mem_objects */,
- const cl_mem * /* mem_list */,
- const void ** /* args_mem_loc */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEMARKER)(cl_command_queue /* command_queue */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEWAITFOREVENTS)(cl_command_queue /* command_queue */,
- cl_uint /* num_events */,
- const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
-
-typedef CL_API_ENTRY cl_int (CL_API_CALL *
-PFNCLENQUEUEBARRIER)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
-// Extension function access
-//
-// Returns the extension function address for the given function name,
-// or NULL if a valid function can not be found. The client must
-// check to make sure the address is not NULL, before using or
-// calling the returned function address.
-//
-typedef CL_API_ENTRY void * (CL_API_CALL * PFNCLGETEXTENSIONFUNCTIONADDRESS)(const char * /* func_name */) CL_API_SUFFIX__VERSION_1_0;
-
-
-#define CLEW_STATIC
-
-#ifdef CLEW_STATIC
-# define CLEWAPI extern
-#else
-# ifdef CLEW_BUILD
-# define CLEWAPI extern __declspec(dllexport)
-# else
-# define CLEWAPI extern __declspec(dllimport)
-# endif
-#endif
-
-#if defined(_WIN32)
-#define CLEW_FUN_EXPORT extern
-#else
-#define CLEW_FUN_EXPORT CLEWAPI
-#endif
-
-#define CLEW_GET_FUN(x) x
-
-
-// Variables holding function entry points
-CLEW_FUN_EXPORT PFNCLGETPLATFORMIDS __oclGetPlatformIDs ;
-CLEW_FUN_EXPORT PFNCLGETPLATFORMINFO __oclGetPlatformInfo ;
-CLEW_FUN_EXPORT PFNCLGETDEVICEIDS __oclGetDeviceIDs ;
-CLEW_FUN_EXPORT PFNCLGETDEVICEINFO __oclGetDeviceInfo ;
-CLEW_FUN_EXPORT PFNCLCREATECONTEXT __oclCreateContext ;
-CLEW_FUN_EXPORT PFNCLCREATECONTEXTFROMTYPE __oclCreateContextFromType ;
-CLEW_FUN_EXPORT PFNCLRETAINCONTEXT __oclRetainContext ;
-CLEW_FUN_EXPORT PFNCLRELEASECONTEXT __oclReleaseContext ;
-CLEW_FUN_EXPORT PFNCLGETCONTEXTINFO __oclGetContextInfo ;
-CLEW_FUN_EXPORT PFNCLCREATECOMMANDQUEUE __oclCreateCommandQueue ;
-CLEW_FUN_EXPORT PFNCLRETAINCOMMANDQUEUE __oclRetainCommandQueue ;
-CLEW_FUN_EXPORT PFNCLRELEASECOMMANDQUEUE __oclReleaseCommandQueue ;
-CLEW_FUN_EXPORT PFNCLGETCOMMANDQUEUEINFO __oclGetCommandQueueInfo ;
-CLEW_FUN_EXPORT PFNCLSETCOMMANDQUEUEPROPERTY __oclSetCommandQueueProperty ;
-CLEW_FUN_EXPORT PFNCLCREATEBUFFER __oclCreateBuffer ;
-CLEW_FUN_EXPORT PFNCLCREATEIMAGE2D __oclCreateImage2D ;
-CLEW_FUN_EXPORT PFNCLCREATEIMAGE3D __oclCreateImage3D ;
-CLEW_FUN_EXPORT PFNCLRETAINMEMOBJECT __oclRetainMemObject ;
-CLEW_FUN_EXPORT PFNCLRELEASEMEMOBJECT __oclReleaseMemObject ;
-CLEW_FUN_EXPORT PFNCLGETSUPPORTEDIMAGEFORMATS __oclGetSupportedImageFormats ;
-CLEW_FUN_EXPORT PFNCLGETMEMOBJECTINFO __oclGetMemObjectInfo ;
-CLEW_FUN_EXPORT PFNCLGETIMAGEINFO __oclGetImageInfo ;
-CLEW_FUN_EXPORT PFNCLCREATESAMPLER __oclCreateSampler ;
-CLEW_FUN_EXPORT PFNCLRETAINSAMPLER __oclRetainSampler ;
-CLEW_FUN_EXPORT PFNCLRELEASESAMPLER __oclReleaseSampler ;
-CLEW_FUN_EXPORT PFNCLGETSAMPLERINFO __oclGetSamplerInfo ;
-CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHSOURCE __oclCreateProgramWithSource ;
-CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHBINARY __oclCreateProgramWithBinary ;
-CLEW_FUN_EXPORT PFNCLRETAINPROGRAM __oclRetainProgram ;
-CLEW_FUN_EXPORT PFNCLRELEASEPROGRAM __oclReleaseProgram ;
-CLEW_FUN_EXPORT PFNCLBUILDPROGRAM __oclBuildProgram ;
-CLEW_FUN_EXPORT PFNCLUNLOADCOMPILER __oclUnloadCompiler ;
-CLEW_FUN_EXPORT PFNCLGETPROGRAMINFO __oclGetProgramInfo ;
-CLEW_FUN_EXPORT PFNCLGETPROGRAMBUILDINFO __oclGetProgramBuildInfo ;
-CLEW_FUN_EXPORT PFNCLCREATEKERNEL __oclCreateKernel ;
-CLEW_FUN_EXPORT PFNCLCREATEKERNELSINPROGRAM __oclCreateKernelsInProgram ;
-CLEW_FUN_EXPORT PFNCLRETAINKERNEL __oclRetainKernel ;
-CLEW_FUN_EXPORT PFNCLRELEASEKERNEL __oclReleaseKernel ;
-CLEW_FUN_EXPORT PFNCLSETKERNELARG __oclSetKernelArg ;
-CLEW_FUN_EXPORT PFNCLGETKERNELINFO __oclGetKernelInfo ;
-CLEW_FUN_EXPORT PFNCLGETKERNELWORKGROUPINFO __oclGetKernelWorkGroupInfo ;
-CLEW_FUN_EXPORT PFNCLWAITFOREVENTS __oclWaitForEvents ;
-CLEW_FUN_EXPORT PFNCLGETEVENTINFO __oclGetEventInfo ;
-CLEW_FUN_EXPORT PFNCLRETAINEVENT __oclRetainEvent ;
-CLEW_FUN_EXPORT PFNCLRELEASEEVENT __oclReleaseEvent ;
-CLEW_FUN_EXPORT PFNCLGETEVENTPROFILINGINFO __oclGetEventProfilingInfo ;
-CLEW_FUN_EXPORT PFNCLFLUSH __oclFlush ;
-CLEW_FUN_EXPORT PFNCLFINISH __oclFinish ;
-CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFER __oclEnqueueReadBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFER __oclEnqueueWriteBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFER __oclEnqueueCopyBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUEREADIMAGE __oclEnqueueReadImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUEWRITEIMAGE __oclEnqueueWriteImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGE __oclEnqueueCopyImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGETOBUFFER __oclEnqueueCopyImageToBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERTOIMAGE __oclEnqueueCopyBufferToImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUEMAPBUFFER __oclEnqueueMapBuffer ;
-CLEW_FUN_EXPORT PFNCLENQUEUEMAPIMAGE __oclEnqueueMapImage ;
-CLEW_FUN_EXPORT PFNCLENQUEUEUNMAPMEMOBJECT __oclEnqueueUnmapMemObject ;
-CLEW_FUN_EXPORT PFNCLENQUEUENDRANGEKERNEL __oclEnqueueNDRangeKernel ;
-CLEW_FUN_EXPORT PFNCLENQUEUETASK __oclEnqueueTask ;
-CLEW_FUN_EXPORT PFNCLENQUEUENATIVEKERNEL __oclEnqueueNativeKernel ;
-CLEW_FUN_EXPORT PFNCLENQUEUEMARKER __oclEnqueueMarker ;
-CLEW_FUN_EXPORT PFNCLENQUEUEWAITFOREVENTS __oclEnqueueWaitForEvents ;
-CLEW_FUN_EXPORT PFNCLENQUEUEBARRIER __oclEnqueueBarrier ;
-CLEW_FUN_EXPORT PFNCLGETEXTENSIONFUNCTIONADDRESS __oclGetExtensionFunctionAddress ;
-
-
-#define clGetPlatformIDs CLEW_GET_FUN(__oclGetPlatformIDs )
-#define clGetPlatformInfo CLEW_GET_FUN(__oclGetPlatformInfo )
-#define clGetDeviceIDs CLEW_GET_FUN(__oclGetDeviceIDs )
-#define clGetDeviceInfo CLEW_GET_FUN(__oclGetDeviceInfo )
-#define clCreateContext CLEW_GET_FUN(__oclCreateContext )
-#define clCreateContextFromType CLEW_GET_FUN(__oclCreateContextFromType )
-#define clRetainContext CLEW_GET_FUN(__oclRetainContext )
-#define clReleaseContext CLEW_GET_FUN(__oclReleaseContext )
-#define clGetContextInfo CLEW_GET_FUN(__oclGetContextInfo )
-#define clCreateCommandQueue CLEW_GET_FUN(__oclCreateCommandQueue )
-#define clRetainCommandQueue CLEW_GET_FUN(__oclRetainCommandQueue )
-#define clReleaseCommandQueue CLEW_GET_FUN(__oclReleaseCommandQueue )
-#define clGetCommandQueueInfo CLEW_GET_FUN(__oclGetCommandQueueInfo )
-#define clSetCommandQueueProperty CLEW_GET_FUN(__oclSetCommandQueueProperty )
-#define clCreateBuffer CLEW_GET_FUN(__oclCreateBuffer )
-#define clCreateImage2D CLEW_GET_FUN(__oclCreateImage2D )
-#define clCreateImage3D CLEW_GET_FUN(__oclCreateImage3D )
-#define clRetainMemObject CLEW_GET_FUN(__oclRetainMemObject )
-#define clReleaseMemObject CLEW_GET_FUN(__oclReleaseMemObject )
-#define clGetSupportedImageFormats CLEW_GET_FUN(__oclGetSupportedImageFormats )
-#define clGetMemObjectInfo CLEW_GET_FUN(__oclGetMemObjectInfo )
-#define clGetImageInfo CLEW_GET_FUN(__oclGetImageInfo )
-#define clCreateSampler CLEW_GET_FUN(__oclCreateSampler )
-#define clRetainSampler CLEW_GET_FUN(__oclRetainSampler )
-#define clReleaseSampler CLEW_GET_FUN(__oclReleaseSampler )
-#define clGetSamplerInfo CLEW_GET_FUN(__oclGetSamplerInfo )
-#define clCreateProgramWithSource CLEW_GET_FUN(__oclCreateProgramWithSource )
-#define clCreateProgramWithBinary CLEW_GET_FUN(__oclCreateProgramWithBinary )
-#define clRetainProgram CLEW_GET_FUN(__oclRetainProgram )
-#define clReleaseProgram CLEW_GET_FUN(__oclReleaseProgram )
-#define clBuildProgram CLEW_GET_FUN(__oclBuildProgram )
-#define clUnloadCompiler CLEW_GET_FUN(__oclUnloadCompiler )
-#define clGetProgramInfo CLEW_GET_FUN(__oclGetProgramInfo )
-#define clGetProgramBuildInfo CLEW_GET_FUN(__oclGetProgramBuildInfo )
-#define clCreateKernel CLEW_GET_FUN(__oclCreateKernel )
-#define clCreateKernelsInProgram CLEW_GET_FUN(__oclCreateKernelsInProgram )
-#define clRetainKernel CLEW_GET_FUN(__oclRetainKernel )
-#define clReleaseKernel CLEW_GET_FUN(__oclReleaseKernel )
-#define clSetKernelArg CLEW_GET_FUN(__oclSetKernelArg )
-#define clGetKernelInfo CLEW_GET_FUN(__oclGetKernelInfo )
-#define clGetKernelWorkGroupInfo CLEW_GET_FUN(__oclGetKernelWorkGroupInfo )
-#define clWaitForEvents CLEW_GET_FUN(__oclWaitForEvents )
-#define clGetEventInfo CLEW_GET_FUN(__oclGetEventInfo )
-#define clRetainEvent CLEW_GET_FUN(__oclRetainEvent )
-#define clReleaseEvent CLEW_GET_FUN(__oclReleaseEvent )
-#define clGetEventProfilingInfo CLEW_GET_FUN(__oclGetEventProfilingInfo )
-#define clFlush CLEW_GET_FUN(__oclFlush )
-#define clFinish CLEW_GET_FUN(__oclFinish )
-#define clEnqueueReadBuffer CLEW_GET_FUN(__oclEnqueueReadBuffer )
-#define clEnqueueWriteBuffer CLEW_GET_FUN(__oclEnqueueWriteBuffer )
-#define clEnqueueCopyBuffer CLEW_GET_FUN(__oclEnqueueCopyBuffer )
-#define clEnqueueReadImage CLEW_GET_FUN(__oclEnqueueReadImage )
-#define clEnqueueWriteImage CLEW_GET_FUN(__oclEnqueueWriteImage )
-#define clEnqueueCopyImage CLEW_GET_FUN(__oclEnqueueCopyImage )
-#define clEnqueueCopyImageToBuffer CLEW_GET_FUN(__oclEnqueueCopyImageToBuffer )
-#define clEnqueueCopyBufferToImage CLEW_GET_FUN(__oclEnqueueCopyBufferToImage )
-#define clEnqueueMapBuffer CLEW_GET_FUN(__oclEnqueueMapBuffer )
-#define clEnqueueMapImage CLEW_GET_FUN(__oclEnqueueMapImage )
-#define clEnqueueUnmapMemObject CLEW_GET_FUN(__oclEnqueueUnmapMemObject )
-#define clEnqueueNDRangeKernel CLEW_GET_FUN(__oclEnqueueNDRangeKernel )
-#define clEnqueueTask CLEW_GET_FUN(__oclEnqueueTask )
-#define clEnqueueNativeKernel CLEW_GET_FUN(__oclEnqueueNativeKernel )
-#define clEnqueueMarker CLEW_GET_FUN(__oclEnqueueMarker )
-#define clEnqueueWaitForEvents CLEW_GET_FUN(__oclEnqueueWaitForEvents )
-#define clEnqueueBarrier CLEW_GET_FUN(__oclEnqueueBarrier )
-#define clGetExtensionFunctionAddress CLEW_GET_FUN(__oclGetExtensionFunctionAddress )
-
-#endif // CLCC_GENERATE_DOCUMENTATION
-
-#define CLEW_SUCCESS 0 //!< Success error code
-#define CLEW_ERROR_OPEN_FAILED -1 //!< Error code for failing to open the dynamic library
-#define CLEW_ERROR_ATEXIT_FAILED -2 //!< Error code for failing to queue the closing of the dynamic library to atexit()
-
-//! \brief Load OpenCL dynamic library and set function entry points
-int clewInit (const char*);
-//! \brief Convert an OpenCL error code to its string equivalent
-const char* clewErrorString (cl_int error);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // CLCC_CLEW_HPP_INCLUDED
diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp
index f3d159d67ef..17bb3817908 100644
--- a/intern/rigidbody/rb_bullet_api.cpp
+++ b/intern/rigidbody/rb_bullet_api.cpp
@@ -390,7 +390,7 @@ float RB_body_get_mass(rbRigidBody *object)
float value = (float)body->getInvMass();
if (value)
- value = 1.0 / value;
+ value = 1.0f / value;
return value;
}
diff --git a/intern/smoke/intern/tnt/tnt_math_utils.h b/intern/smoke/intern/tnt/tnt_math_utils.h
index 9226bc4e753..9f6bd10e23f 100644
--- a/intern/smoke/intern/tnt/tnt_math_utils.h
+++ b/intern/smoke/intern/tnt/tnt_math_utils.h
@@ -7,10 +7,6 @@
/* needed for fabs, sqrt() below */
#include <cmath>
-#if defined(_MSC_VER) && (_MSC_VER < 1800)
-#define hypot _hypot
-#endif
-
namespace TNT
{
/**
diff --git a/release/darwin/README_codesigning.txt b/release/darwin/README_codesigning.txt
index d2ead00da8a..3724ad1b0ac 100644
--- a/release/darwin/README_codesigning.txt
+++ b/release/darwin/README_codesigning.txt
@@ -1,11 +1,12 @@
Tutorial for codesigning Blender releases on OSX ( atm. i do manually when needed ):
+Updated as by august 01.2014 - removed deprecated rules and not recommended deep codesigning
1. You need to obtain the certificates for blender foundation, they can bw pulled at Apple developer account for BF
2. Run the following commands from terminal:
-codesign -s <IDENTITY> <path_to_blender.app> --resource-rules <path_to_blender_source>/release/darwin/codesigning_rules_blender.plist --deep
+codesign -s <IDENTITY> <path_to_blender.app>
-codesign -s <IDENTITY> <path_to_blenderplayer.app> --resource-rules <path_to_blender_source>/release/darwin/codesigning_rules_player.plist --deep
+codesign -s <IDENTITY> <path_to_blenderplayer.app>
3. Checking:
diff --git a/release/darwin/codesigning_rules_blender.plist b/release/darwin/codesigning_rules_blender.plist
deleted file mode 100644
index 5e6198e8ce7..00000000000
--- a/release/darwin/codesigning_rules_blender.plist
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>rules</key>
- <dict>
- <!-- Exclude datafiles, python and scripts -->
- <key>^MacOS/2.71</key>
- <false/>
- <key>^Resources/</key>
- <true/>
- </dict>
-</dict>
-</plist>
diff --git a/release/darwin/codesigning_rules_player.plist b/release/darwin/codesigning_rules_player.plist
deleted file mode 100644
index acbdab20db9..00000000000
--- a/release/darwin/codesigning_rules_player.plist
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>rules</key>
- <dict>
- <!-- Exclude datafiles, python and scripts -->
- <key>^MacOS/2.71</key>
- <false/>
- <!-- Exclude Resources for placing game.blend and own icons -->
- <key>^Resources/</key>
- <false/>
- </dict>
-</dict>
-</plist>
diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg
index 7557b81c804..4a1e2cd1d9a 100644
--- a/release/datafiles/blender_icons.svg
+++ b/release/datafiles/blender_icons.svg
@@ -14,7 +14,7 @@
height="640"
id="svg2"
sodipodi:version="0.32"
- inkscape:version="0.48.4 r"
+ inkscape:version="0.48.5 r10040"
version="1.0"
sodipodi:docname="blender_icons.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
@@ -27,6 +27,17 @@
<defs
id="defs4">
<linearGradient
+ id="linearGradient17265">
+ <stop
+ style="stop-color:#ffb769;stop-opacity:1;"
+ offset="0"
+ id="stop17267" />
+ <stop
+ style="stop-color:#ffeeaa;stop-opacity:0;"
+ offset="1"
+ id="stop17269" />
+ </linearGradient>
+ <linearGradient
id="linearGradient17073">
<stop
style="stop-color:#2561b7;stop-opacity:1;"
@@ -28232,6 +28243,79 @@
id="linearGradient16728"
xlink:href="#linearGradient44939-8-53-7"
inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-0"
+ id="linearGradient36725-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ id="linearGradient319-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-22" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-19" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-0"
+ id="linearGradient36727-5"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ id="linearGradient16404-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16406" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16408" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-0"
+ id="linearGradient36729-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,61.99991,2.2419)"
+ x1="260.67468"
+ y1="108.02418"
+ x2="273.9993"
+ y2="126.37626" />
+ <linearGradient
+ id="linearGradient16411">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16413" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16415" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17265"
+ id="radialGradient17275"
+ cx="1130.7738"
+ cy="440.25275"
+ fx="1130.7738"
+ fy="440.25275"
+ r="3.5"
+ gradientTransform="matrix(1.4878857,2.6976762,-1.4698319,0.81067624,95.409128,-2969.0604)"
+ gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
@@ -88543,6 +88627,135 @@
inkscape:connector-curvature="0" />
</g>
</g>
+ <g
+ transform="translate(21,0)"
+ style="display:inline;enable-background:new"
+ id="g106643-9">
+ <g
+ transform="translate(111,-158)"
+ id="g35778-7"
+ style="opacity:0.55;display:inline">
+ <rect
+ y="336"
+ x="-64"
+ height="16"
+ width="16"
+ id="rect35780-2"
+ 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" />
+ <g
+ id="g35782-9"
+ transform="translate(1,0)">
+ <g
+ id="g35785-7"
+ transform="translate(-386,446.5)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#552200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 329.5,-108.25 -5.5,2 0,6.75 5.5,3 5.5,-3 0,-6.75 -5.5,-2 z"
+ id="path35787-2" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ id="path35789-6"
+ d="m 324,-99.5 0,-7 6,-1.75 0,11.5 -0.5,0.25 -5.5,-3 z"
+ style="fill:#c9c9c9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06898749px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="cccccc" />
+ <g
+ id="g35791-0"
+ transform="translate(179,-179)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ id="path35793-5"
+ d="m 156,79.5 0,-7 -5,-1.75 0,11.5 5,-2.75 z"
+ style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path35795-5"
+ d="m 145,72.5 5.5,-2 5.5,2 -5.5,2.5 -5.5,-2.5 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ id="path35797-0"
+ d="m 334.5,-106.5 0,6.75 -5,2.75 -5,-2.75 0,-6.75"
+ style="fill:none;stroke:url(#linearGradient36725-1);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <rect
+ y="342"
+ x="-57"
+ height="7.75"
+ width="1"
+ id="rect35799-0"
+ style="fill:url(#linearGradient36727-5);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path35801-8"
+ d="m -61,340.65468 c 0,0 4.5,2 4.5,2 l 4.5,-2"
+ style="fill:none;stroke:url(#linearGradient36729-0);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ </g>
+ <rect
+ style="opacity:0.07999998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37868-0-4-8-7"
+ width="3.0000007"
+ height="7.25"
+ x="54"
+ y="185" />
+ <g
+ id="g35818-3"
+ style="fill:url(#radialGradient17275);display:inline;fill-opacity:1"
+ transform="translate(-1080.9861,-256)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ style="fill:url(#radialGradient17275);fill-opacity:1;fill-rule:nonzero;stroke:#542b00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.86274510000000004;stroke-dasharray:none;stroke-dashoffset:7.40000265000000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 1130.4859,445.25 0,-7.5 6,2.75 0,8 -6,-3.25 z"
+ id="path35820-8"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path35822-7"
+ d="m 1136.4859,448.5 -6,-3.25 0,-7.5"
+ style="fill:url(#radialGradient17275);stroke:#462400;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265000000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;fill-opacity:1"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <g
+ transform="translate(41.999513,2.6999762e-4)"
+ style="display:inline;enable-background:new"
+ id="g35803-8">
+ <path
+ style="fill:none;stroke:#542b00;stroke-width:1.495;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 8.0048608,180.50566 0.036785,0 c 0.8181814,0 1.476865,0.66665 1.476865,1.49473 l 0,1.2e-4 c 0,0.82808 -0.6586836,1.49472 -1.476865,1.49472 l -0.036785,0 c -0.8181897,0 -1.4768733,-0.66664 -1.4768733,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.6586836,-1.49473 1.4768733,-1.49473 z"
+ id="path35805-7"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 9.0203881,181.00394 c -0.6673195,0 -1.334639,1e-5 -2.0019585,1e-5 0,0.66706 0,1.33411 0,2.00119 0.6673195,0 1.334639,-1e-5 2.0019585,-1e-5 0,-0.66707 0,-1.33413 0,-2.00119 z"
+ id="path35807-6"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
</g>
<g
inkscape:groupmode="layer"
diff --git a/release/datafiles/blender_icons16/icon16_ipo_bounce.dat b/release/datafiles/blender_icons16/icon16_ipo_bounce.dat
index bede5e12e57..7a3984a3a13 100644
--- a/release/datafiles/blender_icons16/icon16_ipo_bounce.dat
+++ b/release/datafiles/blender_icons16/icon16_ipo_bounce.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_ipo_elastic.dat b/release/datafiles/blender_icons16/icon16_ipo_elastic.dat
index 5db0f974912..221b0a22236 100644
--- a/release/datafiles/blender_icons16/icon16_ipo_elastic.dat
+++ b/release/datafiles/blender_icons16/icon16_ipo_elastic.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_loopsel.dat b/release/datafiles/blender_icons16/icon16_loopsel.dat
new file mode 100644
index 00000000000..78f9bbe1a6f
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_loopsel.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_loopsel.dat b/release/datafiles/blender_icons32/icon32_loopsel.dat
new file mode 100644
index 00000000000..11d3e9d284e
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_loopsel.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_nla_pushdown.dat b/release/datafiles/blender_icons32/icon32_nla_pushdown.dat
index 83216ac5367..3a0e1c73a52 100644
--- a/release/datafiles/blender_icons32/icon32_nla_pushdown.dat
+++ b/release/datafiles/blender_icons32/icon32_nla_pushdown.dat
Binary files differ
diff --git a/release/datafiles/prvicons_update.py b/release/datafiles/prvicons_update.py
index ecc466aab72..448a43df9ce 100755
--- a/release/datafiles/prvicons_update.py
+++ b/release/datafiles/prvicons_update.py
@@ -2,9 +2,16 @@
# This script updates icons from the SVG file
import os
+import sys
BASEDIR = os.path.abspath(os.path.dirname(__file__)) + os.sep
-cmd = 'inkscape "%sprvicons.svg" --without-gui --export-png="%sprvicons.png"' % (BASEDIR, BASEDIR)
-os.system(cmd)
+inkscape_path = 'inkscape'
+
+if sys.platform == 'darwin':
+ inkscape_app_path = '/Applications/Inkscape.app/Contents/Resources/script'
+ if os.path.exists(inkscape_app_path):
+ inkscape_path = inkscape_app_path
+cmd = inkscape_path + ' "%sprvicons.svg" --without-gui --export-png="%sprvicons.png"' % (BASEDIR, BASEDIR)
+os.system(cmd)
diff --git a/release/scripts/freestyle/modules/freestyle/chainingiterators.py b/release/scripts/freestyle/modules/freestyle/chainingiterators.py
index 5cd0dfeff59..8d144bf17fd 100644
--- a/release/scripts/freestyle/modules/freestyle/chainingiterators.py
+++ b/release/scripts/freestyle/modules/freestyle/chainingiterators.py
@@ -77,7 +77,7 @@ NATURES = (
def nature_in_preceding(nature, index):
- """ Returns True if given nature appears before index, else False """
+ """Returns True if given nature appears before index, else False."""
return any(nature & nat for nat in NATURES[:index])
diff --git a/release/scripts/freestyle/modules/freestyle/functions.py b/release/scripts/freestyle/modules/freestyle/functions.py
index 9e03f8f5dbb..674c1f01864 100644
--- a/release/scripts/freestyle/modules/freestyle/functions.py
+++ b/release/scripts/freestyle/modules/freestyle/functions.py
@@ -19,7 +19,7 @@
"""
Functions operating on vertices (0D elements) and polylines (1D
elements). Also intended to be a collection of examples for predicate
-definition in Python
+definition in Python.
"""
# module members
@@ -91,7 +91,6 @@ from freestyle.utils import integrate
from mathutils import Vector
-
# -- Functions for 0D elements (vertices) -- #
@@ -101,18 +100,17 @@ class CurveMaterialF0D(UnaryFunction0DMaterial):
MaterialF0D does not work with Curves and Strokes. Line color
priority is used to pick one of the two materials at material
boundaries.
+
+ Note: expects instances of CurvePoint to be iterated over
"""
def __call__(self, inter):
- cp = inter.object
- assert(isinstance(cp, CurvePoint))
- fe = cp.first_svertex.get_fedge(cp.second_svertex)
+ fe = inter.object.fedge
assert(fe is not None), "CurveMaterialF0D: fe is None"
if fe.is_smooth:
return fe.material
- elif fe.material_right.priority > fe.material_left.priority:
- return fe.material_right
else:
- return fe.material_left
+ right, left = fe.material_right, fe.material_left
+ return right if (right.priority > left.priority) else left
class pyInverseCurvature2DAngleF0D(UnaryFunction0DDouble):
@@ -130,8 +128,8 @@ class pyCurvilinearLengthF0D(UnaryFunction0DDouble):
class pyDensityAnisotropyF0D(UnaryFunction0DDouble):
- """Estimates the anisotropy of density"""
- def __init__(self,level):
+ """Estimates the anisotropy of density."""
+ def __init__(self, level):
UnaryFunction0DDouble.__init__(self)
self.IsoDensity = ReadCompleteViewMapPixelF0D(level)
self.d0Density = ReadSteerableViewMapPixelF0D(0, level)
@@ -145,13 +143,13 @@ class pyDensityAnisotropyF0D(UnaryFunction0DDouble):
c_1 = self.d1Density(inter)
c_2 = self.d2Density(inter)
c_3 = self.d3Density(inter)
- cMax = max(max(c_0,c_1), max(c_2,c_3))
- cMin = min(min(c_0,c_1), min(c_2,c_3))
- return 0 if (c_iso == 0) else (cMax-cMin) / c_iso
+ cMax = max(max(c_0, c_1), max(c_2, c_3))
+ cMin = min(min(c_0, c_1), min(c_2, c_3))
+ return 0 if (c_iso == 0) else (cMax - cMin) / c_iso
class pyViewMapGradientVectorF0D(UnaryFunction0DVec2f):
- """Returns the gradient vector for a pixel
+ """Returns the gradient vector for a pixel.
:arg level: the level at which to compute the gradient
:type level: int
@@ -163,9 +161,9 @@ class pyViewMapGradientVectorF0D(UnaryFunction0DVec2f):
def __call__(self, iter):
p = iter.object.point_2d
- gx = CF.read_complete_view_map_pixel(self._l, int(p.x+self._step), int(p.y)) - \
+ gx = CF.read_complete_view_map_pixel(self._l, int(p.x + self._step), int(p.y)) - \
CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
- gy = CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y+self._step)) - \
+ gy = CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y + self._step)) - \
CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
return Vector((gx, gy))
@@ -184,7 +182,6 @@ class pyViewMapGradientNormF0D(UnaryFunction0DDouble):
CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
return Vector((gx, gy)).length
-
# -- Functions for 1D elements (curves) -- #
@@ -199,11 +196,11 @@ class pyGetSquareInverseProjectedZF1D(UnaryFunction1DDouble):
def __call__(self, inter):
func = GetProjectedZF1D()
z = func(inter)
- return (1.0 - z*z)
+ return (1.0 - pow(z, 2))
class pyDensityAnisotropyF1D(UnaryFunction1DDouble):
- def __init__(self,level, integrationType=IntegrationType.MEAN, sampling=2.0):
+ def __init__(self, level, integrationType=IntegrationType.MEAN, sampling=2.0):
UnaryFunction1DDouble.__init__(self, integrationType)
self._func = pyDensityAnisotropyF0D(level)
self._integration = integrationType
@@ -215,7 +212,7 @@ class pyDensityAnisotropyF1D(UnaryFunction1DDouble):
class pyViewMapGradientNormF1D(UnaryFunction1DDouble):
- def __init__(self,l, integrationType, sampling=2.0):
+ def __init__(self, l, integrationType, sampling=2.0):
UnaryFunction1DDouble.__init__(self, integrationType)
self._func = pyViewMapGradientNormF0D(l)
self._integration = integrationType
diff --git a/release/scripts/freestyle/modules/freestyle/predicates.py b/release/scripts/freestyle/modules/freestyle/predicates.py
index fede3e3e2da..344b89d869c 100644
--- a/release/scripts/freestyle/modules/freestyle/predicates.py
+++ b/release/scripts/freestyle/modules/freestyle/predicates.py
@@ -46,12 +46,13 @@ from _freestyle import (
# constructs for predicate definition in Python
from freestyle.types import (
BinaryPredicate1D,
+ Id,
IntegrationType,
+ Interface0DIterator,
Nature,
TVertex,
UnaryPredicate0D,
UnaryPredicate1D,
- Id,
)
from freestyle.functions import (
Curvature2DAngleF0D,
@@ -82,11 +83,10 @@ class pyHigherCurvature2DAngleUP0D(UnaryPredicate0D):
def __init__(self, a):
UnaryPredicate0D.__init__(self)
self._a = a
+ self.func = Curvature2DAngleF0D()
def __call__(self, inter):
- func = Curvature2DAngleF0D()
- a = func(inter)
- return (a > self._a)
+ return (self.func(inter) > self._a)
class pyUEqualsUP0D(UnaryPredicate0D):
@@ -102,7 +102,7 @@ class pyUEqualsUP0D(UnaryPredicate0D):
class pyVertexNatureUP0D(UnaryPredicate0D):
- def __init__(self,nature):
+ def __init__(self, nature):
UnaryPredicate0D.__init__(self)
self._nature = nature
@@ -112,9 +112,8 @@ class pyVertexNatureUP0D(UnaryPredicate0D):
class pyBackTVertexUP0D(UnaryPredicate0D):
"""
- Check whether an Interface0DIterator
- references a TVertex and is the one that is
- hidden (inferred from the context)
+ Check whether an Interface0DIterator references a TVertex and is
+ the one that is hidden (inferred from the context).
"""
def __init__(self):
UnaryPredicate0D.__init__(self)
@@ -127,7 +126,7 @@ class pyBackTVertexUP0D(UnaryPredicate0D):
class pyParameterUP0DGoodOne(UnaryPredicate0D):
- def __init__(self,pmin,pmax):
+ def __init__(self, pmin, pmax):
UnaryPredicate0D.__init__(self)
self._m = pmin
self._M = pmax
@@ -138,7 +137,7 @@ class pyParameterUP0DGoodOne(UnaryPredicate0D):
class pyParameterUP0D(UnaryPredicate0D):
- def __init__(self,pmin,pmax):
+ def __init__(self, pmin, pmax):
UnaryPredicate0D.__init__(self)
self._m = pmin
self._M = pmax
@@ -154,13 +153,13 @@ class pyParameterUP0D(UnaryPredicate0D):
# -- Unary predicates for 1D elements (curves) -- #
-
class AndUP1D(UnaryPredicate1D):
def __init__(self, *predicates):
UnaryPredicate1D.__init__(self)
self.predicates = predicates
- if len(self.predicates) < 2:
- raise ValueError("Expected two or more UnaryPredicate1D")
+ # there are cases in which only one predicate is supplied (in the parameter editor)
+ if len(self.predicates) < 1:
+ raise ValueError("Expected one or more UnaryPredicate1D, got ", len(predicates))
def __call__(self, inter):
return all(pred(inter) for pred in self.predicates)
@@ -170,8 +169,9 @@ class OrUP1D(UnaryPredicate1D):
def __init__(self, *predicates):
UnaryPredicate1D.__init__(self)
self.predicates = predicates
- if len(self.predicates) < 2:
- raise ValueError("Expected two or more UnaryPredicate1D")
+ # there are cases in which only one predicate is supplied (in the parameter editor)
+ if len(self.predicates) < 1:
+ raise ValueError("Expected one or more UnaryPredicate1D, got ", len(predicates))
def __call__(self, inter):
return any(pred(inter) for pred in self.predicates)
@@ -230,7 +230,7 @@ class pyHigherLengthUP1D(UnaryPredicate1D):
class pyNatureUP1D(UnaryPredicate1D):
- def __init__(self,nature):
+ def __init__(self, nature):
UnaryPredicate1D.__init__(self)
self._nature = nature
self._getNature = CurveNatureF1D()
@@ -244,12 +244,14 @@ class pyHigherNumberOfTurnsUP1D(UnaryPredicate1D):
UnaryPredicate1D.__init__(self)
self._n = n
self._a = a
+ self.func = Curvature2DAngleF0D()
def __call__(self, inter):
- func = Curvature2DAngleF0D()
- it = inter.vertices_begin()
+ it = Interface0DIterator(inter)
# sum the turns, check against n
- return sum(1 for ve in it if func(it) > self._a) > self._n
+ return sum(1 for _ in it if self.func(it) > self._a) > self._n
+ # interesting fact, the line above is 70% faster than:
+ # return sum(self.func(it) > self._a for _ in it) > self._n
class pyDensityUP1D(UnaryPredicate1D):
@@ -345,7 +347,7 @@ class pyZSmallerUP1D(UnaryPredicate1D):
class pyIsOccludedByUP1D(UnaryPredicate1D):
- def __init__(self,id):
+ def __init__(self, id):
UnaryPredicate1D.__init__(self)
if not isinstance(id, Id):
raise TypeError("pyIsOccludedByUP1D expected freestyle.types.Id, not " + type(id).__name__)
@@ -376,7 +378,7 @@ class pyIsOccludedByUP1D(UnaryPredicate1D):
class pyIsInOccludersListUP1D(UnaryPredicate1D):
- def __init__(self,id):
+ def __init__(self, id):
UnaryPredicate1D.__init__(self)
self._id = id
@@ -409,7 +411,7 @@ class pyIsOccludedByIdListUP1D(UnaryPredicate1D):
class pyShapeIdListUP1D(UnaryPredicate1D):
- def __init__(self,idlist):
+ def __init__(self, idlist):
UnaryPredicate1D.__init__(self)
self._funcs = tuple(ShapeUP1D(_id, 0) for _id in idlist)
@@ -417,7 +419,7 @@ class pyShapeIdListUP1D(UnaryPredicate1D):
return any(func(inter) for func in self._funcs)
-## deprecated
+# DEPRECATED
class pyShapeIdUP1D(UnaryPredicate1D):
def __init__(self, _id):
UnaryPredicate1D.__init__(self)
@@ -429,7 +431,7 @@ class pyShapeIdUP1D(UnaryPredicate1D):
class pyHighDensityAnisotropyUP1D(UnaryPredicate1D):
- def __init__(self,threshold, level, sampling=2.0):
+ def __init__(self, threshold, level, sampling=2.0):
UnaryPredicate1D.__init__(self)
self._l = threshold
self.func = pyDensityAnisotropyF1D(level, IntegrationType.MEAN, sampling)
@@ -439,7 +441,7 @@ class pyHighDensityAnisotropyUP1D(UnaryPredicate1D):
class pyHighViewMapGradientNormUP1D(UnaryPredicate1D):
- def __init__(self,threshold, l, sampling=2.0):
+ def __init__(self, threshold, l, sampling=2.0):
UnaryPredicate1D.__init__(self)
self._threshold = threshold
self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN)
@@ -463,8 +465,9 @@ class pyDensityVariableSigmaUP1D(UnaryPredicate1D):
self._sampling = sampling
def __call__(self, inter):
- sigma = (self._sigmaMax-self._sigmaMin)/(self._lmax-self._lmin)*(self._functor(inter)-self._lmin) + self._sigmaMin
- t = (self._tmax-self._tmin)/(self._lmax-self._lmin)*(self._functor(inter)-self._lmin) + self._tmin
+ result = self._functor(inter) - self._lmin
+ sigma = (self._sigmaMax - self._sigmaMin) / (self._lmax - self._lmin) * result + self._sigmaMin
+ t = (self._tmax - self._tmin) / (self._lmax - self._lmin) * result + self._tmin
sigma = max(sigma, self._sigmaMin)
self._func = DensityF1D(sigma, self._integration, self._sampling)
return (self._func(inter) < t)
@@ -480,13 +483,12 @@ class pyClosedCurveUP1D(UnaryPredicate1D):
# -- Binary predicates for 1D elements (curves) -- #
-
class AndBP1D(BinaryPredicate1D):
def __init__(self, *predicates):
BinaryPredicate1D.__init__(self)
self._predicates = predicates
if len(self.predicates) < 2:
- raise ValueError("Expected two or more BinaryPredicate1D")
+ raise ValueError("Expected two or more BinaryPredicate1D, got ", len(predictates))
def __call__(self, i1, i2):
return all(pred(i1, i2) for pred in self._predicates)
@@ -497,7 +499,7 @@ class OrBP1D(BinaryPredicate1D):
BinaryPredicate1D.__init__(self)
self._predicates = predicates
if len(self.predicates) < 2:
- raise ValueError("Expected two or more BinaryPredicate1D")
+ raise ValueError("Expected two or more BinaryPredicate1D, got ", len(predictates))
def __call__(self, i1, i2):
return any(pred(i1, i2) for pred in self._predicates)
@@ -551,11 +553,11 @@ class pyNatureBP1D(BinaryPredicate1D):
class pyViewMapGradientNormBP1D(BinaryPredicate1D):
- def __init__(self,l, sampling=2.0):
+ def __init__(self, l, sampling=2.0):
BinaryPredicate1D.__init__(self)
self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN)
- def __call__(self, i1,i2):
+ def __call__(self, i1, i2):
return (self._GetGradient(i1) > self._GetGradient(i2))
@@ -565,4 +567,4 @@ class pyShuffleBP1D(BinaryPredicate1D):
random.seed = 1
def __call__(self, inter1, inter2):
- return (random.uniform(0,1) < random.uniform(0,1))
+ return (random.uniform(0, 1) < random.uniform(0, 1))
diff --git a/release/scripts/freestyle/modules/freestyle/shaders.py b/release/scripts/freestyle/modules/freestyle/shaders.py
index 8a9faf26017..502d9b69a97 100644
--- a/release/scripts/freestyle/modules/freestyle/shaders.py
+++ b/release/scripts/freestyle/modules/freestyle/shaders.py
@@ -23,7 +23,7 @@
"""
Stroke shaders used for creation of stylized strokes. Also intended
-to be a collection of examples for shader definition in Python
+to be a collection of examples for shader definition in Python.
"""
# module members
@@ -100,7 +100,7 @@ from random import randint
class pyDepthDiscontinuityThicknessShader(StrokeShader):
"""
Assigns a thickness to the stroke based on the stroke's distance
- to the camera (Z-value)
+ to the camera (Z-value).
"""
def __init__(self, min, max):
StrokeShader.__init__(self)
@@ -118,7 +118,7 @@ class pyDepthDiscontinuityThicknessShader(StrokeShader):
class pyConstantThicknessShader(StrokeShader):
"""
- Assigns a constant thickness along the stroke
+ Assigns a constant thickness along the stroke.
"""
def __init__(self, thickness):
StrokeShader.__init__(self)
@@ -131,7 +131,7 @@ class pyConstantThicknessShader(StrokeShader):
class pyFXSVaryingThicknessWithDensityShader(StrokeShader):
"""
- Assings thickness to a stroke based on the density of the diffuse map
+ Assings thickness to a stroke based on the density of the diffuse map.
"""
def __init__(self, wsize, threshold_min, threshold_max, thicknessMin, thicknessMax):
StrokeShader.__init__(self)
@@ -155,7 +155,7 @@ class pyFXSVaryingThicknessWithDensityShader(StrokeShader):
class pyIncreasingThicknessShader(StrokeShader):
"""
- Increasingly thickens the stroke
+ Increasingly thickens the stroke.
"""
def __init__(self, thicknessMin, thicknessMax):
StrokeShader.__init__(self)
@@ -176,7 +176,7 @@ class pyIncreasingThicknessShader(StrokeShader):
class pyConstrainedIncreasingThicknessShader(StrokeShader):
"""
Increasingly thickens the stroke, constrained by a ratio of the
- stroke's length
+ stroke's length.
"""
def __init__(self, thicknessMin, thicknessMax, ratio):
StrokeShader.__init__(self)
@@ -203,7 +203,7 @@ class pyConstrainedIncreasingThicknessShader(StrokeShader):
class pyDecreasingThicknessShader(StrokeShader):
"""
- Inverse of pyIncreasingThicknessShader, decreasingly thickens the stroke
+ Inverse of pyIncreasingThicknessShader, decreasingly thickens the stroke.
"""
def __init__(self, thicknessMin, thicknessMax):
StrokeShader.__init__(self)
@@ -224,7 +224,7 @@ class pyDecreasingThicknessShader(StrokeShader):
class pyNonLinearVaryingThicknessShader(StrokeShader):
"""
- Assigns thickness to a stroke based on an exponential function
+ Assigns thickness to a stroke based on an exponential function.
"""
def __init__(self, thicknessExtremity, thicknessMiddle, exponent):
self._thicknessMin = thicknessMiddle
@@ -243,7 +243,7 @@ class pyNonLinearVaryingThicknessShader(StrokeShader):
class pySLERPThicknessShader(StrokeShader):
"""
- Assigns thickness to a stroke based on spherical linear interpolation
+ Assigns thickness to a stroke based on spherical linear interpolation.
"""
def __init__(self, thicknessMin, thicknessMax, omega=1.2):
StrokeShader.__init__(self)
@@ -267,7 +267,7 @@ class pySLERPThicknessShader(StrokeShader):
class pyTVertexThickenerShader(StrokeShader):
"""
- Thickens TVertices (visual intersections between two edges)
+ Thickens TVertices (visual intersections between two edges).
"""
def __init__(self, a=1.5, n=3):
StrokeShader.__init__(self)
@@ -297,7 +297,7 @@ class pyImportance2DThicknessShader(StrokeShader):
"""
Assigns thickness based on distance to a given point in 2D space.
the thickness is inverted, so the vertices closest to the
- specified point have the lowest thickness
+ specified point have the lowest thickness.
"""
def __init__(self, x, y, w, kmin, kmax):
StrokeShader.__init__(self)
@@ -317,7 +317,7 @@ class pyImportance2DThicknessShader(StrokeShader):
class pyImportance3DThicknessShader(StrokeShader):
"""
- Assigns thickness based on distance to a given point in 3D space
+ Assigns thickness based on distance to a given point in 3D space.
"""
def __init__(self, x, y, z, w, kmin, kmax):
StrokeShader.__init__(self)
@@ -338,7 +338,7 @@ class pyImportance3DThicknessShader(StrokeShader):
class pyZDependingThicknessShader(StrokeShader):
"""
Assigns thickness based on an object's local Z depth (point
- closest to camera is 1, point furthest from camera is zero)
+ closest to camera is 1, point furthest from camera is zero).
"""
def __init__(self, min, max):
StrokeShader.__init__(self)
@@ -363,7 +363,7 @@ class pyZDependingThicknessShader(StrokeShader):
class pyConstantColorShader(StrokeShader):
"""
- Assigns a constant color to the stroke
+ Assigns a constant color to the stroke.
"""
def __init__(self,r,g,b, a = 1):
StrokeShader.__init__(self)
@@ -377,7 +377,7 @@ class pyConstantColorShader(StrokeShader):
class pyIncreasingColorShader(StrokeShader):
"""
- Fades from one color to another along the stroke
+ Fades from one color to another along the stroke.
"""
def __init__(self,r1,g1,b1,a1, r2,g2,b2,a2):
StrokeShader.__init__(self)
@@ -397,7 +397,7 @@ class pyIncreasingColorShader(StrokeShader):
class pyInterpolateColorShader(StrokeShader):
"""
- Fades from one color to another and back
+ Fades from one color to another and back.
"""
def __init__(self,r1,g1,b1,a1, r2,g2,b2,a2):
StrokeShader.__init__(self)
@@ -431,7 +431,7 @@ class pyModulateAlphaShader(StrokeShader):
class pyMaterialColorShader(StrokeShader):
"""
- Assigns the color of the underlying material to the stroke
+ Assigns the color of the underlying material to the stroke.
"""
def __init__(self, threshold=50):
StrokeShader.__init__(self)
@@ -493,7 +493,7 @@ class pyMaterialColorShader(StrokeShader):
class pyRandomColorShader(StrokeShader):
"""
- Assigns a color to the stroke based on given seed
+ Assigns a color to the stroke based on given seed.
"""
def __init__(self, s=1):
StrokeShader.__init__(self)
@@ -510,7 +510,7 @@ class pyRandomColorShader(StrokeShader):
class py2DCurvatureColorShader(StrokeShader):
"""
Assigns a color (greyscale) to the stroke based on the curvature.
- A higher curvature will yield a brighter color
+ A higher curvature will yield a brighter color.
"""
def shade(self, stroke):
func = Curvature2DAngleF0D()
@@ -526,7 +526,7 @@ class py2DCurvatureColorShader(StrokeShader):
class pyTimeColorShader(StrokeShader):
"""
Assigns a greyscale value that increases for every vertex.
- The brightness will increase along the stroke
+ The brightness will increase along the stroke.
"""
def __init__(self, step=0.01):
StrokeShader.__init__(self)
@@ -543,7 +543,7 @@ class pyTimeColorShader(StrokeShader):
class pySamplingShader(StrokeShader):
"""
Resamples the stroke, which gives the stroke the ammount of
- vertices specified
+ vertices specified.
"""
def __init__(self, sampling):
StrokeShader.__init__(self)
@@ -556,7 +556,7 @@ class pySamplingShader(StrokeShader):
class pyBackboneStretcherShader(StrokeShader):
"""
- Stretches the stroke's backbone by a given length (in pixels)
+ Stretches the stroke's backbone by a given length (in pixels).
"""
def __init__(self, l):
StrokeShader.__init__(self)
@@ -617,7 +617,7 @@ class pyGuidingLineShader(StrokeShader):
class pyBackboneStretcherNoCuspShader(StrokeShader):
"""
- Stretches the stroke's backbone, excluding cusp vertices (end junctions)
+ Stretches the stroke's backbone, excluding cusp vertices (end junctions).
"""
def __init__(self, l):
StrokeShader.__init__(self)
@@ -663,7 +663,7 @@ class pyDiffusion2Shader(StrokeShader):
class pyTipRemoverShader(StrokeShader):
"""
- Removes the tips of the stroke
+ Removes the tips of the stroke.
"""
def __init__(self, l):
StrokeShader.__init__(self)
@@ -704,7 +704,7 @@ class pyTipRemoverShader(StrokeShader):
class pyTVertexRemoverShader(StrokeShader):
"""
- Removes t-vertices from the stroke
+ Removes t-vertices from the stroke.
"""
def shade(self, stroke):
if len(stroke) < 4:
@@ -721,7 +721,7 @@ class pyTVertexRemoverShader(StrokeShader):
class pyHLRShader(StrokeShader):
"""
Controlls visibility based upon the quantative invisibility (QI)
- based on hidden line removal (HLR)
+ based on hidden line removal (HLR).
"""
def shade(self, stroke):
if len(stroke) < 4:
@@ -736,7 +736,7 @@ class pyHLRShader(StrokeShader):
class pySinusDisplacementShader(StrokeShader):
"""
- Displaces the stroke in the shape of a sine wave
+ Displaces the stroke in the shape of a sine wave.
"""
def __init__(self, f, a):
StrokeShader.__init__(self)
@@ -758,7 +758,7 @@ class pyPerlinNoise1DShader(StrokeShader):
"""
Displaces the stroke using the curvilinear abscissa. This means
that lines with the same length and sampling interval will be
- identically distorded
+ identically distorded.
"""
def __init__(self, freq=10, amp=10, oct=4, seed=-1):
StrokeShader.__init__(self)
@@ -778,9 +778,9 @@ class pyPerlinNoise1DShader(StrokeShader):
class pyPerlinNoise2DShader(StrokeShader):
"""
Displaces the stroke using the strokes coordinates. This means
- that in a scene no strokes will be distorded identically
+ that in a scene no strokes will be distorded identically.
- More information on the noise shaders can be found at
+ More information on the noise shaders can be found at:
freestyleintegration.wordpress.com/2011/09/25/development-updates-on-september-25/
"""
def __init__(self, freq=10, amp=10, oct=4, seed=-1):
@@ -799,7 +799,7 @@ class pyPerlinNoise2DShader(StrokeShader):
class pyBluePrintCirclesShader(StrokeShader):
"""
- Draws the silhouette of the object as a circle
+ Draws the silhouette of the object as a circle.
"""
def __init__(self, turns=1, random_radius=3, random_center=5):
StrokeShader.__init__(self)
@@ -983,7 +983,7 @@ class pyBluePrintSquaresShader(StrokeShader):
class pyBluePrintDirectedSquaresShader(StrokeShader):
"""
- Replaces the stroke with a directed square
+ Replaces the stroke with a directed square.
"""
def __init__(self, turns=1, bb_len=10, mult=1):
StrokeShader.__init__(self)
diff --git a/release/scripts/freestyle/modules/freestyle/types.py b/release/scripts/freestyle/modules/freestyle/types.py
index 470b7ae14d6..8f596fd275c 100644
--- a/release/scripts/freestyle/modules/freestyle/types.py
+++ b/release/scripts/freestyle/modules/freestyle/types.py
@@ -17,7 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
"""
-Submodule containing all Freestyle types
+Submodule containing all Freestyle types.
"""
# module members
diff --git a/release/scripts/freestyle/modules/freestyle/utils.py b/release/scripts/freestyle/modules/freestyle/utils.py
index 1b576791e9b..e6dca93b777 100644
--- a/release/scripts/freestyle/modules/freestyle/utils.py
+++ b/release/scripts/freestyle/modules/freestyle/utils.py
@@ -17,7 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
"""
-Helper functions used for Freestyle style module writing
+Helper functions used for Freestyle style module writing.
"""
# module members
@@ -27,21 +27,28 @@ from _freestyle import (
integrate,
)
+from freestyle.types import (
+ Interface0DIterator,
+ Stroke,
+ StrokeVertexIterator,
+ )
+
+
from mathutils import Vector
-from functools import lru_cache
+from functools import lru_cache, namedtuple
from math import cos, sin, pi
+from itertools import tee
# -- real utility functions -- #
-
def rgb_to_bw(r, g, b):
- """ Method to convert rgb to a bw intensity value. """
+ """Method to convert rgb to a bw intensity value."""
return 0.35 * r + 0.45 * g + 0.2 * b
def bound(lower, x, higher):
- """ Returns x bounded by a maximum and minimum value. equivalent to:
+ """Returns x bounded by a maximum and minimum value. Equivalent to:
return min(max(x, lower), higher)
"""
# this is about 50% quicker than min(max(x, lower), higher)
@@ -55,7 +62,6 @@ def bounding_box(stroke):
x, y = zip(*(svert.point for svert in stroke))
return (Vector((min(x), min(y))), Vector((max(x), max(y))))
-
# -- General helper functions -- #
@@ -72,12 +78,14 @@ def phase_to_direction(length):
results.append((phase, Vector((cos(2 * pi * phase), sin(2 * pi * phase)))))
return results
+# A named tuple primitive used for storing data that has an upper and
+# lower bound (e.g., thickness, range and certain values)
+BoundedProperty = namedtuple("BoundedProperty", ["min", "max", "delta"])
# -- helper functions for chaining -- #
-
def get_chain_length(ve, orientation):
- """Returns the 2d length of a given ViewEdge """
+ """Returns the 2d length of a given ViewEdge."""
from freestyle.chainingiterators import pyChainSilhouetteGenericIterator
length = 0.0
# setup iterator
@@ -112,156 +120,121 @@ def get_chain_length(ve, orientation):
def find_matching_vertex(id, it):
- """Finds the matching vertexn, or returns None """
+ """Finds the matching vertex, or returns None."""
return next((ve for ve in it if ve.id == id), None)
-
# -- helper functions for iterating -- #
+def pairwise(iterable, types={Stroke, StrokeVertexIterator}):
+ """Yields a tuple containing the previous and current object """
+ # use .incremented() for types that support it
+ if type(iterable) in types:
+ it = iter(iterable)
+ return zip(it, it.incremented())
+ else:
+ a, b = tee(iterable)
+ next(b, None)
+ return zip(a, b)
-def iter_current_previous(stroke):
- """
- iterates over the given iterator. yields a tuple of the form
- (it, prev, current)
- """
- prev = stroke[0]
- it = Interface0DIterator(stroke)
- for current in it:
- yield (it, prev, current)
+
+def tripplewise(iterable):
+ """Yields a tuple containing the current object and its immediate neighbors """
+ a, b, c = tee(iterable)
+ next(b, None)
+ next(c, None)
+ return zip(a, b, c)
def iter_t2d_along_stroke(stroke):
- """
- Yields the distance between two stroke vertices
- relative to the total stroke length.
- """
+ """Yields the progress along the stroke."""
total = stroke.length_2d
distance = 0.0
- for it, prev, svert in iter_current_previous(stroke):
+ # yield for the comparison from the first vertex to itself
+ yield 0.0
+ for prev, svert in pairwise(stroke):
distance += (prev.point - svert.point).length
- t = min(distance / total, 1.0) if total > 0.0 else 0.0
- yield (it, t)
+ yield min(distance / total, 1.0) if total != 0.0 else 0.0
-def iter_distance_from_camera(stroke, range_min, range_max):
+def iter_distance_from_camera(stroke, range_min, range_max, normfac):
"""
Yields the distance to the camera relative to the maximum
possible distance for every stroke vertex, constrained by
given minimum and maximum values.
"""
- normfac = range_max - range_min # normalization factor
- it = Interface0DIterator(stroke)
- for svert in it:
- distance = svert.point_3d.length # in the camera coordinate
- if distance < range_min:
- t = 0.0
- elif distance > range_max:
- t = 1.0
+ for svert in stroke:
+ # length in the camera coordinate
+ distance = svert.point_3d.length
+ if range_min < distance < range_max:
+ yield (svert, (distance - range_min) / normfac)
else:
- t = (distance - range_min) / normfac
- yield (it, t)
+ yield (svert, 0.0) if range_min > distance else (svert, 1.0)
-def iter_distance_from_object(stroke, object, range_min, range_max):
+def iter_distance_from_object(stroke, location, range_min, range_max, normfac):
"""
yields the distance to the given object relative to the maximum
possible distance for every stroke vertex, constrained by
given minimum and maximum values.
"""
- scene = getCurrentScene()
- mv = scene.camera.matrix_world.copy().inverted() # model-view matrix
- loc = mv * object.location # loc in the camera coordinate
- normfac = range_max - range_min # normalization factor
- it = Interface0DIterator(stroke)
- for svert in it:
- distance = (svert.point_3d - loc).length # in the camera coordinate
- if distance < range_min:
- t = 0.0
- elif distance > range_max:
- t = 1.0
- else:
- t = (distance - range_min) / normfac
- yield (it, t)
-
-
-def iter_material_color(stroke, material_attribute):
- """
- yields the specified material attribute for every stroke vertex.
- the material is taken from the object behind the vertex.
- """
- func = CurveMaterialF0D()
- it = Interface0DIterator(stroke)
- for inter in it:
- material = func(it)
- if material_attribute == 'DIFF':
- color = material.diffuse[0:3]
- elif material_attribute == 'SPEC':
- color = material.specular[0:3]
+ for svert in stroke:
+ distance = (svert.point_3d - location).length # in the camera coordinate
+ if range_min < distance < range_max:
+ yield (svert, (distance - range_min) / normfac)
else:
- raise ValueError("unexpected material attribute: " + material_attribute)
- yield (it, color)
+ yield (svert, 0.0) if distance < range_min else (svert, 1.0)
-def iter_material_value(stroke, material_attribute):
- """
- yields a specific material attribute
- from the vertex' underlying material.
- """
- func = CurveMaterialF0D()
+def iter_material_value(stroke, func, attribute):
+ "Yields a specific material attribute from the vertex' underlying material."
it = Interface0DIterator(stroke)
for svert in it:
material = func(it)
- if material_attribute == 'DIFF':
- t = rgb_to_bw(*material.diffuse[0:3])
- elif material_attribute == 'DIFF_R':
- t = material.diffuse[0]
- elif material_attribute == 'DIFF_G':
- t = material.diffuse[1]
- elif material_attribute == 'DIFF_B':
- t = material.diffuse[2]
- elif material_attribute == 'SPEC':
- t = rgb_to_bw(*material.specular[0:3])
- elif material_attribute == 'SPEC_R':
- t = material.specular[0]
- elif material_attribute == 'SPEC_G':
- t = material.specular[1]
- elif material_attribute == 'SPEC_B':
- t = material.specular[2]
- elif material_attribute == 'SPEC_HARDNESS':
- t = material.shininess
- elif material_attribute == 'ALPHA':
- t = material.diffuse[3]
+ # main
+ if attribute == 'LINE':
+ value = rgb_to_bw(*material.line[0:3])
+ elif attribute == 'ALPHA':
+ value = material.line[3]
+ elif attribute == 'DIFF':
+ value = rgb_to_bw(*material.diffuse[0:3])
+ elif attribute == 'SPEC':
+ value = rgb_to_bw(*material.specular[0:3])
+ # line seperate
+ elif attribute == 'LINE_R':
+ value = material.line[0]
+ elif attribute == 'LINE_G':
+ value = material.line[1]
+ elif attribute == 'LINE_B':
+ value = material.line[2]
+ # diffuse seperate
+ elif attribute == 'DIFF_R':
+ value = material.diffuse[0]
+ elif attribute == 'DIFF_G':
+ value = material.diffuse[1]
+ elif attribute == 'DIFF_B':
+ value = material.diffuse[2]
+ # specular seperate
+ elif attribute == 'SPEC_R':
+ value = material.specular[0]
+ elif attribute == 'SPEC_G':
+ value = material.specular[1]
+ elif attribute == 'SPEC_B':
+ value = material.specular[2]
+ elif attribute == 'SPEC_HARDNESS':
+ value = material.shininess
else:
- raise ValueError("unexpected material attribute: " + material_attribute)
- yield (it, t)
-
+ raise ValueError("unexpected material attribute: " + attribute)
+ yield (svert, value)
def iter_distance_along_stroke(stroke):
- """
- yields the absolute distance between
- the current and preceding vertex.
- """
+ "Yields the absolute distance along the stroke up to the current vertex."
distance = 0.0
- prev = stroke[0]
- it = Interface0DIterator(stroke)
- for svert in it:
- p = svert.point
- distance += (prev - p).length
- prev = p.copy() # need a copy because the point can be altered
- yield it, distance
-
-
-def iter_triplet(it):
- """
- Iterates over it, yielding a tuple containing
- the current vertex and its immediate neighbors
- """
- prev = next(it)
- current = next(it)
- for succ in it:
- yield prev, current, succ
- prev, current = current, succ
-
+ # the positions need to be copied, because they are changed in the calling function
+ points = tuple(svert.point.copy() for svert in stroke)
+ yield distance
+ for prev, curr in pairwise(points):
+ distance += (prev - curr).length
+ yield distance
# -- mathmatical operations -- #
@@ -272,55 +245,73 @@ def stroke_curvature(it):
K = 1 / R
where R is the radius of the circle going through the current vertex and its neighbors
"""
+ for _ in it:
+ if (it.is_begin or it.is_end):
+ yield 0.0
+ continue
+ else:
+ it.decrement()
+ prev, current, succ = it.object.point.copy(), next(it).point.copy(), next(it).point.copy()
+ # return the iterator in an unchanged state
+ it.decrement()
- if it.is_end or it.is_begin:
- return 0.0
-
- next = it.incremented().point
- prev = it.decremented().point
- current = it.object.point
-
-
- ab = (current - prev)
- bc = (next - current)
- ac = (prev - next)
-
- a, b, c = ab.length, bc.length, ac.length
-
- try:
- area = 0.5 * ab.cross(ac)
- K = (4 * area) / (a * b * c)
- K = bound(0.0, K, 1.0)
+ ab = (current - prev)
+ bc = (succ - current)
+ ac = (prev - succ)
- except ZeroDivisionError:
- K = 0.0
+ a, b, c = ab.length, bc.length, ac.length
- return K
+ try:
+ area = 0.5 * ab.cross(ac)
+ K = (4 * area) / (a * b * c)
+ except ZeroDivisionError:
+ K = 0.0
+ yield abs(K)
-def stroke_normal(it):
+def stroke_normal(stroke):
"""
Compute the 2D normal at the stroke vertex pointed by the iterator
'it'. It is noted that Normal2DF0D computes normals based on
underlying FEdges instead, which is inappropriate for strokes when
they have already been modified by stroke geometry modifiers.
+
+ The returned normals are dynamic: they update when the
+ vertex position (and therefore the vertex normal) changes.
+ for use in geometry modifiers it is advised to
+ cast this generator function to a tuple or list
"""
- # first stroke segment
- it_next = it.incremented()
- if it.is_begin:
- e = it_next.object.point_2d - it.object.point_2d
- n = Vector((e[1], -e[0]))
- return n.normalized()
- # last stroke segment
- it_prev = it.decremented()
- if it_next.is_end:
- e = it.object.point_2d - it_prev.object.point_2d
- n = Vector((e[1], -e[0]))
- return n.normalized()
- # two subsequent stroke segments
- e1 = it_next.object.point_2d - it.object.point_2d
- e2 = it.object.point_2d - it_prev.object.point_2d
- n1 = Vector((e1[1], -e1[0])).normalized()
- n2 = Vector((e2[1], -e2[0])).normalized()
- n = (n1 + n2)
- return n.normalized()
+ n = len(stroke) - 1
+
+ for i, svert in enumerate(stroke):
+ if i == 0:
+ e = stroke[i + 1].point - svert.point
+ yield Vector((e[1], -e[0])).normalized()
+ elif i == n:
+ e = svert.point - stroke[i - 1].point
+ yield Vector((e[1], -e[0])).normalized()
+ else:
+ e1 = stroke[i + 1].point - svert.point
+ e2 = svert.point - stroke[i - 1].point
+ n1 = Vector((e1[1], -e1[0])).normalized()
+ n2 = Vector((e2[1], -e2[0])).normalized()
+ yield (n1 + n2).normalized()
+
+def get_test_stroke():
+ """Returns a static stroke object for testing """
+ from freestyle.types import Stroke, Interface0DIterator, StrokeVertexIterator, SVertex, Id, StrokeVertex
+ # points for our fake stroke
+ points = (Vector((1.0, 5.0, 3.0)), Vector((1.0, 2.0, 9.0)),
+ Vector((6.0, 2.0, 3.0)), Vector((7.0, 2.0, 3.0)),
+ Vector((2.0, 6.0, 3.0)), Vector((2.0, 8.0, 3.0)))
+ ids = (Id(0, 0), Id(1, 1), Id(2, 2), Id(3, 3), Id(4, 4), Id(5, 5))
+
+ stroke = Stroke()
+ it = iter(stroke)
+
+ for svert in map(SVertex, points, ids):
+ stroke.insert_vertex(StrokeVertex(svert), it)
+ it = iter(stroke)
+
+ stroke.update_length()
+ return stroke
diff --git a/release/scripts/freestyle/modules/parameter_editor.py b/release/scripts/freestyle/modules/parameter_editor.py
index 3529221c5b5..ebd09bd0181 100644
--- a/release/scripts/freestyle/modules/parameter_editor.py
+++ b/release/scripts/freestyle/modules/parameter_editor.py
@@ -32,6 +32,8 @@ from freestyle.types import (
UnaryPredicate0D,
UnaryPredicate1D,
TVertex,
+ Material,
+ ViewEdge,
)
from freestyle.chainingiterators import (
ChainPredicateIterator,
@@ -41,10 +43,10 @@ from freestyle.chainingiterators import (
)
from freestyle.functions import (
Curvature2DAngleF0D,
- CurveMaterialF0D,
Normal2DF0D,
QuantitativeInvisibilityF1D,
VertexOrientation2DF0D,
+ CurveMaterialF0D,
)
from freestyle.predicates import (
AndUP1D,
@@ -78,70 +80,78 @@ from freestyle.shaders import (
pyBluePrintCirclesShader,
pyBluePrintEllipsesShader,
pyBluePrintSquaresShader,
+ RoundCapShader,
+ SquareCapShader,
)
from freestyle.utils import (
ContextFunctions,
getCurrentScene,
+ iter_distance_along_stroke,
+ iter_t2d_along_stroke,
+ iter_distance_from_camera,
+ iter_distance_from_object,
+ iter_material_value,
stroke_normal,
+ bound,
+ pairwise,
+ BoundedProperty
)
from _freestyle import (
blendRamp,
evaluateColorRamp,
evaluateCurveMappingF,
)
-import math
-import mathutils
+
import time
+from mathutils import Vector
+from math import pi, sin, cos, acos, radians
+from itertools import cycle, tee
class ColorRampModifier(StrokeShader):
+ """Primitive for the color modifiers."""
def __init__(self, blend, influence, ramp):
StrokeShader.__init__(self)
- self.__blend = blend
- self.__influence = influence
- self.__ramp = ramp
+ self.blend = blend
+ self.influence = influence
+ self.ramp = ramp
def evaluate(self, t):
- col = evaluateColorRamp(self.__ramp, t)
- col = col.xyz # omit alpha
- return col
+ col = evaluateColorRamp(self.ramp, t)
+ return col.xyz # omit alpha
def blend_ramp(self, a, b):
- return blendRamp(self.__blend, a, self.__influence, b)
+ return blendRamp(self.blend, a, self.influence, b)
class ScalarBlendModifier(StrokeShader):
- def __init__(self, blend, influence):
+ """Primitive for alpha and thickness modifiers."""
+ def __init__(self, blend_type, influence):
StrokeShader.__init__(self)
- self.__blend = blend
- self.__influence = influence
+ self.blend_type = blend_type
+ self.influence = influence
def blend(self, v1, v2):
- fac = self.__influence
+ fac = self.influence
facm = 1.0 - fac
- if self.__blend == 'MIX':
+ if self.blend_type == 'MIX':
v1 = facm * v1 + fac * v2
- elif self.__blend == 'ADD':
+ elif self.blend_type == 'ADD':
v1 += fac * v2
- elif self.__blend == 'MULTIPLY':
+ elif self.blend_type == 'MULTIPLY':
v1 *= facm + fac * v2
- elif self.__blend == 'SUBTRACT':
+ elif self.blend_type == 'SUBTRACT':
v1 -= fac * v2
- elif self.__blend == 'DIVIDE':
- if v2 != 0.0:
- v1 = facm * v1 + fac * v1 / v2
- elif self.__blend == 'DIFFERENCE':
+ elif self.blend_type == 'DIVIDE':
+ v1 = facm * v1 + fac * v1 / v2 if v2 != 0.0 else v1
+ elif self.blend_type == 'DIFFERENCE':
v1 = facm * v1 + fac * abs(v1 - v2)
- elif self.__blend == 'MININUM':
- tmp = fac * v2
- if v1 > tmp:
- v1 = tmp
- elif self.__blend == 'MAXIMUM':
- tmp = fac * v2
- if v1 < tmp:
- v1 = tmp
+ elif self.blend_type == 'MININUM':
+ v1 = min(fac * v2, v1)
+ elif self.blend_type == 'MAXIMUM':
+ v1 = max(fac * v2, v1)
else:
- raise ValueError("unknown curve blend type: " + self.__blend)
+ raise ValueError("unknown curve blend type: " + self.blend_type)
return v1
@@ -149,34 +159,28 @@ class CurveMappingModifier(ScalarBlendModifier):
def __init__(self, blend, influence, mapping, invert, curve):
ScalarBlendModifier.__init__(self, blend, influence)
assert mapping in {'LINEAR', 'CURVE'}
- self.__mapping = getattr(self, mapping)
- self.__invert = invert
- self.__curve = curve
+ self.evaluate = getattr(self, mapping)
+ self.invert = invert
+ self.curve = curve
def LINEAR(self, t):
- if self.__invert:
- return 1.0 - t
- return t
+ return (1.0 - t) if self.invert else t
def CURVE(self, t):
- return evaluateCurveMappingF(self.__curve, 0, t)
-
- def evaluate(self, t):
- return self.__mapping(t)
+ return evaluateCurveMappingF(self.curve, 0, t)
class ThicknessModifierMixIn:
def __init__(self):
scene = getCurrentScene()
- self.__persp_camera = (scene.camera.data.type == 'PERSP')
+ self.persp_camera = (scene.camera.data.type == 'PERSP')
def set_thickness(self, sv, outer, inner):
- fe = sv.first_svertex.get_fedge(sv.second_svertex)
+ fe = sv.fedge
nature = fe.nature
if (nature & Nature.BORDER):
- if self.__persp_camera:
- point = -sv.point_3d.copy()
- point.normalize()
+ if self.persp_camera:
+ point = -sv.point_3d.normalized()
dir = point.dot(fe.normal_left)
else:
dir = fe.normal_left.z
@@ -193,30 +197,42 @@ class ThicknessModifierMixIn:
class ThicknessBlenderMixIn(ThicknessModifierMixIn):
def __init__(self, position, ratio):
ThicknessModifierMixIn.__init__(self)
- self.__position = position
- self.__ratio = ratio
+ self.position = position
+ self.ratio = ratio
- def blend_thickness(self, outer, inner, v):
+ def blend_thickness(self, svert, v):
+ """Blends and sets the thickness."""
+ outer, inner = svert.attribute.thickness
+ fe = svert.fedge
v = self.blend(outer + inner, v)
- if self.__position == 'CENTER':
- outer = v * 0.5
- inner = v - outer
- elif self.__position == 'INSIDE':
- outer = 0
- inner = v
- elif self.__position == 'OUTSIDE':
- outer = v
- inner = 0
- elif self.__position == 'RELATIVE':
- outer = v * self.__ratio
- inner = v - outer
- else:
- raise ValueError("unknown thickness position: " + self.__position)
- return outer, inner
+ # Part 1: blend
+ if self.position == 'CENTER':
+ outer = inner = v * 0.5
+ elif self.position == 'INSIDE':
+ outer, inner = 0, v
+ elif self.position == 'OUTSIDE':
+ outer, inner = v, 0
+ elif self.position == 'RELATIVE':
+ outer, inner = v * self.ratio, v - (v * self.ratio)
+ else:
+ raise ValueError("unknown thickness position: " + position)
-class BaseColorShader(ConstantColorShader):
- pass
+ # Part 2: set
+ if (fe.nature & Nature.BORDER):
+ if self.persp_camera:
+ point = -svert.point_3d.normalized()
+ dir = point.dot(fe.normal_left)
+ else:
+ dir = fe.normal_left.z
+ if dir < 0.0: # the back side is visible
+ outer, inner = inner, outer
+ elif (fe.nature & Nature.SILHOUETTE):
+ if fe.is_smooth: # TODO more tests needed
+ outer, inner = inner, outer
+ else:
+ outer = inner = (outer + inner) / 2
+ svert.attribute.thickness = (outer, inner)
class BaseThicknessShader(StrokeShader, ThicknessModifierMixIn):
@@ -224,520 +240,378 @@ class BaseThicknessShader(StrokeShader, ThicknessModifierMixIn):
StrokeShader.__init__(self)
ThicknessModifierMixIn.__init__(self)
if position == 'CENTER':
- self.__outer = thickness * 0.5
- self.__inner = thickness - self.__outer
+ self.outer = thickness * 0.5
+ self.inner = thickness - self.outer
elif position == 'INSIDE':
- self.__outer = 0
- self.__inner = thickness
+ self.outer = 0
+ self.inner = thickness
elif position == 'OUTSIDE':
- self.__outer = thickness
- self.__inner = 0
+ self.outer = thickness
+ self.inner = 0
elif position == 'RELATIVE':
- self.__outer = thickness * ratio
- self.__inner = thickness - self.__outer
+ self.outer = thickness * ratio
+ self.inner = thickness - self.outer
else:
- raise ValueError("unknown thickness position: " + self.position)
+ raise ValueError("unknown thickness position: " + position)
def shade(self, stroke):
- it = stroke.stroke_vertices_begin()
- while not it.is_end:
- sv = it.object
- self.set_thickness(sv, self.__outer, self.__inner)
- it.increment()
+ for svert in stroke:
+ self.set_thickness(svert, self.outer, self.inner)
# Along Stroke modifiers
-def iter_t2d_along_stroke(stroke):
- total = stroke.length_2d
- distance = 0.0
- it = stroke.stroke_vertices_begin()
- prev = it.object.point
- while not it.is_end:
- p = it.object.point
- distance += (prev - p).length
- prev = p.copy() # need a copy because the point can be altered
- t = min(distance / total, 1.0) if total > 0.0 else 0.0
- yield it, t
- it.increment()
-
-
class ColorAlongStrokeShader(ColorRampModifier):
+ """Maps a ramp to the color of the stroke, using the curvilinear abscissa (t)."""
def shade(self, stroke):
- for it, t in iter_t2d_along_stroke(stroke):
- sv = it.object
- a = sv.attribute.color
+ for svert, t in zip(stroke, iter_t2d_along_stroke(stroke)):
+ a = svert.attribute.color
b = self.evaluate(t)
- sv.attribute.color = self.blend_ramp(a, b)
+ svert.attribute.color = self.blend_ramp(a, b)
class AlphaAlongStrokeShader(CurveMappingModifier):
+ """Maps a curve to the alpha/transparancy of the stroke, using the curvilinear abscissa (t)."""
def shade(self, stroke):
- for it, t in iter_t2d_along_stroke(stroke):
- sv = it.object
- a = sv.attribute.alpha
+ for svert, t in zip(stroke, iter_t2d_along_stroke(stroke)):
+ a = svert.attribute.alpha
b = self.evaluate(t)
- sv.attribute.alpha = self.blend(a, b)
+ svert.attribute.alpha = self.blend(a, b)
class ThicknessAlongStrokeShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ """Maps a curve to the thickness of the stroke, using the curvilinear abscissa (t)."""
def __init__(self, thickness_position, thickness_ratio,
blend, influence, mapping, invert, curve, value_min, value_max):
ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
- self.__value_min = value_min
- self.__value_max = value_max
+ self.value = BoundedProperty(value_min, value_max, value_max - value_min)
def shade(self, stroke):
- for it, t in iter_t2d_along_stroke(stroke):
- sv = it.object
- a = sv.attribute.thickness
- b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
- c = self.blend_thickness(a[0], a[1], b)
- self.set_thickness(sv, c[0], c[1])
-
-
-# Distance from Camera modifiers
-
-def iter_distance_from_camera(stroke, range_min, range_max):
- normfac = range_max - range_min # normalization factor
- it = stroke.stroke_vertices_begin()
- while not it.is_end:
- p = it.object.point_3d # in the camera coordinate
- distance = p.length
- if distance < range_min:
- t = 0.0
- elif distance > range_max:
- t = 1.0
- else:
- t = (distance - range_min) / normfac
- yield it, t
- it.increment()
+ for svert, t in zip(stroke, iter_t2d_along_stroke(stroke)):
+ b = self.value.min + self.evaluate(t) * self.value.delta
+ self.blend_thickness(svert, b)
+
+# -- Distance from Camera modifiers -- #
class ColorDistanceFromCameraShader(ColorRampModifier):
+ """Picks a color value from a ramp based on the vertex' distance from the camera."""
def __init__(self, blend, influence, ramp, range_min, range_max):
ColorRampModifier.__init__(self, blend, influence, ramp)
- self.__range_min = range_min
- self.__range_max = range_max
+ self.range = BoundedProperty(range_min, range_max, range_max - range_min)
def shade(self, stroke):
- for it, t in iter_distance_from_camera(stroke, self.__range_min, self.__range_max):
- sv = it.object
- a = sv.attribute.color
+ it = iter_distance_from_camera(stroke, *self.range)
+ for svert, t in it:
+ a = svert.attribute.color
b = self.evaluate(t)
- sv.attribute.color = self.blend_ramp(a, b)
+ svert.attribute.color = self.blend_ramp(a, b)
class AlphaDistanceFromCameraShader(CurveMappingModifier):
+ """Picks an alpha value from a curve based on the vertex' distance from the camera"""
def __init__(self, blend, influence, mapping, invert, curve, range_min, range_max):
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
- self.__range_min = range_min
- self.__range_max = range_max
+ self.range = BoundedProperty(range_min, range_max, range_max - range_min)
def shade(self, stroke):
- for it, t in iter_distance_from_camera(stroke, self.__range_min, self.__range_max):
- sv = it.object
- a = sv.attribute.alpha
+ it = iter_distance_from_camera(stroke, *self.range)
+ for svert, t in it:
+ a = svert.attribute.alpha
b = self.evaluate(t)
- sv.attribute.alpha = self.blend(a, b)
+ svert.attribute.alpha = self.blend(a, b)
class ThicknessDistanceFromCameraShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ """Picks a thickness value from a curve based on the vertex' distance from the camera."""
def __init__(self, thickness_position, thickness_ratio,
blend, influence, mapping, invert, curve, range_min, range_max, value_min, value_max):
ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
- self.__range_min = range_min
- self.__range_max = range_max
- self.__value_min = value_min
- self.__value_max = value_max
+ self.range = BoundedProperty(range_min, range_max, range_max - range_min)
+ self.value = BoundedProperty(value_min, value_max, value_max - value_min)
def shade(self, stroke):
- for it, t in iter_distance_from_camera(stroke, self.__range_min, self.__range_max):
- sv = it.object
- a = sv.attribute.thickness
- b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
- c = self.blend_thickness(a[0], a[1], b)
- self.set_thickness(sv, c[0], c[1])
+ for (svert, t) in iter_distance_from_camera(stroke, *self.range):
+ b = self.value.min + self.evaluate(t) * self.value.delta
+ self.blend_thickness(svert, b)
# Distance from Object modifiers
-def iter_distance_from_object(stroke, object, range_min, range_max):
- scene = getCurrentScene()
- mv = scene.camera.matrix_world.copy() # model-view matrix
- mv.invert()
- loc = mv * object.location # loc in the camera coordinate
- normfac = range_max - range_min # normalization factor
- it = stroke.stroke_vertices_begin()
- while not it.is_end:
- p = it.object.point_3d # in the camera coordinate
- distance = (p - loc).length
- if distance < range_min:
- t = 0.0
- elif distance > range_max:
- t = 1.0
- else:
- t = (distance - range_min) / normfac
- yield it, t
- it.increment()
-
-
class ColorDistanceFromObjectShader(ColorRampModifier):
+ """Picks a color value from a ramp based on the vertex' distance from a given object."""
def __init__(self, blend, influence, ramp, target, range_min, range_max):
ColorRampModifier.__init__(self, blend, influence, ramp)
- self.__target = target
- self.__range_min = range_min
- self.__range_max = range_max
+ if target is None:
+ raise ValueError("ColorDistanceFromObjectShader: target can't be None ")
+ self.range = BoundedProperty(range_min, range_max, range_max - range_min)
+ # construct a model-view matrix
+ matrix = getCurrentScene().camera.matrix_world.inverted()
+ # get the object location in the camera coordinate
+ self.loc = matrix * target.location
def shade(self, stroke):
- if self.__target is None:
- return
- for it, t in iter_distance_from_object(stroke, self.__target, self.__range_min, self.__range_max):
- sv = it.object
- a = sv.attribute.color
+ it = iter_distance_from_object(stroke, self.loc, *self.range)
+ for svert, t in it:
+ a = svert.attribute.color
b = self.evaluate(t)
- sv.attribute.color = self.blend_ramp(a, b)
+ svert.attribute.color = self.blend_ramp(a, b)
class AlphaDistanceFromObjectShader(CurveMappingModifier):
+ """Picks an alpha value from a curve based on the vertex' distance from a given object."""
def __init__(self, blend, influence, mapping, invert, curve, target, range_min, range_max):
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
- self.__target = target
- self.__range_min = range_min
- self.__range_max = range_max
+ if target is None:
+ raise ValueError("AlphaDistanceFromObjectShader: target can't be None ")
+ self.range = BoundedProperty(range_min, range_max, range_max - range_min)
+ # construct a model-view matrix
+ matrix = getCurrentScene().camera.matrix_world.inverted()
+ # get the object location in the camera coordinate
+ self.loc = matrix * target.location
def shade(self, stroke):
- if self.__target is None:
- return
- for it, t in iter_distance_from_object(stroke, self.__target, self.__range_min, self.__range_max):
- sv = it.object
- a = sv.attribute.alpha
+ it = iter_distance_from_object(stroke, self.loc, *self.range)
+ for svert, t in it:
+ a = svert.attribute.alpha
b = self.evaluate(t)
- sv.attribute.alpha = self.blend(a, b)
+ svert.attribute.alpha = self.blend(a, b)
class ThicknessDistanceFromObjectShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ """Picks a thickness value from a curve based on the vertex' distance from a given object."""
def __init__(self, thickness_position, thickness_ratio,
blend, influence, mapping, invert, curve, target, range_min, range_max, value_min, value_max):
ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
- self.__target = target
- self.__range_min = range_min
- self.__range_max = range_max
- self.__value_min = value_min
- self.__value_max = value_max
+ if target is None:
+ raise ValueError("ThicknessDistanceFromObjectShader: target can't be None ")
+ self.range = BoundedProperty(range_min, range_max, range_max - range_min)
+ self.value = BoundedProperty(value_min, value_max, value_max - value_min)
+ # construct a model-view matrix
+ matrix = getCurrentScene().camera.matrix_world.inverted()
+ # get the object location in the camera coordinate
+ self.loc = matrix * target.location
def shade(self, stroke):
- if self.__target is None:
- return
- for it, t in iter_distance_from_object(stroke, self.__target, self.__range_min, self.__range_max):
- sv = it.object
- a = sv.attribute.thickness
- b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
- c = self.blend_thickness(a[0], a[1], b)
- self.set_thickness(sv, c[0], c[1])
-
+ it = iter_distance_from_object(stroke, self.loc, *self.range)
+ for svert, t in it:
+ b = self.value.min + self.evaluate(t) * self.value.delta
+ self.blend_thickness(svert, b)
# Material modifiers
-
-def iter_material_color(stroke, material_attribute):
- func = CurveMaterialF0D()
- it = stroke.stroke_vertices_begin()
- while not it.is_end:
- material = func(Interface0DIterator(it))
- if material_attribute == 'LINE':
- color = material.line[0:3]
- elif material_attribute == 'DIFF':
- color = material.diffuse[0:3]
- elif material_attribute == 'SPEC':
- color = material.specular[0:3]
- else:
- raise ValueError("unexpected material attribute: " + material_attribute)
- yield it, color
- it.increment()
-
-
-def iter_material_value(stroke, material_attribute):
- func = CurveMaterialF0D()
- it = stroke.stroke_vertices_begin()
- while not it.is_end:
- material = func(Interface0DIterator(it))
- if material_attribute == 'LINE':
- r, g, b = material.line[0:3]
- t = 0.35 * r + 0.45 * g + 0.2 * b
- elif material_attribute == 'LINE_R':
- t = material.line[0]
- elif material_attribute == 'LINE_G':
- t = material.line[1]
- elif material_attribute == 'LINE_B':
- t = material.line[2]
- elif material_attribute == 'ALPHA':
- t = material.line[3]
- elif material_attribute == 'DIFF':
- r, g, b = material.diffuse[0:3]
- t = 0.35 * r + 0.45 * g + 0.2 * b
- elif material_attribute == 'DIFF_R':
- t = material.diffuse[0]
- elif material_attribute == 'DIFF_G':
- t = material.diffuse[1]
- elif material_attribute == 'DIFF_B':
- t = material.diffuse[2]
- elif material_attribute == 'SPEC':
- r, g, b = material.specular[0:3]
- t = 0.35 * r + 0.45 * g + 0.2 * b
- elif material_attribute == 'SPEC_R':
- t = material.specular[0]
- elif material_attribute == 'SPEC_G':
- t = material.specular[1]
- elif material_attribute == 'SPEC_B':
- t = material.specular[2]
- elif material_attribute == 'SPEC_HARDNESS':
- t = material.shininess
- else:
- raise ValueError("unexpected material attribute: " + material_attribute)
- yield it, t
- it.increment()
-
-
class ColorMaterialShader(ColorRampModifier):
+ """Assigns a color to the vertices based on their underlying material."""
def __init__(self, blend, influence, ramp, material_attribute, use_ramp):
ColorRampModifier.__init__(self, blend, influence, ramp)
- self.__material_attribute = material_attribute
- self.__use_ramp = use_ramp
-
- def shade(self, stroke):
- if self.__material_attribute in {'LINE', 'DIFF', 'SPEC'} and not self.__use_ramp:
- for it, b in iter_material_color(stroke, self.__material_attribute):
- sv = it.object
- a = sv.attribute.color
- sv.attribute.color = self.blend_ramp(a, b)
+ self.attribute = material_attribute
+ self.use_ramp = use_ramp
+ self.func = CurveMaterialF0D()
+
+ def shade(self, stroke, attributes={'DIFF', 'SPEC', 'LINE'}):
+ it = Interface0DIterator(stroke)
+ if not self.use_ramp and self.attribute in attributes:
+ for svert in it:
+ material = self.func(it)
+ if self.attribute == 'LINE':
+ b = material.line[0:3]
+ elif self.attribute == 'DIFF':
+ b = material.diffuse[0:3]
+ else:
+ b = material.specular[0:3]
+ a = svert.attribute.color
+ svert.attribute.color = self.blend_ramp(a, b)
else:
- for it, t in iter_material_value(stroke, self.__material_attribute):
- sv = it.object
- a = sv.attribute.color
- b = self.evaluate(t)
- sv.attribute.color = self.blend_ramp(a, b)
-
+ for svert, value in iter_material_value(stroke, self.func, self.attribute):
+ a = svert.attribute.color
+ b = self.evaluate(value)
+ svert.attribute.color = self.blend_ramp(a, b)
class AlphaMaterialShader(CurveMappingModifier):
+ """Assigns an alpha value to the vertices based on their underlying material."""
def __init__(self, blend, influence, mapping, invert, curve, material_attribute):
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
- self.__material_attribute = material_attribute
+ self.attribute = material_attribute
+ self.func = CurveMaterialF0D()
def shade(self, stroke):
- for it, t in iter_material_value(stroke, self.__material_attribute):
- sv = it.object
- a = sv.attribute.alpha
- b = self.evaluate(t)
- sv.attribute.alpha = self.blend(a, b)
+ for svert, value in iter_material_value(stroke, self.func, self.attribute):
+ a = svert.attribute.alpha
+ b = self.evaluate(value)
+ svert.attribute.alpha = self.blend(a, b)
class ThicknessMaterialShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ """Assigns a thickness value to the vertices based on their underlying material."""
def __init__(self, thickness_position, thickness_ratio,
blend, influence, mapping, invert, curve, material_attribute, value_min, value_max):
ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
- self.__material_attribute = material_attribute
- self.__value_min = value_min
- self.__value_max = value_max
+ self.attribute = material_attribute
+ self.value = BoundedProperty(value_min, value_max, value_max - value_min)
+ self.func = CurveMaterialF0D()
def shade(self, stroke):
- for it, t in iter_material_value(stroke, self.__material_attribute):
- sv = it.object
- a = sv.attribute.thickness
- b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
- c = self.blend_thickness(a[0], a[1], b)
- self.set_thickness(sv, c[0], c[1])
+ for svert, value in iter_material_value(stroke, self.func, self.attribute):
+ b = self.value.min + self.evaluate(value) * self.value.delta
+ self.blend_thickness(svert, b)
# Calligraphic thickness modifier
+
class CalligraphicThicknessShader(ThicknessBlenderMixIn, ScalarBlendModifier):
+ """Thickness modifier for achieving a calligraphy-like effect."""
def __init__(self, thickness_position, thickness_ratio,
- blend, influence, orientation, thickness_min, thickness_max):
+ blend_type, influence, orientation, thickness_min, thickness_max):
ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
- ScalarBlendModifier.__init__(self, blend, influence)
- self.__orientation = mathutils.Vector((math.cos(orientation), math.sin(orientation)))
- self.__thickness_min = thickness_min
- self.__thickness_max = thickness_max
+ ScalarBlendModifier.__init__(self, blend_type, influence)
+ self.orientation = Vector((cos(orientation), sin(orientation)))
+ self.thickness = BoundedProperty(thickness_min, thickness_max, thickness_max - thickness_min)
+ self.func = VertexOrientation2DF0D()
def shade(self, stroke):
- func = VertexOrientation2DF0D()
- it = stroke.stroke_vertices_begin()
- while not it.is_end:
- dir = func(Interface0DIterator(it))
- orthDir = mathutils.Vector((-dir.y, dir.x))
- orthDir.normalize()
- fac = abs(orthDir * self.__orientation)
- sv = it.object
- a = sv.attribute.thickness
- b = self.__thickness_min + fac * (self.__thickness_max - self.__thickness_min)
- b = max(b, 0.0)
- c = self.blend_thickness(a[0], a[1], b)
- self.set_thickness(sv, c[0], c[1])
- it.increment()
+ it = Interface0DIterator(stroke)
+ for svert in it:
+ dir = self.func(it)
+ if dir.length != 0.0:
+ dir.normalize()
+ fac = abs(dir.orthogonal() * self.orientation)
+ b = self.thickness.min + fac * self.thickness.delta
+ else:
+ b = self.thickness.min
+ self.blend_thickness(svert, b)
# Geometry modifiers
-def iter_distance_along_stroke(stroke):
- distance = 0.0
- it = stroke.stroke_vertices_begin()
- prev = it.object.point
- while not it.is_end:
- p = it.object.point
- distance += (prev - p).length
- prev = p.copy() # need a copy because the point can be altered
- yield it, distance
- it.increment()
-
-
class SinusDisplacementShader(StrokeShader):
+ """Displaces the stroke in a sinewave-like shape."""
def __init__(self, wavelength, amplitude, phase):
StrokeShader.__init__(self)
- self._wavelength = wavelength
- self._amplitude = amplitude
- self._phase = phase / wavelength * 2 * math.pi
+ self.wavelength = wavelength
+ self.amplitude = amplitude
+ self.phase = phase / wavelength * 2 * pi
def shade(self, stroke):
- # separately iterate over stroke vertices to compute normals
- buf = []
- for it, distance in iter_distance_along_stroke(stroke):
- buf.append((it.object, distance, stroke_normal(it)))
- # iterate over the vertices again to displace them
- for v, distance, normal in buf:
- n = normal * self._amplitude * math.cos(distance / self._wavelength * 2 * math.pi + self._phase)
- v.point = v.point + n
+ # normals are stored in a tuple, so they don't update when we reposition vertices.
+ normals = tuple(stroke_normal(stroke))
+ distances = iter_distance_along_stroke(stroke)
+ coeff = 1 / self.wavelength * 2 * pi
+ for svert, distance, normal in zip(stroke, distances, normals):
+ n = normal * self.amplitude * cos(distance * coeff + self.phase)
+ svert.point += n
stroke.update_length()
class PerlinNoise1DShader(StrokeShader):
- def __init__(self, freq=10, amp=10, oct=4, angle=math.radians(45), seed=-1):
+ """
+ Displaces the stroke using the curvilinear abscissa. This means
+ that lines with the same length and sampling interval will be
+ identically distorded.
+ """
+ def __init__(self, freq=10, amp=10, oct=4, angle=radians(45), seed=-1):
StrokeShader.__init__(self)
- self.__noise = Noise(seed)
- self.__freq = freq
- self.__amp = amp
- self.__oct = oct
- self.__dir = mathutils.Vector((math.cos(angle), math.sin(angle)))
+ self.noise = Noise(seed)
+ self.freq = freq
+ self.amp = amp
+ self.oct = oct
+ self.dir = Vector((cos(angle), sin(angle)))
def shade(self, stroke):
length = stroke.length_2d
- it = stroke.stroke_vertices_begin()
- while not it.is_end:
- v = it.object
- nres = self.__noise.turbulence1(length * v.u, self.__freq, self.__amp, self.__oct)
- v.point = v.point + nres * self.__dir
- it.increment()
+ for svert in stroke:
+ nres = self.noise.turbulence1(length * svert.u, self.freq, self.amp, self.oct)
+ svert.point += nres * self.dir
stroke.update_length()
class PerlinNoise2DShader(StrokeShader):
- def __init__(self, freq=10, amp=10, oct=4, angle=math.radians(45), seed=-1):
+ """
+ Displaces the stroke using the strokes coordinates. This means
+ that in a scene no strokes will be distorded identically.
+
+ More information on the noise shaders can be found at:
+ freestyleintegration.wordpress.com/2011/09/25/development-updates-on-september-25/
+ """
+ def __init__(self, freq=10, amp=10, oct=4, angle=radians(45), seed=-1):
StrokeShader.__init__(self)
- self.__noise = Noise(seed)
- self.__freq = freq
- self.__amp = amp
- self.__oct = oct
- self.__dir = mathutils.Vector((math.cos(angle), math.sin(angle)))
+ self.noise = Noise(seed)
+ self.freq = freq
+ self.amp = amp
+ self.oct = oct
+ self.dir = Vector((cos(angle), sin(angle)))
def shade(self, stroke):
- it = stroke.stroke_vertices_begin()
- while not it.is_end:
- v = it.object
- vec = mathutils.Vector((v.projected_x, v.projected_y))
- nres = self.__noise.turbulence2(vec, self.__freq, self.__amp, self.__oct)
- v.point = v.point + nres * self.__dir
- it.increment()
+ for svert in stroke:
+ projected = Vector((svert.projected_x, svert.projected_y))
+ nres = self.noise.turbulence2(projected, self.freq, self.amp, self.oct)
+ svert.point += nres * self.dir
stroke.update_length()
class Offset2DShader(StrokeShader):
+ """Offsets the stroke by a given amount."""
def __init__(self, start, end, x, y):
StrokeShader.__init__(self)
- self.__start = start
- self.__end = end
- self.__xy = mathutils.Vector((x, y))
+ self.start = start
+ self.end = end
+ self.xy = Vector((x, y))
def shade(self, stroke):
- # first iterate over stroke vertices to compute normals
- buf = []
- it = stroke.stroke_vertices_begin()
- while not it.is_end:
- buf.append((it.object, stroke_normal(it)))
- it.increment()
- # again iterate over the vertices to add displacement
- for v, n in buf:
- a = self.__start + v.u * (self.__end - self.__start)
- n = n * a
- v.point = v.point + n + self.__xy
+ # normals are stored in a tuple, so they don't update when we reposition vertices.
+ normals = tuple(stroke_normal(stroke))
+ for svert, normal in zip(stroke, normals):
+ a = self.start + svert.u * (self.end - self.start)
+ svert.point += (normal * a) + self.xy
stroke.update_length()
class Transform2DShader(StrokeShader):
+ """Transforms the stroke (scale, rotation, location) around a given pivot point """
def __init__(self, pivot, scale_x, scale_y, angle, pivot_u, pivot_x, pivot_y):
StrokeShader.__init__(self)
- self.__pivot = pivot
- self.__scale_x = scale_x
- self.__scale_y = scale_y
- self.__angle = angle
- self.__pivot_u = pivot_u
- self.__pivot_x = pivot_x
- self.__pivot_y = pivot_y
+ self.pivot = pivot
+ self.scale = Vector((scale_x, scale_y))
+ self.cos_theta = cos(angle)
+ self.sin_theta = sin(angle)
+ self.pivot_u = pivot_u
+ self.pivot_x = pivot_x
+ self.pivot_y = pivot_y
+ if pivot not in {'START', 'END', 'CENTER', 'ABSOLUTE', 'PARAM'}:
+ raise ValueError("expected pivot in {'START', 'END', 'CENTER', 'ABSOLUTE', 'PARAM'}, not" + pivot)
def shade(self, stroke):
# determine the pivot of scaling and rotation operations
- if self.__pivot == 'START':
- it = stroke.stroke_vertices_begin()
- pivot = it.object.point
- elif self.__pivot == 'END':
- it = stroke.stroke_vertices_end()
- it.decrement()
- pivot = it.object.point
- elif self.__pivot == 'PARAM':
- p = None
- it = stroke.stroke_vertices_begin()
- while not it.is_end:
- prev = p
- v = it.object
- p = v.point
- u = v.u
- if self.__pivot_u < u:
- break
- it.increment()
- if prev is None:
- pivot = p
+ if self.pivot == 'START':
+ pivot = stroke[0].point
+ elif self.pivot == 'END':
+ pivot = stroke[-1].point
+ elif self.pivot == 'CENTER':
+ # minor rounding errors here, because
+ # given v = Vector(a, b), then (v / n) != Vector(v.x / n, v.y / n)
+ pivot = (1 / len(stroke)) * sum((svert.point for svert in stroke), Vector((0.0, 0.0)))
+ elif self.pivot == 'ABSOLUTE':
+ pivot = Vector((self.pivot_x, self.pivot_y))
+ elif self.pivot == 'PARAM':
+ if self.pivot_u < stroke[0].u:
+ pivot = stroke[0].point
else:
- delta = u - self.__pivot_u
- pivot = p + delta * (prev - p)
- elif self.__pivot == 'CENTER':
- pivot = mathutils.Vector((0.0, 0.0))
- n = 0
- it = stroke.stroke_vertices_begin()
- while not it.is_end:
- p = it.object.point
- pivot = pivot + p
- n += 1
- it.increment()
- pivot.x = pivot.x / n
- pivot.y = pivot.y / n
- elif self.__pivot == 'ABSOLUTE':
- pivot = mathutils.Vector((self.__pivot_x, self.__pivot_y))
+ for prev, svert in pairwise(stroke):
+ if self.pivot_u < svert.u:
+ break
+ pivot = svert.point + (svert.u - self.pivot_u) * (prev.point - svert.point)
+
# apply scaling and rotation operations
- cos_theta = math.cos(self.__angle)
- sin_theta = math.sin(self.__angle)
- it = stroke.stroke_vertices_begin()
- while not it.is_end:
- v = it.object
- p = v.point
- p = p - pivot
- x = p.x * self.__scale_x
- y = p.y * self.__scale_y
- p.x = x * cos_theta - y * sin_theta
- p.y = x * sin_theta + y * cos_theta
- v.point = p + pivot
- it.increment()
+ for svert in stroke:
+ p = (svert.point - pivot)
+ x = p.x * self.scale.x
+ y = p.y * self.scale.y
+ p.x = x * self.cos_theta - y * self.sin_theta
+ p.y = x * self.sin_theta + y * self.cos_theta
+ svert.point = p + pivot
stroke.update_length()
@@ -746,165 +620,46 @@ class Transform2DShader(StrokeShader):
class QuantitativeInvisibilityRangeUP1D(UnaryPredicate1D):
def __init__(self, qi_start, qi_end):
UnaryPredicate1D.__init__(self)
- self.__getQI = QuantitativeInvisibilityF1D()
- self.__qi_start = qi_start
- self.__qi_end = qi_end
+ self.getQI = QuantitativeInvisibilityF1D()
+ self.qi_start = qi_start
+ self.qi_end = qi_end
def __call__(self, inter):
- qi = self.__getQI(inter)
- return self.__qi_start <= qi <= self.__qi_end
-
-
-def join_unary_predicates(upred_list, bpred):
- if not upred_list:
- return None
- upred = upred_list[0]
- for p in upred_list[1:]:
- upred = bpred(upred, p)
- return upred
+ qi = self.getQI(inter)
+ return self.qi_start <= qi <= self.qi_end
class ObjectNamesUP1D(UnaryPredicate1D):
def __init__(self, names, negative):
UnaryPredicate1D.__init__(self)
- self._names = names
- self._negative = negative
+ self.names = names
+ self.negative = negative
def __call__(self, viewEdge):
- found = viewEdge.viewshape.name in self._names
- if self._negative:
+ found = viewEdge.viewshape.name in self.names
+ if self.negative:
return not found
return found
-# Stroke caps
-
-def iter_stroke_vertices(stroke):
- it = stroke.stroke_vertices_begin()
- prev_p = None
- while not it.is_end:
- sv = it.object
- p = sv.point
- if prev_p is None or (prev_p - p).length > 1e-6:
- yield sv
- prev_p = p.copy()
- it.increment()
-
-
-class RoundCapShader(StrokeShader):
- def round_cap_thickness(self, x):
- x = max(0.0, min(x, 1.0))
- return math.sqrt(1.0 - (x ** 2.0))
-
- def shade(self, stroke):
- # save the location and attribute of stroke vertices
- buffer = []
- for sv in iter_stroke_vertices(stroke):
- buffer.append((mathutils.Vector(sv.point), StrokeAttribute(sv.attribute)))
- nverts = len(buffer)
- if nverts < 2:
- return
- # calculate the number of additional vertices to form caps
- R, L = stroke[0].attribute.thickness
- caplen_beg = (R + L) / 2.0
- nverts_beg = max(5, int(R + L))
- R, L = stroke[-1].attribute.thickness
- caplen_end = (R + L) / 2.0
- nverts_end = max(5, int(R + L))
- # adjust the total number of stroke vertices
- stroke.resample(nverts + nverts_beg + nverts_end)
- # restore the location and attribute of the original vertices
- for i in range(nverts):
- p, attr = buffer[i]
- stroke[nverts_beg + i].point = p
- stroke[nverts_beg + i].attribute = attr
- # reshape the cap at the beginning of the stroke
- q, attr = buffer[1]
- p, attr = buffer[0]
- d = p - q
- d = d / d.length * caplen_beg
- n = 1.0 / nverts_beg
- R, L = attr.thickness
- for i in range(nverts_beg):
- t = (nverts_beg - i) * n
- stroke[i].point = p + d * t
- r = self.round_cap_thickness((nverts_beg - i + 1) * n)
- stroke[i].attribute = attr
- stroke[i].attribute.thickness = (R * r, L * r)
- # reshape the cap at the end of the stroke
- q, attr = buffer[-2]
- p, attr = buffer[-1]
- d = p - q
- d = d / d.length * caplen_end
- n = 1.0 / nverts_end
- R, L = attr.thickness
- for i in range(nverts_end):
- t = (nverts_end - i) * n
- stroke[-i - 1].point = p + d * t
- r = self.round_cap_thickness((nverts_end - i + 1) * n)
- stroke[-i - 1].attribute = attr
- stroke[-i - 1].attribute.thickness = (R * r, L * r)
- # update the curvilinear 2D length of each vertex
- stroke.update_length()
-
-
-class SquareCapShader(StrokeShader):
- def shade(self, stroke):
- # save the location and attribute of stroke vertices
- buffer = []
- for sv in iter_stroke_vertices(stroke):
- buffer.append((mathutils.Vector(sv.point), StrokeAttribute(sv.attribute)))
- nverts = len(buffer)
- if nverts < 2:
- return
- # calculate the number of additional vertices to form caps
- R, L = stroke[0].attribute.thickness
- caplen_beg = (R + L) / 2.0
- nverts_beg = 1
- R, L = stroke[-1].attribute.thickness
- caplen_end = (R + L) / 2.0
- nverts_end = 1
- # adjust the total number of stroke vertices
- stroke.resample(nverts + nverts_beg + nverts_end)
- # restore the location and attribute of the original vertices
- for i in range(nverts):
- p, attr = buffer[i]
- stroke[nverts_beg + i].point = p
- stroke[nverts_beg + i].attribute = attr
- # reshape the cap at the beginning of the stroke
- q, attr = buffer[1]
- p, attr = buffer[0]
- d = p - q
- stroke[0].point = p + d / d.length * caplen_beg
- stroke[0].attribute = attr
- # reshape the cap at the end of the stroke
- q, attr = buffer[-2]
- p, attr = buffer[-1]
- d = p - q
- stroke[-1].point = p + d / d.length * caplen_beg
- stroke[-1].attribute = attr
- # update the curvilinear 2D length of each vertex
- stroke.update_length()
-
-
-# Split by dashed line pattern
+# -- Split by dashed line pattern -- #
class SplitPatternStartingUP0D(UnaryPredicate0D):
def __init__(self, controller):
UnaryPredicate0D.__init__(self)
- self._controller = controller
+ self.controller = controller
def __call__(self, inter):
- return self._controller.start()
+ return self.controller.start()
class SplitPatternStoppingUP0D(UnaryPredicate0D):
def __init__(self, controller):
UnaryPredicate0D.__init__(self)
- self._controller = controller
+ self.controller = controller
def __call__(self, inter):
- return self._controller.stop()
+ return self.controller.stop()
class SplitPatternController:
@@ -946,29 +701,29 @@ class SplitPatternController:
class DashedLineShader(StrokeShader):
def __init__(self, pattern):
StrokeShader.__init__(self)
- self._pattern = pattern
+ self.pattern = pattern
def shade(self, stroke):
- index = 0 # pattern index
start = 0.0 # 2D curvilinear length
visible = True
+ # The extra 'sampling' term is added below, because the
+ # visibility attribute of the i-th vertex refers to the
+ # visibility of the stroke segment between the i-th and
+ # (i+1)-th vertices.
sampling = 1.0
it = stroke.stroke_vertices_begin(sampling)
- while not it.is_end:
+ pattern_cycle = cycle(self.pattern)
+ pattern = next(pattern_cycle)
+ for svert in it:
pos = it.t # curvilinear abscissa
- # The extra 'sampling' term is added below, because the
- # visibility attribute of the i-th vertex refers to the
- # visibility of the stroke segment between the i-th and
- # (i+1)-th vertices.
- if pos - start + sampling > self._pattern[index]:
+
+ if pos - start + sampling > pattern:
start = pos
- index += 1
- if index == len(self._pattern):
- index = 0
+ pattern = next(pattern_cycle)
visible = not visible
+
if not visible:
- it.object.attribute.visible = visible
- it.increment()
+ it.object.attribute.visible = False
# predicates for chaining
@@ -976,7 +731,7 @@ class DashedLineShader(StrokeShader):
class AngleLargerThanBP1D(BinaryPredicate1D):
def __init__(self, angle):
BinaryPredicate1D.__init__(self)
- self._angle = angle
+ self.angle = angle
def __call__(self, i1, i2):
sv1a = i1.first_fedge.first_svertex.point_2d
@@ -1001,38 +756,28 @@ class AngleLargerThanBP1D(BinaryPredicate1D):
if denom < 1e-6:
return False
x = (dir1 * dir2) / denom
- return math.acos(min(max(x, -1.0), 1.0)) > self._angle
-
-
-class AndBP1D(BinaryPredicate1D):
- def __init__(self, pred1, pred2):
- BinaryPredicate1D.__init__(self)
- self.__pred1 = pred1
- self.__pred2 = pred2
-
- def __call__(self, i1, i2):
- return self.__pred1(i1, i2) and self.__pred2(i1, i2)
-
+ return acos(bound(-1.0, x, 1.0)) > self.angle
# predicates for selection
+
class LengthThresholdUP1D(UnaryPredicate1D):
def __init__(self, length_min=None, length_max=None):
UnaryPredicate1D.__init__(self)
- self._length_min = length_min
- self._length_max = length_max
+ self.length_min = length_min
+ self.length_max = length_max
def __call__(self, inter):
length = inter.length_2d
- if self._length_min is not None and length < self._length_min:
+ if self.length_min is not None and length < self.length_min:
return False
- if self._length_max is not None and length > self._length_max:
+ if self.length_max is not None and length > self.length_max:
return False
return True
class FaceMarkBothUP1D(UnaryPredicate1D):
- def __call__(self, inter): # ViewEdge
+ def __call__(self, inter: ViewEdge):
fe = inter.first_fedge
while fe is not None:
if fe.is_smooth:
@@ -1049,7 +794,7 @@ class FaceMarkBothUP1D(UnaryPredicate1D):
class FaceMarkOneUP1D(UnaryPredicate1D):
- def __call__(self, inter): # ViewEdge
+ def __call__(self, inter: ViewEdge):
fe = inter.first_fedge
while fe is not None:
if fe.is_smooth:
@@ -1069,17 +814,14 @@ class FaceMarkOneUP1D(UnaryPredicate1D):
class MaterialBoundaryUP0D(UnaryPredicate0D):
def __call__(self, it):
- if it.is_begin:
- return False
- it_prev = Interface0DIterator(it)
- it_prev.decrement()
- v = it.object
- it.increment()
- if it.is_end:
+ # can't use only it.is_end here, see commit rBeb8964fb7f19
+ if it.is_begin or it.at_last or it.is_end:
return False
- fe = v.get_fedge(it_prev.object)
+ it.decrement()
+ prev, v, succ = next(it), next(it), next(it)
+ fe = v.get_fedge(prev)
idx1 = fe.material_index if fe.is_smooth else fe.material_index_left
- fe = v.get_fedge(it.object)
+ fe = v.get_fedge(succ)
idx2 = fe.material_index if fe.is_smooth else fe.material_index_left
return idx1 != idx2
@@ -1087,15 +829,15 @@ class MaterialBoundaryUP0D(UnaryPredicate0D):
class Curvature2DAngleThresholdUP0D(UnaryPredicate0D):
def __init__(self, angle_min=None, angle_max=None):
UnaryPredicate0D.__init__(self)
- self._angle_min = angle_min
- self._angle_max = angle_max
- self._func = Curvature2DAngleF0D()
+ self.angle_min = angle_min
+ self.angle_max = angle_max
+ self.func = Curvature2DAngleF0D()
def __call__(self, inter):
- angle = math.pi - self._func(inter)
- if self._angle_min is not None and angle < self._angle_min:
+ angle = pi - self.func(inter)
+ if self.angle_min is not None and angle < self.angle_min:
return True
- if self._angle_max is not None and angle > self._angle_max:
+ if self.angle_max is not None and angle > self.angle_max:
return True
return False
@@ -1103,17 +845,17 @@ class Curvature2DAngleThresholdUP0D(UnaryPredicate0D):
class Length2DThresholdUP0D(UnaryPredicate0D):
def __init__(self, length_limit):
UnaryPredicate0D.__init__(self)
- self._length_limit = length_limit
- self._t = 0.0
+ self.length_limit = length_limit
+ self.t = 0.0
def __call__(self, inter):
t = inter.t # curvilinear abscissa
- if t < self._t:
- self._t = 0.0
+ if t < self.t:
+ self.t = 0.0
return False
- if t - self._t < self._length_limit:
+ if t - self.t < self.length_limit:
return False
- self._t = t
+ self.t = t
return True
@@ -1192,9 +934,9 @@ def process(layer_name, lineset_name):
upred = ExternalContourUP1D()
edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_external_contour else upred)
if lineset.edge_type_combination == 'OR':
- upred = join_unary_predicates(edge_type_criteria, OrUP1D)
+ upred = OrUP1D(*edge_type_criteria)
else:
- upred = join_unary_predicates(edge_type_criteria, AndUP1D)
+ upred = AndUP1D(*edge_type_criteria)
if upred is not None:
if lineset.edge_type_negation == 'EXCLUSIVE':
upred = NotUP1D(upred)
@@ -1205,22 +947,22 @@ def process(layer_name, lineset_name):
upred = FaceMarkBothUP1D()
else:
upred = FaceMarkOneUP1D()
+
if lineset.face_mark_negation == 'EXCLUSIVE':
upred = NotUP1D(upred)
selection_criteria.append(upred)
# prepare selection criteria by group of objects
if lineset.select_by_group:
if lineset.group is not None:
- names = dict((ob.name, True) for ob in lineset.group.objects)
+ names = {ob.name: True for ob in lineset.group.objects}
upred = ObjectNamesUP1D(names, lineset.group_negation == 'EXCLUSIVE')
selection_criteria.append(upred)
# prepare selection criteria by image border
if lineset.select_by_image_border:
- xmin, ymin, xmax, ymax = ContextFunctions.get_border()
- upred = WithinImageBoundaryUP1D(xmin, ymin, xmax, ymax)
+ upred = WithinImageBoundaryUP1D(*ContextFunctions.get_border())
selection_criteria.append(upred)
# select feature edges
- upred = join_unary_predicates(selection_criteria, AndUP1D)
+ upred = AndUP1D(*selection_criteria)
if upred is None:
upred = TrueUP1D()
Operators.select(upred)
@@ -1330,15 +1072,7 @@ def process(layer_name, lineset_name):
elif m.type == '2D_TRANSFORM':
shaders_list.append(Transform2DShader(
m.pivot, m.scale_x, m.scale_y, m.angle, m.pivot_u, m.pivot_x, m.pivot_y))
- if linestyle.use_texture:
- has_tex = False
- for slot in linestyle.texture_slots:
- if slot is not None:
- shaders_list.append(BlenderTextureShader(slot))
- has_tex = True
- if has_tex:
- shaders_list.append(StrokeTextureStepShader(linestyle.texture_spacing))
- color = linestyle.color
+ # -- Base color, alpha and thickness -- #
if (not linestyle.use_chaining) or (linestyle.chaining == 'PLAIN' and linestyle.use_same_object):
thickness_position = linestyle.thickness_position
else:
@@ -1347,9 +1081,10 @@ def process(layer_name, lineset_name):
if bpy.app.debug_freestyle:
print("Warning: Thickness position options are applied when chaining is disabled\n"
" or the Plain chaining is used with the Same Object option enabled.")
- shaders_list.append(BaseColorShader(color.r, color.g, color.b, linestyle.alpha))
+ shaders_list.append(ConstantColorShader(*(linestyle.color), alpha=linestyle.alpha))
shaders_list.append(BaseThicknessShader(linestyle.thickness, thickness_position,
linestyle.thickness_ratio))
+ # -- Modifiers -- #
for m in linestyle.color_modifiers:
if not m.use:
continue
@@ -1360,7 +1095,7 @@ def process(layer_name, lineset_name):
shaders_list.append(ColorDistanceFromCameraShader(
m.blend, m.influence, m.color_ramp,
m.range_min, m.range_max))
- elif m.type == 'DISTANCE_FROM_OBJECT':
+ elif m.type == 'DISTANCE_FROM_OBJECT' and m.target is not None:
shaders_list.append(ColorDistanceFromObjectShader(
m.blend, m.influence, m.color_ramp, m.target,
m.range_min, m.range_max))
@@ -1378,7 +1113,7 @@ def process(layer_name, lineset_name):
shaders_list.append(AlphaDistanceFromCameraShader(
m.blend, m.influence, m.mapping, m.invert, m.curve,
m.range_min, m.range_max))
- elif m.type == 'DISTANCE_FROM_OBJECT':
+ elif m.type == 'DISTANCE_FROM_OBJECT' and m.target is not None:
shaders_list.append(AlphaDistanceFromObjectShader(
m.blend, m.influence, m.mapping, m.invert, m.curve, m.target,
m.range_min, m.range_max))
@@ -1399,7 +1134,7 @@ def process(layer_name, lineset_name):
thickness_position, linestyle.thickness_ratio,
m.blend, m.influence, m.mapping, m.invert, m.curve,
m.range_min, m.range_max, m.value_min, m.value_max))
- elif m.type == 'DISTANCE_FROM_OBJECT':
+ elif m.type == 'DISTANCE_FROM_OBJECT' and m.target is not None:
shaders_list.append(ThicknessDistanceFromObjectShader(
thickness_position, linestyle.thickness_ratio,
m.blend, m.influence, m.mapping, m.invert, m.curve, m.target,
@@ -1414,10 +1149,26 @@ def process(layer_name, lineset_name):
thickness_position, linestyle.thickness_ratio,
m.blend, m.influence,
m.orientation, m.thickness_min, m.thickness_max))
+ # -- Textures -- #
+ has_tex = False
+ if scene.render.use_shading_nodes:
+ if linestyle.use_nodes and linestyle.node_tree:
+ shaders_list.append(BlenderTextureShader(linestyle.node_tree))
+ has_tex = True
+ else:
+ if linestyle.use_texture:
+ textures = tuple(BlenderTextureShader(slot) for slot in linestyle.texture_slots if slot is not None)
+ if textures:
+ shaders_list.extend(textures)
+ has_tex = True
+ if has_tex:
+ shaders_list.append(StrokeTextureStepShader(linestyle.texture_spacing))
+ # -- Stroke caps -- #
if linestyle.caps == 'ROUND':
shaders_list.append(RoundCapShader())
elif linestyle.caps == 'SQUARE':
shaders_list.append(SquareCapShader())
+ # -- Dashed line -- #
if linestyle.use_dashed_line:
pattern = []
if linestyle.dash1 > 0 and linestyle.gap1 > 0:
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 99475603bf2..a887ebde449 100644
--- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
@@ -363,6 +363,7 @@ class SpellChecker():
"icosphere",
"inpaint",
"lightmap",
+ "linearlight",
"lossless", "lossy",
"matcap",
"midtones",
@@ -372,6 +373,7 @@ class SpellChecker():
"nurb", "nurbs",
"perlin",
"phong",
+ "pinlight",
"qi",
"radiosity",
"raycasting",
@@ -379,6 +381,7 @@ class SpellChecker():
"renderfarm",
"scanfill",
"shader", "shaders",
+ "softlight",
"specular", "specularity",
"spillmap",
"sobel",
@@ -386,6 +389,7 @@ class SpellChecker():
"tonemap",
"toon",
"timecode",
+ "vividlight",
"voronoi",
"voxel", "voxels",
"vsync",
diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py
index ccc9df93b0d..874efc2e131 100644
--- a/release/scripts/modules/bpy/path.py
+++ b/release/scripts/modules/bpy/path.py
@@ -219,7 +219,10 @@ def resolve_ncase(path):
# we are expecting 'dirpath' to be a directory, but it could be a file
if _os.path.isdir(dirpath):
- files = _os.listdir(dirpath)
+ try:
+ files = _os.listdir(dirpath)
+ except PermissionError: # We might not have the permission to list dirpath...
+ return path, False
else:
return path, False
diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py
index 5621af29bc3..b3a7a13e331 100644
--- a/release/scripts/modules/bpy/utils.py
+++ b/release/scripts/modules/bpy/utils.py
@@ -429,7 +429,7 @@ def time_from_frame(frame, fps=None, fps_base=None):
:arg frame: number.
:type frame: the frame number
:return: the time in seconds.
- :rtype: timedate.timedelta
+ :rtype: datetime.timedelta
"""
if fps is None:
@@ -440,18 +440,18 @@ def time_from_frame(frame, fps=None, fps_base=None):
from datetime import timedelta
- return timedelta((frame * fps_base) / fps)
+ return timedelta(0, (frame * fps_base) / fps)
def time_to_frame(time, fps=None, fps_base=None):
"""
Returns a float frame number from a time given in seconds or
- as a timedate.timedelta object.
+ as a datetime.timedelta object.
If *fps* and *fps_base* are not given the current scene is used.
:arg time: time in seconds.
- :type time: number or a timedate.timedelta object
+ :type time: number or a datetime.timedelta object
:return: the frame.
:rtype: float
"""
diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py
index 1e3e4c873a8..4293930e823 100644
--- a/release/scripts/modules/bpy_extras/mesh_utils.py
+++ b/release/scripts/modules/bpy_extras/mesh_utils.py
@@ -421,7 +421,6 @@ def ngon_tessellate(from_data, indices, fix_loops=True):
loop_segments.append(context_loop)
else:
if context_loop and context_loop[-1][1] == v[1]:
- #raise "as"
pass
else:
context_loop.append(v)
diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index 766da46107b..01390760c76 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -245,6 +245,7 @@ def object_image_guess(obj, bm=None):
me = obj.data
if bm is None:
if obj.mode == 'EDIT':
+ import bmesh
bm = bmesh.from_edit_mesh(me)
if bm is not None:
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index d2683471915..bc2e9368b71 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -140,6 +140,15 @@ class WindowManager(bpy_types.ID):
finally:
self.pupmenu_end__internal(popup)
+ def popup_menu_pie(self, event, draw_func, title="", icon='NONE'):
+ import bpy
+ pie = self.piemenu_begin__internal(title, icon, event)
+
+ try:
+ draw_func(pie, bpy.context)
+ finally:
+ self.piemenu_end__internal(pie)
+
class _GenericBone:
"""
diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py
index e9c96d59eae..e278b0d20fe 100644
--- a/release/scripts/modules/rna_prop_ui.py
+++ b/release/scripts/modules/rna_prop_ui.py
@@ -57,6 +57,7 @@ def rna_idprop_ui_prop_clear(item, prop):
except:
pass
+
def rna_idprop_context_value(context, context_member, property_type):
space = context.space_data
@@ -73,11 +74,13 @@ def rna_idprop_context_value(context, context_member, property_type):
return rna_item, context_member
+
def rna_idprop_has_properties(rna_item):
keys = rna_item.keys()
nbr_props = len(keys)
return (nbr_props > 1) or (nbr_props and '_RNA_UI' not in keys)
+
def draw(layout, context, context_member, property_type, use_edit=True):
def assign_props(prop, val, key):
diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py
index f87cf611dd4..7fd97c4d347 100644
--- a/release/scripts/modules/sys_info.py
+++ b/release/scripts/modules/sys_info.py
@@ -153,7 +153,8 @@ def write_sysinfo(op):
else:
output.write("\nOpenGL\n")
output.write(lilies)
- output.write("renderer:\t%r\n" % (bgl.glGetString(bgl.GL_RENDERER)))
+ version = bgl.glGetString(bgl.GL_RENDERER);
+ output.write("renderer:\t%r\n" % version)
output.write("vendor:\t\t%r\n" % (bgl.glGetString(bgl.GL_VENDOR)))
output.write("version:\t%r\n" % (bgl.glGetString(bgl.GL_VERSION)))
output.write("extensions:\n")
@@ -163,6 +164,29 @@ def write_sysinfo(op):
for l in glext:
output.write("\t\t%r\n" % (l))
+ output.write("\nImplementation Dependent OpenGL Limits:\n")
+ output.write(lilies)
+ limit = bgl.Buffer(bgl.GL_INT, 1)
+ bgl.glGetIntegerv(bgl.GL_MAX_TEXTURE_UNITS, limit)
+ output.write("Maximum Fixed Function Texture Units:\t%d\n" % limit[0])
+
+ output.write("\nGLSL:\n")
+ if version[0] > '1':
+ bgl.glGetIntegerv(bgl.GL_MAX_VARYING_FLOATS, limit)
+ output.write("Maximum Varying Floats:\t%d\n" % limit[0])
+ bgl.glGetIntegerv(bgl.GL_MAX_VERTEX_ATTRIBS, limit)
+ output.write("Maximum Vertex Attributes:\t%d\n" % limit[0])
+ bgl.glGetIntegerv(bgl.GL_MAX_VERTEX_UNIFORM_COMPONENTS, limit)
+ output.write("Maximum Vertex Uniform Components:\t%d\n" % limit[0])
+ bgl.glGetIntegerv(bgl.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, limit)
+ output.write("Maximum Fragment Uniform Components:\t%d\n" % limit[0])
+ bgl.glGetIntegerv(bgl.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, limit)
+ output.write("Maximum Vertex Image Units:\t%d\n" % limit[0])
+ bgl.glGetIntegerv(bgl.GL_MAX_TEXTURE_IMAGE_UNITS, limit)
+ output.write("Maximum Fragment Image Units:\t%d\n" % limit[0])
+ bgl.glGetIntegerv(bgl.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, limit)
+ output.write("Maximum Pipeline Image Units:\t%d\n" % limit[0])
+
output.current_line_index = 0
op.report({'INFO'}, "System information generated in 'system-info.txt'")
diff --git a/release/scripts/presets/camera/1__colon__2.3_inch.py b/release/scripts/presets/camera/1__colon__2.3_inch.py
index 829a060ab35..72548384401 100644
--- a/release/scripts/presets/camera/1__colon__2.3_inch.py
+++ b/release/scripts/presets/camera/1__colon__2.3_inch.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 6.16
-bpy.context.object.data.sensor_height = 4.62
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 6.16
+bpy.context.camera.sensor_height = 4.62
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/1__colon__2.5_inch.py b/release/scripts/presets/camera/1__colon__2.5_inch.py
index 3ddd240ab50..90f60e7d7f0 100644
--- a/release/scripts/presets/camera/1__colon__2.5_inch.py
+++ b/release/scripts/presets/camera/1__colon__2.5_inch.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 5.76
-bpy.context.object.data.sensor_height = 4.29
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 5.76
+bpy.context.camera.sensor_height = 4.29
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/2__colon__3_inch.py b/release/scripts/presets/camera/2__colon__3_inch.py
index edf3bbba2c9..46436970efc 100644
--- a/release/scripts/presets/camera/2__colon__3_inch.py
+++ b/release/scripts/presets/camera/2__colon__3_inch.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 9.6
-bpy.context.object.data.sensor_height = 5.4
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 9.6
+bpy.context.camera.sensor_height = 5.4
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/4__colon__3_inch.py b/release/scripts/presets/camera/4__colon__3_inch.py
index 6e38782c4d8..88346c01ef8 100644
--- a/release/scripts/presets/camera/4__colon__3_inch.py
+++ b/release/scripts/presets/camera/4__colon__3_inch.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 17.31
-bpy.context.object.data.sensor_height = 12.98
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 17.31
+bpy.context.camera.sensor_height = 12.98
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Arri_Alexa.py b/release/scripts/presets/camera/Arri_Alexa.py
index 2bdcf12240b..6a6cdfee12b 100644
--- a/release/scripts/presets/camera/Arri_Alexa.py
+++ b/release/scripts/presets/camera/Arri_Alexa.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 23.760
-bpy.context.object.data.sensor_height = 13.365
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 23.760
+bpy.context.camera.sensor_height = 13.365
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Blackmagic_Cinema_Camera.py b/release/scripts/presets/camera/Blackmagic_Cinema_Camera.py
index 402a5b30cbb..6fde30756da 100644
--- a/release/scripts/presets/camera/Blackmagic_Cinema_Camera.py
+++ b/release/scripts/presets/camera/Blackmagic_Cinema_Camera.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 15.81
-bpy.context.object.data.sensor_height = 8.88
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 15.81
+bpy.context.camera.sensor_height = 8.88
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Blackmagic_Pocket_Cinema_Camera.py b/release/scripts/presets/camera/Blackmagic_Pocket_Cinema_Camera.py
new file mode 100644
index 00000000000..bb2b172919e
--- /dev/null
+++ b/release/scripts/presets/camera/Blackmagic_Pocket_Cinema_Camera.py
@@ -0,0 +1,4 @@
+import bpy
+bpy.context.camera.sensor_width = 12.48
+bpy.context.camera.sensor_height = 7.02
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Blackmagic_Production_Camera_4K.py b/release/scripts/presets/camera/Blackmagic_Production_Camera_4K.py
new file mode 100644
index 00000000000..dbc12c5aa68
--- /dev/null
+++ b/release/scripts/presets/camera/Blackmagic_Production_Camera_4K.py
@@ -0,0 +1,4 @@
+import bpy
+bpy.context.camera.sensor_width = 21.12
+bpy.context.camera.sensor_height = 11.88
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Blender.py b/release/scripts/presets/camera/Blender.py
index 9fa4ab752e3..ca4906fbb39 100644
--- a/release/scripts/presets/camera/Blender.py
+++ b/release/scripts/presets/camera/Blender.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 32
-bpy.context.object.data.sensor_height = 18
-bpy.context.object.data.sensor_fit = 'AUTO'
+bpy.context.camera.sensor_width = 32
+bpy.context.camera.sensor_height = 18
+bpy.context.camera.sensor_fit = 'AUTO'
diff --git a/release/scripts/presets/camera/Canon_1100D.py b/release/scripts/presets/camera/Canon_1100D.py
index 54f2cf75b54..e665e9e95d5 100644
--- a/release/scripts/presets/camera/Canon_1100D.py
+++ b/release/scripts/presets/camera/Canon_1100D.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 22.2
-bpy.context.object.data.sensor_height = 14.7
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 22.2
+bpy.context.camera.sensor_height = 14.7
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Canon_APS-C.py b/release/scripts/presets/camera/Canon_APS-C.py
index 829e03cc5cf..95108b2187f 100644
--- a/release/scripts/presets/camera/Canon_APS-C.py
+++ b/release/scripts/presets/camera/Canon_APS-C.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 22.3
-bpy.context.object.data.sensor_height = 14.9
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 22.3
+bpy.context.camera.sensor_height = 14.9
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Canon_APS-H.py b/release/scripts/presets/camera/Canon_APS-H.py
index d5cc02f4e4a..d3b61d1aa46 100644
--- a/release/scripts/presets/camera/Canon_APS-H.py
+++ b/release/scripts/presets/camera/Canon_APS-H.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 27.90
-bpy.context.object.data.sensor_height = 18.60
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 27.90
+bpy.context.camera.sensor_height = 18.60
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Canon_C300.py b/release/scripts/presets/camera/Canon_C300.py
index 70c760c73b5..e22af779854 100644
--- a/release/scripts/presets/camera/Canon_C300.py
+++ b/release/scripts/presets/camera/Canon_C300.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 24.4
-bpy.context.object.data.sensor_height = 13.5
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 24.4
+bpy.context.camera.sensor_height = 13.5
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Full_Frame_35mm_Camera.py b/release/scripts/presets/camera/Full_Frame_35mm_Camera.py
index d3e141ba4d9..c8017331b28 100644
--- a/release/scripts/presets/camera/Full_Frame_35mm_Camera.py
+++ b/release/scripts/presets/camera/Full_Frame_35mm_Camera.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 36
-bpy.context.object.data.sensor_height = 24
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 36
+bpy.context.camera.sensor_height = 24
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/GoPro_Hero3_Black.py b/release/scripts/presets/camera/GoPro_Hero3_Black.py
index 9cea698d8ab..e294f802a02 100644
--- a/release/scripts/presets/camera/GoPro_Hero3_Black.py
+++ b/release/scripts/presets/camera/GoPro_Hero3_Black.py
@@ -1,6 +1,6 @@
import bpy
-bpy.context.object.data.sensor_width = 6.16
-bpy.context.object.data.sensor_height = 4.62
-bpy.context.object.data.lens = 2.77
+bpy.context.camera.sensor_width = 6.16
+bpy.context.camera.sensor_height = 4.62
+bpy.context.camera.lens = 2.77
-bpy.context.object.data.sensor_fit = 'AUTO'
+bpy.context.camera.sensor_fit = 'AUTO'
diff --git a/release/scripts/presets/camera/GoPro_Hero3_Silver.py b/release/scripts/presets/camera/GoPro_Hero3_Silver.py
index 1eee0750c2d..247bd7c4aaf 100644
--- a/release/scripts/presets/camera/GoPro_Hero3_Silver.py
+++ b/release/scripts/presets/camera/GoPro_Hero3_Silver.py
@@ -1,6 +1,6 @@
import bpy
-bpy.context.object.data.sensor_width = 5.371
-bpy.context.object.data.sensor_height = 4.035
-bpy.context.object.data.lens = 2.77
+bpy.context.camera.sensor_width = 5.371
+bpy.context.camera.sensor_height = 4.035
+bpy.context.camera.lens = 2.77
-bpy.context.object.data.sensor_fit = 'AUTO'
+bpy.context.camera.sensor_fit = 'AUTO'
diff --git a/release/scripts/presets/camera/GoPro_Hero3_White.py b/release/scripts/presets/camera/GoPro_Hero3_White.py
index 3d1f368aab0..948f838f5d6 100644
--- a/release/scripts/presets/camera/GoPro_Hero3_White.py
+++ b/release/scripts/presets/camera/GoPro_Hero3_White.py
@@ -1,6 +1,6 @@
import bpy
-bpy.context.object.data.sensor_width = 5.76
-bpy.context.object.data.sensor_height = 4.29
-bpy.context.object.data.lens = 2.77
+bpy.context.camera.sensor_width = 5.76
+bpy.context.camera.sensor_height = 4.29
+bpy.context.camera.lens = 2.77
-bpy.context.object.data.sensor_fit = 'AUTO'
+bpy.context.camera.sensor_fit = 'AUTO'
diff --git a/release/scripts/presets/camera/Nexus_5.py b/release/scripts/presets/camera/Nexus_5.py
index aa781782acb..36e741cbba5 100644
--- a/release/scripts/presets/camera/Nexus_5.py
+++ b/release/scripts/presets/camera/Nexus_5.py
@@ -1,5 +1,5 @@
import bpy
-bpy.context.object.data.sensor_width = 4.5
-bpy.context.object.data.sensor_height = 3.37
-bpy.context.object.data.lens = 3.91
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 4.5
+bpy.context.camera.sensor_height = 3.37
+bpy.context.camera.lens = 3.91
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Nikon_D3100.py b/release/scripts/presets/camera/Nikon_D3100.py
index 238d9c22d12..b4ceb3aa721 100644
--- a/release/scripts/presets/camera/Nikon_D3100.py
+++ b/release/scripts/presets/camera/Nikon_D3100.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 23.1
-bpy.context.object.data.sensor_height = 15.4
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 23.1
+bpy.context.camera.sensor_height = 15.4
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Nikon_DX.py b/release/scripts/presets/camera/Nikon_DX.py
index a0505bf9b9c..dbe9e7fcc18 100644
--- a/release/scripts/presets/camera/Nikon_DX.py
+++ b/release/scripts/presets/camera/Nikon_DX.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 23.6
-bpy.context.object.data.sensor_height = 15.8
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 23.6
+bpy.context.camera.sensor_height = 15.8
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Panasonic_AG-HVX200.py b/release/scripts/presets/camera/Panasonic_AG-HVX200.py
index ee82cbe9bf0..71ad3c3a161 100644
--- a/release/scripts/presets/camera/Panasonic_AG-HVX200.py
+++ b/release/scripts/presets/camera/Panasonic_AG-HVX200.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 4.68
-bpy.context.object.data.sensor_height = 2.633
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 4.68
+bpy.context.camera.sensor_height = 2.633
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Panasonic_LX2.py b/release/scripts/presets/camera/Panasonic_LX2.py
index 8e0f844e507..d66e02e32d4 100644
--- a/release/scripts/presets/camera/Panasonic_LX2.py
+++ b/release/scripts/presets/camera/Panasonic_LX2.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 8.5
-bpy.context.object.data.sensor_height = 4.78
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 8.5
+bpy.context.camera.sensor_height = 4.78
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Red_Epic.py b/release/scripts/presets/camera/Red_Epic.py
index 14f4abaee90..5d71a69a33d 100644
--- a/release/scripts/presets/camera/Red_Epic.py
+++ b/release/scripts/presets/camera/Red_Epic.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 30.0
-bpy.context.object.data.sensor_height = 15.0
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 30.0
+bpy.context.camera.sensor_height = 15.0
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Red_One_2K.py b/release/scripts/presets/camera/Red_One_2K.py
index ef2708f75b2..894aedcf9ea 100644
--- a/release/scripts/presets/camera/Red_One_2K.py
+++ b/release/scripts/presets/camera/Red_One_2K.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 11.1
-bpy.context.object.data.sensor_height = 6.24
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 11.1
+bpy.context.camera.sensor_height = 6.24
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Red_One_3K.py b/release/scripts/presets/camera/Red_One_3K.py
index 5ddff2746eb..9ac84c1485a 100644
--- a/release/scripts/presets/camera/Red_One_3K.py
+++ b/release/scripts/presets/camera/Red_One_3K.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 16.65
-bpy.context.object.data.sensor_height = 9.36
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 16.65
+bpy.context.camera.sensor_height = 9.36
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Red_One_4K.py b/release/scripts/presets/camera/Red_One_4K.py
index 8ab9b38cbd5..067322cd07e 100644
--- a/release/scripts/presets/camera/Red_One_4K.py
+++ b/release/scripts/presets/camera/Red_One_4K.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 22.2
-bpy.context.object.data.sensor_height = 12.6
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 22.2
+bpy.context.camera.sensor_height = 12.6
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Samsung_Galaxy_S3.py b/release/scripts/presets/camera/Samsung_Galaxy_S3.py
index 35670042e48..23eaea7cd27 100644
--- a/release/scripts/presets/camera/Samsung_Galaxy_S3.py
+++ b/release/scripts/presets/camera/Samsung_Galaxy_S3.py
@@ -1,5 +1,5 @@
import bpy
-bpy.context.object.data.sensor_width = 4.8
-bpy.context.object.data.sensor_height = 3.6
-bpy.context.object.data.lens = 3.70
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 4.8
+bpy.context.camera.sensor_height = 3.6
+bpy.context.camera.lens = 3.70
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Samsung_Galaxy_S4.py b/release/scripts/presets/camera/Samsung_Galaxy_S4.py
index ae16d4172f9..cc929d26dac 100644
--- a/release/scripts/presets/camera/Samsung_Galaxy_S4.py
+++ b/release/scripts/presets/camera/Samsung_Galaxy_S4.py
@@ -1,5 +1,5 @@
import bpy
-bpy.context.object.data.sensor_width = 4.8
-bpy.context.object.data.sensor_height = 3.6
-bpy.context.object.data.lens = 4.20
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 4.8
+bpy.context.camera.sensor_height = 3.6
+bpy.context.camera.lens = 4.20
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Sony_A55.py b/release/scripts/presets/camera/Sony_A55.py
index b0f172206fa..0468deb6d4c 100644
--- a/release/scripts/presets/camera/Sony_A55.py
+++ b/release/scripts/presets/camera/Sony_A55.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 23.4
-bpy.context.object.data.sensor_height = 15.6
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 23.4
+bpy.context.camera.sensor_height = 15.6
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Sony_EX1.py b/release/scripts/presets/camera/Sony_EX1.py
index 00708175b40..3c6b235f21e 100644
--- a/release/scripts/presets/camera/Sony_EX1.py
+++ b/release/scripts/presets/camera/Sony_EX1.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 6.97
-bpy.context.object.data.sensor_height = 3.92
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 6.97
+bpy.context.camera.sensor_height = 3.92
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Sony_F65.py b/release/scripts/presets/camera/Sony_F65.py
index e187828058b..e62b3511836 100644
--- a/release/scripts/presets/camera/Sony_F65.py
+++ b/release/scripts/presets/camera/Sony_F65.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 24.33
-bpy.context.object.data.sensor_height = 12.83
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 24.33
+bpy.context.camera.sensor_height = 12.83
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Super_16_Film.py b/release/scripts/presets/camera/Super_16_Film.py
index 1e42953bf05..4ca397a7e27 100644
--- a/release/scripts/presets/camera/Super_16_Film.py
+++ b/release/scripts/presets/camera/Super_16_Film.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 12.52
-bpy.context.object.data.sensor_height = 7.41
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 12.52
+bpy.context.camera.sensor_height = 7.41
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Super_35_Film.py b/release/scripts/presets/camera/Super_35_Film.py
index 65ccb0f216c..b22ff545c68 100644
--- a/release/scripts/presets/camera/Super_35_Film.py
+++ b/release/scripts/presets/camera/Super_35_Film.py
@@ -1,4 +1,4 @@
import bpy
-bpy.context.object.data.sensor_width = 24.89
-bpy.context.object.data.sensor_height = 18.66
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 24.89
+bpy.context.camera.sensor_height = 18.66
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/iPhone_4.py b/release/scripts/presets/camera/iPhone_4.py
index b87dda18097..1e43cd11494 100644
--- a/release/scripts/presets/camera/iPhone_4.py
+++ b/release/scripts/presets/camera/iPhone_4.py
@@ -1,5 +1,5 @@
import bpy
-bpy.context.object.data.sensor_width = 4.54
-bpy.context.object.data.sensor_height = 3.42
-bpy.context.object.data.lens = 3.85
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 4.54
+bpy.context.camera.sensor_height = 3.42
+bpy.context.camera.lens = 3.85
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/iPhone_4S.py b/release/scripts/presets/camera/iPhone_4S.py
index ea747f339d4..1139b7395b5 100644
--- a/release/scripts/presets/camera/iPhone_4S.py
+++ b/release/scripts/presets/camera/iPhone_4S.py
@@ -1,5 +1,5 @@
import bpy
-bpy.context.object.data.sensor_width = 4.54
-bpy.context.object.data.sensor_height = 3.42
-bpy.context.object.data.lens = 4.28
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 4.54
+bpy.context.camera.sensor_height = 3.42
+bpy.context.camera.lens = 4.28
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/iPhone_5.py b/release/scripts/presets/camera/iPhone_5.py
index 2764788a405..a6b6bbc2ec5 100644
--- a/release/scripts/presets/camera/iPhone_5.py
+++ b/release/scripts/presets/camera/iPhone_5.py
@@ -1,5 +1,5 @@
import bpy
-bpy.context.object.data.sensor_width = 4.54
-bpy.context.object.data.sensor_height = 3.42
-bpy.context.object.data.lens = 4.10
-bpy.context.object.data.sensor_fit = 'HORIZONTAL'
+bpy.context.camera.sensor_width = 4.54
+bpy.context.camera.sensor_height = 3.42
+bpy.context.camera.lens = 4.10
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/cycles/integrator/direct_light.py b/release/scripts/presets/cycles/integrator/direct_light.py
index 504068722d7..12b332cb431 100644
--- a/release/scripts/presets/cycles/integrator/direct_light.py
+++ b/release/scripts/presets/cycles/integrator/direct_light.py
@@ -3,9 +3,11 @@ cycles = bpy.context.scene.cycles
cycles.max_bounces = 8
cycles.min_bounces = 8
-cycles.no_caustics = True
+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 8687f169b8a..69fa6e735bd 100644
--- a/release/scripts/presets/cycles/integrator/full_global_illumination.py
+++ b/release/scripts/presets/cycles/integrator/full_global_illumination.py
@@ -3,9 +3,11 @@ cycles = bpy.context.scene.cycles
cycles.max_bounces = 128
cycles.min_bounces = 3
-cycles.no_caustics = False
+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 f2a7e1f7b7a..22a8478d23b 100644
--- a/release/scripts/presets/cycles/integrator/limited_global_illumination.py
+++ b/release/scripts/presets/cycles/integrator/limited_global_illumination.py
@@ -3,9 +3,11 @@ cycles = bpy.context.scene.cycles
cycles.max_bounces = 8
cycles.min_bounces = 3
-cycles.no_caustics = True
+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/interface_theme/back_to_black.xml b/release/scripts/presets/interface_theme/back_to_black.xml
index b9e84e1eb7e..152e944a7ba 100644
--- a/release/scripts/presets/interface_theme/back_to_black.xml
+++ b/release/scripts/presets/interface_theme/back_to_black.xml
@@ -152,6 +152,18 @@
shadedown="0">
</ThemeWidgetColors>
</wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors outline="#0a0a0a"
+ inner="#191919e6"
+ inner_sel="#8c8c8cff"
+ item="#2d2d2de6"
+ text="#a0a0a0"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="10"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
<wcol_tooltip>
<ThemeWidgetColors outline="#000000"
inner="#191919e6"
@@ -231,6 +243,7 @@
lamp="#c1d40028"
speaker="#535353"
camera="#000000"
+ view_overlay="#000000"
empty="#000000"
object_selected="#f15800"
object_active="#ff8c19"
@@ -260,10 +273,10 @@
handle_free="#7f7f7f"
handle_auto="#909000"
handle_vect="#409030"
+ handle_sel_vect="#40c030"
handle_align="#803060"
handle_sel_free="#3b3b3b"
handle_sel_auto="#f0ff40"
- handle_sel_vect="#40c030"
handle_sel_align="#f090a0"
lastsel_point="#ffffff"
extra_edge_len="#ffedf8"
@@ -280,7 +293,9 @@
outline_width="1"
bundle_solid="#c8c8c8"
camera_path="#5a5a5a"
- skin_root="#000000">
+ skin_root="#000000"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
<space>
<ThemeSpaceGradient title="#5d5d5d"
text="#7d7d7d"
@@ -292,13 +307,13 @@
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff"
- tab_active="#000000"
+ tab_active="#212947"
tab_inactive="#000000"
- tab_back="#060606"
+ tab_back="#060606ff"
tab_outline="#3a3a3a">
<gradients>
- <ThemeGradientColors show_grad="FALSE"
- gradient="#393939"
+ <ThemeGradientColors show_grad="TRUE"
+ gradient="#0a0a0a"
high_gradient="#000000">
</ThemeGradientColors>
</gradients>
@@ -329,10 +344,10 @@
handle_free="#808080"
handle_auto="#909000"
handle_vect="#409030"
+ handle_sel_vect="#40c030"
handle_align="#803060"
handle_sel_free="#808080"
handle_sel_auto="#f0ff40"
- handle_sel_vect="#40c030"
handle_sel_align="#f090a0"
handle_auto_clamped="#994030"
handle_sel_auto_clamped="#f0af90"
@@ -354,7 +369,7 @@
button_text_hi="#ffffff"
tab_active="#000000"
tab_inactive="#000000"
- tab_back="#060606"
+ tab_back="#060606ff"
tab_outline="#3a3a3a">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -394,7 +409,7 @@
button_text_hi="#ffffff"
tab_active="#000000"
tab_inactive="#000000"
- tab_back="#060606"
+ tab_back="#060606ff"
tab_outline="#3a3a3a">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -417,21 +432,21 @@
<nla_editor>
<ThemeNLAEditor grid="#5e5e5e"
view_sliders="#969696"
- active_action="#00000000"
- active_action_unset="#00000000"
- strips="#aa8d8d"
+ active_action="#cc701a66"
+ active_action_unset="#9987614d"
+ strips="#0c0a0a"
strips_selected="#ff8c00"
- transition_strips="#000000"
- transition_strips_selected="#000000"
- meta_strips="#000000"
- meta_strips_selected="#000000"
- sound_strips="#000000"
- sound_strips_selected="#000000"
- tweak="#000000"
- tweak_duplicate="#000000"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
keyframe_border="#000000ff"
keyframe_border_selected="#000000ff"
- frame_current="#2f6421">
+ frame_current="#60c040">
<space>
<ThemeSpaceGeneric back="#0d0d0d"
title="#585858"
@@ -446,7 +461,7 @@
button_text_hi="#ffffff"
tab_active="#000000"
tab_inactive="#000000"
- tab_back="#060606"
+ tab_back="#060606ff"
tab_outline="#3a3a3a">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -504,7 +519,7 @@
button_text_hi="#ffffff"
tab_active="#000000"
tab_inactive="#000000"
- tab_back="#060606"
+ tab_back="#060606ff"
tab_outline="#3a3a3a">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -545,7 +560,21 @@
preview_stitch_unstitchable="#ff0000ff"
preview_stitch_active="#e1d2c323"
uv_shadow="#707070ff"
- uv_others="#606060ff">
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
<space>
<ThemeSpaceGeneric back="#000000"
title="#5d5d5d"
@@ -560,7 +589,7 @@
button_text_hi="#ffffff"
tab_active="#000000"
tab_inactive="#000000"
- tab_back="#060606"
+ tab_back="#060606ff"
tab_outline="#3a3a3a">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -602,7 +631,7 @@
button_text_hi="#ffffff"
tab_active="#000000"
tab_inactive="#000000"
- tab_back="#060606"
+ tab_back="#060606ff"
tab_outline="#3a3a3a">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -631,7 +660,7 @@
button_text_hi="#ffffff"
tab_active="#000000"
tab_inactive="#000000"
- tab_back="#060606"
+ tab_back="#060606ff"
tab_outline="#3a3a3a">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -670,7 +699,7 @@
button_text_hi="#ffffff"
tab_active="#000000"
tab_inactive="#000000"
- tab_back="#060606"
+ tab_back="#060606ff"
tab_outline="#3a3a3a">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -700,7 +729,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -751,7 +780,7 @@
button_text_hi="#ffffff"
tab_active="#000000"
tab_inactive="#000000"
- tab_back="#060606"
+ tab_back="#060606ff"
tab_outline="#3a3a3a">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -787,7 +816,7 @@
button_text_hi="#ffffff"
tab_active="#000000"
tab_inactive="#000000"
- tab_back="#060606"
+ tab_back="#060606ff"
tab_outline="#3a3a3a">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -817,7 +846,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -855,7 +884,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -884,7 +913,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -918,7 +947,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -942,11 +971,19 @@
path_after="#0000ff"
grid="#5e5e5e"
frame_current="#1b501b"
- handle_vertex="#e2e2e2"
- handle_vertex_select="#ffff00"
- handle_vertex_size="4"
strips="#0c0a0a"
- strips_selected="#ff8c00">
+ strips_selected="#ff8c00"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5">
<space>
<ThemeSpaceGeneric back="#0d0d0d"
title="#5d5d5d"
@@ -961,7 +998,7 @@
button_text_hi="#ffffff"
tab_active="#000000"
tab_inactive="#000000"
- tab_back="#060606"
+ tab_back="#060606ff"
tab_outline="#3a3a3a">
<panelcolors>
<ThemePanelColors header="#00000019"
diff --git a/release/scripts/presets/interface_theme/blender_24x.xml b/release/scripts/presets/interface_theme/blender_24x.xml
index f11a26f9700..9cb3276b103 100644
--- a/release/scripts/presets/interface_theme/blender_24x.xml
+++ b/release/scripts/presets/interface_theme/blender_24x.xml
@@ -152,6 +152,18 @@
shadedown="25">
</ThemeWidgetColors>
</wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors outline="#0a0a0a"
+ inner="#191919e6"
+ inner_sel="#8c8c8cff"
+ item="#2d2d2de6"
+ text="#a0a0a0"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="10"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
<wcol_tooltip>
<ThemeWidgetColors outline="#000000"
inner="#ffffddff"
@@ -231,6 +243,7 @@
lamp="#00000028"
speaker="#000000"
camera="#000000"
+ view_overlay="#000000"
empty="#000000"
object_selected="#ff88ff"
object_active="#ffbbff"
@@ -260,10 +273,10 @@
handle_free="#000000"
handle_auto="#909000"
handle_vect="#409030"
+ handle_sel_vect="#40c030"
handle_align="#803060"
handle_sel_free="#000000"
handle_sel_auto="#f0ff40"
- handle_sel_vect="#40c030"
handle_sel_align="#f090a0"
lastsel_point="#ffffff"
extra_edge_len="#200000"
@@ -280,7 +293,9 @@
outline_width="1"
bundle_solid="#c8c8c8"
camera_path="#000000"
- skin_root="#000000">
+ skin_root="#000000"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
<space>
<ThemeSpaceGradient title="#000000"
text="#000000"
@@ -294,7 +309,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<gradients>
<ThemeGradientColors show_grad="FALSE"
@@ -329,10 +344,10 @@
handle_free="#000000"
handle_auto="#909000"
handle_vect="#409030"
+ handle_sel_vect="#40c030"
handle_align="#803060"
handle_sel_free="#000000"
handle_sel_auto="#f0ff40"
- handle_sel_vect="#40c030"
handle_sel_align="#f090a0"
handle_auto_clamped="#000000"
handle_sel_auto_clamped="#000000"
@@ -354,7 +369,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -394,7 +409,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -446,7 +461,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -504,7 +519,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -545,7 +560,21 @@
preview_stitch_unstitchable="#ff0000ff"
preview_stitch_active="#e1d2c323"
uv_shadow="#707070ff"
- uv_others="#606060ff">
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
<space>
<ThemeSpaceGeneric back="#353535"
title="#000000"
@@ -560,7 +589,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -602,7 +631,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -631,7 +660,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -670,7 +699,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -700,7 +729,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -751,7 +780,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -787,7 +816,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -817,7 +846,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -855,7 +884,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -884,7 +913,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -918,7 +947,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -942,11 +971,19 @@
path_after="#0000ff"
grid="#5e5e5e"
frame_current="#60c040"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
handle_vertex="#000000"
handle_vertex_select="#ffff00"
- handle_vertex_size="4"
- strips="#0c0a0a"
- strips_selected="#ff8c00">
+ handle_vertex_size="4">
<space>
<ThemeSpaceGeneric back="#757575"
title="#000000"
@@ -961,7 +998,7 @@
button_text_hi="#ffffff"
tab_active="#b4b4b4"
tab_inactive="#999999"
- tab_back="#757575"
+ tab_back="#757575ff"
tab_outline="#3c3c3c">
<panelcolors>
<ThemePanelColors header="#00000019"
diff --git a/release/scripts/presets/interface_theme/elsyiun.xml b/release/scripts/presets/interface_theme/elsyiun.xml
index 3fef9486d9e..2d213d0ed70 100644
--- a/release/scripts/presets/interface_theme/elsyiun.xml
+++ b/release/scripts/presets/interface_theme/elsyiun.xml
@@ -152,6 +152,18 @@
shadedown="-20">
</ThemeWidgetColors>
</wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors outline="#0a0a0a"
+ inner="#191919e6"
+ inner_sel="#8c8c8cff"
+ item="#2d2d2de6"
+ text="#a0a0a0"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="10"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
<wcol_tooltip>
<ThemeWidgetColors outline="#000000"
inner="#191919e6"
@@ -231,6 +243,7 @@
lamp="#00000028"
speaker="#000000"
camera="#000000"
+ view_overlay="#000000"
empty="#000000"
object_selected="#ff8500"
object_active="#ffc280"
@@ -260,10 +273,10 @@
handle_free="#000000"
handle_auto="#909000"
handle_vect="#409030"
+ handle_sel_vect="#40c030"
handle_align="#803060"
handle_sel_free="#000000"
handle_sel_auto="#f0ff40"
- handle_sel_vect="#40c030"
handle_sel_align="#f090a0"
lastsel_point="#ffffff"
extra_edge_len="#200000"
@@ -280,7 +293,9 @@
outline_width="1"
bundle_solid="#c8c8c8"
camera_path="#000000"
- skin_root="#000000">
+ skin_root="#000000"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
<space>
<ThemeSpaceGradient title="#000000"
text="#b8b8b8"
@@ -294,7 +309,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<gradients>
<ThemeGradientColors show_grad="FALSE"
@@ -329,10 +344,10 @@
handle_free="#000000"
handle_auto="#909000"
handle_vect="#409030"
+ handle_sel_vect="#40c030"
handle_align="#803060"
handle_sel_free="#000000"
handle_sel_auto="#f0ff40"
- handle_sel_vect="#40c030"
handle_sel_align="#f090a0"
handle_auto_clamped="#994030"
handle_sel_auto_clamped="#f0af90"
@@ -354,7 +369,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -394,7 +409,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -446,7 +461,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -504,7 +519,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -545,7 +560,21 @@
preview_stitch_unstitchable="#ff0000ff"
preview_stitch_active="#e1d2c323"
uv_shadow="#707070ff"
- uv_others="#606060ff">
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
<space>
<ThemeSpaceGeneric back="#4b4b4b"
title="#8b8b8b"
@@ -560,7 +589,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -602,7 +631,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -631,7 +660,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -670,7 +699,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -700,7 +729,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -751,7 +780,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -787,7 +816,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -817,7 +846,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -855,7 +884,7 @@
button_text_hi="#000000"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -884,7 +913,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -918,7 +947,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -942,11 +971,19 @@
path_after="#0000ff"
grid="#5e5e5e"
frame_current="#60c040"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
handle_vertex="#000000"
handle_vertex_select="#ffff00"
- handle_vertex_size="4"
- strips="#0c0a0a"
- strips_selected="#ff8c00">
+ handle_vertex_size="4">
<space>
<ThemeSpaceGeneric back="#393939"
title="#000000"
@@ -961,7 +998,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
diff --git a/release/scripts/presets/interface_theme/hexagon.xml b/release/scripts/presets/interface_theme/hexagon.xml
index d32bd81b6f6..d2221bc9935 100644
--- a/release/scripts/presets/interface_theme/hexagon.xml
+++ b/release/scripts/presets/interface_theme/hexagon.xml
@@ -152,6 +152,18 @@
shadedown="-40">
</ThemeWidgetColors>
</wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors outline="#0a0a0a"
+ inner="#191919e6"
+ inner_sel="#8c8c8cff"
+ item="#2d2d2de6"
+ text="#a0a0a0"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="10"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
<wcol_tooltip>
<ThemeWidgetColors outline="#000000"
inner="#191919e6"
@@ -231,6 +243,7 @@
lamp="#00000028"
speaker="#000000"
camera="#000000"
+ view_overlay="#000000"
empty="#000000"
object_selected="#52c6ff"
object_active="#6ed8ff"
@@ -260,10 +273,10 @@
handle_free="#000000"
handle_auto="#909000"
handle_vect="#409030"
+ handle_sel_vect="#40c030"
handle_align="#803060"
handle_sel_free="#000000"
handle_sel_auto="#f0ff40"
- handle_sel_vect="#40c030"
handle_sel_align="#f090a0"
lastsel_point="#ffffff"
extra_edge_len="#200000"
@@ -280,7 +293,9 @@
outline_width="1"
bundle_solid="#c8c8c8"
camera_path="#000000"
- skin_root="#000000">
+ skin_root="#000000"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
<space>
<ThemeSpaceGradient title="#000000"
text="#000000"
@@ -294,7 +309,7 @@
button_text_hi="#ffffff"
tab_active="#6c717f"
tab_inactive="#565b65"
- tab_back="#4b5058"
+ tab_back="#4b5058ff"
tab_outline="#2d2d32">
<gradients>
<ThemeGradientColors show_grad="FALSE"
@@ -329,10 +344,10 @@
handle_free="#000000"
handle_auto="#909000"
handle_vect="#409030"
+ handle_sel_vect="#40c030"
handle_align="#803060"
handle_sel_free="#000000"
handle_sel_auto="#f0ff40"
- handle_sel_vect="#40c030"
handle_sel_align="#f090a0"
handle_auto_clamped="#000000"
handle_sel_auto_clamped="#000000"
@@ -354,7 +369,7 @@
button_text_hi="#ffffff"
tab_active="#6c717f"
tab_inactive="#565b65"
- tab_back="#4b5058"
+ tab_back="#4b5058ff"
tab_outline="#2d2d32">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -394,7 +409,7 @@
button_text_hi="#ffffff"
tab_active="#6c717f"
tab_inactive="#565b65"
- tab_back="#4b5058"
+ tab_back="#4b5058ff"
tab_outline="#2d2d32">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -446,7 +461,7 @@
button_text_hi="#ffffff"
tab_active="#6c717f"
tab_inactive="#565b65"
- tab_back="#4b5058"
+ tab_back="#4b5058ff"
tab_outline="#2d2d32">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -504,7 +519,7 @@
button_text_hi="#ffffff"
tab_active="#6c717f"
tab_inactive="#565b65"
- tab_back="#4b5058"
+ tab_back="#4b5058ff"
tab_outline="#2d2d32">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -545,7 +560,21 @@
preview_stitch_unstitchable="#ff0000ff"
preview_stitch_active="#e1d2c323"
uv_shadow="#707070ff"
- uv_others="#606060ff">
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
<space>
<ThemeSpaceGeneric back="#7c7e88"
title="#000000"
@@ -560,7 +589,7 @@
button_text_hi="#ffffff"
tab_active="#6c717f"
tab_inactive="#565b65"
- tab_back="#4b5058"
+ tab_back="#4b5058ff"
tab_outline="#2d2d32">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -602,7 +631,7 @@
button_text_hi="#ffffff"
tab_active="#6c717f"
tab_inactive="#565b65"
- tab_back="#4b5058"
+ tab_back="#4b5058ff"
tab_outline="#2d2d32">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -631,7 +660,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#404040"
+ tab_back="#404040ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -670,7 +699,7 @@
button_text_hi="#ffffff"
tab_active="#6c717f"
tab_inactive="#565b65"
- tab_back="#4b5058"
+ tab_back="#4b5058ff"
tab_outline="#2d2d32">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -700,7 +729,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -751,7 +780,7 @@
button_text_hi="#ffffff"
tab_active="#6c717f"
tab_inactive="#565b65"
- tab_back="#4b5058"
+ tab_back="#4b5058ff"
tab_outline="#2d2d32">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -787,7 +816,7 @@
button_text_hi="#ffffff"
tab_active="#6c717f"
tab_inactive="#565b65"
- tab_back="#4b5058"
+ tab_back="#4b5058ff"
tab_outline="#2d2d32">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -817,7 +846,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -855,7 +884,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -884,7 +913,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -918,7 +947,7 @@
button_text_hi="#ffffff"
tab_active="#464646"
tab_inactive="#393939"
- tab_back="#000000"
+ tab_back="#000000ff"
tab_outline="#323232">
<panelcolors>
<ThemePanelColors header="#00000019"
@@ -942,11 +971,19 @@
path_after="#0000ff"
grid="#5e5e5e"
frame_current="#60c040"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
handle_vertex="#000000"
handle_vertex_select="#ffff00"
- handle_vertex_size="4"
- strips="#0c0a0a"
- strips_selected="#ff8c00">
+ handle_vertex_size="4">
<space>
<ThemeSpaceGeneric back="#7c7e88"
title="#000000"
@@ -961,7 +998,7 @@
button_text_hi="#ffffff"
tab_active="#6c717f"
tab_inactive="#565b65"
- tab_back="#4b5058"
+ tab_back="#4b5058ff"
tab_outline="#2d2d32">
<panelcolors>
<ThemePanelColors header="#00000019"
diff --git a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
index 9de72b93bcf..06d29a97745 100644
--- a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
+++ b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
@@ -152,6 +152,18 @@
shadedown="-20">
</ThemeWidgetColors>
</wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors outline="#0a0a0a"
+ inner="#191919e6"
+ inner_sel="#8c8c8cff"
+ item="#2d2d2de6"
+ text="#a0a0a0"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="10"
+ shadedown="-10">
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
<wcol_tooltip>
<ThemeWidgetColors outline="#000000"
inner="#191919e6"
@@ -231,6 +243,7 @@
lamp="#ffffff34"
speaker="#93237f"
camera="#159dce"
+ view_overlay="#000000"
empty="#93237f"
object_selected="#f15800"
object_active="#f47421"
@@ -260,10 +273,10 @@
handle_free="#a5ca00"
handle_auto="#00c59a"
handle_vect="#409030"
+ handle_sel_vect="#82c036"
handle_align="#93237f"
handle_sel_free="#f47421"
handle_sel_auto="#f47421"
- handle_sel_vect="#82c036"
handle_sel_align="#f47421"
lastsel_point="#ffffff"
extra_edge_len="#200000"
@@ -280,7 +293,9 @@
outline_width="2"
bundle_solid="#c8c8c8"
camera_path="#7dbd00"
- skin_root="#000000">
+ skin_root="#000000"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
<space>
<ThemeSpaceGradient title="#9c9c9c"
text="#9c9c9c"
@@ -294,7 +309,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<gradients>
<ThemeGradientColors show_grad="FALSE"
@@ -329,10 +344,10 @@
handle_free="#a5ca00"
handle_auto="#00c59a"
handle_vect="#409030"
+ handle_sel_vect="#40c030"
handle_align="#93237f"
handle_sel_free="#f49600"
handle_sel_auto="#f49600"
- handle_sel_vect="#40c030"
handle_sel_align="#f49600"
handle_auto_clamped="#03aa60"
handle_sel_auto_clamped="#f49600"
@@ -354,7 +369,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -394,7 +409,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -446,7 +461,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -504,7 +519,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -545,7 +560,21 @@
preview_stitch_unstitchable="#ff0000ff"
preview_stitch_active="#e1d2c323"
uv_shadow="#707070ff"
- uv_others="#606060ff">
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
<space>
<ThemeSpaceGeneric back="#131311"
title="#000000"
@@ -560,7 +589,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -602,7 +631,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -631,7 +660,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -670,7 +699,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -700,7 +729,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -751,7 +780,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -787,7 +816,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -817,7 +846,7 @@
button_text_hi="#f47421"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -855,7 +884,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -884,7 +913,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -918,7 +947,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
@@ -942,11 +971,19 @@
path_after="#19b6ee"
grid="#302e2c"
frame_current="#f47421"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
handle_vertex="#000000"
handle_vertex_select="#ffff00"
- handle_vertex_size="4"
- strips="#0c0a0a"
- strips_selected="#ff8c00">
+ handle_vertex_size="4">
<space>
<ThemeSpaceGeneric back="#131311"
title="#9c9c9c"
@@ -961,7 +998,7 @@
button_text_hi="#ffffff"
tab_active="#3c3b37"
tab_inactive="#333333"
- tab_back="#2e2e2e"
+ tab_back="#2e2e2eff"
tab_outline="#000000">
<panelcolors>
<ThemePanelColors header="#00000000"
diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py
index 808ba7cee81..f85d3b43041 100644
--- a/release/scripts/presets/keyconfig/3dsmax.py
+++ b/release/scripts/presets/keyconfig/3dsmax.py
@@ -14,8 +14,8 @@ kmi = km.keymap_items.new('wm.call_menu', 'O', 'PRESS', shift=True, ctrl=True)
kmi.properties.name = 'INFO_MT_file_open_recent'
kmi = km.keymap_items.new('wm.open_mainfile', 'O', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.open_mainfile', 'F1', 'PRESS')
-kmi = km.keymap_items.new('wm.link_append', 'O', 'PRESS', ctrl=True, alt=True)
-kmi = km.keymap_items.new('wm.link_append', 'F1', 'PRESS', shift=True)
+kmi = km.keymap_items.new('wm.link', 'O', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('wm.append', 'F1', 'PRESS', shift=True)
kmi.properties.link = False
kmi.properties.instance_groups = False
kmi = km.keymap_items.new('wm.save_mainfile', 'S', 'PRESS', ctrl=True)
@@ -295,8 +295,6 @@ kmi.properties.data_path = 'tool_settings.proportional_edit_falloff'
kmi = km.keymap_items.new('wm.context_toggle', 'O', 'PRESS')
kmi.properties.data_path = 'tool_settings.use_proportional_edit_objects'
kmi = km.keymap_items.new('view3d.game_start', 'P', 'PRESS', shift=True, ctrl=True, alt=True)
-kmi = km.keymap_items.new('object.select_all', 'LEFTMOUSE', 'CLICK')
-kmi.properties.action = 'DESELECT'
kmi = km.keymap_items.new('object.select_all', 'A', 'PRESS', ctrl=True)
kmi.properties.action = 'INVERT'
kmi = km.keymap_items.new('object.select_linked', 'L', 'PRESS', shift=True)
@@ -588,56 +586,56 @@ kmi = km.keymap_items.new('wm.context_toggle_enum', 'Z', 'PRESS', alt=True)
kmi.properties.data_path = 'space_data.viewport_shade'
kmi.properties.value_1 = 'SOLID'
kmi.properties.value_2 = 'TEXTURED'
-kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE')
+kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK')
kmi.properties.extend = False
kmi.properties.deselect = False
kmi.properties.toggle = False
kmi.properties.center = False
kmi.properties.enumerate = False
kmi.properties.object = False
-kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', ctrl=True)
+kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', ctrl=True)
kmi.properties.extend = False
kmi.properties.deselect = False
kmi.properties.toggle = True
kmi.properties.center = False
kmi.properties.enumerate = False
kmi.properties.object = False
-kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True)
kmi.properties.extend = False
kmi.properties.deselect = False
kmi.properties.toggle = False
kmi.properties.center = True
kmi.properties.enumerate = False
kmi.properties.object = True
-kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', alt=True)
+kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', alt=True)
kmi.properties.extend = False
kmi.properties.deselect = False
kmi.properties.toggle = False
kmi.properties.center = False
kmi.properties.enumerate = True
kmi.properties.object = False
-kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True, ctrl=True)
+kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, ctrl=True)
kmi.properties.extend = True
kmi.properties.deselect = False
kmi.properties.toggle = True
kmi.properties.center = True
kmi.properties.enumerate = False
kmi.properties.object = False
-kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', ctrl=True, alt=True)
+kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', ctrl=True, alt=True)
kmi.properties.extend = False
kmi.properties.deselect = False
kmi.properties.toggle = False
kmi.properties.center = True
kmi.properties.enumerate = True
kmi.properties.object = False
-kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True, alt=True)
+kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, alt=True)
kmi.properties.extend = False
kmi.properties.deselect = False
kmi.properties.toggle = True
kmi.properties.center = False
kmi.properties.enumerate = True
kmi.properties.object = False
-kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, ctrl=True, alt=True)
kmi.properties.extend = False
kmi.properties.deselect = False
kmi.properties.toggle = True
@@ -1076,7 +1074,7 @@ kmi = km.keymap_items.new('node.select_all', 'I', 'PRESS', ctrl=True)
kmi.properties.action = 'INVERT'
kmi = km.keymap_items.new('node.select_linked_to', 'L', 'PRESS', shift=True)
kmi = km.keymap_items.new('node.select_linked_from', 'L', 'PRESS')
-kmi = km.keymap_items.new('node.select_same_type', 'G', 'PRESS', shift=True)
+kmi = km.keymap_items.new('node.select_grouped', 'G', 'PRESS', shift=True)
kmi = km.keymap_items.new('node.select_same_type_step', 'RIGHT_BRACKET', 'PRESS', shift=True)
kmi.properties.prev = False
kmi = km.keymap_items.new('node.select_same_type_step', 'LEFT_BRACKET', 'PRESS', shift=True)
@@ -1389,32 +1387,32 @@ kmi.properties.camera = 10
kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS')
kmi.properties.extend = False
kmi.properties.linked_handle = False
-kmi.properties.left_right = False
+kmi.properties.left_right = 'NONE'
kmi.properties.linked_time = False
kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS', shift=True)
kmi.properties.extend = True
kmi.properties.linked_handle = False
-kmi.properties.left_right = False
+kmi.properties.left_right = 'NONE'
kmi.properties.linked_time = False
kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS', alt=True)
kmi.properties.extend = False
kmi.properties.linked_handle = True
-kmi.properties.left_right = False
+kmi.properties.left_right = 'NONE'
kmi.properties.linked_time = False
kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True)
kmi.properties.extend = True
kmi.properties.linked_handle = True
-kmi.properties.left_right = False
+kmi.properties.left_right = 'NONE'
kmi.properties.linked_time = False
kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS', ctrl=True)
kmi.properties.extend = False
kmi.properties.linked_handle = False
-kmi.properties.left_right = True
+kmi.properties.left_right = 'MOUSE'
kmi.properties.linked_time = True
kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True)
kmi.properties.extend = True
kmi.properties.linked_handle = False
-kmi.properties.left_right = False
+kmi.properties.left_right = 'NONE'
kmi.properties.linked_time = True
kmi = km.keymap_items.new('sequencer.select_more', 'NUMPAD_PLUS', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('sequencer.select_less', 'NUMPAD_MINUS', 'PRESS', ctrl=True)
@@ -2112,8 +2110,6 @@ kmi.properties.extend = False
kmi.properties.deselect = False
kmi.properties.toggle = True
kmi = km.keymap_items.new('mesh.shortest_path_pick', 'SELECTMOUSE', 'PRESS', ctrl=True)
-kmi = km.keymap_items.new('mesh.select_all', 'LEFTMOUSE', 'CLICK')
-kmi.properties.action = 'DESELECT'
kmi = km.keymap_items.new('mesh.select_all', 'I', 'PRESS', ctrl=True)
kmi.properties.action = 'INVERT'
kmi = km.keymap_items.new('mesh.select_more', 'NUMPAD_PLUS', 'PRESS', ctrl=True)
diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py
index da10b17422e..436541d85f8 100644
--- a/release/scripts/presets/keyconfig/maya.py
+++ b/release/scripts/presets/keyconfig/maya.py
@@ -15,8 +15,8 @@ kmi = km.keymap_items.new('wm.call_menu', 'O', 'PRESS', shift=True, ctrl=True)
kmi.properties.name = 'INFO_MT_file_open_recent'
kmi = km.keymap_items.new('wm.open_mainfile', 'O', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.open_mainfile', 'F1', 'PRESS')
-kmi = km.keymap_items.new('wm.link_append', 'O', 'PRESS', ctrl=True, alt=True)
-kmi = km.keymap_items.new('wm.link_append', 'F1', 'PRESS', shift=True)
+kmi = km.keymap_items.new('wm.link', 'O', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('wm.append', 'F1', 'PRESS', shift=True)
kmi.properties.link = False
kmi.properties.instance_groups = False
kmi = km.keymap_items.new('wm.save_mainfile', 'S', 'PRESS', ctrl=True)
@@ -329,6 +329,7 @@ kmi = km.keymap_items.new('armature.layers_show_all', 'ACCENT_GRAVE', 'PRESS', c
kmi = km.keymap_items.new('armature.armature_layers', 'M', 'PRESS', shift=True)
kmi = km.keymap_items.new('pose.bone_layers', 'M', 'PRESS')
kmi = km.keymap_items.new('transform.transform', 'S', 'PRESS', ctrl=True, alt=True)
+kmi.properties.mode = 'BONE_SIZE'
kmi = km.keymap_items.new('anim.keyframe_insert_menu', 'S', 'PRESS')
kmi = km.keymap_items.new('anim.keyframe_delete_v3d', 'S', 'PRESS', alt=True)
kmi = km.keymap_items.new('anim.keying_set_active_set', 'I', 'PRESS', shift=True, ctrl=True, alt=True)
@@ -1486,7 +1487,7 @@ kmi = km.keymap_items.new('node.delete_reconnect', 'X', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('node.select_all', 'A', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('node.select_linked_to', 'L', 'PRESS', shift=True)
kmi = km.keymap_items.new('node.select_linked_from', 'L', 'PRESS')
-kmi = km.keymap_items.new('node.select_same_type', 'G', 'PRESS', shift=True)
+kmi = km.keymap_items.new('node.select_grouped', 'G', 'PRESS', shift=True)
kmi = km.keymap_items.new('node.select_same_type_step', 'RIGHT_BRACKET', 'PRESS', shift=True)
kmi.properties.prev = True
kmi = km.keymap_items.new('node.select_same_type_step', 'LEFT_BRACKET', 'PRESS', shift=True)
@@ -1745,32 +1746,32 @@ kmi.properties.camera = 10
kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'CLICK')
kmi.properties.extend = False
kmi.properties.linked_handle = False
-kmi.properties.left_right = False
+kmi.properties.left_right = 'NONE'
kmi.properties.linked_time = False
kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'CLICK', shift=True)
kmi.properties.extend = True
kmi.properties.linked_handle = False
-kmi.properties.left_right = False
+kmi.properties.left_right = 'NONE'
kmi.properties.linked_time = False
kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS', alt=True)
kmi.properties.extend = False
kmi.properties.linked_handle = True
-kmi.properties.left_right = False
+kmi.properties.left_right = 'NONE'
kmi.properties.linked_time = False
kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'CLICK', shift=True, alt=True)
kmi.properties.extend = True
kmi.properties.linked_handle = True
-kmi.properties.left_right = False
+kmi.properties.left_right = 'NONE'
kmi.properties.linked_time = False
kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS', ctrl=True)
kmi.properties.extend = False
kmi.properties.linked_handle = False
-kmi.properties.left_right = True
+kmi.properties.left_right = 'MOUSE'
kmi.properties.linked_time = True
kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True)
kmi.properties.extend = True
kmi.properties.linked_handle = False
-kmi.properties.left_right = False
+kmi.properties.left_right = 'NONE'
kmi.properties.linked_time = True
kmi = km.keymap_items.new('sequencer.select_more', 'PERIOD', 'PRESS', shift=True)
kmi = km.keymap_items.new('sequencer.select_less', 'COMMA', 'PRESS', shift=True)
diff --git a/release/scripts/presets/sunsky/classic.py b/release/scripts/presets/sunsky/classic.py
index 4394dcce242..edb065d553c 100644
--- a/release/scripts/presets/sunsky/classic.py
+++ b/release/scripts/presets/sunsky/classic.py
@@ -1,14 +1,14 @@
import bpy
-bpy.context.object.data.sky.atmosphere_turbidity = 4.0
-bpy.context.object.data.sky.sky_blend_type = 'ADD'
-bpy.context.object.data.sky.sky_blend = 1.0
-bpy.context.object.data.sky.horizon_brightness = 10.0
-bpy.context.object.data.sky.spread = 1.49011614159e-09
-bpy.context.object.data.sky.sky_color_space = 'SMPTE'
-bpy.context.object.data.sky.sky_exposure = 1.0
-bpy.context.object.data.sky.sun_brightness = 1.00000011921
-bpy.context.object.data.sky.sun_size = 1.00000166893
-bpy.context.object.data.sky.backscattered_light = 0.0
-bpy.context.object.data.sky.sun_intensity = 4.0
-bpy.context.object.data.sky.atmosphere_inscattering = 1.0
-bpy.context.object.data.sky.atmosphere_extinction = 1.0
+bpy.context.lamp.sky.atmosphere_turbidity = 4.0
+bpy.context.lamp.sky.sky_blend_type = 'ADD'
+bpy.context.lamp.sky.sky_blend = 1.0
+bpy.context.lamp.sky.horizon_brightness = 10.0
+bpy.context.lamp.sky.spread = 1.49011614159e-09
+bpy.context.lamp.sky.sky_color_space = 'SMPTE'
+bpy.context.lamp.sky.sky_exposure = 1.0
+bpy.context.lamp.sky.sun_brightness = 1.00000011921
+bpy.context.lamp.sky.sun_size = 1.00000166893
+bpy.context.lamp.sky.backscattered_light = 0.0
+bpy.context.lamp.sky.sun_intensity = 4.0
+bpy.context.lamp.sky.atmosphere_inscattering = 1.0
+bpy.context.lamp.sky.atmosphere_extinction = 1.0
diff --git a/release/scripts/presets/sunsky/desert.py b/release/scripts/presets/sunsky/desert.py
index f68ea23845b..8dd587a6eaf 100644
--- a/release/scripts/presets/sunsky/desert.py
+++ b/release/scripts/presets/sunsky/desert.py
@@ -1,14 +1,14 @@
import bpy
-bpy.context.object.data.sky.atmosphere_turbidity = 6.0
-bpy.context.object.data.sky.sky_blend_type = 'ADD'
-bpy.context.object.data.sky.sky_blend = 1.0
-bpy.context.object.data.sky.horizon_brightness = 4.99999761581
-bpy.context.object.data.sky.spread = 1.49011614159e-09
-bpy.context.object.data.sky.sky_color_space = 'SMPTE'
-bpy.context.object.data.sky.sky_exposure = 1.0
-bpy.context.object.data.sky.sun_brightness = 1.00000011921
-bpy.context.object.data.sky.sun_size = 4.0
-bpy.context.object.data.sky.backscattered_light = 1.0
-bpy.context.object.data.sky.sun_intensity = 1.0
-bpy.context.object.data.sky.atmosphere_inscattering = 1.0
-bpy.context.object.data.sky.atmosphere_extinction = 1.0
+bpy.context.lamp.sky.atmosphere_turbidity = 6.0
+bpy.context.lamp.sky.sky_blend_type = 'ADD'
+bpy.context.lamp.sky.sky_blend = 1.0
+bpy.context.lamp.sky.horizon_brightness = 4.99999761581
+bpy.context.lamp.sky.spread = 1.49011614159e-09
+bpy.context.lamp.sky.sky_color_space = 'SMPTE'
+bpy.context.lamp.sky.sky_exposure = 1.0
+bpy.context.lamp.sky.sun_brightness = 1.00000011921
+bpy.context.lamp.sky.sun_size = 4.0
+bpy.context.lamp.sky.backscattered_light = 1.0
+bpy.context.lamp.sky.sun_intensity = 1.0
+bpy.context.lamp.sky.atmosphere_inscattering = 1.0
+bpy.context.lamp.sky.atmosphere_extinction = 1.0
diff --git a/release/scripts/presets/sunsky/mountain.py b/release/scripts/presets/sunsky/mountain.py
index 9b81ffd4399..f0540af8100 100644
--- a/release/scripts/presets/sunsky/mountain.py
+++ b/release/scripts/presets/sunsky/mountain.py
@@ -1,14 +1,14 @@
import bpy
-bpy.context.object.data.sky.atmosphere_turbidity = 2.00000023842
-bpy.context.object.data.sky.sky_blend_type = 'ADD'
-bpy.context.object.data.sky.sky_blend = 1.0
-bpy.context.object.data.sky.horizon_brightness = 0.100000016391
-bpy.context.object.data.sky.spread = 1.0
-bpy.context.object.data.sky.sky_color_space = 'SMPTE'
-bpy.context.object.data.sky.sky_exposure = 1.0
-bpy.context.object.data.sky.sun_brightness = 1.99999988079
-bpy.context.object.data.sky.sun_size = 4.0
-bpy.context.object.data.sky.backscattered_light = -1.0
-bpy.context.object.data.sky.sun_intensity = 10.0
-bpy.context.object.data.sky.atmosphere_inscattering = 1.0
-bpy.context.object.data.sky.atmosphere_extinction = 1.0
+bpy.context.lamp.sky.atmosphere_turbidity = 2.00000023842
+bpy.context.lamp.sky.sky_blend_type = 'ADD'
+bpy.context.lamp.sky.sky_blend = 1.0
+bpy.context.lamp.sky.horizon_brightness = 0.100000016391
+bpy.context.lamp.sky.spread = 1.0
+bpy.context.lamp.sky.sky_color_space = 'SMPTE'
+bpy.context.lamp.sky.sky_exposure = 1.0
+bpy.context.lamp.sky.sun_brightness = 1.99999988079
+bpy.context.lamp.sky.sun_size = 4.0
+bpy.context.lamp.sky.backscattered_light = -1.0
+bpy.context.lamp.sky.sun_intensity = 10.0
+bpy.context.lamp.sky.atmosphere_inscattering = 1.0
+bpy.context.lamp.sky.atmosphere_extinction = 1.0
diff --git a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_Cinema_Camera.py b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_Cinema_Camera.py
new file mode 100644
index 00000000000..a9c81f47c21
--- /dev/null
+++ b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_Cinema_Camera.py
@@ -0,0 +1,9 @@
+import bpy
+camera = bpy.context.edit_movieclip.tracking.camera
+
+camera.sensor_width = 12.48
+camera.units = 'MILLIMETERS'
+camera.pixel_aspect = 1
+camera.k1 = 0.0
+camera.k2 = 0.0
+camera.k3 = 0.0
diff --git a/release/scripts/presets/tracking_camera/Blackmagic_Production_Camera_4K.py b/release/scripts/presets/tracking_camera/Blackmagic_Production_Camera_4K.py
new file mode 100644
index 00000000000..d644d2a26c9
--- /dev/null
+++ b/release/scripts/presets/tracking_camera/Blackmagic_Production_Camera_4K.py
@@ -0,0 +1,9 @@
+import bpy
+camera = bpy.context.edit_movieclip.tracking.camera
+
+camera.sensor_width = 21.12
+camera.units = 'MILLIMETERS'
+camera.pixel_aspect = 1
+camera.k1 = 0.0
+camera.k2 = 0.0
+camera.k3 = 0.0
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py
index 29b75e64fca..c1f75c74bb4 100644
--- a/release/scripts/startup/bl_operators/object.py
+++ b/release/scripts/startup/bl_operators/object.py
@@ -249,9 +249,9 @@ class SubdivisionSet(Operator):
if mod.type == 'MULTIRES':
if not relative:
if level > mod.total_levels:
- sub = level - mod.total_levels
- for i in range (0, sub):
- bpy.ops.object.multires_subdivide(modifier="Multires")
+ sub = level - mod.total_levels
+ for i in range (0, sub):
+ bpy.ops.object.multires_subdivide(modifier="Multires")
if obj.mode == 'SCULPT':
if mod.sculpt_levels != level:
@@ -775,22 +775,15 @@ class DupliOffsetFromCursor(Operator):
bl_label = "Set Offset From Cursor"
bl_options = {'REGISTER', 'UNDO'}
- group = IntProperty(
- name="Group",
- description="Group index to set offset for",
- default=0,
- )
-
@classmethod
def poll(cls, context):
return (context.active_object is not None)
def execute(self, context):
scene = context.scene
- ob = context.active_object
- group = self.group
+ group = context.group
- ob.users_group[group].dupli_offset = scene.cursor_location
+ group.dupli_offset = scene.cursor_location
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py
index 556d34bb0ac..32688299b76 100644
--- a/release/scripts/startup/bl_operators/object_quick_effects.py
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -289,6 +289,10 @@ def obj_bb_minmax(obj, min_co, max_co):
max_co[0] = max(bb_vec[0], max_co[0])
max_co[1] = max(bb_vec[1], max_co[1])
max_co[2] = max(bb_vec[2], max_co[2])
+
+
+def grid_location(x, y):
+ return (x * 200, y * 150)
class QuickSmoke(Operator):
@@ -298,10 +302,11 @@ class QuickSmoke(Operator):
style = EnumProperty(
name="Smoke Style",
- items=(('STREAM', "Stream", ""),
+ items=(('SMOKE', "Smoke", ""),
('FIRE', "Fire", ""),
+ ('BOTH', "Smoke + Fire", ""),
),
- default='STREAM',
+ default='SMOKE',
)
show_flows = BoolProperty(
@@ -327,8 +332,8 @@ class QuickSmoke(Operator):
bpy.ops.object.modifier_add(fake_context, type='SMOKE')
obj.modifiers[-1].smoke_type = 'FLOW'
- if self.style == 'FIRE':
- obj.modifiers[-1].flow_settings.smoke_flow_type = 'FIRE'
+ # set type
+ obj.modifiers[-1].flow_settings.smoke_flow_type = self.style
if not self.show_flows:
obj.draw_type = 'WIRE'
@@ -348,57 +353,177 @@ class QuickSmoke(Operator):
# setup smoke domain
bpy.ops.object.modifier_add(type='SMOKE')
obj.modifiers[-1].smoke_type = 'DOMAIN'
- if self.style == 'FIRE':
+ if self.style == 'FIRE' or self.style == 'BOTH':
obj.modifiers[-1].domain_settings.use_high_resolution = True
- # create a volume material with a voxel data texture for the domain
- bpy.ops.object.material_slot_add()
+ # Setup material
+
+ # Cycles
+ if context.scene.render.use_shading_nodes:
+ bpy.ops.object.material_slot_add()
+
+ mat = bpy.data.materials.new("Smoke Domain Material")
+ obj.material_slots[0].material = mat
+
+ # Make sure we use nodes
+ mat.use_nodes = True
+
+ # Set node variables and clear the default nodes
+ tree = mat.node_tree
+ nodes = tree.nodes
+ links = tree.links
+
+ nodes.clear()
+
+ # Create shader nodes
+
+ # Material output
+ node_out = nodes.new(type='ShaderNodeOutputMaterial')
+ node_out.location = grid_location(6, 1)
+
+ # Add shader 1
+ node_add_shader_1 = nodes.new(type='ShaderNodeAddShader')
+ node_add_shader_1.location = grid_location(5, 1)
+ links.new(node_add_shader_1.outputs["Shader"],
+ node_out.inputs["Volume"])
+
+ # Smoke
+
+ # Add shader 2
+ node_add_shader_2 = nodes.new(type='ShaderNodeAddShader')
+ node_add_shader_2.location = grid_location(4, 2)
+ links.new(node_add_shader_2.outputs["Shader"],
+ node_add_shader_1.inputs[0])
+
+ # Volume scatter
+ node_scatter = nodes.new(type='ShaderNodeVolumeScatter')
+ node_scatter.location = grid_location(3, 3)
+ links.new(node_scatter.outputs["Volume"],
+ node_add_shader_2.inputs[0])
+
+ # Volume absorption
+ node_absorption = nodes.new(type='ShaderNodeVolumeAbsorption')
+ node_absorption.location = grid_location(3, 2)
+ links.new(node_absorption.outputs["Volume"],
+ node_add_shader_2.inputs[1])
+
+ # Density Multiplier
+ node_densmult = nodes.new(type='ShaderNodeMath')
+ node_densmult.location = grid_location(2, 2)
+ node_densmult.operation = 'MULTIPLY'
+ node_densmult.inputs[1].default_value = 5.0
+ links.new(node_densmult.outputs["Value"],
+ node_scatter.inputs["Density"])
+ links.new(node_densmult.outputs["Value"],
+ node_absorption.inputs["Density"])
+
+ # Attribute "density"
+ node_attrib_density = nodes.new(type='ShaderNodeAttribute')
+ node_attrib_density.attribute_name = "density"
+ node_attrib_density.location = grid_location(1, 2)
+ links.new(node_attrib_density.outputs["Fac"],
+ node_densmult.inputs[0])
+
+ # Attribute "color"
+ node_attrib_color = nodes.new(type='ShaderNodeAttribute')
+ node_attrib_color.attribute_name = "color"
+ node_attrib_color.location = grid_location(2, 3)
+ links.new(node_attrib_color.outputs["Color"],
+ node_scatter.inputs["Color"])
+ links.new(node_attrib_color.outputs["Color"],
+ node_absorption.inputs["Color"])
+
+ # Fire
+
+ # Emission
+ node_emission = nodes.new(type='ShaderNodeEmission')
+ node_emission.inputs["Color"].default_value = (0.8, 0.1, 0.01, 1.0)
+ node_emission.location = grid_location(4, 1)
+ links.new(node_emission.outputs["Emission"],
+ node_add_shader_1.inputs[1])
+
+ # Flame strength multiplier
+ node_flame_strength_mult = nodes.new(type='ShaderNodeMath')
+ node_flame_strength_mult.location = grid_location(3, 1)
+ node_flame_strength_mult.operation = 'MULTIPLY'
+ node_flame_strength_mult.inputs[1].default_value = 2.5
+ links.new(node_flame_strength_mult.outputs["Value"],
+ node_emission.inputs["Strength"])
+
+ # Color ramp Flame
+ node_flame_ramp = nodes.new(type='ShaderNodeValToRGB')
+ node_flame_ramp.location = grid_location(1, 1)
+ ramp = node_flame_ramp.color_ramp
+ ramp.interpolation = 'EASE'
+
+ # orange
+ elem = ramp.elements.new(0.5)
+ elem.color = (1.0, 0.128, 0.0, 1.0)
+
+ # yellow
+ elem = ramp.elements.new(0.9)
+ elem.color = (0.9, 0.6, 0.1, 1.0)
+
+ links.new(node_flame_ramp.outputs["Color"],
+ node_emission.inputs["Color"])
+
+ # Attribute "flame"
+ node_attrib_flame = nodes.new(type='ShaderNodeAttribute')
+ node_attrib_flame.attribute_name = "flame"
+ node_attrib_flame.location = grid_location(0, 1)
+ links.new(node_attrib_flame.outputs["Fac"],
+ node_flame_ramp.inputs["Fac"])
+ links.new(node_attrib_flame.outputs["Fac"],
+ node_flame_strength_mult.inputs[0])
+
+ # Blender Internal
+ else:
+ # create a volume material with a voxel data texture for the domain
+ bpy.ops.object.material_slot_add()
+
+ mat = bpy.data.materials.new("Smoke Domain Material")
+ obj.material_slots[0].material = mat
+ mat.type = 'VOLUME'
+ mat.volume.density = 0
+ mat.volume.density_scale = 5
+ mat.volume.step_size = 0.1
+
+ tex = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA')
+ tex.voxel_data.domain_object = obj
+ tex.voxel_data.interpolation = 'TRICUBIC_BSPLINE'
+
+ tex_slot = mat.texture_slots.add()
+ tex_slot.texture = tex
+ tex_slot.texture_coords = 'ORCO'
+ tex_slot.use_map_color_emission = False
+ tex_slot.use_map_density = True
+ tex_slot.use_map_color_reflection = True
+
+ # for fire add a second texture for flame emission
+ mat.volume.emission_color = Vector((0.0, 0.0, 0.0))
+ tex = bpy.data.textures.new("Flame", 'VOXEL_DATA')
+ tex.voxel_data.domain_object = obj
+ tex.voxel_data.smoke_data_type = 'SMOKEFLAME'
+ tex.voxel_data.interpolation = 'TRICUBIC_BSPLINE'
+ tex.use_color_ramp = True
- mat = bpy.data.materials.new("Smoke Domain Material")
- obj.material_slots[0].material = mat
- mat.type = 'VOLUME'
- mat.volume.density = 0
- mat.volume.density_scale = 5
- mat.volume.step_size = 0.1
-
- tex = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA')
- tex.voxel_data.domain_object = obj
- tex.voxel_data.interpolation = 'TRICUBIC_BSPLINE'
-
- tex_slot = mat.texture_slots.add()
- tex_slot.texture = tex
- tex_slot.use_map_color_emission = False
- tex_slot.use_map_density = True
- tex_slot.use_map_color_reflection = True
-
- # for fire add a second texture for flame emission
- mat.volume.emission_color = Vector((0.0, 0.0, 0.0))
- tex = bpy.data.textures.new("Flame", 'VOXEL_DATA')
- tex.voxel_data.domain_object = obj
- tex.voxel_data.smoke_data_type = 'SMOKEFLAME'
- tex.voxel_data.interpolation = 'TRICUBIC_BSPLINE'
- tex.use_color_ramp = True
-
- tex_slot = mat.texture_slots.add()
- tex_slot.texture = tex
-
- # add color ramp for flame color
- ramp = tex.color_ramp
- # dark orange
- elem = ramp.elements.new(0.333)
- elem.color[0] = 0.2
- elem.color[1] = 0.03
- elem.color[2] = 0
- elem.color[3] = 1
- # yellow glow
- elem = ramp.elements.new(0.666)
- elem.color[0] = elem.color[3] = 1
- elem.color[1] = 0.65
- elem.color[2] = 0.25
-
- mat.texture_slots[1].use_map_density = True
- mat.texture_slots[1].use_map_emission = True
- mat.texture_slots[1].emission_factor = 5
+ tex_slot = mat.texture_slots.add()
+ tex_slot.texture = tex
+ tex_slot.texture_coords = 'ORCO'
+
+ # add color ramp for flame color
+ ramp = tex.color_ramp
+ # dark orange
+ elem = ramp.elements.new(0.333)
+ elem.color = (0.2, 0.03, 0.0, 1.0)
+
+ # yellow glow
+ elem = ramp.elements.new(0.666)
+ elem.color = (1, 0.65, 0.25, 1.0)
+
+ mat.texture_slots[1].use_map_density = True
+ mat.texture_slots[1].use_map_emission = True
+ mat.texture_slots[1].emission_factor = 5
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index 8b0ed7d9942..f89792bea6e 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -253,7 +253,7 @@ class AddPresetCamera(AddPresetBase, Operator):
preset_menu = "CAMERA_MT_presets"
preset_defines = [
- "cam = bpy.context.object.data"
+ "cam = bpy.context.camera"
]
preset_subdir = "camera"
@@ -352,7 +352,7 @@ class AddPresetSunSky(AddPresetBase, Operator):
preset_menu = "LAMP_MT_sunsky_presets"
preset_defines = [
- "sky = bpy.context.object.data.sky"
+ "sky = bpy.context.lamp.sky"
]
preset_values = [
diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
index 6f54c051c0b..8f618e0632e 100644
--- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py
+++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
@@ -470,9 +470,7 @@ def lightmap_uvpack(meshes,
pretty_faces.append(pf_parent)
w, h = pf_parent.width, pf_parent.height
-
- if w > h:
- raise "error"
+ assert(w <= h)
if w == h:
even_dict.setdefault(w, []).append(pf_parent)
diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
index bf8b10ac4af..aa8a1742c1e 100644
--- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py
+++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
@@ -634,7 +634,7 @@ def packIslands(islandList):
# print 'Box Packing Time:', time.time() - time1
#if len(pa ckedLs) != len(islandList):
- # raise "Error packed boxes differs from original length"
+ # raise ValueError("Packed boxes differs from original length")
#print '\tWriting Packed Data to faces'
#XXX Window.DrawProgressBar(0.8, "Writing Packed Data to faces")
diff --git a/release/scripts/startup/bl_operators/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
index 68c9bc143be..ecb1ecf7f47 100644
--- a/release/scripts/startup/bl_operators/vertexpaint_dirt.py
+++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
@@ -109,7 +109,7 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
active_col_layer = me.vertex_colors[0].data
if not active_col_layer:
- return
+ return {'CANCELLED'}
use_paint_mask = me.use_paint_mask
diff --git a/release/scripts/startup/bl_operators/view3d.py b/release/scripts/startup/bl_operators/view3d.py
index 85cc9210c2d..df4a93bb87f 100644
--- a/release/scripts/startup/bl_operators/view3d.py
+++ b/release/scripts/startup/bl_operators/view3d.py
@@ -169,6 +169,13 @@ class VIEW3D_OT_select_or_deselect_all(Operator):
default=False,
)
+ @classmethod
+ def poll(cls, context):
+ active_object = context.active_object
+ if active_object:
+ return active_object.mode in {'EDIT', 'OBJECT', 'POSE'}
+ return True
+
def invoke(self, context, event):
x = event.mouse_region_x
y = event.mouse_region_y
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 4281c908afd..5c3f94a8739 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -527,7 +527,76 @@ class WM_OT_context_menu_enum(Operator):
context.window_manager.popup_menu(draw_func=draw_cb, title=prop.name, icon=prop.icon)
- return {'PASS_THROUGH'}
+ return {'FINISHED'}
+
+
+class WM_OT_context_pie_enum(Operator):
+ bl_idname = "wm.context_pie_enum"
+ bl_label = "Context Enum Pie"
+ bl_options = {'UNDO', 'INTERNAL'}
+ data_path = rna_path_prop
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+ data_path = self.data_path
+ value = context_path_validate(context, data_path)
+
+ if value is Ellipsis:
+ return {'PASS_THROUGH'}
+
+ base_path, prop_string = data_path.rsplit(".", 1)
+ value_base = context_path_validate(context, base_path)
+ prop = value_base.bl_rna.properties[prop_string]
+
+ def draw_cb(self, context):
+ layout = self.layout
+ layout.prop(value_base, prop_string, expand=True)
+
+ wm.popup_menu_pie(draw_func=draw_cb, title=prop.name, icon=prop.icon, event=event)
+
+ return {'FINISHED'}
+
+
+class WM_OT_operator_pie_enum(Operator):
+ bl_idname = "wm.operator_pie_enum"
+ bl_label = "Operator Enum Pie"
+ bl_options = {'UNDO', 'INTERNAL'}
+ data_path = StringProperty(
+ name="Operator",
+ description="Operator name (in python as string)",
+ maxlen=1024,
+ )
+ prop_string = StringProperty(
+ name="Property",
+ description="Property name (as a string)",
+ maxlen=1024,
+ )
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+
+ data_path = self.data_path
+ prop_string = self.prop_string
+
+ # same as eval("bpy.ops." + data_path)
+ op_mod_str, ob_id_str = data_path.split(".", 1)
+ op = getattr(getattr(bpy.ops, op_mod_str), ob_id_str)
+ del op_mod_str, ob_id_str
+
+ try:
+ op_rna = op.get_rna()
+ except KeyError:
+ self.report({'ERROR'}, "Operator not found: bpy.ops.%s" % data_path)
+ return {'CANCELLED'}
+
+ def draw_cb(self, context):
+ layout = self.layout
+ pie = layout.menu_pie()
+ pie.operator_enum(data_path, prop_string)
+
+ wm.popup_menu_pie(draw_func=draw_cb, title=op_rna.bl_rna.name, event=event)
+
+ return {'FINISHED'}
class WM_OT_context_set_id(Operator):
@@ -1033,13 +1102,13 @@ rna_property = StringProperty(
rna_min = FloatProperty(
name="Min",
- default=0.0,
+ default=-10000.0,
precision=3,
)
rna_max = FloatProperty(
name="Max",
- default=1.0,
+ default=10000.0,
precision=3,
)
@@ -1883,7 +1952,7 @@ class WM_OT_addon_install(Operator):
addons_old = {mod.__name__ for mod in addon_utils.modules()}
- #check to see if the file is in compressed format (.zip)
+ # check to see if the file is in compressed format (.zip)
if zipfile.is_zipfile(pyfile):
try:
file_to_extract = zipfile.ZipFile(pyfile, 'r')
@@ -1916,7 +1985,7 @@ class WM_OT_addon_install(Operator):
self.report({'WARNING'}, "File already installed to %r\n" % path_dest)
return {'CANCELLED'}
- #if not compressed file just copy into the addon path
+ # if not compressed file just copy into the addon path
try:
shutil.copyfile(pyfile, path_dest)
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index 50107604b3b..4baf31a591b 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -788,6 +788,10 @@ class ConstraintButtonsPanel():
row.prop(con, "use_active_clip")
row.prop(con, "use_3d_position")
+ sub = row.column()
+ sub.active = not con.use_3d_position
+ sub.prop(con, "use_undistorted_position")
+
col = layout.column()
if not con.use_active_clip:
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index 0f5039a40ea..c07e9d677e7 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -253,7 +253,7 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel):
active = pchan.is_in_ik_chain
split = layout.split(percentage=0.25)
- split.prop(pchan, "lock_ik_x", text="X", icon_only=True)
+ split.prop(pchan, "lock_ik_x", text="X")
split.active = active
row = split.row()
row.prop(pchan, "ik_stiffness_x", text="Stiffness", slider=True)
@@ -270,7 +270,7 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel):
sub.active = pchan.lock_ik_x is False and pchan.use_ik_limit_x and active
split = layout.split(percentage=0.25)
- split.prop(pchan, "lock_ik_y", text="Y", icon_only=True)
+ split.prop(pchan, "lock_ik_y", text="Y")
split.active = active
row = split.row()
row.prop(pchan, "ik_stiffness_y", text="Stiffness", slider=True)
@@ -288,7 +288,7 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel):
sub.active = pchan.lock_ik_y is False and pchan.use_ik_limit_y and active
split = layout.split(percentage=0.25)
- split.prop(pchan, "lock_ik_z", text="Z", icon_only=True)
+ split.prop(pchan, "lock_ik_z", text="Z")
split.active = active
sub = split.row()
sub.prop(pchan, "ik_stiffness_z", text="Stiffness", slider=True)
diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py
index b19fce1c7d0..c93bebf2673 100644
--- a/release/scripts/startup/bl_ui/properties_data_empty.py
+++ b/release/scripts/startup/bl_ui/properties_data_empty.py
@@ -42,7 +42,7 @@ class DATA_PT_empty(DataButtonsPanel, Panel):
layout.prop(ob, "empty_draw_type", text="Display")
if ob.empty_draw_type == 'IMAGE':
- layout.template_ID(ob, "data", open="image.open")
+ layout.template_ID(ob, "data", open="image.open", unlink="object.unlink_data")
layout.template_image(ob, "data", ob.image_user, compact=True)
row = layout.row(align=True)
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 41cf93f71ad..909c6ab0b56 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -29,7 +29,8 @@ class MESH_MT_vertex_group_specials(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("object.vertex_group_sort", icon='SORTALPHA')
+ layout.operator("object.vertex_group_sort", icon='SORTALPHA').sort_type = "NAME"
+ layout.operator("object.vertex_group_sort", icon='ARMATURE_DATA', text="Sort by Bone Hierarchy").sort_type = "BONE_HIERARCHY"
layout.operator("object.vertex_group_copy", icon='COPY_ID')
layout.operator("object.vertex_group_copy_to_linked", icon='LINK_AREA')
layout.operator("object.vertex_group_copy_to_selected", icon='LINK_AREA')
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 60187ff1cd5..efc430db50f 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -127,6 +127,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "width")
col.prop(md, "segments")
col.prop(md, "profile")
+ col.prop(md, "material")
col = split.column()
col.prop(md, "use_only_vertices")
@@ -817,6 +818,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "use_even_offset")
col.prop(md, "use_quality_normals")
col.prop(md, "use_rim")
+ col_rim = col.column()
+ col_rim.active = md.use_rim
+ col_rim.prop(md, "use_rim_only")
col.separator()
diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py
index c5716dff86d..58818e90440 100644
--- a/release/scripts/startup/bl_ui/properties_freestyle.py
+++ b/release/scripts/startup/bl_ui/properties_freestyle.py
@@ -39,7 +39,7 @@ class RenderFreestyleButtonsPanel():
class RENDER_PT_freestyle(RenderFreestyleButtonsPanel, Panel):
bl_label = "Freestyle"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'CYCLES'}
def draw_header(self, context):
rd = context.scene.render
@@ -59,10 +59,6 @@ class RENDER_PT_freestyle(RenderFreestyleButtonsPanel, Panel):
if (rd.line_thickness_mode == 'ABSOLUTE'):
layout.prop(rd, "line_thickness")
- row = layout.row()
- row.label(text="Line style settings are in the Render Layers tab")
- row.operator("wm.properties_context_change", text="", icon='RENDERLAYERS').context = 'RENDER_LAYER'
-
# Render layer properties
@@ -115,7 +111,7 @@ class RENDER_MT_lineset_specials(Menu):
class RENDERLAYER_PT_freestyle(RenderLayerFreestyleButtonsPanel, Panel):
bl_label = "Freestyle"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'CYCLES'}
def draw(self, context):
layout = self.layout
@@ -169,7 +165,7 @@ class RENDERLAYER_PT_freestyle(RenderLayerFreestyleButtonsPanel, Panel):
class RENDERLAYER_PT_freestyle_lineset(RenderLayerFreestyleEditorButtonsPanel, Panel):
bl_label = "Freestyle Line Set"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'CYCLES'}
def draw_edge_type_buttons(self, box, lineset, edge_type):
# property names
@@ -261,7 +257,7 @@ class RENDERLAYER_PT_freestyle_lineset(RenderLayerFreestyleEditorButtonsPanel, P
class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel, Panel):
bl_label = "Freestyle Line Style"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'CYCLES'}
def draw_modifier_box_header(self, box, modifier):
row = box.row()
@@ -678,7 +674,10 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
layout.separator()
row = layout.row()
- row.prop(linestyle, "use_texture")
+ if rd.use_shading_nodes:
+ row.prop(linestyle, "use_nodes")
+ else:
+ row.prop(linestyle, "use_texture")
row.prop(linestyle, "texture_spacing", text="Spacing Along Stroke")
row = layout.row()
@@ -711,7 +710,7 @@ class MaterialFreestyleButtonsPanel():
class MATERIAL_PT_freestyle_line(MaterialFreestyleButtonsPanel, Panel):
bl_label = "Freestyle Line"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'} # TODO: 'CYCLES'
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'CYCLES'}
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 6b7e7b47281..e6d6a3952ea 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -18,7 +18,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Panel
+from bpy.types import Panel, Menu
from rna_prop_ui import PropertyPanel
@@ -151,6 +151,16 @@ class OBJECT_PT_relations(ObjectButtonsPanel, Panel):
sub.prop_search(ob, "parent_bone", parent.data, "bones", text="")
sub.active = (parent is not None)
+class GROUP_MT_specials(Menu):
+ bl_label = "Group Specials"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("object.group_unlink", icon='X')
+ layout.operator("object.grouped_select")
+ layout.operator("object.dupli_offset_from_cursor")
+
class OBJECT_PT_groups(ObjectButtonsPanel, Panel):
bl_label = "Groups"
@@ -167,8 +177,6 @@ class OBJECT_PT_groups(ObjectButtonsPanel, Panel):
row.operator("object.group_add", text="Add to Group")
row.operator("object.group_add", text="", icon='ZOOMIN')
- # XXX, this is bad practice, yes, I wrote it :( - campbell
- index = 0
obj_name = obj.name
for group in bpy.data.groups:
# XXX this is slow and stupid!, we need 2 checks, one thats fast
@@ -183,6 +191,7 @@ class OBJECT_PT_groups(ObjectButtonsPanel, Panel):
row = col.box().row()
row.prop(group, "name", text="")
row.operator("object.group_remove", text="", icon='X', emboss=False)
+ row.menu("GROUP_MT_specials", icon='DOWNARROW_HLT', text="")
split = col.box().split()
@@ -192,10 +201,6 @@ class OBJECT_PT_groups(ObjectButtonsPanel, Panel):
col = split.column()
col.prop(group, "dupli_offset", text="")
- props = col.operator("object.dupli_offset_from_cursor", text="From Cursor")
- props.group = index
- index += 1
-
class OBJECT_PT_display(ObjectButtonsPanel, Panel):
bl_label = "Display"
@@ -301,10 +306,11 @@ class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel):
split = layout.split()
- col = split.column()
- col.label(text="Tracking Axes:")
- col.prop(ob, "track_axis", text="Axis")
- col.prop(ob, "up_axis", text="Up Axis")
+ if context.scene.render.engine != 'BLENDER_GAME':
+ col = split.column()
+ col.label(text="Tracking Axes:")
+ col.prop(ob, "track_axis", text="Axis")
+ col.prop(ob, "up_axis", text="Up Axis")
col = split.column()
col.prop(ob, "use_slow_parent")
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 462ca2e85ca..5c758b6568b 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -17,6 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
+from bpy.types import Menu
class UnifiedPaintPanel():
@@ -50,6 +51,10 @@ class UnifiedPaintPanel():
row.prop(ups, "use_unified_strength", text="Strength")
if context.weight_paint_object:
parent.prop(ups, "use_unified_weight", text="Weight")
+ elif context.vertex_paint_object or context.image_paint_object:
+ parent.prop(ups, "use_unified_color", text="Color")
+ else:
+ parent.prop(ups, "use_unified_color", text="Color")
@staticmethod
def prop_unified_size(parent, context, brush, prop_name, icon='NONE', text="", slider=False):
@@ -69,6 +74,155 @@ class UnifiedPaintPanel():
ptr = ups if ups.use_unified_weight else brush
parent.prop(ptr, prop_name, icon=icon, text=text, slider=slider)
+ @staticmethod
+ def prop_unified_color(parent, context, brush, prop_name, text=""):
+ ups = context.tool_settings.unified_paint_settings
+ ptr = ups if ups.use_unified_color else brush
+ parent.prop(ptr, prop_name, text=text)
+
+ @staticmethod
+ def prop_unified_color_picker(parent, context, brush, prop_name, value_slider=True):
+ ups = context.tool_settings.unified_paint_settings
+ ptr = ups if ups.use_unified_color else brush
+ parent.template_color_picker(ptr, prop_name, value_slider=value_slider)
+
+
+class VIEW3D_MT_tools_projectpaint_clone(Menu):
+ bl_label = "Clone Layer"
+
+ def draw(self, context):
+ layout = self.layout
+
+ for i, tex in enumerate(context.active_object.data.uv_textures):
+ props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
+ props.data_path = "active_object.data.uv_texture_clone_index"
+ props.value = i
+
+
+def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=False):
+ capabilities = brush.image_paint_capabilities
+
+ col = layout.column()
+
+ if brush.image_tool in {'DRAW', 'FILL'}:
+ if brush.blend not in {'ERASE_ALPHA', 'ADD_ALPHA'}:
+ if not brush.use_gradient:
+ panel.prop_unified_color_picker(col, context, brush, "color", value_slider=True)
+
+ if settings.palette:
+ col.template_palette(settings, "palette", color=True)
+
+ if brush.use_gradient:
+ col.label("Gradient Colors")
+ col.template_color_ramp(brush, "gradient", expand=True)
+
+ if brush.image_tool != 'FILL':
+ col.label("Background Color")
+ row = col.row(align=True)
+ panel.prop_unified_color(row, context, brush, "secondary_color", text="")
+
+ if brush.image_tool == 'DRAW':
+ col.prop(brush, "gradient_stroke_mode", text="Mode")
+ if brush.gradient_stroke_mode in {'SPACING_REPEAT', 'SPACING_CLAMP'}:
+ col.prop(brush, "grad_spacing")
+ elif brush.image_tool == 'FILL':
+ col.prop(brush, "gradient_fill_mode")
+ else:
+ row = col.row(align=True)
+ panel.prop_unified_color(row, context, brush, "color", text="")
+ if brush.image_tool == 'FILL':
+ col.prop(brush, "fill_threshold")
+ else:
+ panel.prop_unified_color(row, context, brush, "secondary_color", text="")
+ row.separator()
+ row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="")
+
+ elif brush.image_tool == 'SOFTEN':
+ col = layout.column(align=True)
+ col.row().prop(brush, "direction", expand=True)
+ col.separator()
+ col.prop(brush, "sharp_threshold")
+ if not projpaint:
+ col.prop(brush, "blur_kernel_radius")
+ col.separator()
+ col.prop(brush, "blur_mode")
+ elif brush.image_tool == 'MASK':
+ col.prop(brush, "weight", text="Mask Value", slider=True)
+
+ elif brush.image_tool == 'CLONE':
+ col.separator()
+ if projpaint:
+ if settings.mode == 'MATERIAL':
+ 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")
+
+ if settings.use_clone_layer:
+ ob = context.active_object
+ col = layout.column()
+
+ if settings.mode == 'MATERIAL':
+ if len(ob.material_slots) > 1:
+ col.label("Materials")
+ col.template_list("MATERIAL_UL_matslots", "",
+ ob, "material_slots",
+ ob, "active_material_index", rows=2)
+
+ mat = ob.active_material
+ if mat:
+ col.label("Clone Slot")
+ col.template_list("TEXTURE_UL_texpaintslots", "",
+ mat, "texture_paint_images",
+ mat, "paint_clone_slot", rows=2)
+
+ elif settings.mode == 'IMAGE':
+ mesh = ob.data
+
+ clone_text = mesh.uv_texture_clone.name if mesh.uv_texture_clone else ""
+ col.label("Image")
+ col.template_ID(settings, "clone_image")
+ col.label("UV Map")
+ col.menu("VIEW3D_MT_tools_projectpaint_clone", text=clone_text, translate=False)
+
+
+ else:
+ col.prop(brush, "clone_image", text="Image")
+ col.prop(brush, "clone_alpha", text="Alpha")
+
+
+
+ col.separator()
+
+ if capabilities.has_radius:
+ row = col.row(align=True)
+ panel.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
+ panel.prop_unified_size(row, context, brush, "use_pressure_size")
+
+ row = col.row(align=True)
+
+ if capabilities.has_space_attenuation:
+ row.prop(brush, "use_space_attenuation", toggle=True, icon_only=True)
+
+ panel.prop_unified_strength(row, context, brush, "strength", text="Strength")
+ panel.prop_unified_strength(row, context, brush, "use_pressure_strength")
+
+ if brush.image_tool in {'DRAW', 'FILL'}:
+ col.separator()
+ col.prop(brush, "blend", text="Blend")
+
+ col = layout.column()
+
+ # use_accumulate
+ if capabilities.has_accumulate:
+ col = layout.column(align=True)
+ col.prop(brush, "use_accumulate")
+
+ col.prop(brush, "use_alpha")
+ col.prop(brush, "use_gradient")
+
+ col.separator()
+ col.template_ID(settings, "palette", new="palette.new")
+
# Used in both the View3D toolbar and texture properties
def brush_texture_settings(layout, brush, sculpt):
@@ -136,6 +290,7 @@ def brush_mask_texture_settings(layout, brush):
layout.operator("brush.stencil_reset_transform").mask = True
col = layout.column()
+ col.prop(brush, "use_pressure_masking", text="")
col.label(text="Angle:")
col.active = brush.brush_capabilities.has_texture_angle
col.prop(mask_tex_slot, "angle", text="")
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index 626cdaa8b1b..faf0d4cb0e8 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -1172,7 +1172,6 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel):
col = split.column()
factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
-
layout.separator()
if not isinstance(idblock, ParticleSettings):
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 96ad70e0015..13aad4c3888 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -261,7 +261,7 @@ class CLIP_PT_tools_marker(CLIP_PT_tracking_panel, Panel):
layout = self.layout
sc = context.space_data
- clip = sc.clip
+ # clip = sc.clip
col = layout.column(align=True)
row = col.row(align=True)
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 97c89df0693..8fd0ded17f7 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -22,6 +22,7 @@ from bpy.types import Header, Menu, Panel
from bl_ui.properties_paint_common import (
UnifiedPaintPanel,
brush_texture_settings,
+ brush_texpaint_common,
brush_mask_texture_settings,
)
from bl_ui.properties_grease_pencil_common import GreasePencilPanel
@@ -31,13 +32,11 @@ from bpy.app.translations import pgettext_iface as iface_
class ImagePaintPanel(UnifiedPaintPanel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
- bl_category = "Tools"
-class BrushButtonsPanel:
+class BrushButtonsPanel(UnifiedPaintPanel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
- bl_category = "Tools"
@classmethod
def poll(cls, context):
@@ -66,6 +65,7 @@ class IMAGE_MT_view(Menu):
sima = context.space_data
uv = sima.uv_editor
toolsettings = context.tool_settings
+ paint = toolsettings.image_paint
show_uvedit = sima.show_uvedit
show_render = sima.show_render
@@ -80,6 +80,8 @@ class IMAGE_MT_view(Menu):
layout.prop(toolsettings, "show_uv_local_view")
layout.prop(uv, "show_other_objects")
+ if paint.brush and (context.image_paint_object or sima.mode == 'PAINT'):
+ layout.prop(uv, "show_texpaint")
layout.separator()
@@ -140,6 +142,24 @@ class IMAGE_MT_select(Menu):
layout.operator("uv.select_split")
+class IMAGE_MT_brush(Menu):
+ bl_label = "Brush"
+
+ def draw(self, context):
+ layout = self.layout
+ toolsettings = context.tool_settings
+ settings = toolsettings.image_paint
+ brush = settings.brush
+
+ ups = context.tool_settings.unified_paint_settings
+ layout.prop(ups, "use_unified_size", text="Unified Size")
+ layout.prop(ups, "use_unified_strength", text="Unified Strength")
+ layout.separator()
+
+ # brush tool
+ layout.prop_menu_enum(brush, "image_tool")
+
+
class IMAGE_MT_image(Menu):
bl_label = "Image"
@@ -156,6 +176,8 @@ class IMAGE_MT_image(Menu):
layout.operator("image.read_renderlayers")
+ layout.operator("image.save_dirty", text="Save All Images")
+
if ima:
if not show_render:
layout.operator("image.replace")
@@ -382,7 +404,6 @@ class IMAGE_HT_header(Header):
mode = sima.mode
show_render = sima.show_render
- # show_paint = sima.show_paint
show_uvedit = sima.show_uvedit
show_maskedit = sima.show_maskedit
@@ -401,8 +422,7 @@ class IMAGE_HT_header(Header):
row = layout.row()
row.template_ID(sima, "mask", new="mask.new")
- if show_uvedit or show_maskedit:
- layout.prop(sima, "pivot_point", icon_only=True)
+ layout.prop(sima, "pivot_point", icon_only=True)
# uv editing
if show_uvedit:
@@ -462,6 +482,7 @@ class MASK_MT_editor_menus(Menu):
show_uvedit = sima.show_uvedit
show_maskedit = sima.show_maskedit
+ show_paint = sima.show_paint
layout.menu("IMAGE_MT_view")
@@ -469,6 +490,8 @@ class MASK_MT_editor_menus(Menu):
layout.menu("IMAGE_MT_select")
if show_maskedit:
layout.menu("MASK_MT_select")
+ if show_paint:
+ layout.menu("IMAGE_MT_brush")
if ima and ima.is_dirty:
layout.menu("IMAGE_MT_image", text="Image*")
@@ -658,49 +681,27 @@ class IMAGE_PT_tools_transform_uvs(Panel, UVToolsPanel):
col.operator("transform.shear")
-class IMAGE_PT_paint(Panel, ImagePaintPanel):
+class IMAGE_PT_paint(Panel, BrushButtonsPanel):
bl_label = "Paint"
-
- @classmethod
- def poll(cls, context):
- sima = context.space_data
- return sima.show_paint
+ bl_category = "Tools"
def draw(self, context):
layout = self.layout
- toolsettings = context.tool_settings.image_paint
- brush = toolsettings.brush
+ settings = context.tool_settings.image_paint
+ brush = settings.brush
col = layout.column()
- col.template_ID_preview(toolsettings, "brush", new="brush.add", rows=2, cols=6)
+ col.template_ID_preview(settings, "brush", new="brush.add", rows=2, cols=6)
if brush:
- col = layout.column()
-
- if brush.image_tool == 'DRAW' and brush.blend not in ('ERASE_ALPHA', 'ADD_ALPHA'):
- col.template_color_picker(brush, "color", value_slider=True)
- col.prop(brush, "color", text="")
-
- row = col.row(align=True)
- self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
- self.prop_unified_size(row, context, brush, "use_pressure_size")
-
- row = col.row(align=True)
- self.prop_unified_strength(row, context, brush, "strength", slider=True, text="Strength")
- self.prop_unified_strength(row, context, brush, "use_pressure_strength")
-
- col.prop(brush, "blend", text="Blend")
-
- if brush.image_tool == 'CLONE':
- col.separator()
- col.prop(brush, "clone_image", text="Image")
- col.prop(brush, "clone_alpha", text="Alpha")
+ brush_texpaint_common(self, context, layout, brush, settings)
class IMAGE_PT_tools_brush_overlay(BrushButtonsPanel, Panel):
bl_label = "Overlay"
bl_options = {'DEFAULT_CLOSED'}
+ bl_category = "Options"
def draw(self, context):
layout = self.layout
@@ -754,6 +755,7 @@ class IMAGE_PT_tools_brush_overlay(BrushButtonsPanel, Panel):
class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
bl_label = "Texture"
bl_options = {'DEFAULT_CLOSED'}
+ bl_category = "Tools"
def draw(self, context):
layout = self.layout
@@ -770,6 +772,7 @@ class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
class IMAGE_PT_tools_mask_texture(BrushButtonsPanel, Panel):
bl_label = "Texture Mask"
bl_options = {'DEFAULT_CLOSED'}
+ bl_category = "Tools"
def draw(self, context):
layout = self.layout
@@ -786,6 +789,7 @@ class IMAGE_PT_tools_mask_texture(BrushButtonsPanel, Panel):
class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, Panel):
bl_label = "Tool"
bl_options = {'DEFAULT_CLOSED'}
+ bl_category = "Options"
def draw(self, context):
layout = self.layout
@@ -804,6 +808,7 @@ class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, Panel):
class IMAGE_PT_paint_stroke(BrushButtonsPanel, Panel):
bl_label = "Paint Stroke"
bl_options = {'DEFAULT_CLOSED'}
+ bl_category = "Tools"
def draw(self, context):
layout = self.layout
@@ -828,10 +833,19 @@ class IMAGE_PT_paint_stroke(BrushButtonsPanel, Panel):
if brush.use_space:
col.separator()
row = col.row(align=True)
- row.active = brush.use_space
row.prop(brush, "spacing", text="Spacing")
row.prop(brush, "use_pressure_spacing", toggle=True, text="")
+ if brush.use_line or brush.use_curve:
+ col.separator()
+ row = col.row(align=True)
+ row.prop(brush, "spacing", text="Spacing")
+
+ if brush.use_curve:
+ col.separator()
+ col.template_ID(brush, "paint_curve", new="paintcurve.new")
+ col.operator("paintcurve.draw")
+
col = layout.column()
col.separator()
@@ -846,25 +860,23 @@ class IMAGE_PT_paint_stroke(BrushButtonsPanel, Panel):
col = layout.column()
col.separator()
- col.prop(brush, "use_smooth_stroke")
+ if brush.brush_capabilities.has_smooth_stroke:
+ col.prop(brush, "use_smooth_stroke")
- sub = col.column()
- sub.active = brush.use_smooth_stroke
- sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
- sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
+ sub = col.column()
+ sub.active = brush.use_smooth_stroke
+ sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
+ sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
- col.separator()
+ col.separator()
col.prop(toolsettings, "input_samples")
- col.separator()
-
- col.prop(brush, "use_wrap")
-
class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
bl_label = "Paint Curve"
bl_options = {'DEFAULT_CLOSED'}
+ bl_category = "Tools"
def draw(self, context):
layout = self.layout
@@ -874,7 +886,8 @@ class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
layout.template_curve_mapping(brush, "curve")
- row = layout.row(align=True)
+ col = layout.column(align=True)
+ row = col.row(align=True)
row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
@@ -886,6 +899,7 @@ class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
class IMAGE_PT_tools_brush_appearance(BrushButtonsPanel, Panel):
bl_label = "Appearance"
bl_options = {'DEFAULT_CLOSED'}
+ bl_category = "Options"
def draw(self, context):
layout = self.layout
@@ -912,6 +926,30 @@ class IMAGE_PT_tools_brush_appearance(BrushButtonsPanel, Panel):
sub.prop(brush, "icon_filepath", text="")
+class IMAGE_PT_tools_paint_options(BrushButtonsPanel, Panel):
+ bl_label = "Image Paint"
+ bl_category = "Options"
+
+ def draw(self, context):
+ layout = self.layout
+
+ toolsettings = context.tool_settings
+ brush = toolsettings.image_paint.brush
+
+ ups = toolsettings.unified_paint_settings
+
+ col = layout.column(align=True)
+
+ col.prop(brush, "use_wrap")
+ col.separator()
+
+ col.label(text="Unified Settings:")
+ row = col.row()
+ row.prop(ups, "use_unified_size", text="Size")
+ row.prop(ups, "use_unified_strength", text="Strength")
+ col.prop(ups, "use_unified_color", text="Color")
+
+
class IMAGE_UV_sculpt_curve(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
@@ -1032,7 +1070,7 @@ class IMAGE_PT_view_waveform(Panel):
layout.template_waveform(sima, "scopes")
row = layout.split(percentage=0.75)
row.prop(sima.scopes, "waveform_alpha")
- row.prop(sima.scopes, "waveform_mode", icon_only=True)
+ row.prop(sima.scopes, "waveform_mode", text="")
class IMAGE_PT_view_vectorscope(Panel):
diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index ddb83310fe8..67b2bbe1905 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -57,11 +57,9 @@ class INFO_HT_header(Header):
row = layout.row(align=True)
if bpy.app.autoexec_fail is True and bpy.app.autoexec_fail_quiet is False:
- layout.operator_context = 'EXEC_DEFAULT'
row.label("Auto-run disabled: %s" % bpy.app.autoexec_fail_message, icon='ERROR')
if bpy.data.is_saved:
- props = row.operator("wm.open_mainfile", icon='SCREEN_BACK', text="Reload Trusted")
- props.filepath = bpy.data.filepath
+ props = row.operator("wm.revert_mainfile", icon='SCREEN_BACK', text="Reload Trusted")
props.use_scripts = True
row.operator("script.autoexec_warn_clear", text="Ignore")
@@ -129,10 +127,8 @@ class INFO_MT_file(Menu):
layout.separator()
layout.operator_context = 'INVOKE_AREA'
- layout.operator("wm.link_append", text="Link", icon='LINK_BLEND')
- props = layout.operator("wm.link_append", text="Append", icon='APPEND_BLEND')
- props.link = False
- props.instance_groups = False
+ layout.operator("wm.link", text="Link", icon='LINK_BLEND')
+ layout.operator("wm.append", text="Append", icon='APPEND_BLEND')
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 959043f7931..e8914a3e9b0 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -67,6 +67,16 @@ class NODE_HT_header(Header):
if snode_id:
row.prop(snode_id, "use_nodes")
+ if scene.render.use_shading_nodes and snode.shader_type == 'LINESTYLE':
+ rl = context.scene.render.layers.active
+ lineset = rl.freestyle_settings.linesets.active
+ if lineset is not None:
+ row = layout.row()
+ row.enabled = not snode.pin
+ row.template_ID(lineset, "linestyle", new="scene.freestyle_linestyle_new")
+ if snode_id:
+ row.prop(snode_id, "use_nodes")
+
elif snode.tree_type == 'TextureNodeTree':
layout.prop(snode, "texture_type", text="", expand=True)
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index b77078bf5d4..17e37f17974 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -59,12 +59,17 @@ class SEQUENCER_HT_header(Header):
layout = self.layout
st = context.space_data
+ scene = context.scene
row = layout.row(align=True)
row.template_header()
SEQUENCER_MT_editor_menus.draw_collapsible(context, layout)
+ row = layout.row(align=True)
+ row.prop(scene, "use_preview_range", text="", toggle=True)
+ row.prop(scene, "lock_frame_selection_to_range", text="", toggle=True)
+
layout.prop(st, "view_type", expand=True, text="")
if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
@@ -122,6 +127,7 @@ class SEQUENCER_MT_editor_menus(Menu):
layout.menu("SEQUENCER_MT_select")
layout.menu("SEQUENCER_MT_marker")
layout.menu("SEQUENCER_MT_add")
+ layout.menu("SEQUENCER_MT_frame")
layout.menu("SEQUENCER_MT_strip")
@@ -160,14 +166,14 @@ class SEQUENCER_MT_view(Menu):
if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
layout.operator_context = 'INVOKE_REGION_PREVIEW'
layout.operator("sequencer.view_all_preview", text="Fit preview in window")
-
+
layout.separator()
-
+
ratios = ((1, 8), (1, 4), (1, 2), (1, 1), (2, 1), (4, 1), (8, 1))
for a, b in ratios:
layout.operator("sequencer.view_zoom_ratio", text=iface_("Zoom %d:%d") % (a, b), translate=False).ratio = a / b
-
+
layout.separator()
layout.operator_context = 'INVOKE_DEFAULT'
@@ -203,6 +209,13 @@ 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'
+ op = layout.operator("sequencer.select", text="All strips to the Left")
+ op.left_right = 'LEFT'
+ op.linked_time = True
+ op = layout.operator("sequencer.select", text="All strips to the Right")
+ op.left_right = 'RIGHT'
+ op.linked_time = True
+
layout.separator()
layout.operator("sequencer.select_handles", text="Surrounding Handles").side = 'BOTH'
layout.operator("sequencer.select_handles", text="Left Handle").side = 'LEFT'
@@ -237,6 +250,15 @@ class SEQUENCER_MT_change(Menu):
layout.operator("sequencer.change_path", text="Path/Files")
+class SEQUENCER_MT_frame(Menu):
+ bl_label = "Frame"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("anim.previewrange_clear")
+ layout.operator("anim.previewrange_set")
+
class SEQUENCER_MT_add(Menu):
bl_label = "Add"
@@ -284,6 +306,7 @@ class SEQUENCER_MT_add_effect(Menu):
layout.operator("sequencer.effect_strip_add", text="Alpha Under").type = 'ALPHA_UNDER'
layout.operator("sequencer.effect_strip_add", text="Cross").type = 'CROSS'
layout.operator("sequencer.effect_strip_add", text="Gamma Cross").type = 'GAMMA_CROSS'
+ layout.operator("sequencer.effect_strip_add", text="Gaussian Blur").type = 'GAUSSIAN_BLUR'
layout.operator("sequencer.effect_strip_add", text="Multiply").type = 'MULTIPLY'
layout.operator("sequencer.effect_strip_add", text="Over Drop").type = 'OVER_DROP'
layout.operator("sequencer.effect_strip_add", text="Wipe").type = 'WIPE'
@@ -490,7 +513,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
return strip.type in {'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED',
- 'MULTICAM'}
+ 'MULTICAM', 'GAUSSIAN_BLUR'}
def draw(self, context):
layout = self.layout
@@ -588,6 +611,9 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
col.prop(strip, "use_default_fade", "Default fade")
if not strip.use_default_fade:
col.prop(strip, "effect_fader", text="Effect fader")
+ elif strip.type == 'GAUSSIAN_BLUR':
+ col.prop(strip, "size_x")
+ col.prop(strip, "size_y")
class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py
index c96b8fd568e..cfb147b3566 100644
--- a/release/scripts/startup/bl_ui/space_time.py
+++ b/release/scripts/startup/bl_ui/space_time.py
@@ -176,8 +176,11 @@ class TIME_MT_frame(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("time.start_frame_set")
+ layout.operator("anim.previewrange_clear")
+ layout.operator("anim.previewrange_set")
+ layout.separator()
layout.operator("time.end_frame_set")
+ layout.operator("time.start_frame_set")
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index cba6f065a6f..999e41e17f7 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -217,6 +217,13 @@ class USERPREF_PT_interface(Panel):
sub.prop(view, "open_sublevel_delay", text="Sub Level")
col.separator()
+ col.label(text="Pie Menus:")
+ sub = col.column(align=True)
+ sub.prop(view, "pie_animation_timeout")
+ sub.prop(view, "pie_initial_timeout")
+ sub.prop(view, "pie_menu_radius")
+ sub.prop(view, "pie_menu_threshold")
+ col.separator()
col.separator()
col.separator()
@@ -417,6 +424,12 @@ class USERPREF_PT_system(Panel):
col.prop(system, "use_gpu_mipmap")
col.prop(system, "use_16bit_textures")
+
+ if system.is_occlusion_query_supported():
+ col.separator()
+ col.label(text="Selection")
+ col.prop(system, "select_method", text="")
+
col.separator()
col.label(text="Anisotropic Filtering")
@@ -675,6 +688,9 @@ class USERPREF_PT_theme(Panel):
col.label(text="Menu:")
self._theme_widget_style(col, ui.wcol_menu)
+ col.label(text="Pie Menu:")
+ self._theme_widget_style(col, ui.wcol_pie_menu)
+
col.label(text="Pulldown:")
self._theme_widget_style(col, ui.wcol_pulldown)
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 6f0b97fcb4b..61d359ebdac 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2223,7 +2223,7 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
layout.separator()
- if with_freestyle and not scene.render.use_shading_nodes:
+ if with_freestyle:
layout.operator("mesh.mark_freestyle_edge").clear = False
layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
layout.separator()
@@ -2266,11 +2266,12 @@ class VIEW3D_MT_edit_mesh_faces(Menu):
layout.operator("mesh.inset")
layout.operator("mesh.bevel").vertex_only = False
layout.operator("mesh.solidify")
+ layout.operator("mesh.intersect")
layout.operator("mesh.wireframe")
layout.separator()
- if with_freestyle and not scene.render.use_shading_nodes:
+ if with_freestyle:
layout.operator("mesh.mark_freestyle_face").clear = False
layout.operator("mesh.mark_freestyle_face", text="Clear Freestyle Face").clear = True
layout.separator()
@@ -2278,6 +2279,7 @@ class VIEW3D_MT_edit_mesh_faces(Menu):
layout.operator("mesh.poke")
layout.operator("mesh.quads_convert_to_tris")
layout.operator("mesh.tris_convert_to_quads")
+ layout.operator("mesh.face_split_by_edges")
layout.separator()
@@ -2933,7 +2935,7 @@ class VIEW3D_PT_view3d_meshdisplay(Panel):
col.prop(mesh, "show_edge_seams", text="Seams")
col.prop(mesh, "show_edge_sharp", text="Sharp", text_ctxt=i18n_contexts.plural)
col.prop(mesh, "show_edge_bevel_weight", text="Bevel")
- if with_freestyle and not scene.render.use_shading_nodes:
+ if with_freestyle:
col.prop(mesh, "show_freestyle_edge_marks", text="Edge Marks")
col.prop(mesh, "show_freestyle_face_marks", text="Face Marks")
@@ -2944,7 +2946,7 @@ class VIEW3D_PT_view3d_meshdisplay(Panel):
row = col.row(align=True)
row.prop(mesh, "show_normal_vertex", text="", icon='VERTEXSEL')
- row.prop(mesh, "show_normal_loop", text="", icon='VERTEXSEL')
+ row.prop(mesh, "show_normal_loop", text="", icon='LOOPSEL')
row.prop(mesh, "show_normal_face", text="", icon='FACESEL')
sub = row.row(align=True)
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 0f2c04d1cdc..6b0c5b1e993 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -18,11 +18,12 @@
# <pep8 compliant>
import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
from bl_ui.properties_grease_pencil_common import GreasePencilPanel
from bl_ui.properties_paint_common import (
UnifiedPaintPanel,
brush_texture_settings,
+ brush_texpaint_common,
brush_mask_texture_settings,
)
@@ -34,14 +35,6 @@ class View3DPanel():
# **************** standard tool clusters ******************
-# History/Repeat tools
-def draw_repeat_tools(context, layout):
- col = layout.column(align=True)
- col.label(text="Repeat:")
- col.operator("screen.repeat_last")
- col.operator("screen.repeat_history", text="History...")
-
-
# Keyframing tools
def draw_keyframing_tools(context, layout):
col = layout.column(align=True)
@@ -105,24 +98,6 @@ class VIEW3D_PT_tools_object(View3DPanel, Panel):
row.operator("object.shade_flat", text="Flat")
-class VIEW3D_PT_tools_objectmode(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "objectmode"
- bl_label = "History"
- bl_options = {'DEFAULT_CLOSED'}
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- row = col.row(align=True)
- row.operator("ed.undo")
- row.operator("ed.redo")
- col.operator("ed.undo_history")
-
- draw_repeat_tools(context, layout)
-
-
class VIEW3D_PT_tools_add_object(View3DPanel, Panel):
bl_category = "Create"
bl_context = "objectmode"
@@ -361,7 +336,6 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
col.operator_menu_enum("mesh.merge", "type")
col.operator("mesh.remove_doubles")
- draw_repeat_tools(context, layout)
class VIEW3D_PT_tools_meshweight(View3DPanel, Panel):
bl_category = "Tools"
@@ -388,6 +362,7 @@ class VIEW3D_PT_tools_meshweight(View3DPanel, Panel):
layout = self.layout
self.draw_generic(layout)
+
class VIEW3D_PT_tools_add_mesh_edit(View3DPanel, Panel):
bl_category = "Create"
bl_context = "mesh_edit"
@@ -538,8 +513,6 @@ class VIEW3D_PT_tools_curveedit(View3DPanel, Panel):
col.operator("curve.smooth")
col.operator("object.vertex_random")
- draw_repeat_tools(context, layout)
-
class VIEW3D_PT_tools_add_curve_edit(View3DPanel, Panel):
bl_category = "Create"
@@ -594,8 +567,6 @@ class VIEW3D_PT_tools_surfaceedit(View3DPanel, Panel):
col.label(text="Deform:")
col.operator("object.vertex_random")
- draw_repeat_tools(context, layout)
-
class VIEW3D_PT_tools_add_surface_edit(View3DPanel, Panel):
bl_category = "Create"
@@ -632,8 +603,6 @@ class VIEW3D_PT_tools_textedit(View3DPanel, Panel):
col.operator("font.style_toggle", text="Italic").style = 'ITALIC'
col.operator("font.style_toggle", text="Underline").style = 'UNDERLINE'
- draw_repeat_tools(context, layout)
-
# ********** default tools for editmode_armature ****************
@@ -675,8 +644,6 @@ class VIEW3D_PT_tools_armatureedit(View3DPanel, Panel):
col.label(text="Deform:")
col.operator("object.vertex_random")
- draw_repeat_tools(context, layout)
-
class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel):
bl_category = "Options"
@@ -710,8 +677,6 @@ class VIEW3D_PT_tools_mballedit(View3DPanel, Panel):
col.label(text="Deform:")
col.operator("object.vertex_random")
- draw_repeat_tools(context, layout)
-
class VIEW3D_PT_tools_add_mball_edit(View3DPanel, Panel):
bl_category = "Create"
@@ -750,8 +715,6 @@ class VIEW3D_PT_tools_latticeedit(View3DPanel, Panel):
col.label(text="Deform:")
col.operator("object.vertex_random")
- draw_repeat_tools(context, layout)
-
# ********** default tools for pose-mode ****************
@@ -794,8 +757,6 @@ class VIEW3D_PT_tools_posemode(View3DPanel, Panel):
row.operator("pose.paths_calculate", text="Calculate")
row.operator("pose.paths_clear", text="Clear")
- draw_repeat_tools(context, layout)
-
class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel):
bl_category = "Options"
@@ -979,25 +940,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
# Texture Paint Mode #
elif context.image_paint_object and brush:
- col = layout.column()
-
- if brush.image_tool == 'DRAW' and brush.blend not in ('ERASE_ALPHA', 'ADD_ALPHA'):
- col.template_color_picker(brush, "color", value_slider=True)
- col.prop(brush, "color", text="")
-
- row = col.row(align=True)
- self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
- self.prop_unified_size(row, context, brush, "use_pressure_size")
-
- row = col.row(align=True)
- self.prop_unified_strength(row, context, brush, "strength", text="Strength")
- self.prop_unified_strength(row, context, brush, "use_pressure_strength")
-
- col.prop(brush, "blend", text="Blend")
-
- col = layout.column()
- col.active = (brush.blend not in {'ERASE_ALPHA', 'ADD_ALPHA'})
- col.prop(brush, "use_alpha")
+ brush_texpaint_common(self, context, layout, brush, settings, True)
# Weight Paint Mode #
elif context.weight_paint_object and brush:
@@ -1024,9 +967,12 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
# Vertex Paint Mode #
elif context.vertex_paint_object and brush:
col = layout.column()
- col.template_color_picker(brush, "color", value_slider=True)
- col.prop(brush, "color", text="")
+ self.prop_unified_color_picker(col, context, brush, "color", value_slider=True)
+ if settings.palette:
+ col.template_palette(settings, "palette", color=True)
+ self.prop_unified_color(col, context, brush, "color", text="")
+ col.separator()
row = col.row(align=True)
self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
self.prop_unified_size(row, context, brush, "use_pressure_size")
@@ -1036,12 +982,128 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
# XXX - TODO
- #row = col.row(align=True)
- #row.prop(brush, "jitter", slider=True)
- #row.prop(brush, "use_pressure_jitter", toggle=True, text="")
-
+ # row = col.row(align=True)
+ # row.prop(brush, "jitter", slider=True)
+ # row.prop(brush, "use_pressure_jitter", toggle=True, text="")
+ col.separator()
col.prop(brush, "vertex_tool", text="Blend")
+ col.separator()
+ col.template_ID(settings, "palette", new="palette.new")
+
+
+class TEXTURE_UL_texpaintslots(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ mat = data
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.prop(item, "name", text="", emboss=False, icon_value=icon)
+ if (not mat.use_nodes) and (context.scene.render.engine == 'BLENDER_RENDER'):
+ mtex_index = mat.texture_paint_slots[index].index
+ layout.prop(mat, "use_textures", text="", index=mtex_index)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="")
+
+
+class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
+ bl_context = "imagepaint"
+ bl_label = "Slots"
+ bl_category = "Slots"
+
+ @classmethod
+ def poll(cls, context):
+ brush = context.tool_settings.image_paint.brush
+ ob = context.active_object
+ return (brush is not None and ob is not None)
+
+ def draw(self, context):
+ layout = self.layout
+
+ settings = context.tool_settings.image_paint
+ # brush = settings.brush
+
+ ob = context.active_object
+ col = layout.column()
+
+ 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.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.template_list("TEXTURE_UL_texpaintslots", "",
+ mat, "texture_paint_images",
+ mat, "paint_active_slot", rows=2)
+
+ if (not mat.use_nodes) and (context.scene.render.engine == 'BLENDER_RENDER'):
+ row = col.row(align=True)
+ row.operator_menu_enum("paint.add_texture_paint_slot", "type")
+ row.operator("paint.delete_texture_paint_slot", text="", icon='X')
+
+ if mat.texture_paint_slots:
+ slot = mat.texture_paint_slots[mat.paint_active_slot]
+
+ col.prop(mat.texture_slots[slot.index], "blend_type")
+ col.separator()
+ col.label("UV Map")
+ col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="")
+
+ elif settings.mode == 'IMAGE':
+ col.template_ID(settings, "canvas")
+
+ col.separator()
+ col.operator("image.save_dirty", text="Save All Images")
+
+
+
+class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
+ bl_context = "imagepaint"
+ bl_label = "Stencil"
+ bl_category = "Slots"
+
+ @classmethod
+ def poll(cls, context):
+ brush = context.tool_settings.image_paint.brush
+ ob = context.active_object
+ return (brush is not None and ob is not None)
+
+ def draw_header(self, context):
+ ipaint = context.tool_settings.image_paint
+ self.layout.prop(ipaint, "use_stencil_layer", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ toolsettings = context.tool_settings
+ ipaint = toolsettings.image_paint
+ ob = context.active_object
+ mesh = ob.data
+
+ col = layout.column()
+ col.active = ipaint.use_stencil_layer
+
+ stencil_text = mesh.uv_texture_stencil.name if mesh.uv_texture_stencil else ""
+ col.label("UV Map")
+ col.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False)
+
+ col.label("Image")
+ row = col.row(align=True)
+ row.template_ID(ipaint, "stencil_image")
+
+ col.label("Visualization")
+ row = col.row(align=True)
+ row.prop(ipaint, "stencil_color", text="")
+ row.prop(ipaint, "invert_stencil", text="", icon='IMAGE_ALPHA')
+
class VIEW3D_PT_tools_brush_overlay(Panel, View3DPaintPanel):
bl_category = "Options"
@@ -1194,10 +1256,19 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
if brush.use_space:
col.separator()
row = col.row(align=True)
- row.active = brush.use_space
row.prop(brush, "spacing", text="Spacing")
row.prop(brush, "use_pressure_spacing", toggle=True, text="")
+ if brush.use_line or brush.use_curve:
+ col.separator()
+ row = col.row(align=True)
+ row.prop(brush, "spacing", text="Spacing")
+
+ if brush.use_curve:
+ col.separator()
+ col.template_ID(brush, "paint_curve", new="paintcurve.new")
+ col.operator("paintcurve.draw")
+
if context.sculpt_object:
if brush.sculpt_capabilities.has_jitter:
col.separator()
@@ -1234,12 +1305,13 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
col = layout.column()
col.separator()
- col.prop(brush, "use_smooth_stroke")
+ if brush.brush_capabilities.has_smooth_stroke:
+ col.prop(brush, "use_smooth_stroke")
- sub = col.column()
- sub.active = brush.use_smooth_stroke
- sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
- sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
+ sub = col.column()
+ sub.active = brush.use_smooth_stroke
+ sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
+ sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
layout.prop(settings, "input_samples")
@@ -1263,7 +1335,8 @@ class VIEW3D_PT_tools_brush_curve(Panel, View3DPaintPanel):
layout.template_curve_mapping(brush, "curve", brush=True)
- row = layout.row(align=True)
+ col = layout.column(align=True)
+ row = col.row(align=True)
row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
@@ -1300,8 +1373,8 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
sub.active = (brush and brush.sculpt_tool != 'MASK')
if (sculpt.detail_type_method == 'CONSTANT'):
row = sub.row(align=True)
- row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER')
row.prop(sculpt, "constant_detail")
+ row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER')
else:
sub.prop(sculpt, "detail_size")
sub.prop(sculpt, "detail_refine_method", text="")
@@ -1327,7 +1400,7 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
def draw(self, context):
layout = self.layout
- scene = context.scene
+ # scene = context.scene
toolsettings = context.tool_settings
sculpt = toolsettings.sculpt
@@ -1493,7 +1566,7 @@ class VIEW3D_PT_tools_vertexpaint(Panel, View3DPaintPanel):
col = layout.column()
row = col.row()
- #col.prop(vpaint, "mode", text="")
+ # col.prop(vpaint, "mode", text="")
row.prop(vpaint, "use_normal")
col.prop(vpaint, "use_spray")
@@ -1528,10 +1601,9 @@ class VIEW3D_PT_tools_imagepaint_external(Panel, View3DPaintPanel):
col.row().prop(ipaint, "screen_grab_size", text="")
col.operator("paint.project_image", text="Apply Camera Image")
- col.operator("image.save_dirty", text="Save All Edited")
-class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
+class VIEW3D_PT_tools_projectpaint(View3DPaintPanel, Panel):
bl_category = "Options"
bl_context = "imagepaint"
bl_label = "Project Paint"
@@ -1544,13 +1616,11 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
def draw(self, context):
layout = self.layout
- ob = context.active_object
- mesh = ob.data
toolsettings = context.tool_settings
ipaint = toolsettings.image_paint
- settings = toolsettings.image_paint
col = layout.column()
+
col.prop(ipaint, "use_occlude")
col.prop(ipaint, "use_backface_culling")
@@ -1561,23 +1631,8 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
sub.active = (ipaint.use_normal_falloff)
sub.prop(ipaint, "normal_angle", text="")
- split = layout.split()
-
- split.prop(ipaint, "use_stencil_layer", text="Stencil")
-
- row = split.row()
- row.active = (ipaint.use_stencil_layer)
- stencil_text = mesh.uv_texture_stencil.name if mesh.uv_texture_stencil else ""
- row.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False)
- row.prop(ipaint, "invert_stencil", text="", icon='IMAGE_ALPHA')
-
- col = layout.column()
- col.active = (settings.brush.image_tool == 'CLONE')
- col.prop(ipaint, "use_clone_layer", text="Clone from UV map")
- clone_text = mesh.uv_texture_clone.name if mesh.uv_texture_clone else ""
- col.menu("VIEW3D_MT_tools_projectpaint_clone", text=clone_text, translate=False)
-
layout.prop(ipaint, "seam_bleed")
+ self.unified_paint_settings(layout, context)
class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
@@ -1595,18 +1650,6 @@ class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
self.unified_paint_settings(col, context)
-class VIEW3D_MT_tools_projectpaint_clone(Menu):
- bl_label = "Clone Layer"
-
- def draw(self, context):
- layout = self.layout
-
- for i, tex in enumerate(context.active_object.data.uv_textures):
- props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
- props.data_path = "active_object.data.uv_texture_clone_index"
- props.value = i
-
-
class VIEW3D_MT_tools_projectpaint_stencil(Menu):
bl_label = "Mask Layer"
@@ -1694,5 +1737,30 @@ class VIEW3D_PT_tools_grease_pencil(GreasePencilPanel, Panel):
bl_category = "Grease Pencil"
+# Note: moved here so that it's always in last position in 'Tools' panels!
+class VIEW3D_PT_tools_history(View3DPanel, Panel):
+ bl_category = "Tools"
+ # No bl_context, we are always available!
+ bl_label = "History"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+ obj = context.object
+
+ col = layout.column(align=True)
+ row = col.row(align=True)
+ row.operator("ed.undo")
+ row.operator("ed.redo")
+ if obj is None or obj.mode not in {'SCULPT'}:
+ # Sculpt mode does not generate an undo menu it seems...
+ col.operator("ed.undo_history")
+
+ col = layout.column(align=True)
+ col.label(text="Repeat:")
+ col.operator("screen.repeat_last")
+ col.operator("screen.repeat_history", text="History...")
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 0a90b9f01f8..5dccda789e0 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -105,6 +105,13 @@ def group_input_output_item_poll(context):
return False
+# only show input/output nodes when editing line style node trees
+def line_style_shader_nodes_poll(context):
+ snode = context.space_data
+ return (snode.tree_type == 'ShaderNodeTree' and
+ snode.shader_type == 'LINESTYLE')
+
+
# All standard node categories currently used in nodes.
shader_node_categories = [
@@ -169,12 +176,14 @@ shader_node_categories = [
NodeItem("ShaderNodeParticleInfo"),
NodeItem("ShaderNodeCameraData"),
NodeItem("ShaderNodeUVMap"),
+ NodeItem("ShaderNodeUVAlongStroke", poll=line_style_shader_nodes_poll),
NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
]),
ShaderNewNodeCategory("SH_NEW_OUTPUT", "Output", items=[
NodeItem("ShaderNodeOutputMaterial"),
NodeItem("ShaderNodeOutputLamp"),
NodeItem("ShaderNodeOutputWorld"),
+ NodeItem("ShaderNodeOutputLineStyle", poll=line_style_shader_nodes_poll),
NodeItem("NodeGroupOutput", poll=group_input_output_item_poll),
]),
ShaderNewNodeCategory("SH_NEW_SHADER", "Shader", items=[
@@ -318,6 +327,7 @@ compositor_node_categories = [
NodeItem("CompositorNodeInpaint"),
NodeItem("CompositorNodeDBlur"),
NodeItem("CompositorNodePixelate"),
+ NodeItem("CompositorNodeSunBeams"),
]),
CompositorNodeCategory("CMP_OP_VECTOR", "Vector", items=[
NodeItem("CompositorNodeNormal"),
diff --git a/release/scripts/templates_osl/fresnel_conductive.osl b/release/scripts/templates_osl/fresnel_conductive.osl
new file mode 100644
index 00000000000..c197656eaee
--- /dev/null
+++ b/release/scripts/templates_osl/fresnel_conductive.osl
@@ -0,0 +1,38 @@
+/*
+ * 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
+ */
+
+color fresnel_conductor(float cosi, color eta, color k)
+{
+ color cosi2 = color(cosi*cosi);
+ color one = color(1, 1, 1);
+ color tmp_f = eta * eta + k * k;
+ color tmp = tmp_f * cosi2;
+ color Rparl2 = (tmp - (2.0 * eta * cosi) + one) /
+ (tmp + (2.0 * eta * cosi) + one);
+ color Rperp2 = (tmp_f - (2.0 * eta * cosi) + cosi2) /
+ (tmp_f + (2.0 * eta * cosi) + cosi2);
+ return (Rparl2 + Rperp2) * 0.5;
+}
+
+shader node_fresnel_conductive(
+ color n = color(0.084136, 0.410708, 1.472421),
+ color k = color(4.018579, 2.363371, 1.607574),
+ normal Normal = N,
+ output color Color = color(0.8, 0.8, 0.8))
+{
+ float cosi = dot(I, Normal);
+ Color = fresnel_conductor(cosi, n, k);
+}
diff --git a/release/scripts/templates_py/ui_pie_menu.py b/release/scripts/templates_py/ui_pie_menu.py
new file mode 100644
index 00000000000..87500b682d6
--- /dev/null
+++ b/release/scripts/templates_py/ui_pie_menu.py
@@ -0,0 +1,32 @@
+import bpy
+from bpy.types import Menu
+
+# spawn an edit mode selection pie (run while object is in edit mode to get a valid output)
+
+
+class VIEW3D_PIE_template(Menu):
+ # label is displayed at the center of the pie menu.
+ bl_label = "Select Mode"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ # operator_enum will just spread all available options
+ # for the type enum of the operator on the pie
+ pie.operator_enum("mesh.select_mode", "type")
+
+
+def register():
+ bpy.utils.register_class(VIEW3D_PIE_template)
+
+
+def unregister():
+ bpy.utils.unregister_class(VIEW3D_PIE_template)
+
+
+if __name__ == "__main__":
+ register()
+
+ bpy.ops.wm.call_menu_pie(name="VIEW3D_PIE_template")
+
diff --git a/release/text/readme.html b/release/text/readme.html
index 452293ad702..4d8b0bf24d2 100644
--- a/release/text/readme.html
+++ b/release/text/readme.html
@@ -20,18 +20,18 @@
</style>
</head>
<body>
-<p class="p1"><b>Blender 2.71</b></p>
+<p class="p1"><b>Blender 2.72</b></p>
<p class="p2"><br></p>
<p class="p3"><b>About</b></p>
<p class="p4">Welcome to Blender, the free, open source 3D application for modeling, animation, rendering, compositing, video editing and game creation. Blender is available for Linux, Mac OS X and Windows and has a large world-wide community.</p>
<p class="p4">Blender can be used freely for any purpose, including commercial use and distribution. It's free and open-source software, released under the GNU GPL licence. The entire source code is available on our website.</p>
<p class="p4">For more information, visit <a href="http://www.blender.org/"><span class="s1">blender.org</span></a>.</p>
<p class="p2"><br></p>
-<p class="p3"><b>2.71</b></p>
-<p class="p4">The Blender Foundation and online developer community is proud to present Blender 2.71. This release is the second official stable release of the Blender 2.7 series. <a href="http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.71"><span class="s1">More information about this release</span></a>.</p>
+<p class="p3"><b>2.72</b></p>
+<p class="p4">The Blender Foundation and online developer community is proud to present Blender 2.72. This release is the third official stable release of the Blender 2.7 series. <a href="http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.72"><span class="s1">More information about this release</span></a>.</p>
<p class="p2"><br></p>
<p class="p3"><b>Bugs</b></p>
-<p class="p4">Although Blender 2.71 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help <span class="s2">→</span> Report a Bug from inside Blender. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.</p>
+<p class="p4">Although Blender 2.72 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help <span class="s2">→</span> Report a Bug from inside Blender. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.</p>
<p class="p2"><br></p>
<p class="p3"><b>Package Contents</b></p>
<p class="p4">The downloaded Blender package includes:</p>
@@ -55,7 +55,7 @@
<p class="p3"><b>Links</b></p>
<p class="p4">Users:</p>
<p class="p5"><span class="s3">General information <a href="http://www.blender.org/"><span class="s4">www.blender.org</span></a> <br>
-Full release log <a href="http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.71"><span class="s4">wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.71</span></a><br>
+Full release log <a href="http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.72"><span class="s4">wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.72</span></a><br>
Tutorials <a href="http://www.blender.org/support/tutorials/"><span class="s4">www.blender.org/support/tutorials/</span></a> <br>
Manual <a href="http://wiki.blender.org/index.php/Doc:2.6/Manual"><span class="s4">wiki.blender.org/index.php/Doc:2.6/Manual</span></a><br>
User Forum <a href="http://www.blenderartists.org/"><span class="s4">www.blenderartists.org</span></a><br>
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 2bdae87dc83..4891c332c87 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -186,9 +186,9 @@ void blf_font_draw(FontBLF *font, const char *str, size_t len)
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
- if (c == BLI_UTF8_ERR)
+ if (UNLIKELY(c == BLI_UTF8_ERR))
break;
- if (g == NULL)
+ if (UNLIKELY(g == NULL))
continue;
if (has_kerning)
BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
@@ -196,7 +196,7 @@ void blf_font_draw(FontBLF *font, const char *str, size_t len)
/* do not return this loop if clipped, we want every character tested */
blf_glyph_render(font, g, (float)pen_x, (float)pen_y);
- pen_x += (int)g->advance;
+ pen_x += g->advance_i;
g_prev = g;
}
}
@@ -224,7 +224,7 @@ void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len)
/* do not return this loop if clipped, we want every character tested */
blf_glyph_render(font, g, (float)pen_x, (float)pen_y);
- pen_x += (int)g->advance;
+ pen_x += g->advance_i;
g_prev = g;
}
}
@@ -244,9 +244,9 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
- if (c == BLI_UTF8_ERR)
+ if (UNLIKELY(c == BLI_UTF8_ERR))
break;
- if (g == NULL)
+ if (UNLIKELY(g == NULL))
continue;
/* do not return this loop if clipped, we want every character tested */
@@ -303,9 +303,9 @@ void blf_font_buffer(FontBLF *font, const char *str)
while (str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
- if (c == BLI_UTF8_ERR)
+ if (UNLIKELY(c == BLI_UTF8_ERR))
break;
- if (g == NULL)
+ if (UNLIKELY(g == NULL))
continue;
if (has_kerning)
BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
@@ -415,7 +415,7 @@ void blf_font_buffer(FontBLF *font, const char *str)
}
}
- pen_x += (int)g->advance;
+ pen_x += g->advance_i;
g_prev = g;
}
}
@@ -438,14 +438,14 @@ size_t blf_font_width_to_strlen(FontBLF *font, const char *str, size_t len, floa
while ((i_prev = i), (width_new = pen_x), ((i < len) && str[i])) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
- if (c == BLI_UTF8_ERR)
+ if (UNLIKELY(c == BLI_UTF8_ERR))
break;
- if (g == NULL)
+ if (UNLIKELY(g == NULL))
continue;
if (has_kerning)
BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
- pen_x += (int)g->advance;
+ pen_x += g->advance_i;
if (width_i < pen_x) {
break;
@@ -501,14 +501,14 @@ size_t blf_font_width_to_rstrlen(FontBLF *font, const char *str, size_t len, flo
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
- if (c == BLI_UTF8_ERR)
+ if (UNLIKELY(c == BLI_UTF8_ERR))
break;
- if (g == NULL)
+ if (UNLIKELY(g == NULL))
continue;
if (has_kerning)
BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
- pen_x += (int)g->advance;
+ pen_x += g->advance_i;
width_accum[width_accum_ofs][0] = (int)i;
width_accum[width_accum_ofs][1] = pen_x;
@@ -570,9 +570,9 @@ void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *box)
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
- if (c == BLI_UTF8_ERR)
+ if (UNLIKELY(c == BLI_UTF8_ERR))
break;
- if (g == NULL)
+ if (UNLIKELY(g == NULL))
continue;
if (has_kerning)
BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
@@ -588,7 +588,7 @@ void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *box)
if (gbox.xmax > box->xmax) box->xmax = gbox.xmax;
if (gbox.ymax > box->ymax) box->ymax = gbox.ymax;
- pen_x += (int)g->advance;
+ pen_x += g->advance_i;
g_prev = g;
}
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 7c3cfa30e16..a2462f3e302 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -153,7 +153,7 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
/* move the index. */
gc->cur_tex++;
- if (gc->cur_tex >= gc->ntex) {
+ if (UNLIKELY(gc->cur_tex >= gc->ntex)) {
gc->ntex *= 2;
gc->textures = (GLuint *)MEM_reallocN((void *)gc->textures, sizeof(GLuint) * gc->ntex);
}
@@ -279,6 +279,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
}
g->advance = ((float)slot->advance.x) / 64.0f;
+ g->advance_i = (int)g->advance;
g->pos_x = (float)slot->bitmap_left;
g->pos_y = (float)slot->bitmap_top;
g->pitch = slot->bitmap.pitch;
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index c64b7e974e7..da756d65483 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -99,6 +99,8 @@ typedef struct GlyphBLF {
/* advance size. */
float advance;
+ /* avoid conversion to int while drawing */
+ int advance_i;
/* texture id where this glyph is store. */
GLuint tex;
diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c
index 2852b8161c8..12d71827136 100644
--- a/source/blender/blenfont/intern/blf_lang.c
+++ b/source/blender/blenfont/intern/blf_lang.c
@@ -235,15 +235,11 @@ void BLF_lang_set(const char *str)
else {
short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale);
}
+ bl_locale_set(short_locale_utf8);
+ MEM_freeN((void *)short_locale_utf8);
}
else {
- short_locale_utf8 = short_locale;
- }
-
- bl_locale_set(short_locale_utf8);
-
- if (short_locale[0]) {
- MEM_freeN((void *)short_locale_utf8);
+ bl_locale_set(short_locale);
}
#else
(void)str;
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 1ab5ec51de8..229d2fc17cd 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -150,8 +150,10 @@ typedef DMDrawOption (*DMSetDrawOptions)(void *userData, int index);
typedef DMDrawOption (*DMSetDrawOptionsTex)(struct MTFace *tface, const bool has_vcol, int matnr);
typedef enum DMDrawFlag {
- DM_DRAW_USE_COLORS = 1,
- DM_DRAW_ALWAYS_SMOOTH = 2
+ DM_DRAW_USE_COLORS = (1 << 0),
+ DM_DRAW_ALWAYS_SMOOTH = (1 << 1),
+ DM_DRAW_USE_ACTIVE_UV = (1 << 2),
+ DM_DRAW_USE_TEXPAINT_UV = (1 << 3),
} DMDrawFlag;
typedef enum DMForeachFlag {
@@ -389,7 +391,7 @@ struct DerivedMesh {
void (*drawFacesTex)(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData);
+ void *userData, DMDrawFlag uvflag);
/** Draw all faces with GLSL materials
* o setMaterial is called for every different material nr
@@ -423,7 +425,7 @@ struct DerivedMesh {
void (*drawMappedFacesTex)(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData);
+ void *userData, DMDrawFlag uvflag);
/** Draw mapped faces with GLSL materials
* - setMaterial is called for every different material nr
@@ -593,6 +595,8 @@ void DM_ensure_tessface(DerivedMesh *dm);
void DM_update_tessface_data(DerivedMesh *dm);
void DM_update_materials(DerivedMesh *dm, struct Object *ob);
+struct MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr);
+
/** interpolates vertex data from the vertices indexed by src_indices in the
* source mesh using the given weights and stores the result in the vertex
* indexed by dest_index in the dest mesh
@@ -647,6 +651,7 @@ void vDM_ColorBand_store(const struct ColorBand *coba, const char alert_color[4]
* In use now by vertex/weight paint and particles */
DMCoNo *mesh_get_mapped_verts_nors(struct Scene *scene, struct Object *ob);
#endif
+void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int totcos);
/* */
DerivedMesh *mesh_get_derived_final(struct Scene *scene, struct Object *ob,
@@ -687,6 +692,9 @@ DerivedMesh *editbmesh_get_derived_cage(struct Scene *scene, struct Object *,
DerivedMesh *editbmesh_get_derived_cage_and_final(struct Scene *scene, struct Object *,
struct BMEditMesh *em, DerivedMesh **r_final,
CustomDataMask dataMask);
+
+DerivedMesh *object_get_derived_final(struct Object *ob, const bool for_render);
+
float (*editbmesh_get_vertex_cos(struct BMEditMesh *em, int *r_numVerts))[3];
bool editbmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, DerivedMesh *dm);
void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct BMEditMesh *em,
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 0af45a147a4..46a0c36a5f2 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 271
-#define BLENDER_SUBVERSION 1
+#define BLENDER_SUBVERSION 6
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 5
@@ -69,10 +69,12 @@ int BKE_read_file(struct bContext *C, const char *filepath, struct ReportList *r
#define BKE_READ_FILE_OK 1 /* OK */
#define BKE_READ_FILE_OK_USERPREFS 2 /* OK, and with new user settings */
-int BKE_read_file_from_memory(struct bContext *C, const void *filebuf,
- int filelength, struct ReportList *reports, int update_defaults);
-int BKE_read_file_from_memfile(struct bContext *C, struct MemFile *memfile,
- struct ReportList *reports);
+bool BKE_read_file_from_memory(
+ struct bContext *C, const void *filebuf,
+ int filelength, struct ReportList *reports, bool update_defaults);
+bool BKE_read_file_from_memfile(
+ struct bContext *C, struct MemFile *memfile,
+ struct ReportList *reports);
int BKE_read_file_userdef(const char *filepath, struct ReportList *reports);
int BKE_write_file_userdef(const char *filepath, struct ReportList *reports);
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index 104e80e815c..d48753590bb 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -81,7 +81,11 @@ unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side, bool
/* radial control */
struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br, bool secondary);
-/* unified strength and size */
+/* unified strength size and color */
+
+float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush);
+float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush);
+void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3]);
int BKE_brush_size_get(const struct Scene *scene, struct Brush *brush);
void BKE_brush_size_set(struct Scene *scene, struct Brush *brush, int value);
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index dffc2b665c2..b0ade7bacdf 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -58,7 +58,13 @@ struct DerivedMesh *CDDM_from_bmesh(struct BMesh *bm, const bool use_mdisps);
DerivedMesh *CDDM_from_editbmesh(struct BMEditMesh *em, const bool use_mdisps, const bool use_tessface);
/* merge verts */
-DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap);
+/* Enum for merge_mode of CDDM_merge_verts.
+ * Refer to cdderivedmesh.c for details. */
+enum {
+ CDDM_MERGE_VERTS_DUMP_IF_MAPPED,
+ CDDM_MERGE_VERTS_DUMP_IF_EQUAL,
+};
+DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap, const int merge_mode);
/* creates a CDDerivedMesh from the given curve object */
struct DerivedMesh *CDDM_from_curve(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index e30c8ecee2b..877e376b343 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -234,7 +234,6 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas
struct Main *CTX_data_main(const bContext *C);
struct Scene *CTX_data_scene(const bContext *C);
struct ToolSettings *CTX_data_tool_settings(const bContext *C);
-struct FreestyleLineStyle *CTX_data_linestyle_from_scene(struct Scene *scene);
const char *CTX_data_mode_string(const bContext *C);
int CTX_data_mode_enum(const bContext *C);
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 0f9f8cb2f08..5de7d9936e6 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -84,9 +84,12 @@ 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], bool do_keys, const float unit_scale);
+void BKE_curve_transform(struct Curve *cu, float mat[4][4], bool do_keys);
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);
+int BKE_curve_material_index_validate(struct Curve *cu);
ListBase *BKE_curve_nurbs_get(struct Curve *cu);
@@ -110,6 +113,7 @@ struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu);
float *BKE_curve_make_orco(struct Scene *scene, struct Object *ob, int *r_numVerts);
float *BKE_curve_surf_make_orco(struct Object *ob);
+void BKE_curve_bevelList_free(struct ListBase *bev);
void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render);
void BKE_curve_bevel_make(struct Scene *scene, struct Object *ob, struct ListBase *disp,
const bool for_render, const bool use_render_resolution);
diff --git a/source/blender/blenkernel/BKE_editmesh_bvh.h b/source/blender/blenkernel/BKE_editmesh_bvh.h
index 355e817f621..168f700d132 100644
--- a/source/blender/blenkernel/BKE_editmesh_bvh.h
+++ b/source/blender/blenkernel/BKE_editmesh_bvh.h
@@ -43,9 +43,16 @@ struct Scene;
typedef struct BMBVHTree BMBVHTree;
-BMBVHTree *BKE_bmbvh_new_from_editmesh(struct BMEditMesh *em, int flag, const float (*cos_cage)[3], const bool cos_cage_free);
-BMBVHTree *BKE_bmbvh_new(struct BMesh *bm, struct BMLoop *(*looptris)[3], int looptris_tot, int flag,
- const float (*cos_cage)[3], const bool cos_cage_free);
+BMBVHTree *BKE_bmbvh_new_from_editmesh(
+ struct BMEditMesh *em, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free);
+BMBVHTree *BKE_bmbvh_new_ex(
+ struct BMesh *bm, struct BMLoop *(*looptris)[3], int looptris_tot, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free,
+ bool (*test_fn)(struct BMFace *, void *user_data), void *user_data);
+BMBVHTree *BKE_bmbvh_new(
+ struct BMesh *bm, struct BMLoop *(*looptris)[3], int looptris_tot, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free);
void BKE_bmbvh_free(BMBVHTree *tree);
struct BVHTree *BKE_bmbvh_tree_get(BMBVHTree *tree);
struct BMFace *BKE_bmbvh_ray_cast(BMBVHTree *tree, const float co[3], const float dir[3], const float radius,
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 3cf944fa236..2ab3d84dea5 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -121,13 +121,29 @@ void IDP_ClearProperty(IDProperty *prop);
void IDP_UnlinkProperty(struct IDProperty *prop);
#define IDP_Int(prop) ((prop)->data.val)
-#define IDP_Float(prop) (*(float *)&(prop)->data.val)
-#define IDP_Double(prop) (*(double *)&(prop)->data.val)
-#define IDP_String(prop) ((char *) (prop)->data.pointer)
#define IDP_Array(prop) ((prop)->data.pointer)
-#define IDP_IDPArray(prop) ((IDProperty *) (prop)->data.pointer)
+/* C11 const correctness for casts */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+# define IDP_Float(prop) _Generic((prop), \
+ IDProperty *: (*(float *)&(prop)->data.val), \
+ const IDProperty *: (*(const float *)&(prop)->data.val))
+# define IDP_Double(prop) _Generic((prop), \
+ IDProperty *: (*(double *)&(prop)->data.val), \
+ const IDProperty *: (*(const double *)&(prop)->data.val))
+# define IDP_String(prop) _Generic((prop), \
+ IDProperty *: ((char *) (prop)->data.pointer), \
+ const IDProperty *: ((const char *) (prop)->data.pointer))
+# define IDP_IDPArray(prop) _Generic((prop), \
+ IDProperty *: ((IDProperty *) (prop)->data.pointer), \
+ const IDProperty *: ((const IDProperty *) (prop)->data.pointer))
+#else
+# define IDP_Float(prop) (*(float *)&(prop)->data.val)
+# define IDP_Double(prop) (*(double *)&(prop)->data.val)
+# define IDP_String(prop) ((char *) (prop)->data.pointer)
+# define IDP_IDPArray(prop) ((IDProperty *) (prop)->data.pointer)
+#endif
-#ifdef DEBUG
+#ifndef NDEBUG
/* for printout only */
void IDP_spit(IDProperty *prop);
#endif
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 8d8d3702634..5fb1053b53f 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -84,6 +84,7 @@ void BKE_lattice_minmax(struct Lattice *lt, float min[3], float max[3]);
void BKE_lattice_center_median(struct Lattice *lt, float cent[3]);
void BKE_lattice_center_bounds(struct Lattice *lt, float cent[3]);
void BKE_lattice_translate(struct Lattice *lt, float offset[3], bool do_keys);
+void BKE_lattice_transform(struct Lattice *lt, float mat[4][4], bool do_keys);
int BKE_lattice_index_from_uvw(struct Lattice *lt, const int u, const int v, const int w);
void BKE_lattice_index_to_uvw(struct Lattice *lt, const int index, int *r_u, int *r_v, int *r_w);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 0372931dc49..1d37f9e64e1 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -71,7 +71,7 @@ void id_clear_lib_data(struct Main *bmain, struct ID *id);
struct ListBase *which_libbase(struct Main *mainlib, short type);
-#define MAX_LIBARRAY 41
+#define MAX_LIBARRAY 43
int set_listbasepointers(struct Main *main, struct ListBase **lb);
void BKE_libblock_free(struct Main *bmain, void *idv);
@@ -104,6 +104,7 @@ void test_idbutton(char *name);
void BKE_library_make_local(struct Main *bmain, struct Library *lib, bool untagged_only);
+struct ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void set_free_windowmanager_cb(void (*func)(struct bContext *, struct wmWindowManager *) );
diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h
index 8bc8cc44d92..ae10ba4caab 100644
--- a/source/blender/blenkernel/BKE_linestyle.h
+++ b/source/blender/blenkernel/BKE_linestyle.h
@@ -35,6 +35,10 @@
#include "DNA_linestyle_types.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define LS_MODIFIER_TYPE_COLOR 1
#define LS_MODIFIER_TYPE_ALPHA 2
#define LS_MODIFIER_TYPE_THICKNESS 3
@@ -43,34 +47,45 @@
struct Main;
struct Object;
struct ColorBand;
+struct bContext;
+
+FreestyleLineStyle *BKE_linestyle_new(const char *name, struct Main *main);
+void BKE_linestyle_free(FreestyleLineStyle *linestyle);
+FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle);
+
+FreestyleLineStyle *BKE_linestyle_active_from_scene(struct Scene *scene);
+
+LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type);
+LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type);
+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);
-FreestyleLineStyle *BKE_new_linestyle(const char *name, struct Main *main);
-void BKE_free_linestyle(FreestyleLineStyle *linestyle);
-FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle);
+int BKE_linestyle_color_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
+int BKE_linestyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
+int BKE_linestyle_thickness_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
+int BKE_linestyle_geometry_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
-LineStyleModifier *BKE_add_linestyle_color_modifier(FreestyleLineStyle *linestyle, const char *name, int type);
-LineStyleModifier *BKE_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, const char *name, int type);
-LineStyleModifier *BKE_add_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, const char *name, int type);
-LineStyleModifier *BKE_add_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, const char *name, int type);
+void BKE_linestyle_color_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
+void BKE_linestyle_alpha_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
+void BKE_linestyle_thickness_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
+void BKE_linestyle_geometry_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
-LineStyleModifier *BKE_copy_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m);
-LineStyleModifier *BKE_copy_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m);
-LineStyleModifier *BKE_copy_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m);
-LineStyleModifier *BKE_copy_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m);
+void BKE_linestyle_modifier_list_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase);
+char *BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle, struct ColorBand *color_ramp);
-int BKE_remove_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
-int BKE_remove_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
-int BKE_remove_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
-int BKE_remove_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
+void BKE_linestyle_target_object_unlink(FreestyleLineStyle *linestyle, struct Object *ob);
-void BKE_move_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
-void BKE_move_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
-void BKE_move_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
-void BKE_move_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
+bool BKE_linestyle_use_textures(FreestyleLineStyle *linestyle, const bool use_shading_nodes);
-void BKE_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase);
-char *BKE_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, struct ColorBand *color_ramp);
+void BKE_linestyle_default_shader(const struct bContext *C, FreestyleLineStyle *linestyle);
-void BKE_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Object *ob);
+#ifdef __cplusplus
+}
+#endif
#endif /* __BKE_LINESTYLE_H__ */
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 82b03127237..ec654ea4b71 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -87,6 +87,8 @@ typedef struct Main {
ListBase nodetree;
ListBase brush;
ListBase particle;
+ ListBase palettes;
+ ListBase paintcurves;
ListBase wm;
ListBase gpencil;
ListBase movieclip;
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 89d310753fc..2f20505bea3 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -86,6 +86,9 @@ short find_material_index(struct Object *ob, struct Material *ma);
bool object_add_material_slot(struct Object *ob);
bool object_remove_material_slot(struct Object *ob);
+void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma);
+void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob);
+
/* rna api */
void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user);
void BKE_material_append_id(struct ID *id, struct Material *ma);
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index 56ea44fa6e9..c021960e730 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -63,6 +63,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_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 587dea5095c..b2b9e37f500 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -133,6 +133,7 @@ struct Mesh *BKE_mesh_new_from_object(struct Main *bmain, struct Scene *sce, str
/* vertex level transformations & checks (no derived mesh) */
bool BKE_mesh_minmax(struct Mesh *me, float r_min[3], float r_max[3]);
+void BKE_mesh_transform(struct Mesh *me, float mat[4][4], bool do_keys);
void BKE_mesh_translate(struct Mesh *me, const float offset[3], const bool do_keys);
void BKE_mesh_ensure_navmesh(struct Mesh *me);
@@ -212,6 +213,10 @@ bool BKE_mesh_center_median(struct Mesh *me, float cent[3]);
bool BKE_mesh_center_bounds(struct Mesh *me, float cent[3]);
bool BKE_mesh_center_centroid(struct Mesh *me, float cent[3]);
+void BKE_mesh_calc_volume(struct MVert *mverts, int numVerts,
+ struct MFace *mfaces, int numFaces,
+ float *r_vol, float *r_com);
+
/* tessface */
void BKE_mesh_loops_to_mface_corners(
struct CustomData *fdata, struct CustomData *ldata,
@@ -283,6 +288,7 @@ void BKE_mesh_calc_relative_deform(
int BKE_mesh_validate(struct Mesh *me, const int do_verbose);
void BKE_mesh_cd_validate(struct Mesh *me);
+int BKE_mesh_validate_material_indices(struct Mesh *me);
bool BKE_mesh_validate_arrays(
struct Mesh *me,
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index c81133a85fa..cb96538ad81 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -342,7 +342,7 @@ struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char
/* copy/free funcs, need to manage ID users */
void ntreeFreeTree_ex(struct bNodeTree *ntree, const bool do_id_user);
void ntreeFreeTree(struct bNodeTree *ntree);
-struct bNodeTree *ntreeCopyTree_ex(struct bNodeTree *ntree, const bool do_id_user);
+struct bNodeTree *ntreeCopyTree_ex(struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user);
struct bNodeTree *ntreeCopyTree(struct bNodeTree *ntree);
void ntreeSwitchID_ex(struct bNodeTree *ntree, struct ID *sce_from, struct ID *sce_to, const bool do_id_user);
void ntreeSwitchID(struct bNodeTree *ntree, struct ID *sce_from, struct ID *sce_to);
@@ -585,6 +585,9 @@ void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufu
void node_type_internal_links(struct bNodeType *ntype, void (*update_internal_links)(struct bNodeTree *, struct bNode *));
void node_type_compatibility(struct bNodeType *ntype, short compatibility);
+/* ************** GENERIC NODE FUNCTIONS *************** */
+bool BKE_node_is_connected_to_output(struct bNodeTree *ntree, struct bNode *node);
+
/* ************** COMMON NODES *************** */
#define NODE_UNDEFINED -2 /* node type is not registered */
@@ -749,6 +752,8 @@ struct ShadeResult;
#define SH_NODE_UVMAP 187
#define SH_NODE_SEPXYZ 188
#define SH_NODE_COMBXYZ 189
+#define SH_NODE_OUTPUT_LINESTYLE 190
+#define SH_NODE_UVALONGSTROKE 191
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
@@ -891,6 +896,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
#define CMP_NODE_GLARE 301
#define CMP_NODE_TONEMAP 302
#define CMP_NODE_LENSDIST 303
+#define CMP_NODE_SUNBEAMS 304
#define CMP_NODE_COLORCORRECTION 312
#define CMP_NODE_MASK_BOX 313
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index c0da816ca59..1bfd26d4f8c 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -103,6 +103,8 @@ void BKE_object_make_local(struct Object *ob);
bool BKE_object_is_libdata(struct Object *ob);
bool BKE_object_obdata_is_libdata(struct Object *ob);
+void BKE_object_obdata_size_init(struct Object *ob, const float scale);
+
void BKE_object_scale_to_mat3(struct Object *ob, float mat[3][3]);
void BKE_object_rot_to_mat3(struct Object *ob, float mat[3][3], bool use_drot);
void BKE_object_mat3_to_rot(struct Object *ob, float mat[3][3], bool use_compat);
@@ -124,14 +126,18 @@ void BKE_object_where_is_calc_mat4(struct Scene *scene, struct Object *ob, float
/* possibly belong in own moduke? */
struct BoundBox *BKE_boundbox_alloc_unit(void);
void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], const float max[3]);
-bool BKE_boundbox_ray_hit_check(struct BoundBox *bb, const float ray_start[3], const float ray_normal[3],
- float *r_lambda);
+bool BKE_boundbox_ray_hit_check(
+ const struct BoundBox *bb,
+ const float ray_start[3], const float ray_normal[3],
+ float *r_lambda);
+void BKE_boundbox_calc_center_aabb(const struct BoundBox *bb, float r_cent[3]);
+void BKE_boundbox_calc_size_aabb(const struct BoundBox *bb, float r_size[3]);
struct BoundBox *BKE_object_boundbox_get(struct Object *ob);
void BKE_object_dimensions_get(struct Object *ob, float vec[3]);
void BKE_object_dimensions_set(struct Object *ob, const float value[3]);
void BKE_object_empty_draw_type_set(struct Object *ob, const int value);
-void BKE_object_boundbox_flag(struct Object *ob, int flag, int set);
+void BKE_object_boundbox_flag(struct Object *ob, int flag, const bool set);
void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden);
bool BKE_object_minmax_dupli(struct Scene *scene, struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 43813300850..a81da8c18af 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -40,11 +40,15 @@ struct CurveMapping;
struct MDisps;
struct MeshElemMap;
struct GridPaintMask;
+struct Main;
struct MFace;
struct MultireModifierData;
struct MVert;
struct Object;
struct Paint;
+struct PaintCurve;
+struct Palette;
+struct PaletteColor;
struct PBVH;
struct Scene;
struct Sculpt;
@@ -52,6 +56,7 @@ struct StrokeCache;
struct Tex;
struct ImagePool;
struct UnifiedPaintSettings;
+struct wmOperator;
enum OverlayFlags;
@@ -91,6 +96,19 @@ OverlayControlFlags BKE_paint_get_overlay_flags(void);
void BKE_paint_reset_overlay_invalid(OverlayControlFlags flag);
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 PaletteColor *BKE_palette_color_add(struct Palette *palette);
+void BKE_palette_color_delete(struct Palette *palette);
+bool BKE_palette_is_empty(const struct Palette *palette);
+void BKE_palette_color_remove(struct Palette *palette, struct PaletteColor *color);
+void BKE_palette_cleanup(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);
+
void BKE_paint_init(struct Paint *p, const char col[3]);
void BKE_paint_free(struct Paint *p);
void BKE_paint_copy(struct Paint *src, struct Paint *tar);
@@ -100,6 +118,9 @@ struct Paint *BKE_paint_get_active_from_context(const struct bContext *C);
PaintMode BKE_paintmode_get_active_from_context(const struct bContext *C);
struct Brush *BKE_paint_brush(struct Paint *paint);
void BKE_paint_brush_set(struct Paint *paint, struct Brush *br);
+struct Palette *BKE_paint_palette(struct Paint *paint);
+void BKE_paint_palette_set(struct Paint *p, struct Palette *palette);
+void BKE_paint_curve_set(struct Brush *br, struct PaintCurve *pc);
/* testing face select mode
* Texture paint could be removed since selected faces are not used
@@ -117,7 +138,10 @@ bool paint_is_bmesh_face_hidden(struct BMFace *f);
/* paint masks */
float paint_grid_paint_mask(const struct GridPaintMask *gpm, unsigned level,
unsigned x, unsigned y);
+
+/* stroke related */
void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, const float mouse_pos[2]);
+
/* Session data (mode-specific) */
typedef struct SculptSession {
@@ -146,7 +170,7 @@ typedef struct SculptSession {
struct PBVH *pbvh;
bool show_diffuse_color;
- /* Paiting on deformed mesh */
+ /* Painting on deformed mesh */
bool modifiers_active; /* object is deformed with some modifiers */
float (*orig_cos)[3]; /* coords of undeformed mesh */
float (*deform_cos)[3]; /* coords of deformed mesh but without stroke displacement */
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index 86be3bfe770..c946f3ac9e8 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -69,6 +69,9 @@ void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw);
/* 'validate' (i.e. make new or replace old) Physics-Engine objects */
void BKE_rigidbody_validate_sim_world(struct Scene *scene, struct RigidBodyWorld *rbw, bool rebuild);
+void BKE_rigidbody_calc_volume(struct Object *ob, float *r_vol);
+void BKE_rigidbody_calc_center_of_mass(struct Object *ob, float r_com[3]);
+
/* -------------- */
/* Utilities */
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index a10a3f3f59f..1bfe0eeea0b 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -48,6 +48,7 @@ struct RenderData;
struct SceneRenderLayer;
struct Scene;
struct Text;
+struct UnitSettings;
struct Main;
#define SCE_COPY_NEW 0
@@ -84,6 +85,7 @@ typedef struct SceneBaseIter {
struct ListBase *duplilist;
struct DupliObject *dupob;
float omat[4][4];
+ struct Object *dupli_refob;
int phase;
} SceneBaseIter;
@@ -129,6 +131,7 @@ int get_render_shadow_samples(struct RenderData *r, int samples);
float get_render_aosss_error(struct RenderData *r, float error);
bool BKE_scene_use_new_shading_nodes(struct Scene *scene);
+bool BKE_scene_uses_blender_internal(struct Scene *scene);
void BKE_scene_disable_color_management(struct Scene *scene);
bool BKE_scene_check_color_management_enabled(const struct Scene *scene);
@@ -137,6 +140,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);
+double BKE_scene_unit_scale(const struct UnitSettings *unit, const int unit_type, double value);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 4cbd7e966f2..188b8e22815 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -53,6 +53,8 @@ struct wmNotifier;
struct wmWindow;
struct wmWindowManager;
+#include "BLI_compiler_attrs.h"
+
#include "RNA_types.h"
/* spacetype has everything stored to get an editor working, it gets initialized via
@@ -280,6 +282,11 @@ struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type);
struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype, const short min);
+unsigned int BKE_screen_view3d_layer_active_ex(
+ const struct View3D *v3d, const struct Scene *scene, bool use_localvd) ATTR_NONNULL(2);
+unsigned int BKE_screen_view3d_layer_active(
+ const struct View3D *v3d, const struct Scene *scene) ATTR_NONNULL(2);
+
void BKE_screen_view3d_sync(struct View3D *v3d, struct Scene *scene);
void BKE_screen_view3d_scene_sync(struct bScreen *sc);
void BKE_screen_view3d_main_sync(ListBase *screen_lb, struct Scene *scene);
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index de52c72a136..13cc5d2e84f 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -308,7 +308,7 @@ void BKE_sequencer_offset_animdata(struct Scene *scene, struct Sequence *seq, in
void BKE_sequencer_dupe_animdata(struct Scene *scene, const char *name_src, const char *name_dst);
bool BKE_sequence_base_shuffle(struct ListBase *seqbasep, struct Sequence *test, struct Scene *evil_scene);
bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, struct Scene *evil_scene);
-bool BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase);
+bool BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase, bool one_only);
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);
int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str);
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index 59de43af907..070cd4a9cf0 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -31,52 +31,6 @@
* \ingroup bke
*/
-/* mesh util */
-
-//TODO: move this somewhere else
-#include "BKE_customdata.h"
-struct DerivedMesh;
-struct Object;
-struct DerivedMesh *object_get_derived_final(struct Object *ob, bool for_render);
-
-
-/* SpaceTransform stuff */
-/*
- * TODO: move this somewhere else
- *
- * this structs encapsulates all needed data to convert between 2 coordinate spaces
- * (where conversion can be represented by a matrix multiplication)
- *
- * This is used to reduce the number of arguments to pass to functions that need to perform
- * this kind of operation and make it easier for the coder, as he/she doenst needs to recode
- * the matrix calculation.
- *
- * A SpaceTransform is initialized using:
- * SPACE_TRANSFORM_SETUP( &data, ob1, ob2 )
- *
- * After that the following calls can be used:
- * space_transform_apply (&data, co); //converts a coordinate in ob1 coords space to the corresponding ob2 coords
- * space_transform_invert(&data, co); //converts a coordinate in ob2 coords space to the corresponding ob1 coords
- *
- * //Same Concept as space_transform_apply and space_transform_invert, but no is normalized after conversion
- * space_transform_apply_normal (&data, &no);
- * space_transform_invert_normal(&data, &no);
- *
- */
-struct Object;
-
-typedef struct SpaceTransform {
- float local2target[4][4];
- float target2local[4][4];
-
-} SpaceTransform;
-
-void space_transform_from_matrixs(struct SpaceTransform *data, float local[4][4], float target[4][4]);
-void space_transform_apply(const struct SpaceTransform *data, float co[3]);
-void space_transform_invert(const struct SpaceTransform *data, float co[3]);
-
-#define SPACE_TRANSFORM_SETUP(data, local, target) space_transform_from_matrixs(data, (local)->obmat, (target)->obmat)
-
/* Shrinkwrap stuff */
#include "BKE_bvhutils.h"
@@ -100,6 +54,7 @@ struct MDeformVert;
struct ShrinkwrapModifierData;
struct MDeformVert;
struct BVHTree;
+struct SpaceTransform;
typedef struct ShrinkwrapCalcData {
@@ -115,7 +70,7 @@ typedef struct ShrinkwrapCalcData {
int vgroup; //Vertex group num
struct DerivedMesh *target; //mesh we are shrinking to
- SpaceTransform local2target; //transform to move between local and target space
+ struct SpaceTransform local2target; //transform to move between local and target space
float keepDist; //Distance to keep above target surface (units are in local space)
@@ -136,7 +91,7 @@ void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object
*/
bool BKE_shrinkwrap_project_normal(
char options, const float vert[3], const float dir[3],
- const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit,
+ const struct SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit,
BVHTree_RayCastCallback callback, void *userdata);
/*
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index 4f77e4f5a23..1e79eaa8431 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -85,6 +85,7 @@ void txt_delete_char (struct Text *text);
void txt_delete_word (struct Text *text);
void txt_delete_selected (struct Text *text);
void txt_sel_all (struct Text *text);
+void txt_sel_clear (struct Text *text);
void txt_sel_line (struct Text *text);
char *txt_sel_to_buf (struct Text *text);
void txt_insert_buf (struct Text *text, const char *in_buffer);
diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h
index 598817298b8..b351bc6fe3e 100644
--- a/source/blender/blenkernel/BKE_unit.h
+++ b/source/blender/blenkernel/BKE_unit.h
@@ -37,7 +37,7 @@ extern "C" {
size_t bUnit_AsString(char *str, int len_max, double value, int prec, int system, int type, bool split, bool pad);
/* replace units with values, used before python button evaluation */
-int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type);
+bool bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type);
/* make string keyboard-friendly: 10µm --> 10um */
void bUnit_ToUnitAltName(char *str, int len_max, const char *orig_str, int system, int type);
@@ -49,7 +49,7 @@ double bUnit_ClosestScalar(double value, int system, int type);
double bUnit_BaseScalar(int system, int type);
/* return true is the unit system exists */
-int bUnit_IsValid(int system, int type);
+bool bUnit_IsValid(int system, int type);
/* loop over scales, coudl add names later */
//double bUnit_Iter(void **unit, char **name, int system, int type);
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index 6cda0a1bc33..623fb50b62c 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -119,7 +119,7 @@ static void _ehash_insert(EHash *eh, EHEntry *entry)
eh->buckets[hash] = entry;
eh->numEntries++;
- if (eh->numEntries > (numBuckets * 3)) {
+ if (UNLIKELY(eh->numEntries > (numBuckets * 3))) {
EHEntry **oldBuckets = eh->buckets;
eh->curSize = kHashSizes[++eh->curSizeIdx];
@@ -1274,7 +1274,7 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV
CCGFace *f = NULL, *fNew;
int j, k, topologyChanged = 0;
- if (numVerts > ss->lenTempArrays) {
+ if (UNLIKELY(numVerts > ss->lenTempArrays)) {
ss->lenTempArrays = (numVerts < ss->lenTempArrays * 2) ? ss->lenTempArrays * 2 : numVerts;
ss->tempVerts = MEM_reallocN(ss->tempVerts, sizeof(*ss->tempVerts) * ss->lenTempArrays);
ss->tempEdges = MEM_reallocN(ss->tempEdges, sizeof(*ss->tempEdges) * ss->lenTempArrays);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index a70238da34e..52ded77b117 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -37,12 +37,14 @@
#include "DNA_cloth_types.h"
#include "DNA_key_types.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
+#include "BLI_bitmap.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
@@ -500,11 +502,36 @@ void DM_update_materials(DerivedMesh *dm, Object *ob)
dm->mat = MEM_callocN(totmat * sizeof(*dm->mat), "DerivedMesh.mat");
- for (i = 1; i < totmat; i++) {
- dm->mat[i] = give_current_material(ob, i);
+ /* we leave last material as empty - rationale here is being able to index
+ * the materials by using the mf->mat_nr directly and leaving the last
+ * material as NULL in case no materials exist on mesh, so indexing will not fail */
+ for (i = 0; i < totmat - 1; i++) {
+ dm->mat[i] = give_current_material(ob, i + 1);
}
}
+MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr)
+{
+ MTFace *tf_base;
+
+ BLI_assert(mat_nr < dm->totmat);
+
+ if (dm->mat[mat_nr] && dm->mat[mat_nr]->texpaintslot &&
+ dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname)
+ {
+ tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
+ dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname);
+ /* This can fail if we have changed the name in the UV layer list and have assigned the old name in the material
+ * texture slot.*/
+ if (!tf_base)
+ tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ }
+ else {
+ tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ }
+
+ return tf_base;
+}
void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask)
{
@@ -1107,7 +1134,7 @@ static void weightpaint_color(unsigned char r_col[4], DMWeightColorInfo *dm_wcin
static void calc_weightpaint_vert_color(
unsigned char r_col[4],
- MDeformVert *dv,
+ const MDeformVert *dv,
DMWeightColorInfo *dm_wcinfo,
const int defbase_tot, const int defbase_act,
const bool *defbase_sel, const int defbase_sel_tot,
@@ -1122,7 +1149,7 @@ static void calc_weightpaint_vert_color(
bool was_a_nonzero = false;
unsigned int i;
- MDeformWeight *dw = dv->dw;
+ const MDeformWeight *dw = dv->dw;
for (i = dv->totweight; i != 0; i--, dw++) {
/* in multipaint, get the average if auto normalize is inactive
* get the sum if it is active */
@@ -1995,9 +2022,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
previewmd = modifiers_getLastPreview(scene, md, required_mode);
/* even if the modifier doesn't need the data, to make a preview it may */
if (previewmd) {
- if (do_mod_wmcol) {
- previewmask = CD_MASK_MDEFORMVERT;
- }
+ previewmask = CD_MASK_MDEFORMVERT;
}
}
@@ -2473,6 +2498,28 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em)
return getEditDerivedBMesh(em, obedit, NULL);
}
+/***/
+
+/* get derived mesh from an object, using editbmesh if available. */
+DerivedMesh *object_get_derived_final(Object *ob, const bool for_render)
+{
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+
+ if (for_render) {
+ /* TODO(sergey): use proper derived render here in the future. */
+ return ob->derivedFinal;
+ }
+
+ if (em) {
+ DerivedMesh *dm = em->derivedFinal;
+ return dm;
+ }
+
+ return ob->derivedFinal;
+}
+
+
/* UNUSED */
#if 0
@@ -2533,6 +2580,46 @@ DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
#endif
+/* same as above but for vert coords */
+typedef struct {
+ float (*vertexcos)[3];
+ BLI_bitmap *vertex_visit;
+} MappedUserData;
+
+static void make_vertexcos__mapFunc(void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+ MappedUserData *mappedData = (MappedUserData *)userData;
+
+ if (BLI_BITMAP_TEST(mappedData->vertex_visit, index) == 0) {
+ /* we need coord from prototype vertex, not from copies,
+ * assume they stored in the beginning of vertex array stored in DM
+ * (mirror modifier for eg does this) */
+ copy_v3_v3(mappedData->vertexcos[index], co);
+ BLI_BITMAP_ENABLE(mappedData->vertex_visit, index);
+ }
+}
+
+void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int totcos)
+{
+ float (*vertexcos)[3];
+
+ if (dm->foreachMappedVert) {
+ MappedUserData userData;
+ memset(r_cos, 0, sizeof(r_cos) * totcos);
+ userData.vertexcos = r_cos;
+ userData.vertex_visit = BLI_BITMAP_NEW(totcos, "vertexcos flags");
+ dm->foreachMappedVert(dm, make_vertexcos__mapFunc, &userData, DM_FOREACH_NOP);
+ MEM_freeN(userData.vertex_visit);
+ }
+ else {
+ int i;
+ for (i = 0; i < totcos; i++) {
+ dm->getVertCo(dm, i, vertexcos[i]);
+ }
+ }
+}
+
/* ******************* GLSL ******************** */
typedef struct {
@@ -3090,7 +3177,7 @@ static void navmesh_drawColored(DerivedMesh *dm)
static void navmesh_DM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag UNUSED(flag))
{
(void) setDrawOptions;
(void) compareDrawOptions;
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 8f1382dacc3..c6dcca576fb 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -315,7 +315,7 @@ bActionGroup *action_groups_add_new(bAction *act, const char name[])
void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve)
{
/* sanity checks */
- if (ELEM3(NULL, act, agrp, fcurve))
+ if (ELEM(NULL, act, agrp, fcurve))
return;
/* if no channels anywhere, just add to two lists at the same time */
@@ -417,7 +417,7 @@ void action_groups_remove_channel(bAction *act, FCurve *fcu)
bActionGroup *BKE_action_group_find_name(bAction *act, const char name[])
{
/* sanity checks */
- if (ELEM3(NULL, act, act->groups.first, name) || (name[0] == 0))
+ if (ELEM(NULL, act, act->groups.first, name) || (name[0] == 0))
return NULL;
/* do string comparisons */
@@ -526,7 +526,7 @@ bPoseChannel *BKE_pose_channel_active(Object *ob)
bArmature *arm = (ob) ? ob->data : NULL;
bPoseChannel *pchan;
- if (ELEM3(NULL, ob, ob->pose, arm)) {
+ if (ELEM(NULL, ob, ob->pose, arm)) {
return NULL;
}
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 995b2ac5321..5ee82bb5842 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -405,7 +405,7 @@ void action_move_fcurves_by_basepath(bAction *srcAct, bAction *dstAct, const cha
FCurve *fcu, *fcn = NULL;
/* sanity checks */
- if (ELEM3(NULL, srcAct, dstAct, basepath)) {
+ if (ELEM(NULL, srcAct, dstAct, basepath)) {
if (G.debug & G_DEBUG) {
printf("ERROR: action_partition_fcurves_by_basepath(%p, %p, %p) has insufficient info to work with\n",
(void *)srcAct, (void *)dstAct, (void *)basepath);
@@ -1062,7 +1062,7 @@ KS_Path *BKE_keyingset_find_path(KeyingSet *ks, ID *id, const char group_name[],
KS_Path *ksp;
/* sanity checks */
- if (ELEM3(NULL, ks, rna_path, id))
+ if (ELEM(NULL, ks, rna_path, id))
return NULL;
/* loop over paths in the current KeyingSet, finding the first one where all settings match
@@ -2338,6 +2338,17 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData
/* 3. free temporary evaluation data that's not used elsewhere */
BLI_freelistN(&estrips);
+
+ /* Tag ID as updated so render engines will recognize changes in data
+ * which is animated but doesn't have actions.
+ */
+ if (ptr->id.data != NULL) {
+ ID *id = ptr->id.data;
+ if (!(id->flag & LIB_ANIM_NO_RECALC)) {
+ id->flag |= LIB_ID_RECALC;
+ DAG_id_type_tag(G.main, GS(id->name));
+ }
+ }
}
/* NLA Evaluation function (mostly for use through do_animdata)
@@ -2392,7 +2403,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt)
/* Overview of how this system works:
* 1) Depsgraph sorts data as necessary, so that data is in an order that means
- * that all dependencies are resolved before dependants.
+ * that all dependencies are resolved before dependents.
* 2) All normal animation is evaluated, so that drivers have some basis values to
* work with
* a. NLA stacks are done first, as the Active Actions act as 'tweaking' tracks
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 95f8426872d..16b5574709e 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -574,7 +574,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
if (do_scale) {
/* correct for scaling when this matrix is used in scaled space */
- mul_serie_m4(result_array[a].mat, iscalemat, result_array[a].mat, scalemat, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(result_array[a].mat, iscalemat, result_array[a].mat, scalemat);
}
}
}
@@ -622,8 +622,7 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info
invert_m4_m4(tmat, b_bone_rest[a].mat);
- mul_serie_m4(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat,
- NULL, NULL, NULL);
+ mul_m4_series(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat);
if (use_quaternion)
mat4_to_dquat(&b_bone_dual_quats[a], bone->arm_mat, b_bone_mats[a + 1].mat);
@@ -1042,7 +1041,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float
if (!use_quaternion) /* quaternion already is scale corrected */
mul_m3_fl(smat, armature_weight / contrib);
- mul_serie_m3(defMats[i], tmpmat, pre, smat, post, NULL, NULL, NULL, NULL);
+ mul_m3_series(defMats[i], post, smat, pre, tmpmat);
}
}
@@ -1881,7 +1880,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
*/
/* only happens on reload file, but violates depsgraph still... fix! */
- if (ELEM3(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
+ if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
BKE_displist_make_curveTypes(scene, ikData->tar, 0);
/* path building may fail in EditMode after removing verts [#33268]*/
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 9be9db77d39..fff8265a158 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -170,7 +170,7 @@ static void clear_global(void)
static bool clean_paths_visit_cb(void *UNUSED(userdata), char *path_dst, const char *path_src)
{
strcpy(path_dst, path_src);
- BLI_clean(path_dst);
+ BLI_path_native_slash(path_dst);
return !STREQ(path_dst, path_src);
}
@@ -182,7 +182,7 @@ static void clean_paths(Main *main)
BKE_bpath_traverse_main(main, clean_paths_visit_cb, BKE_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL);
for (scene = main->scene.first; scene; scene = scene->id.next) {
- BLI_clean(scene->r.pic);
+ BLI_path_native_slash(scene->r.pic);
}
}
@@ -479,7 +479,9 @@ int BKE_read_file(bContext *C, const char *filepath, ReportList *reports)
return (bfd ? retval : BKE_READ_FILE_FAIL);
}
-int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength, ReportList *reports, int update_defaults)
+bool BKE_read_file_from_memory(
+ bContext *C, const void *filebuf, int filelength,
+ ReportList *reports, bool update_defaults)
{
BlendFileData *bfd;
@@ -496,7 +498,9 @@ int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength,
}
/* memfile is the undo buffer */
-int BKE_read_file_from_memfile(bContext *C, MemFile *memfile, ReportList *reports)
+bool BKE_read_file_from_memfile(
+ bContext *C, MemFile *memfile,
+ ReportList *reports)
{
BlendFileData *bfd;
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index dc2d0924bba..3cd26dacebd 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -107,7 +107,7 @@ typedef struct BPathRemap_Data {
int count_failed;
} BPathRemap_Data;
-static bool makeFilesRelative_visit_cb(void *userdata, char *path_dst, const char *path_src)
+static bool bpath_relative_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
{
BPathRemap_Data *data = (BPathRemap_Data *)userdata;
@@ -133,6 +133,7 @@ static bool makeFilesRelative_visit_cb(void *userdata, char *path_dst, const cha
void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports)
{
BPathRemap_Data data = {NULL};
+ const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
if (basedir[0] == '\0') {
printf("%s: basedir='', this is a bug\n", __func__);
@@ -142,14 +143,14 @@ void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *re
data.basedir = basedir;
data.reports = reports;
- BKE_bpath_traverse_main(bmain, makeFilesRelative_visit_cb, 0, (void *)&data);
+ BKE_bpath_traverse_main(bmain, bpath_relative_convert_visit_cb, flag, (void *)&data);
BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
"Total files %d | Changed %d | Failed %d",
data.count_tot, data.count_changed, data.count_failed);
}
-static bool makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const char *path_src)
+static bool bpath_absolute_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
{
BPathRemap_Data *data = (BPathRemap_Data *)userdata;
@@ -176,6 +177,7 @@ static bool makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const cha
void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports)
{
BPathRemap_Data data = {NULL};
+ const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
if (basedir[0] == '\0') {
printf("%s: basedir='', this is a bug\n", __func__);
@@ -185,7 +187,7 @@ void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *re
data.basedir = basedir;
data.reports = reports;
- BKE_bpath_traverse_main(bmain, makeFilesAbsolute_visit_cb, 0, (void *)&data);
+ BKE_bpath_traverse_main(bmain, bpath_absolute_convert_visit_cb, flag, (void *)&data);
BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
"Total files %d | Changed %d | Failed %d",
@@ -422,7 +424,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
Image *ima;
ima = (Image *)id;
if (ima->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
- if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
+ if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) {
if (!ima->packedfile) {
BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 967e89e0dd1..76b0cad337f 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -83,6 +83,7 @@ static void brush_defaults(Brush *brush)
brush->plane_trim = 0.5f;
brush->clone.alpha = 0.5f;
brush->normal_weight = 0.0f;
+ brush->fill_threshold = 0.2f;
brush->flag |= BRUSH_ALPHA_PRESSURE;
/* BRUSH PAINT TOOL SETTINGS */
@@ -90,6 +91,8 @@ static void brush_defaults(Brush *brush)
brush->rgb[1] = 1.0f;
brush->rgb[2] = 1.0f;
+ zero_v3(brush->secondary_rgb);
+
/* BRUSH STROKE SETTINGS */
brush->flag |= (BRUSH_SPACE | BRUSH_SPACE_ATTEN);
brush->spacing = 10; /* how far each brush dot should be spaced as a percentage of brush diameter */
@@ -161,6 +164,9 @@ Brush *BKE_brush_copy(Brush *brush)
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);
@@ -180,11 +186,9 @@ Brush *BKE_brush_copy(Brush *brush)
/* not brush itself */
void BKE_brush_free(Brush *brush)
{
- if (brush->mtex.tex)
- brush->mtex.tex->id.us--;
-
- if (brush->mask_mtex.tex)
- brush->mask_mtex.tex->id.us--;
+ id_us_min((ID *)brush->mtex.tex);
+ id_us_min((ID *)brush->mask_mtex.tex);
+ id_us_min((ID *)brush->paint_curve);
if (brush->icon_imbuf)
IMB_freeImBuf(brush->icon_imbuf);
@@ -192,6 +196,9 @@ void BKE_brush_free(Brush *brush)
BKE_previewimg_free(&(brush->preview));
curvemapping_free(brush->curve);
+
+ if (brush->gradient)
+ MEM_freeN(brush->gradient);
}
static void extern_local_brush(Brush *brush)
@@ -199,6 +206,7 @@ static void extern_local_brush(Brush *brush)
id_lib_extern((ID *)brush->mtex.tex);
id_lib_extern((ID *)brush->mask_mtex.tex);
id_lib_extern((ID *)brush->clone.image);
+ id_lib_extern((ID *)brush->paint_curve);
}
void BKE_brush_make_local(Brush *brush)
@@ -742,10 +750,23 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
}
+ CLAMP(intensity, 0.0f, 1.0f);
+
+ switch (br->mask_pressure) {
+ case BRUSH_MASK_PRESSURE_CUTOFF:
+ intensity = ((1.0f - intensity) < ups->size_pressure_value) ? 1.0f : 0.0f;
+ break;
+ case BRUSH_MASK_PRESSURE_RAMP:
+ intensity = ups->size_pressure_value + intensity * (1.0f - ups->size_pressure_value);
+ break;
+ default:
+ break;
+ }
+
return intensity;
}
-/* Unified Size and Strength */
+/* Unified Size / Strength / Color */
/* XXX: be careful about setting size and unprojected radius
* because they depend on one another
@@ -760,6 +781,29 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
* In any case, a better solution is needed to prevent
* inconsistency. */
+
+float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush)
+{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->rgb : brush->rgb;
+}
+
+float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush)
+{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->secondary_rgb : brush->secondary_rgb;
+}
+
+void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3])
+{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+
+ if (ups->flag & UNIFIED_PAINT_COLOR)
+ copy_v3_v3(ups->rgb, color);
+ else
+ copy_v3_v3(brush->rgb, color);
+}
+
void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
@@ -886,39 +930,27 @@ void BKE_brush_scale_size(int *r_brush_size,
void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2], float jitterpos[2])
{
- int use_jitter = (brush->flag & BRUSH_ABSOLUTE_JITTER) ?
- (brush->jitter_absolute != 0) : (brush->jitter != 0);
+ float rand_pos[2];
+ float spread;
+ int diameter;
- /* jitter-ed brush gives weird and unpredictable result for this
- * kinds of stroke, so manually disable jitter usage (sergey) */
- use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0;
+ do {
+ rand_pos[0] = BLI_rng_get_float(brush_rng) - 0.5f;
+ rand_pos[1] = BLI_rng_get_float(brush_rng) - 0.5f;
+ } while (len_squared_v2(rand_pos) > (0.5f * 0.5f));
- if (use_jitter) {
- float rand_pos[2];
- float spread;
- int diameter;
- do {
- rand_pos[0] = BLI_rng_get_float(brush_rng) - 0.5f;
- rand_pos[1] = BLI_rng_get_float(brush_rng) - 0.5f;
- } while (len_squared_v2(rand_pos) > (0.5f * 0.5f));
-
-
- if (brush->flag & BRUSH_ABSOLUTE_JITTER) {
- diameter = 2 * brush->jitter_absolute;
- spread = 1.0;
- }
- else {
- diameter = 2 * BKE_brush_size_get(scene, brush);
- spread = brush->jitter;
- }
- /* find random position within a circle of diameter 1 */
- jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * spread;
- jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread;
+ if (brush->flag & BRUSH_ABSOLUTE_JITTER) {
+ diameter = 2 * brush->jitter_absolute;
+ spread = 1.0;
}
else {
- copy_v2_v2(jitterpos, pos);
+ diameter = 2 * BKE_brush_size_get(scene, brush);
+ spread = brush->jitter;
}
+ /* find random position within a circle of diameter 1 */
+ jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * spread;
+ jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread;
}
void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups, bool mask)
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index f85a91b66cb..4ad577a7bda 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -77,288 +77,6 @@ static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, con
return FLT_MAX;
}
-
-/*
- * Function adapted from David Eberly's distance tools (LGPL)
- * http://www.geometrictools.com/LibFoundation/Distance/Distance.html
- */
-float nearest_point_in_tri_surface_squared(
- const float v0[3], const float v1[3], const float v2[3],
- const float p[3], int *v, int *e, float nearest[3])
-{
- float diff[3];
- float e0[3];
- float e1[3];
- float A00;
- float A01;
- float A11;
- float B0;
- float B1;
- float C;
- float Det;
- float S;
- float T;
- float sqrDist;
- int lv = -1, le = -1;
-
- sub_v3_v3v3(diff, v0, p);
- sub_v3_v3v3(e0, v1, v0);
- sub_v3_v3v3(e1, v2, v0);
-
- A00 = dot_v3v3(e0, e0);
- A01 = dot_v3v3(e0, e1);
- A11 = dot_v3v3(e1, e1);
- B0 = dot_v3v3(diff, e0);
- B1 = dot_v3v3(diff, e1);
- C = dot_v3v3(diff, diff);
- Det = fabsf(A00 * A11 - A01 * A01);
- S = A01 * B1 - A11 * B0;
- T = A01 * B0 - A00 * B1;
-
- if (S + T <= Det) {
- if (S < 0.0f) {
- if (T < 0.0f) { /* Region 4 */
- if (B0 < 0.0f) {
- T = 0.0f;
- if (-B0 >= A00) {
- S = 1.0f;
- sqrDist = A00 + 2.0f * B0 + C;
- lv = 1;
- }
- else {
- if (fabsf(A00) > FLT_EPSILON)
- S = -B0 / A00;
- else
- S = 0.0f;
- sqrDist = B0 * S + C;
- le = 0;
- }
- }
- else {
- S = 0.0f;
- if (B1 >= 0.0f) {
- T = 0.0f;
- sqrDist = C;
- lv = 0;
- }
- else if (-B1 >= A11) {
- T = 1.0f;
- sqrDist = A11 + 2.0f * B1 + C;
- lv = 2;
- }
- else {
- if (fabsf(A11) > FLT_EPSILON)
- T = -B1 / A11;
- else
- T = 0.0f;
- sqrDist = B1 * T + C;
- le = 1;
- }
- }
- }
- else { /* Region 3 */
- S = 0.0f;
- if (B1 >= 0.0f) {
- T = 0.0f;
- sqrDist = C;
- lv = 0;
- }
- else if (-B1 >= A11) {
- T = 1.0f;
- sqrDist = A11 + 2.0f * B1 + C;
- lv = 2;
- }
- else {
- if (fabsf(A11) > FLT_EPSILON)
- T = -B1 / A11;
- else
- T = 0.0;
- sqrDist = B1 * T + C;
- le = 1;
- }
- }
- }
- else if (T < 0.0f) { /* Region 5 */
- T = 0.0f;
- if (B0 >= 0.0f) {
- S = 0.0f;
- sqrDist = C;
- lv = 0;
- }
- else if (-B0 >= A00) {
- S = 1.0f;
- sqrDist = A00 + 2.0f * B0 + C;
- lv = 1;
- }
- else {
- if (fabsf(A00) > FLT_EPSILON)
- S = -B0 / A00;
- else
- S = 0.0f;
- sqrDist = B0 * S + C;
- le = 0;
- }
- }
- else { /* Region 0 */
- /* Minimum at interior lv */
- float invDet;
- if (fabsf(Det) > FLT_EPSILON)
- invDet = 1.0f / Det;
- else
- invDet = 0.0f;
- S *= invDet;
- T *= invDet;
- sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) +
- T * (A01 * S + A11 * T + 2.0f * B1) + C;
- }
- }
- else {
- float tmp0, tmp1, numer, denom;
-
- if (S < 0.0f) { /* Region 2 */
- tmp0 = A01 + B0;
- tmp1 = A11 + B1;
- if (tmp1 > tmp0) {
- numer = tmp1 - tmp0;
- denom = A00 - 2.0f * A01 + A11;
- if (numer >= denom) {
- S = 1.0f;
- T = 0.0f;
- sqrDist = A00 + 2.0f * B0 + C;
- lv = 1;
- }
- else {
- if (fabsf(denom) > FLT_EPSILON)
- S = numer / denom;
- else
- S = 0.0f;
- T = 1.0f - S;
- sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) +
- T * (A01 * S + A11 * T + 2.0f * B1) + C;
- le = 2;
- }
- }
- else {
- S = 0.0f;
- if (tmp1 <= 0.0f) {
- T = 1.0f;
- sqrDist = A11 + 2.0f * B1 + C;
- lv = 2;
- }
- else if (B1 >= 0.0f) {
- T = 0.0f;
- sqrDist = C;
- lv = 0;
- }
- else {
- if (fabsf(A11) > FLT_EPSILON)
- T = -B1 / A11;
- else
- T = 0.0f;
- sqrDist = B1 * T + C;
- le = 1;
- }
- }
- }
- else if (T < 0.0f) { /* Region 6 */
- tmp0 = A01 + B1;
- tmp1 = A00 + B0;
- if (tmp1 > tmp0) {
- numer = tmp1 - tmp0;
- denom = A00 - 2.0f * A01 + A11;
- if (numer >= denom) {
- T = 1.0f;
- S = 0.0f;
- sqrDist = A11 + 2.0f * B1 + C;
- lv = 2;
- }
- else {
- if (fabsf(denom) > FLT_EPSILON)
- T = numer / denom;
- else
- T = 0.0f;
- S = 1.0f - T;
- sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) +
- T * (A01 * S + A11 * T + 2.0f * B1) + C;
- le = 2;
- }
- }
- else {
- T = 0.0f;
- if (tmp1 <= 0.0f) {
- S = 1.0f;
- sqrDist = A00 + 2.0f * B0 + C;
- lv = 1;
- }
- else if (B0 >= 0.0f) {
- S = 0.0f;
- sqrDist = C;
- lv = 0;
- }
- else {
- if (fabsf(A00) > FLT_EPSILON)
- S = -B0 / A00;
- else
- S = 0.0f;
- sqrDist = B0 * S + C;
- le = 0;
- }
- }
- }
- else { /* Region 1 */
- numer = A11 + B1 - A01 - B0;
- if (numer <= 0.0f) {
- S = 0.0f;
- T = 1.0f;
- sqrDist = A11 + 2.0f * B1 + C;
- lv = 2;
- }
- else {
- denom = A00 - 2.0f * A01 + A11;
- if (numer >= denom) {
- S = 1.0f;
- T = 0.0f;
- sqrDist = A00 + 2.0f * B0 + C;
- lv = 1;
- }
- else {
- if (fabsf(denom) > FLT_EPSILON)
- S = numer / denom;
- else
- S = 0.0f;
- T = 1.0f - S;
- sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) +
- T * (A01 * S + A11 * T + 2.0f * B1) + C;
- le = 2;
- }
- }
- }
- }
-
- /* Account for numerical round-off error */
- if (sqrDist < FLT_EPSILON)
- sqrDist = 0.0f;
-
- {
- float w[3], x[3], y[3], z[3];
- copy_v3_v3(w, v0);
- copy_v3_v3(x, e0);
- mul_v3_fl(x, S);
- copy_v3_v3(y, e1);
- mul_v3_fl(y, T);
- add_v3_v3v3(z, w, x);
- add_v3_v3v3(z, z, y);
- //sub_v3_v3v3(d, p, z);
- copy_v3_v3(nearest, z);
- //d = p - ( v0 + S * e0 + T * e1 );
- }
- *v = lv;
- *e = le;
-
- return sqrDist;
-}
-
-
/*
* BVH from meshes callbacks
*/
@@ -380,9 +98,10 @@ static void mesh_faces_nearest_point(void *userdata, int index, const float co[3
do {
float nearest_tmp[3], dist_sq;
- int vertex, edge;
-
- dist_sq = nearest_point_in_tri_surface_squared(t0, t1, t2, co, &vertex, &edge, nearest_tmp);
+
+ closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
+ dist_sq = len_squared_v3v3(co, nearest_tmp);
+
if (dist_sq < nearest->dist_sq) {
nearest->index = index;
nearest->dist_sq = dist_sq;
@@ -413,9 +132,10 @@ static void editmesh_faces_nearest_point(void *userdata, int index, const float
{
float nearest_tmp[3], dist_sq;
- int vertex, edge;
- dist_sq = nearest_point_in_tri_surface_squared(t0, t1, t2, co, &vertex, &edge, nearest_tmp);
+ closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
+ dist_sq = len_squared_v3v3(co, nearest_tmp);
+
if (dist_sq < nearest->dist_sq) {
nearest->index = index;
nearest->dist_sq = dist_sq;
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index b20ba40c0dd..6ce3abe7a32 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -201,7 +201,7 @@ void BKE_camera_params_init(CameraParams *params)
/* fallback for non camera objects */
params->clipsta = 0.1f;
- params->clipsta = 100.0f;
+ params->clipend = 100.0f;
}
void BKE_camera_params_from_object(CameraParams *params, Object *ob)
@@ -473,7 +473,7 @@ static void camera_to_frame_view_cb(const float co[3], void *user_data)
unsigned int i;
for (i = 0; i < 4; i++) {
- float nd = dist_squared_to_plane_v3(co, data->plane_tx[i]);
+ float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]);
if (nd < data->dist_vals_sq[i]) {
data->dist_vals_sq[i] = nd;
}
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index f39b4e20b70..08052127fbf 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -49,6 +49,7 @@
#include "BKE_editmesh.h"
#include "BKE_curve.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -668,7 +669,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
DMSetDrawOptionsTex drawParams,
DMSetDrawOptions drawParamsMapped,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag uvflag)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
MVert *mv = cddm->mvert;
@@ -679,6 +680,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
MCol *mcol;
int i, orig;
int colType, startFace = 0;
+ bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0;
/* double lookup */
const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
@@ -717,14 +719,35 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
cdDM_update_normals_from_pbvh(dm);
if (GPU_buffer_legacy(dm)) {
+ int mat_nr_cache = -1;
+ MTFace *tf_base = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ MTFace *tf_stencil_base = NULL;
+ MTFace *tf_stencil = NULL;
+
+ if (uvflag & DM_DRAW_USE_TEXPAINT_UV) {
+ int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
+ tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+ }
+
DEBUG_VBO("Using legacy code. cdDM_drawFacesTex_common\n");
for (i = 0; i < dm->numTessFaceData; i++, mf++) {
MVert *mvert;
DMDrawOption draw_option;
unsigned char *cp = NULL;
+ if (uvflag & DM_DRAW_USE_TEXPAINT_UV) {
+ if (mf->mat_nr != mat_nr_cache) {
+ tf_base = DM_paint_uvlayer_active_get(dm, mf->mat_nr);
+
+ mat_nr_cache = mf->mat_nr;
+ }
+ }
+
+ tf = tf_base ? tf_base + i : NULL;
+ tf_stencil = tf_stencil_base ? tf_stencil_base + i : NULL;
+
if (drawParams) {
- draw_option = drawParams(tf ? &tf[i] : NULL, (mcol != NULL), mf->mat_nr);
+ draw_option = drawParams(use_tface ? tf : NULL, (mcol != NULL), mf->mat_nr);
}
else {
if (index_mf_to_mpoly) {
@@ -777,21 +800,24 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
}
glBegin(mf->v4 ? GL_QUADS : GL_TRIANGLES);
- if (tf) glTexCoord2fv(tf[i].uv[0]);
+ if (tf) glTexCoord2fv(tf->uv[0]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
mvert = &mv[mf->v1];
if (lnors) glNormal3sv((const GLshort *)lnors[0][0]);
else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
glVertex3fv(mvert->co);
- if (tf) glTexCoord2fv(tf[i].uv[1]);
+ if (tf) glTexCoord2fv(tf->uv[1]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
mvert = &mv[mf->v2];
if (lnors) glNormal3sv((const GLshort *)lnors[0][1]);
else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
glVertex3fv(mvert->co);
- if (tf) glTexCoord2fv(tf[i].uv[2]);
+ if (tf) glTexCoord2fv(tf->uv[2]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
mvert = &mv[mf->v3];
if (lnors) glNormal3sv((const GLshort *)lnors[0][2]);
@@ -799,7 +825,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
glVertex3fv(mvert->co);
if (mf->v4) {
- if (tf) glTexCoord2fv(tf[i].uv[3]);
+ if (tf) glTexCoord2fv(tf->uv[3]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
mvert = &mv[mf->v4];
if (lnors) glNormal3sv((const GLshort *)lnors[0][3]);
@@ -818,7 +845,10 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
- GPU_uv_setup(dm);
+ if (uvflag & DM_DRAW_USE_TEXPAINT_UV)
+ GPU_texpaint_uv_setup(dm);
+ else
+ GPU_uv_setup(dm);
if (mcol) {
GPU_color_setup(dm, colType);
}
@@ -838,7 +868,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
if (drawParams) {
- draw_option = drawParams(tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr);
+ draw_option = drawParams(use_tface && tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr);
}
else {
if (index_mf_to_mpoly) {
@@ -894,9 +924,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
static void cdDM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag uvflag)
{
- cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
+ cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, uvflag);
}
static void cdDM_drawMappedFaces(DerivedMesh *dm,
@@ -1122,9 +1152,9 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm,
static void cdDM_drawMappedFacesTex(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag flag)
{
- cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
+ cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
}
static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert,
@@ -2541,25 +2571,200 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm)
#if 1
/**
+ * Poly compare with vtargetmap
+ * Function used by #CDDM_merge_verts.
+ * The function compares poly_source after applying vtargetmap, with poly_target.
+ * The two polys are identical if they share the same vertices in the same order, or in reverse order,
+ * but starting position loopstart may be different.
+ * The function is called with direct_reverse=1 for same order (i.e. same normal),
+ * and may be called again with direct_reverse=-1 for reverse order.
+ * \return 1 if polys are identical, 0 if polys are different.
+ */
+static int cddm_poly_compare(MLoop *mloop_array, MPoly *mpoly_source, MPoly *mpoly_target, const int *vtargetmap, const int direct_reverse)
+{
+ int vert_source, first_vert_source, vert_target;
+ int i_loop_source;
+ int i_loop_target, i_loop_target_start, i_loop_target_offset, i_loop_target_adjusted;
+ bool compare_completed = false;
+ bool same_loops = false;
+
+ MLoop *mloop_source, *mloop_target;
+
+ BLI_assert(direct_reverse == 1 || direct_reverse == -1);
+
+ i_loop_source = 0;
+ mloop_source = mloop_array + mpoly_source->loopstart;
+ vert_source = mloop_source->v;
+
+ if (vtargetmap[vert_source] != -1) {
+ vert_source = vtargetmap[vert_source];
+ }
+ else {
+ /* All source loop vertices should be mapped */
+ BLI_assert(false);
+ }
+
+ /* Find same vertex within mpoly_target's loops */
+ mloop_target = mloop_array + mpoly_target->loopstart;
+ for (i_loop_target = 0; i_loop_target < mpoly_target->totloop; i_loop_target++, mloop_target++) {
+ if (mloop_target->v == vert_source) {
+ break;
+ }
+ }
+
+ /* If same vertex not found, then polys cannot be equal */
+ if (i_loop_target >= mpoly_target->totloop) {
+ return false;
+ }
+
+ /* Now mloop_source and m_loop_target have one identical vertex */
+ /* mloop_source is at position 0, while m_loop_target has advanced to find identical vertex */
+ /* Go around the loop and check that all vertices match in same order */
+ /* Skipping source loops when consecutive source vertices are mapped to same target vertex */
+
+ i_loop_target_start = i_loop_target;
+ i_loop_target_offset = 0;
+ first_vert_source = vert_source;
+
+ compare_completed = false;
+ same_loops = false;
+
+ while (!compare_completed) {
+
+ vert_target = mloop_target->v;
+
+ /* First advance i_loop_source, until it points to different vertex, after mapping applied */
+ do {
+ i_loop_source++;
+
+ if (i_loop_source == mpoly_source->totloop) {
+ /* End of loops for source, must match end of loop for target. */
+ if (i_loop_target_offset == mpoly_target->totloop - 1) {
+ compare_completed = true;
+ same_loops = true;
+ break; /* Polys are identical */
+ }
+ else {
+ compare_completed = true;
+ same_loops = false;
+ break; /* Polys are different */
+ }
+ }
+
+ mloop_source++;
+ vert_source = mloop_source->v;
+
+ if (vtargetmap[vert_source] != -1) {
+ vert_source = vtargetmap[vert_source];
+ }
+ else {
+ /* All source loop vertices should be mapped */
+ BLI_assert(false);
+ }
+
+ } while (vert_source == vert_target);
+
+ if (compare_completed) {
+ break;
+ }
+
+ /* Now advance i_loop_target as well */
+ i_loop_target_offset++;
+
+ if (i_loop_target_offset == mpoly_target->totloop) {
+ /* End of loops for target only, that means no match */
+ /* except if all remaining source vertices are mapped to first target */
+ for (; i_loop_source < mpoly_source->totloop; i_loop_source++, mloop_source++) {
+ vert_source = vtargetmap[mloop_source->v];
+ if (vert_source != first_vert_source) {
+ compare_completed = true;
+ same_loops = false;
+ break;
+ }
+ }
+ if (!compare_completed) {
+ same_loops = true;
+ }
+ break;
+ }
+
+ /* Adjust i_loop_target for cycling around and for direct/reverse order defined by delta = +1 or -1 */
+ i_loop_target_adjusted = (i_loop_target_start + direct_reverse * i_loop_target_offset) % mpoly_target->totloop;
+ if (i_loop_target_adjusted < 0) {
+ i_loop_target_adjusted += mpoly_target->totloop;
+ }
+ mloop_target = mloop_array + mpoly_target->loopstart + i_loop_target_adjusted;
+ vert_target = mloop_target->v;
+
+ if (vert_target != vert_source) {
+ same_loops = false; /* Polys are different */
+ break;
+ }
+ }
+ return same_loops;
+}
+
+/* Utility stuff for using GHash with polys */
+
+typedef struct PolyKey {
+ int poly_index; /* index of the MPoly within the derived mesh */
+ int totloops; /* number of loops in the poly */
+ unsigned int hash_sum; /* Sum of all vertices indices */
+ unsigned int hash_xor; /* Xor of all vertices indices */
+} PolyKey;
+
+
+static unsigned int poly_gset_hash_fn(const void *key)
+{
+ const PolyKey *pk = key;
+ return pk->hash_sum;
+}
+
+static int poly_gset_compare_fn(const void *k1, const void *k2)
+{
+ const PolyKey *pk1 = k1;
+ const PolyKey *pk2 = k2;
+ if ((pk1->hash_sum == pk2->hash_sum) &&
+ (pk1->hash_xor == pk2->hash_xor) &&
+ (pk1->totloops == pk2->totloops))
+ {
+ /* Equality - note that this does not mean equality of polys */
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+/**
* Merge Verts
*
+ * This frees dm, and returns a new one.
+ *
* \param vtargetmap The table that maps vertices to target vertices. a value of -1
* indicates a vertex is a target, and is to be kept.
* This array is aligned with 'dm->numVertData'
*
- * \param tot_vtargetmap The number of non '-1' values in vtargetmap.
- * (not the size )
- *
- * this frees dm, and returns a new one.
+ * \param tot_vtargetmap The number of non '-1' values in vtargetmap. (not the size)
*
- * note, CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces.
+ * \param merge_mode enum with two modes.
+ * - #CDDM_MERGE_VERTS_DUMP_IF_MAPPED
+ * When called by the Mirror Modifier,
+ * In this mode it skips any faces that have all vertices merged (to avoid creating pairs
+ * of faces sharing the same set of vertices)
+ * - #CDDM_MERGE_VERTS_DUMP_IF_EQUAL
+ * When called by the Array Modifier,
+ * In this mode, faces where all vertices are merged are double-checked,
+ * to see whether all target vertices actually make up a poly already.
+ * Indeed it could be that all of a poly's vertices are merged,
+ * but merged to vertices that do not make up a single poly,
+ * in which case the original poly should not be dumped.
+ * Actually this later behavior could apply to the Mirror Modifier as well, but the additional checks are
+ * costly and not necessary in the case of mirror, because each vertex is only merged to its own mirror.
*
- * Note: This function is currently only used by the Mirror modifier, so it
- * skips any faces that have all vertices merged (to avoid creating pairs
- * of faces sharing the same set of vertices). If used elsewhere, it may
- * be necessary to make this functionality optional.
+ * \note #CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces.
*/
-DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap)
+DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap, const int merge_mode)
{
// #define USE_LOOPS
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
@@ -2600,7 +2805,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
EdgeHash *ehash = BLI_edgehash_new_ex(__func__, totedge);
int i, j, c;
-
+
+ PolyKey *poly_keys;
+ GSet *poly_gset = NULL;
+
STACK_INIT(oldv, totvert_final);
STACK_INIT(olde, totedge);
STACK_INIT(oldl, totloop);
@@ -2642,10 +2850,9 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
med = cddm->medge;
c = 0;
for (i = 0; i < totedge; i++, med++) {
-
- if (LIKELY(med->v1 != med->v2)) {
- const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1;
- const unsigned int v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2;
+ const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1;
+ const unsigned int v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2;
+ if (LIKELY(v1 != v2)) {
void **eh_p = BLI_edgehash_lookup_p(ehash, v1, v2);
if (eh_p) {
@@ -2664,13 +2871,49 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
}
}
+ if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_EQUAL) {
+ /* In this mode, we need to determine, whenever a poly' vertices are all mapped */
+ /* if the targets already make up a poly, in which case the new poly is dropped */
+ /* This poly equality check is rather complex. We use a BLI_ghash to speed it up with a first level check */
+ PolyKey *mpgh;
+ poly_keys = MEM_mallocN(sizeof(PolyKey) * totpoly, __func__);
+ poly_gset = BLI_gset_new_ex(poly_gset_hash_fn, poly_gset_compare_fn, __func__, totpoly);
+ /* Duplicates allowed because our compare function is not pure equality */
+ BLI_gset_flag_set(poly_gset, GHASH_FLAG_ALLOW_DUPES);
+
+ mp = cddm->mpoly;
+ mpgh = poly_keys;
+ for (i = 0; i < totpoly; i++, mp++, mpgh++) {
+ mpgh->poly_index = i;
+ mpgh->totloops = mp->totloop;
+ ml = cddm->mloop + mp->loopstart;
+ mpgh->hash_sum = mpgh->hash_xor = 0;
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ mpgh->hash_sum += ml->v;
+ mpgh->hash_xor ^= ml->v;
+ }
+ BLI_gset_insert(poly_gset, mpgh);
+ }
+
+ if (cddm->pmap) {
+ MEM_freeN(cddm->pmap);
+ MEM_freeN(cddm->pmap_mem);
+ }
+ /* Can we optimise by reusing an old pmap ? How do we know an old pmap is stale ? */
+ /* When called by MOD_array.c, the cddm has just been created, so it has no valid pmap. */
+ BKE_mesh_vert_poly_map_create(&cddm->pmap, &cddm->pmap_mem,
+ cddm->mpoly, cddm->mloop,
+ totvert, totpoly, totloop);
+ } /* done preparing for fast poly compare */
+
+
mp = cddm->mpoly;
for (i = 0; i < totpoly; i++, mp++) {
MPoly *mp_new;
ml = cddm->mloop + mp->loopstart;
- /* skip faces with all vertices merged */
+ /* check faces with all vertices merged */
{
bool all_vertices_merged = true;
@@ -2682,16 +2925,86 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
}
if (UNLIKELY(all_vertices_merged)) {
- continue;
+ if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_MAPPED) {
+ /* In this mode, all vertices merged is enough to dump face */
+ continue;
+ }
+ else if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_EQUAL) {
+ /* Additional condition for face dump: target vertices must make up an identical face */
+ /* The test has 2 steps: (1) first step is fast ghash lookup, but not failproof */
+ /* (2) second step is thorough but more costly poly compare */
+ int i_poly, v_target, v_prev;
+ bool found = false;
+ PolyKey pkey;
+
+ /* Use poly_gset for fast (although not 100% certain) identification of same poly */
+ /* First, make up a poly_summary structure */
+ ml = cddm->mloop + mp->loopstart;
+ pkey.hash_sum = pkey.hash_xor = 0;
+ pkey.totloops = 0;
+ v_prev = vtargetmap[(ml + mp->totloop -1)->v]; /* since it loops around, the prev of first is the last */
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ v_target = vtargetmap[ml->v]; /* Cannot be -1, they are all mapped */
+ if (v_target == v_prev) {
+ /* consecutive vertices in loop map to the same target: discard */
+ /* but what about last to first ? */
+ continue;
+ }
+ pkey.hash_sum += v_target;
+ pkey.hash_xor ^= v_target;
+ pkey.totloops++;
+ v_prev = v_target;
+ }
+ if (BLI_gset_haskey(poly_gset, &pkey)) {
+
+ /* There might be a poly that matches this one.
+ * We could just leave it there and say there is, and do a "continue".
+ * ... but we are checking whether there is an exact poly match.
+ * It's not so costly in terms of CPU since it's very rare, just a lot of complex code.
+ */
+
+ /* Consider current loop again */
+ ml = cddm->mloop + mp->loopstart;
+ /* Consider the target of the loop's first vert */
+ v_target = vtargetmap[ml->v];
+ /* Now see if v_target belongs to a poly that shares all vertices with source poly,
+ * in same order, or reverse order */
+
+ for (i_poly = 0; i_poly < cddm->pmap[v_target].count; i_poly++) {
+ 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))
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ /* Current poly's vertices are mapped to a poly that is strictly identical */
+ /* Current poly is dumped */
+ continue;
+ }
+ }
+ }
}
}
+
+ /* Here either the poly's vertices were not all merged
+ * or they were all merged, but targets do not make up an identical poly,
+ * the poly is retained.
+ */
ml = cddm->mloop + mp->loopstart;
c = 0;
for (j = 0; j < mp->totloop; j++, ml++) {
+ unsigned int v1, v2;
+
med = cddm->medge + ml->e;
- if (LIKELY(med->v1 != med->v2)) {
+ v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1;
+ v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2;
+ if (LIKELY(v1 != v2)) {
#ifdef USE_LOOPS
newl[j + mp->loopstart] = STACK_SIZE(mloop);
#endif
@@ -2711,6 +3024,14 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
mp_new->loopstart = STACK_SIZE(mloop) - c;
STACK_PUSH(oldp, i);
+ } /* end of the loop that tests polys */
+
+
+ if (poly_gset) {
+ // printf("hash quality %.6f\n", BLI_gset_calc_quality(poly_gset));
+
+ BLI_gset_free(poly_gset, NULL);
+ MEM_freeN(poly_keys);
}
/*create new cddm*/
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index b27655c8c19..d80529ee780 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -3375,7 +3375,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
unit_m4(ct->matrix);
if (target != NULL) {
- space_transform_from_matrixs(&transform, cob->matrix, ct->tar->obmat);
+ BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->obmat);
switch (scon->shrinkType) {
case MOD_SHRINKWRAP_NEAREST_SURFACE:
@@ -3397,7 +3397,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
break;
}
- space_transform_apply(&transform, co);
+ BLI_space_transform_apply(&transform, co);
BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
@@ -3405,7 +3405,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
if (dist != 0.0f) {
interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist) / dist); /* linear interpolation */
}
- space_transform_invert(&transform, co);
+ BLI_space_transform_invert(&transform, co);
break;
}
case MOD_SHRINKWRAP_PROJECT:
@@ -3909,7 +3909,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, imat);
invert_m4(imat);
- mul_serie_m4(cob->matrix, obmat, mat, imat, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(cob->matrix, obmat, mat, imat);
translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
}
else {
@@ -3943,19 +3943,31 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
if (len > FLT_EPSILON) {
CameraParams params;
+ int width, height;
float pos[2], rmat[4][4];
+ BKE_movieclip_get_size(clip, NULL, &width, &height);
+
marker = BKE_tracking_marker_get(track, framenr);
add_v2_v2v2(pos, marker->pos, track->offset);
+ if (data->flag & FOLLOWTRACK_USE_UNDISTORTION) {
+ /* Undistortion need to happen in pixel space. */
+ pos[0] *= width;
+ pos[1] *= height;
+
+ BKE_tracking_undistort_v2(tracking, pos, pos);
+
+ /* Normalize pixel coordinates back. */
+ pos[0] /= width;
+ pos[1] /= height;
+ }
+
/* aspect correction */
if (data->frame_method != FOLLOWTRACK_FRAME_STRETCH) {
- int width, height;
float w_src, h_src, w_dst, h_dst, asp_src, asp_dst;
- BKE_movieclip_get_size(clip, NULL, &width, &height);
-
/* apply clip display aspect */
w_src = width * clip->aspx;
h_src = height * clip->aspy;
@@ -4187,7 +4199,7 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
invert_m4_m4(imat, mat);
- mul_serie_m4(cob->matrix, cammat, imat, camimat, parmat, obmat, NULL, NULL, NULL);
+ mul_m4_series(cob->matrix, cammat, imat, camimat, parmat, obmat);
}
}
}
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 47b29b49689..de285f87444 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -48,7 +48,6 @@
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_screen.h"
-#include "BKE_freestyle.h"
#include "RNA_access.h"
@@ -1091,16 +1090,3 @@ int CTX_data_visible_pose_bones(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "visible_pose_bones", list);
}
-
-FreestyleLineStyle *CTX_data_linestyle_from_scene(Scene *scene)
-{
- SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- FreestyleConfig *config = &actsrl->freestyleConfig;
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
-
- if (lineset) {
- return lineset->linestyle;
- }
-
- return NULL;
-}
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 7ca5d6b4f28..911bb19a594 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -40,7 +40,6 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BLI_bitmap.h"
#include "BKE_crazyspace.h"
#include "BKE_DerivedMesh.h"
@@ -49,11 +48,6 @@
#include "BKE_mesh.h"
#include "BKE_editmesh.h"
-typedef struct {
- float (*vertexcos)[3];
- BLI_bitmap *vertex_visit;
-} MappedUserData;
-
BLI_INLINE void tan_calc_quat_v3(
float r_quat[4],
const float co_1[3], const float co_2[3], const float co_3[3])
@@ -88,20 +82,6 @@ static void set_crazy_vertex_quat(
sub_qt_qtqt(r_quat, q2, q1);
}
-static void make_vertexcos__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
-{
- MappedUserData *mappedData = (MappedUserData *)userData;
-
- if (BLI_BITMAP_TEST(mappedData->vertex_visit, index) == 0) {
- /* we need coord from prototype vertex, not from copies,
- * assume they stored in the beginning of vertex array stored in DM
- * (mirror modifier for eg does this) */
- copy_v3_v3(mappedData->vertexcos[index], co);
- BLI_BITMAP_ENABLE(mappedData->vertex_visit, index);
- }
-}
-
static int modifiers_disable_subsurf_temporary(Object *ob)
{
ModifierData *md;
@@ -124,8 +104,6 @@ float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3]
DerivedMesh *dm;
float (*vertexcos)[3];
int nverts = me->edit_btmesh->bm->totvert;
- BLI_bitmap *vertex_visit;
- MappedUserData userData;
/* disable subsurf temporal, get mapped cos, and enable it */
if (modifiers_disable_subsurf_temporary(obedit)) {
@@ -134,22 +112,17 @@ float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3]
}
/* now get the cage */
- dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH);
+ vertexcos = MEM_mallocN(sizeof(*vertexcos) * nverts, "vertexcos map");
- vertexcos = MEM_callocN(sizeof(*vertexcos) * nverts, "vertexcos map");
- vertex_visit = BLI_BITMAP_NEW(nverts, "vertexcos flags");
+ dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH);
- userData.vertexcos = vertexcos;
- userData.vertex_visit = vertex_visit;
- dm->foreachMappedVert(dm, make_vertexcos__mapFunc, &userData, DM_FOREACH_NOP);
+ mesh_get_mapped_verts_coords(dm, vertexcos, nverts);
dm->release(dm);
/* set back the flag, no new cage needs to be built, transform does it */
modifiers_disable_subsurf_temporary(obedit);
- MEM_freeN(vertex_visit);
-
return vertexcos;
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 0abe956b599..9275b626b49 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -52,6 +52,7 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_font.h"
#include "BKE_global.h"
@@ -642,8 +643,9 @@ void BKE_nurb_test2D(Nurb *nu)
}
}
-/* if use_radius is truth, minmax will take points' radius into account,
- * which will make boundbox closer to bevelled curve.
+/**
+ * if use_radius is truth, minmax will take points' radius into account,
+ * which will make boundbox closer to beveled curve.
*/
void BKE_nurb_minmax(Nurb *nu, bool use_radius, float min[3], float max[3])
{
@@ -2498,6 +2500,22 @@ static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl)
}
}
+void BKE_curve_bevelList_free(ListBase *bev)
+{
+ BevList *bl, *blnext;
+ for (bl = bev->first; bl != NULL; bl = blnext) {
+ blnext = bl->next;
+ if (bl->seglen != NULL) {
+ MEM_freeN(bl->seglen);
+ }
+ if (bl->segbevcount != NULL) {
+ MEM_freeN(bl->segbevcount);
+ }
+ MEM_freeN(bl);
+ }
+ bev->first = bev->last = NULL;
+}
+
void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
{
/*
@@ -2506,21 +2524,29 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
* - separate in individual blocks with BoundBox
* - AutoHole detection
*/
- Curve *cu;
+
+ /* this function needs an object, because of tflag and upflag */
+ Curve *cu = ob->data;
Nurb *nu;
BezTriple *bezt, *prevbezt;
BPoint *bp;
BevList *bl, *blnew, *blnext;
BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
+ const float treshold = 0.00001f;
float min, inp;
+ float *seglen;
struct BevelSort *sortdata, *sd, *sd1;
- int a, b, nr, poly, resolu = 0, len = 0;
+ int a, b, nr, poly, resolu = 0, len = 0, segcount;
+ int *segbevcount;
bool do_tilt, do_radius, do_weight;
bool is_editmode = false;
ListBase *bev;
- /* this function needs an object, because of tflag and upflag */
- cu = ob->data;
+ /* segbevcount alsp requires seglen. */
+ const bool need_seglen =
+ ELEM(cu->bevfac1_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE) ||
+ ELEM(cu->bevfac2_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE);
+
bev = &ob->curve_cache->bev;
@@ -2529,7 +2555,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
/* STEP 1: MAKE POLYS */
- BLI_freelistN(&(ob->curve_cache->bev));
+ BKE_curve_bevelList_free(&ob->curve_cache->bev);
nu = nurbs->first;
if (cu->editnurb && ob->type != OB_FONT) {
is_editmode = 1;
@@ -2559,9 +2585,15 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
else
resolu = nu->resolu;
+ segcount = SEGMENTSU(nu);
+
if (nu->type == CU_POLY) {
len = nu->pntsu;
bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList2");
+ if (need_seglen) {
+ bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelList2_seglen");
+ bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelList2_segbevcount");
+ }
BLI_addtail(bev, bl);
bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
@@ -2569,7 +2601,11 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
bl->dupe_nr = 0;
bl->charidx = nu->charidx;
bevp = bl->bevpoints;
+ bevp->offset = 0;
bp = nu->bp;
+ seglen = bl->seglen;
+ segbevcount = bl->segbevcount;
+ BLI_assert(segcount >= len);
while (len--) {
copy_v3_v3(bevp->vec, bp->vec);
@@ -2577,23 +2613,53 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
bevp->radius = bp->radius;
bevp->weight = bp->weight;
bevp->split_tag = true;
- bevp++;
bp++;
+ if (seglen != NULL) {
+ *seglen = len_v3v3(bevp->vec, bp->vec);
+ bevp++;
+ bevp->offset = *seglen;
+ if (*seglen > treshold) *segbevcount = 1;
+ else *segbevcount = 0;
+ seglen++;
+ segbevcount++;
+ }
+ else {
+ bevp++;
+ }
}
if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
bevlist_firstlast_direction_calc_from_bpoint(nu, bl);
+ if (seglen != NULL) {
+ *seglen = len_v3v3(bevp->vec, nu->bp->vec);
+ bl->bevpoints->offset = *seglen;
+ *segbevcount = 1;
+ }
}
}
else if (nu->type == CU_BEZIER) {
/* in case last point is not cyclic */
- len = resolu * (nu->pntsu + (nu->flagu & CU_NURB_CYCLIC) - 1) + 1;
+ len = segcount * resolu + 1;
+
bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelBPoints");
+ if (need_seglen) {
+ bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelBPoints_seglen");
+ bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelBPoints_segbevcount");
+ }
BLI_addtail(bev, bl);
bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
bl->charidx = nu->charidx;
+
bevp = bl->bevpoints;
+ seglen = bl->seglen;
+ segbevcount = bl->segbevcount;
+
+ bevp->offset = 0;
+ if (seglen != NULL) {
+ *seglen = 0;
+ *segbevcount = 0;
+ }
a = nu->pntsu - 1;
bezt = nu->bezt;
@@ -2609,6 +2675,8 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
sub_v3_v3v3(bevp->dir, prevbezt->vec[2], prevbezt->vec[1]);
normalize_v3(bevp->dir);
+ BLI_assert(segcount >= a);
+
while (a--) {
if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) {
@@ -2621,6 +2689,14 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
bevp++;
bl->nr++;
bl->dupe_nr = 1;
+ if (seglen != NULL) {
+ *seglen = len_v3v3(prevbezt->vec[1], bezt->vec[1]);
+ bevp->offset = *seglen;
+ seglen++;
+ /* match segbevcount to the cleaned up bevel lists (see STEP 2) */
+ if (bevp->offset > treshold) *segbevcount = 1;
+ segbevcount++;
+ }
}
else {
/* always do all three, to prevent data hanging around */
@@ -2658,8 +2734,28 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
else if (prevbezt->h2 == 0 || prevbezt->h2 == HD_VECT)
bevp->split_tag = true;
}
+
+ /* seglen */
+ if (seglen != NULL) {
+ *seglen = 0;
+ *segbevcount = 0;
+ for (j = 0; j < resolu; j++) {
+ bevp0 = bevp;
+ bevp++;
+ bevp->offset = len_v3v3(bevp0->vec, bevp->vec);
+ /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */
+ if (bevp->offset > treshold) {
+ *seglen += bevp->offset;
+ *segbevcount += 1;
+ }
+ }
+ seglen++;
+ segbevcount++;
+ }
+ else {
+ bevp += resolu;
+ }
bl->nr += resolu;
- bevp += resolu;
}
prevbezt = bezt;
bezt++;
@@ -2679,15 +2775,22 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
}
else if (nu->type == CU_NURBS) {
if (nu->pntsv == 1) {
- len = (resolu * SEGMENTSU(nu));
+ len = (resolu * segcount);
bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList3");
+ if (need_seglen) {
+ bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelList3_seglen");
+ bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelList3_segbevcount");
+ }
BLI_addtail(bev, bl);
bl->nr = len;
bl->dupe_nr = 0;
bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
bl->charidx = nu->charidx;
+
bevp = bl->bevpoints;
+ seglen = bl->seglen;
+ segbevcount = bl->segbevcount;
BKE_nurb_makeCurve(nu, &bevp->vec[0],
do_tilt ? &bevp->alfa : NULL,
@@ -2695,6 +2798,31 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
do_weight ? &bevp->weight : NULL,
resolu, sizeof(BevPoint));
+ /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */
+ if (seglen != NULL) {
+ nr = segcount;
+ bevp0 = bevp;
+ bevp++;
+ while (nr) {
+ int j;
+ *seglen = 0;
+ *segbevcount = 0;
+ /* We keep last bevel segment zero-length. */
+ for (j = 0; j < ((nr == 1) ? (resolu - 1) : resolu); j++) {
+ bevp->offset = len_v3v3(bevp0->vec, bevp->vec);
+ if (bevp->offset > treshold) {
+ *seglen += bevp->offset;
+ *segbevcount += 1;
+ }
+ bevp0 = bevp;
+ bevp++;
+ }
+ seglen++;
+ segbevcount++;
+ nr--;
+ }
+ }
+
if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
bevlist_firstlast_direction_calc_from_bpoint(nu, bl);
}
@@ -2715,15 +2843,24 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
}
else {
bevp0 = bl->bevpoints;
+ bevp0->offset = 0;
bevp1 = bevp0 + 1;
}
nr--;
while (nr--) {
- if (fabsf(bevp0->vec[0] - bevp1->vec[0]) < 0.00001f) {
- if (fabsf(bevp0->vec[1] - bevp1->vec[1]) < 0.00001f) {
- if (fabsf(bevp0->vec[2] - bevp1->vec[2]) < 0.00001f) {
- bevp0->dupe_tag = true;
- bl->dupe_nr++;
+ if (seglen != NULL) {
+ if (fabsf(bevp1->offset) < treshold) {
+ bevp0->dupe_tag = true;
+ bl->dupe_nr++;
+ }
+ }
+ else {
+ if (fabsf(bevp0->vec[0] - bevp1->vec[0]) < 0.00001f) {
+ if (fabsf(bevp0->vec[1] - bevp1->vec[1]) < 0.00001f) {
+ if (fabsf(bevp0->vec[2] - bevp1->vec[2]) < 0.00001f) {
+ bevp0->dupe_tag = true;
+ bl->dupe_nr++;
+ }
}
}
}
@@ -2740,6 +2877,8 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
nr = bl->nr - bl->dupe_nr + 1; /* +1 because vectorbezier sets flag too */
blnew = MEM_mallocN(sizeof(BevList) + nr * sizeof(BevPoint), "makeBevelList4");
memcpy(blnew, bl, sizeof(BevList));
+ blnew->segbevcount = bl->segbevcount;
+ blnew->seglen = bl->seglen;
blnew->nr = 0;
BLI_remlink(bev, bl);
BLI_insertlinkbefore(bev, blnext, blnew); /* to make sure bevlijst is tuned with nurblist */
@@ -3070,7 +3209,13 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n
madd_v3_v3v3fl(p2_h2, p2, dvec_b, 1.0f / 3.0f);
}
- if (skip_align || (!ELEM(HD_ALIGN, bezt->h1, bezt->h2) && !ELEM(HD_ALIGN_DOUBLESIDE, bezt->h1, bezt->h2))) {
+ if (skip_align ||
+ /* when one handle is free, alignming makes no sense, see: T35952 */
+ (ELEM(HD_FREE, bezt->h1, bezt->h2)) ||
+ /* also when no handles are aligned, skip this step */
+ (!ELEM(HD_ALIGN, bezt->h1, bezt->h2) &&
+ !ELEM(HD_ALIGN_DOUBLESIDE, bezt->h1, bezt->h2)))
+ {
/* handles need to be updated during animation and applying stuff like hooks,
* but in such situations it's quite difficult to distinguish in which order
* align handles should be aligned so skip them for now */
@@ -3168,6 +3313,31 @@ void BKE_nurb_handles_calc(Nurb *nu) /* first, if needed, set handle flags */
calchandlesNurb_intern(nu, false);
}
+/**
+ * Workaround #BKE_nurb_handles_calc logic
+ * that makes unselected align to the selected handle.
+ */
+static void nurbList_handles_swap_select(Nurb *nu)
+{
+ BezTriple *bezt;
+ int i;
+
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if ((bezt->f1 & SELECT) != (bezt->f3 & SELECT)) {
+ bezt->f1 ^= SELECT;
+ bezt->f3 ^= SELECT;
+ }
+ }
+}
+
+/* internal use only (weak) */
+static void nurb_handles_calc__align_selected(Nurb *nu)
+{
+ nurbList_handles_swap_select(nu);
+ BKE_nurb_handles_calc(nu);
+ nurbList_handles_swap_select(nu);
+}
+
/* similar to BKE_nurb_handle_calc but for curves and
* figures out the previous and next for us */
void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt)
@@ -3365,7 +3535,9 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code)
}
bezt++;
}
- BKE_nurb_handles_calc(nu);
+
+ /* like BKE_nurb_handles_calc but moves selected */
+ nurb_handles_calc__align_selected(nu);
}
nu = nu->next;
}
@@ -3409,7 +3581,9 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code)
bezt++;
}
- BKE_nurb_handles_calc(nu);
+
+ /* like BKE_nurb_handles_calc but moves selected */
+ nurb_handles_calc__align_selected(nu);
}
}
}
@@ -4143,7 +4317,50 @@ bool BKE_curve_center_bounds(Curve *cu, float cent[3])
return false;
}
-void BKE_curve_translate(Curve *cu, float offset[3], const bool do_keys)
+
+void BKE_curve_transform_ex(Curve *cu, float mat[4][4], bool do_keys, float unit_scale)
+{
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int i;
+
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ i = nu->pntsu;
+ for (bezt = nu->bezt; i--; bezt++) {
+ 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;
+ }
+ BKE_nurb_handles_calc(nu);
+ }
+ else {
+ i = nu->pntsu * nu->pntsv;
+ for (bp = nu->bp; i--; bp++)
+ mul_m4_v3(mat, bp->vec);
+ }
+ }
+
+ if (do_keys && cu->key) {
+ KeyBlock *kb;
+ for (kb = cu->key->block.first; kb; kb = kb->next) {
+ float *fp = kb->data;
+ for (i = kb->totelem; i--; fp += 3) {
+ mul_m4_v3(mat, fp);
+ }
+ }
+ }
+}
+
+void BKE_curve_transform(Curve *cu, float mat[4][4], bool do_keys)
+{
+ float unit_scale = mat4_to_scale(mat);
+ BKE_curve_transform_ex(cu, mat, do_keys, unit_scale);
+}
+
+void BKE_curve_translate(Curve *cu, float offset[3], bool do_keys)
{
ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
Nurb *nu;
@@ -4230,6 +4447,45 @@ void BKE_curve_material_index_clear(Curve *cu)
}
}
+int BKE_curve_material_index_validate(Curve *cu)
+{
+ const int curvetype = BKE_curve_type_get(cu);
+ bool is_valid = true;
+
+ if (curvetype == OB_FONT) {
+ CharInfo *info = cu->strinfo;
+ const int max_idx = max_ii(0, cu->totcol); /* OB_FONT use 1 as first mat index, not 0!!! */
+ int i;
+ for (i = cu->len_wchar - 1; i >= 0; i--, info++) {
+ if (info->mat_nr > max_idx) {
+ info->mat_nr = 0;
+ is_valid = false;
+ }
+ }
+ }
+ else {
+ Nurb *nu;
+ const int max_idx = max_ii(0, cu->totcol - 1);
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ if (nu->mat_nr > max_idx) {
+ nu->mat_nr = 0;
+ if (curvetype == OB_CURVE) {
+ nu->charidx = 0;
+ }
+ is_valid = false;
+ }
+ }
+ }
+
+ if (!is_valid) {
+ DAG_id_tag_update(&cu->id, OB_RECALC_DATA);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect)
{
r_rect->xmin = cu->xof + tb->x;
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index d072088ac8e..528ff2d7b19 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -559,7 +559,7 @@ void defgroup_unique_name(bDeformGroup *dg, Object *ob)
static bool is_char_sep(const char c)
{
- return ELEM4(c, '.', ' ', '-', '_');
+ return ELEM(c, '.', ' ', '-', '_');
}
/* based on BLI_split_dirfile() / os.path.splitext(), "a.b.c" -> ("a.b", ".c") */
@@ -614,6 +614,7 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[
char replace[MAX_VGROUP_NAME] = ""; /* The replacement string */
char number[MAX_VGROUP_NAME] = ""; /* The number extension string */
char *index = NULL;
+ bool is_set = false;
/* always copy the name, since this can be called with an uninitialized string */
BLI_strncpy(name, from_name, MAX_VGROUP_NAME);
@@ -640,6 +641,7 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[
/* first case; separator . - _ with extensions r R l L */
if (is_char_sep(name[len - 2])) {
+ is_set = true;
switch (name[len - 1]) {
case 'l':
prefix[len - 1] = 0;
@@ -657,10 +659,14 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[
prefix[len - 1] = 0;
strcpy(replace, "L");
break;
+ default:
+ is_set = false;
}
}
+
/* case; beginning with r R l L, with separator after it */
- else if (is_char_sep(name[1])) {
+ if (!is_set && is_char_sep(name[1])) {
+ is_set = true;
switch (name[0]) {
case 'l':
strcpy(replace, "r");
@@ -682,40 +688,43 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[
BLI_strncpy(suffix, name + 1, sizeof(suffix));
prefix[0] = 0;
break;
+ default:
+ is_set = false;
}
}
- else if (len > 5) {
+
+ if (!is_set && len > 5) {
/* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
- index = BLI_strcasestr(prefix, "right");
- if (index == prefix || index == prefix + len - 5) {
- if (index[0] == 'r')
+ if (((index = BLI_strcasestr(prefix, "right")) == prefix) ||
+ (index == prefix + len - 5))
+ {
+ is_set = true;
+ if (index[0] == 'r') {
strcpy(replace, "left");
+ }
else {
- if (index[1] == 'I')
- strcpy(replace, "LEFT");
- else
- strcpy(replace, "Left");
+ strcpy(replace, (index[1] == 'I') ? "LEFT" : "Left");
}
*index = 0;
BLI_strncpy(suffix, index + 5, sizeof(suffix));
}
- else {
- index = BLI_strcasestr(prefix, "left");
- if (index == prefix || index == prefix + len - 4) {
- if (index[0] == 'l')
- strcpy(replace, "right");
- else {
- if (index[1] == 'E')
- strcpy(replace, "RIGHT");
- else
- strcpy(replace, "Right");
- }
- *index = 0;
- BLI_strncpy(suffix, index + 4, sizeof(suffix));
+ else if (((index = BLI_strcasestr(prefix, "left")) == prefix) ||
+ (index == prefix + len - 4))
+ {
+ is_set = true;
+ if (index[0] == 'l') {
+ strcpy(replace, "right");
+ }
+ else {
+ strcpy(replace, (index[1] == 'E') ? "RIGHT" : "Right");
}
+ *index = 0;
+ BLI_strncpy(suffix, index + 4, sizeof(suffix));
}
}
+ (void)is_set; /* quiet warning */
+
BLI_snprintf(name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 24b580672d1..93bb4849718 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -59,8 +59,10 @@
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
+#include "BKE_anim.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
@@ -79,6 +81,8 @@
#include "BKE_screen.h"
#include "BKE_tracking.h"
+#include "GPU_buffers.h"
+
#include "atomic_ops.h"
#include "depsgraph_private.h"
@@ -524,7 +528,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
if (ct->tar->type == OB_MESH)
node3->customdata_mask |= CD_MASK_MDEFORMVERT;
}
- else if (ELEM3(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK))
+ else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK))
dag_add_relation(dag, node3, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name);
else
dag_add_relation(dag, node3, node, DAG_RL_OB_DATA, cti->name);
@@ -688,6 +692,29 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Taper");
}
if (ob->type == OB_FONT) {
+ /* Really rather dirty hack. needs to support font family to work
+ * reliably on render export.
+ *
+ * This totally mimics behavior of regular verts duplication with
+ * parenting. The only tricky thing here is to get list of objects
+ * used for the custom "font".
+ *
+ * This shouldn't harm so much because this code only runs on DAG
+ * rebuild and this feature is not that commonly used.
+ *
+ * - sergey -
+ */
+ if (cu->family[0] != '\n') {
+ ListBase *duplilist;
+ DupliObject *dob;
+ duplilist = object_duplilist(G.main->eval_ctx, scene, ob);
+ for (dob = duplilist->first; dob; dob = dob->next) {
+ node2 = dag_get_node(dag, dob->ob);
+ dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Object Font");
+ }
+ free_object_duplilist(duplilist);
+ }
+
if (cu->textoncurve) {
node2 = dag_get_node(dag, cu->textoncurve);
/* Text on curve requires path to be evaluated for the target curve. */
@@ -803,7 +830,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
continue;
/* special case for camera tracking -- it doesn't use targets to define relations */
- if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
+ if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
int depends_on_camera = 0;
if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
@@ -843,7 +870,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO))
dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
else {
- if (ELEM3(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
+ if (ELEM(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
if (obt->type == OB_MESH)
node2->customdata_mask |= CD_MASK_MDEFORMVERT;
@@ -1386,7 +1413,7 @@ static bool check_object_needs_evaluation(Object *object)
if (object->type == OB_MESH) {
return object->derivedFinal == NULL;
}
- else if (ELEM5(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ else if (ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
return object->curve_cache == NULL;
}
@@ -1400,7 +1427,7 @@ static bool check_object_tagged_for_update(Object *object)
return true;
}
- if (ELEM6(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ if (ELEM(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
ID *data_id = object->data;
return (data_id->flag & (LIB_ID_RECALC_DATA | LIB_ID_RECALC)) != 0;
}
@@ -1747,7 +1774,8 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime)
}
/* node was checked to have lasttime != curtime, and is of type ID_OB */
-static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node, int curtime, int reset)
+static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node,
+ int curtime, unsigned int lay, bool reset)
{
DagAdjList *itA;
Object *ob;
@@ -1761,14 +1789,17 @@ static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node, int
if (reset || (ob->recalc & OB_RECALC_ALL)) {
if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &ob->id);
+ /* Don't tag nodes which are on invisible layer. */
+ if (itA->node->lay & lay) {
+ ob->recalc |= OB_RECALC_DATA;
+ lib_id_recalc_data_tag(bmain, &ob->id);
+ }
}
- flush_pointcache_reset(bmain, scene, itA->node, curtime, 1);
+ flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, true);
}
else
- flush_pointcache_reset(bmain, scene, itA->node, curtime, 0);
+ flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, false);
}
}
}
@@ -1885,10 +1916,12 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho
lib_id_recalc_data_tag(bmain, &ob->id);
}
- flush_pointcache_reset(bmain, sce, itA->node, lasttime, 1);
+ flush_pointcache_reset(bmain, sce, itA->node, lasttime,
+ lay, true);
}
else
- flush_pointcache_reset(bmain, sce, itA->node, lasttime, 0);
+ flush_pointcache_reset(bmain, sce, itA->node, lasttime,
+ lay, false);
}
}
}
@@ -1983,7 +2016,7 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
if (cti) {
/* special case for camera tracking -- it doesn't use targets to define relations */
- if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
+ if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
ob->recalc |= OB_RECALC_OB;
}
else if (cti->get_constraint_targets) {
@@ -2272,7 +2305,7 @@ static void dag_group_on_visible_update(Group *group)
group->id.flag |= LIB_DOIT;
for (go = group->gobject.first; go; go = go->next) {
- if (ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ if (ELEM(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
go->ob->recalc |= OB_RECALC_DATA;
go->ob->id.flag |= LIB_DOIT;
lib_id_recalc_tag(G.main, &go->ob->id);
@@ -2319,7 +2352,7 @@ void DAG_on_visible_update(Main *bmain, const bool do_time)
oblay = (node) ? node->lay : ob->lay;
if ((oblay & lay) & ~scene->lay_updated) {
- if (ELEM6(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
ob->recalc |= OB_RECALC_DATA;
lib_id_recalc_tag(bmain, &ob->id);
}
@@ -2472,6 +2505,14 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
}
+ if (ELEM(idtype, ID_MA, ID_TE)) {
+ obt = sce->basact ? sce->basact->object : NULL;
+ if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) {
+ BKE_texpaint_slots_refresh_object(sce, obt);
+ GPU_drawobject_free(obt->derivedFinal);
+ }
+ }
+
if (idtype == ID_MC) {
MovieClip *clip = (MovieClip *) id;
@@ -2481,7 +2522,7 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
bConstraint *con;
for (con = obt->constraints.first; con; con = con->next) {
bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
+ if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
CONSTRAINT_TYPE_OBJECTSOLVER))
{
obt->recalc |= OB_RECALC_OB;
@@ -2502,6 +2543,23 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
}
}
+ /* Not pretty to iterate all the nodes here, but it's as good as it
+ * could be with the current depsgraph design/
+ */
+ if (idtype == ID_IM) {
+ FOREACH_NODETREE(bmain, ntree, parent_id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->id == id) {
+ lib_id_recalc_tag(bmain, &ntree->id);
+ break;
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
if (idtype == ID_MSK) {
if (sce->nodetree) {
bNode *node;
@@ -2742,7 +2800,7 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
if (ob->type == OB_FONT) {
Curve *cu = ob->data;
- if (ELEM4((struct VFont *)id, cu->vfont, cu->vfontb, cu->vfonti, cu->vfontbi)) {
+ if (ELEM((struct VFont *)id, cu->vfont, cu->vfontb, cu->vfonti, cu->vfontbi)) {
ob->recalc |= (flag & OB_RECALC_ALL);
}
}
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index cf894e72324..98f0025921d 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -122,7 +122,7 @@ bool BKE_displist_has_faces(ListBase *lb)
DispList *dl;
for (dl = lb->first; dl; dl = dl->next) {
- if (ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
+ if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
return true;
}
}
@@ -653,8 +653,8 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis
bevels_to_filledpoly(cu, dispbase);
}
else {
- /* TODO, investigate passing zup instead of NULL */
- BKE_displist_fill(dispbase, dispbase, NULL, false);
+ const float z_up[3] = {0.0f, 0.0f, 1.0f};
+ BKE_displist_fill(dispbase, dispbase, z_up, false);
}
}
@@ -715,21 +715,20 @@ void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object *
if (!ob || ob->type != OB_MBALL)
return;
- if (ob->curve_cache) {
- BKE_displist_free(&(ob->curve_cache->disp));
- }
- else {
- ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
- }
+ if (ob == BKE_mball_basis_find(scene, ob)) {
+ if (ob->curve_cache) {
+ BKE_displist_free(&(ob->curve_cache->disp));
+ }
+ else {
+ ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
+ }
- if (ob->type == OB_MBALL) {
- if (ob == BKE_mball_basis_find(scene, ob)) {
- BKE_mball_polygonize(eval_ctx, scene, ob, &ob->curve_cache->disp);
- BKE_mball_texspace_calc(ob);
+ BKE_mball_polygonize(eval_ctx, scene, ob, &ob->curve_cache->disp);
+ BKE_mball_texspace_calc(ob);
- object_deform_mball(ob, &ob->curve_cache->disp);
- }
+ object_deform_mball(ob, &ob->curve_cache->disp);
+ /* NOP for MBALLs anyway... */
boundbox_displist_object(ob);
}
}
@@ -767,7 +766,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob,
if (mti->type == eModifierTypeType_Constructive)
return pretessellatePoint;
- if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
+ if (ELEM(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
pretessellatePoint = md;
/* this modifiers are moving point of tessellation automatically
@@ -1357,31 +1356,57 @@ static void fillBevelCap(Nurb *nu, DispList *dlb, float *prev_fp, ListBase *disp
BLI_addtail(dispbase, dl);
}
+static void calc_bevfac_segment_mapping(BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend)
+{
+ float normlen, normsum = 0.0f;
+ float *seglen = bl->seglen;
+ int *segbevcount = bl->segbevcount;
+ int bevcount = 0, nr = bl->nr;
+
+ float bev_fl = bevfac * (bl->nr - 1);
+ *r_bev = (int)bev_fl;
+
+ while (bevcount < nr - 1) {
+ normlen = *seglen / spline_length;
+ if (normsum + normlen > bevfac) {
+ bev_fl = bevcount + (bevfac - normsum) / normlen * *segbevcount;
+ *r_bev = (int) bev_fl;
+ *r_blend = bev_fl - *r_bev;
+ break;
+ }
+ normsum += normlen;
+ bevcount += *segbevcount;
+ segbevcount++;
+ seglen++;
+ }
+}
-static void calc_bevfac_spline_mapping(BevList *bl, float bevfac, float spline_length, const float *bevp_array,
+static void calc_bevfac_spline_mapping(BevList *bl, float bevfac,
+ float spline_length,
int *r_bev, float *r_blend)
{
const float len_target = bevfac * spline_length;
- float len = 0.0f;
- float len_step = 0.0f;
- int i;
- for (i = 0; i < bl->nr - 1; i++) {
- float len_next;
- len_step = bevp_array[i];
- len_next = len + len_step;
+ BevPoint *bevp = bl->bevpoints;
+ float len_next = 0.0f, len = 0.0f;
+ int i = 0, nr = bl->nr;
+
+ while (nr--) {
+ bevp++;
+ len_next = len + bevp->offset;
if (len_next > len_target) {
break;
}
len = len_next;
+ i++;
}
*r_bev = i;
- *r_blend = (len_target - len) / len_step;
+ *r_blend = (len_target - len) / bevp->offset;
}
-static void calc_bevfac_mapping_default(
- BevList *bl,
- int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend)
+static void calc_bevfac_mapping_default(BevList *bl,
+ int *r_start, float *r_firstblend,
+ int *r_steps, float *r_lastblend)
{
*r_start = 0;
*r_steps = bl->nr;
@@ -1389,19 +1414,11 @@ static void calc_bevfac_mapping_default(
*r_lastblend = 1.0f;
}
-static void calc_bevfac_mapping(
- Curve *cu, BevList *bl, Nurb *nu, const bool use_render_resolution,
+static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu,
int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend)
{
- const int resolu = (nu->type == CU_POLY) ?
- 1 : (use_render_resolution && (cu->resolu_ren != 0)) ?
- cu->resolu_ren : cu->resolu;
- const int segcount = ((nu->type == CU_POLY) ? bl->nr : nu->pntsu) - 1;
-
- float l, startf, endf, tmpf, total_length = 0.0f;
- float *bevp_array = NULL;
- float *segments = NULL;
- int end = 0, i, j;
+ float tmpf, total_length = 0.0f;
+ int end = 0, i;
if ((BKE_nurb_check_valid_u(nu) == false) ||
/* not essential, but skips unnecessary calculation */
@@ -1412,57 +1429,12 @@ static void calc_bevfac_mapping(
return;
}
- if ((cu->bevfac1_mapping != CU_BEVFAC_MAP_RESOLU) ||
- (cu->bevfac2_mapping != CU_BEVFAC_MAP_RESOLU))
+ if (ELEM(cu->bevfac1_mapping,
+ CU_BEVFAC_MAP_SEGMENT,
+ CU_BEVFAC_MAP_SPLINE))
{
- BezTriple *bezt, *bezt_prev;
- BevPoint *bevp, *bevp_prev;
- int bevp_i;
-
- bevp_array = MEM_mallocN(sizeof(*bevp_array) * (bl->nr - 1), "bevp_dists");
- segments = MEM_callocN(sizeof(*segments) * segcount, "bevp_segmentlengths");
- bevp_prev = bl->bevpoints;
- bevp = bevp_prev + 1;
-
- if (nu->type == CU_BEZIER) {
- bezt_prev = nu->bezt;
- bezt = bezt_prev + 1;
- for (i = 0, bevp_i = 0; i < segcount; i++, bezt_prev++, bezt++) {
- float seglen = 0.0f;
- if (bezt_prev->h2 == HD_VECT && bezt->h1 == HD_VECT) {
- seglen = len_v3v3(bevp->vec, bevp_prev->vec);
- BLI_assert(bevp_i < bl->nr - 1);
- bevp_array[bevp_i++] = seglen;
-
- bevp_prev = bevp++;
- }
- else {
- for (j = 0; j < resolu; j++, bevp_prev = bevp++) {
- l = len_v3v3(bevp->vec, bevp_prev->vec);
- seglen += l;
- BLI_assert(bevp_i < bl->nr - 1);
- bevp_array[bevp_i++] = l;
- }
- }
- BLI_assert(i < segcount);
- segments[i] = seglen;
- total_length += seglen;
- seglen = 0.0f;
- }
- }
- else {
- float seglen = 0.0f;
- for (i = 1, j = 0; i < bl->nr; i++, bevp_prev = bevp++) {
- BLI_assert(i - 1 < bl->nr);
- bevp_array[i - 1] = len_v3v3(bevp->vec, bevp_prev->vec);
- total_length += bevp_array[i - 1];
- seglen += bevp_array[i - 1];
- if ((i % resolu) == 0 || (bl->nr - 1) == i) {
- BLI_assert(j < segcount);
- segments[j++] = seglen;
- seglen = 0.0f;
- }
- }
+ for (i = 0; i < SEGMENTSU(nu); i++) {
+ total_length += bl->seglen[i];
}
}
@@ -1471,31 +1443,18 @@ static void calc_bevfac_mapping(
{
const float start_fl = cu->bevfac1 * (bl->nr - 1);
*r_start = (int)start_fl;
-
*r_firstblend = 1.0f - (start_fl - (*r_start));
break;
}
case CU_BEVFAC_MAP_SEGMENT:
{
- float sum = 0.0f;
- const float start_fl = cu->bevfac1 * (bl->nr - 1);
- *r_start = (int)start_fl;
-
- for (i = 0; i < segcount; i++) {
- l = segments[i] / total_length;
- if (sum + l > cu->bevfac1) {
- startf = i * resolu + (cu->bevfac1 - sum) / l * resolu;
- *r_start = (int) startf;
- *r_firstblend = 1.0f - (startf - *r_start);
- break;
- }
- sum += l;
- }
+ calc_bevfac_segment_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend);
+ *r_firstblend = 1.0f - *r_firstblend;
break;
}
case CU_BEVFAC_MAP_SPLINE:
{
- calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, bevp_array, r_start, r_firstblend);
+ calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend);
*r_firstblend = 1.0f - *r_firstblend;
break;
}
@@ -1513,27 +1472,13 @@ static void calc_bevfac_mapping(
}
case CU_BEVFAC_MAP_SEGMENT:
{
- float sum = 0.0f;
- const float end_fl = cu->bevfac2 * (bl->nr - 1);
- end = (int)end_fl;
-
+ calc_bevfac_segment_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend);
*r_steps = end - *r_start + 2;
- for (i = 0; i < segcount; i++) {
- l = segments[i] / total_length;
- if (sum + l > cu->bevfac2) {
- endf = i * resolu + (cu->bevfac2 - sum) / l * resolu;
- end = (int)endf;
- *r_lastblend = (endf - end);
- *r_steps = end - *r_start + 2;
- break;
- }
- sum += l;
- }
break;
}
case CU_BEVFAC_MAP_SPLINE:
{
- calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, bevp_array, &end, r_lastblend);
+ calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend);
*r_steps = end - *r_start + 2;
break;
}
@@ -1551,13 +1496,6 @@ static void calc_bevfac_mapping(
*r_steps = bl->nr - *r_start;
*r_lastblend = 1.0f;
}
-
- if (bevp_array) {
- MEM_freeN(bevp_array);
- }
- if (segments) {
- MEM_freeN(segments);
- }
}
static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase,
@@ -1567,7 +1505,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
Curve *cu = ob->data;
/* we do allow duplis... this is only displist on curve level */
- if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
+ if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
if (ob->type == OB_SURF) {
BKE_displist_make_surf(scene, ob, dispbase, r_dm_final, for_render, for_orco, use_render_resolution);
@@ -1576,7 +1514,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
ListBase dlbev;
ListBase nubase = {NULL, NULL};
- BLI_freelistN(&(ob->curve_cache->bev));
+ BKE_curve_bevelList_free(&ob->curve_cache->bev);
/* We only re-evlauate path if evaluation is not happening for orco.
* If the calculation happens for orco, we should never free data which
@@ -1668,8 +1606,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
continue;
}
- calc_bevfac_mapping(cu, bl, nu, use_render_resolution,
- &start, &firstblend, &steps, &lastblend);
+ calc_bevfac_mapping(cu, bl, nu, &start, &firstblend, &steps, &lastblend);
}
for (dlb = dlbev.first; dlb; dlb = dlb->next) {
@@ -1810,7 +1747,7 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, const bool for_orco)
/* The same check for duplis as in do_makeDispListCurveTypes.
* Happens when curve used for constraint/bevel was converted to mesh.
* check there is still needed for render displist and orco displists. */
- if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT))
+ if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT))
return;
BKE_object_free_derived_caches(ob);
@@ -1831,7 +1768,7 @@ void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *
const bool use_render_resolution)
{
if (ob->curve_cache == NULL) {
- ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
+ ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
}
do_makeDispListCurveTypes(scene, ob, dispbase, r_dm_final, true, for_orco, use_render_resolution);
@@ -1840,7 +1777,7 @@ void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *
void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase)
{
if (ob->curve_cache == NULL) {
- ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
+ ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
}
do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1, 1);
@@ -1895,8 +1832,8 @@ void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3])
/* this is confusing, there's also min_max_object, appplying the obmat... */
static void boundbox_displist_object(Object *ob)
{
- if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- /* Curver's BB is already calculated as a part of modifier stack,
+ if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ /* Curve's BB is already calculated as a part of modifier stack,
* here we only calculate object BB based on final display list.
*/
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 11737bccef2..4719013e2f8 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -2942,9 +2942,10 @@ static void mesh_faces_nearest_point_dp(void *userdata, int index, const float c
do {
float nearest_tmp[3], dist_sq;
- int vertex, edge;
-
- dist_sq = nearest_point_in_tri_surface_squared(t0, t1, t2, co, &vertex, &edge, nearest_tmp);
+
+ closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
+ dist_sq = len_squared_v3v3(co, nearest_tmp);
+
if (dist_sq < nearest->dist_sq) {
nearest->index = index;
nearest->dist_sq = dist_sq;
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index e74adea529b..ce7804d9878 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -910,7 +910,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
static void emDM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag UNUSED(flag))
{
emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
}
@@ -918,7 +918,7 @@ static void emDM_drawFacesTex(DerivedMesh *dm,
static void emDM_drawMappedFacesTex(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag UNUSED(flag))
{
emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
}
diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c
index 76ea340ecbd..442ab26ffc8 100644
--- a/source/blender/blenkernel/intern/editmesh_bvh.c
+++ b/source/blender/blenkernel/intern/editmesh_bvh.c
@@ -53,13 +53,17 @@ struct BMBVHTree {
int flag;
};
-BMBVHTree *BKE_bmbvh_new_from_editmesh(BMEditMesh *em, int flag, const float (*cos_cage)[3], const bool cos_cage_free)
+BMBVHTree *BKE_bmbvh_new_from_editmesh(
+ BMEditMesh *em, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free)
{
return BKE_bmbvh_new(em->bm, em->looptris, em->tottri, flag, cos_cage, cos_cage_free);
}
-BMBVHTree *BKE_bmbvh_new(BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag, const float (*cos_cage)[3],
-const bool cos_cage_free)
+BMBVHTree *BKE_bmbvh_new_ex(
+ BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free,
+ bool (*test_fn)(BMFace *, void *user_data), void *user_data)
{
/* could become argument */
const float epsilon = FLT_EPSILON * 2.0f;
@@ -69,6 +73,10 @@ const bool cos_cage_free)
int i;
int tottri;
+ /* avoid testing every tri */
+ BMFace *f_test, *f_test_prev;
+ bool test_fn_ret;
+
/* BKE_editmesh_tessface_calc() must be called already */
BLI_assert(looptris_tot != 0 || bm->totface == 0);
@@ -83,18 +91,22 @@ const bool cos_cage_free)
bmtree->cos_cage_free = cos_cage_free;
bmtree->flag = flag;
- if (flag & (BMBVH_RESPECT_SELECT)) {
+ if (test_fn) {
+ /* callback must do... */
+ BLI_assert(!(flag & (BMBVH_RESPECT_SELECT | BMBVH_RESPECT_HIDDEN)));
+
+ f_test_prev = NULL;
+ test_fn_ret = false;
+
tottri = 0;
for (i = 0; i < looptris_tot; i++) {
- if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_SELECT)) {
- tottri++;
+ f_test = looptris[i][0]->f;
+ if (f_test != f_test_prev) {
+ test_fn_ret = test_fn(f_test, user_data);
+ f_test_prev = f_test;
}
- }
- }
- else if (flag & (BMBVH_RESPECT_HIDDEN)) {
- tottri = 0;
- for (i = 0; i < looptris_tot; i++) {
- if (!BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) {
+
+ if (test_fn_ret) {
tottri++;
}
}
@@ -105,17 +117,19 @@ const bool cos_cage_free)
bmtree->tree = BLI_bvhtree_new(tottri, epsilon, 8, 8);
- for (i = 0; i < looptris_tot; i++) {
+ f_test_prev = NULL;
+ test_fn_ret = false;
- if (flag & BMBVH_RESPECT_SELECT) {
+ for (i = 0; i < looptris_tot; i++) {
+ if (test_fn) {
/* note, the arrays wont align now! take care */
- if (!BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_SELECT)) {
- continue;
+ f_test = looptris[i][0]->f;
+ if (f_test != f_test_prev) {
+ test_fn_ret = test_fn(f_test, user_data);
+ f_test_prev = f_test;
}
- }
- else if (flag & BMBVH_RESPECT_HIDDEN) {
- /* note, the arrays wont align now! take care */
- if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) {
+
+ if (!test_fn_ret) {
continue;
}
}
@@ -139,6 +153,38 @@ const bool cos_cage_free)
return bmtree;
}
+static bool bm_face_is_select(BMFace *f, void *UNUSED(user_data))
+{
+ return (BM_elem_flag_test(f, BM_ELEM_SELECT) != 0);
+}
+
+static bool bm_face_is_not_hidden(BMFace *f, void *UNUSED(user_data))
+{
+ return (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == 0);
+}
+
+BMBVHTree *BKE_bmbvh_new(
+ BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free)
+{
+ bool (*test_fn)(BMFace *, void *user_data);
+
+ if (flag & BMBVH_RESPECT_SELECT) {
+ test_fn = bm_face_is_select;
+ }
+ else if (flag & BMBVH_RESPECT_HIDDEN) {
+ test_fn = bm_face_is_not_hidden;
+ }
+ else {
+ test_fn = NULL;
+ }
+
+ flag &= ~(BMBVH_RESPECT_SELECT | BMBVH_RESPECT_HIDDEN);
+
+ return BKE_bmbvh_new_ex(bm, looptris, looptris_tot, flag, cos_cage, cos_cage_free, test_fn, NULL);
+}
+
+
void BKE_bmbvh_free(BMBVHTree *bmtree)
{
BLI_bvhtree_free(bmtree->tree);
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index e28152dbc1a..4859aa8f791 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -935,7 +935,7 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected
if (pd->flag & PFIELD_DO_LOCATION) {
madd_v3_v3fl(total_force, force, 1.0f/point->vel_to_sec);
- if (ELEM3(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_SMOKEFLOW)==0 && pd->f_flow != 0.0f) {
+ if (ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_SMOKEFLOW)==0 && pd->f_flow != 0.0f) {
madd_v3_v3fl(total_force, point->vel, -pd->f_flow * efd->falloff);
}
}
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index a8de9b69fbe..09c1dcf701d 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -276,7 +276,7 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix,
int matches = 0;
/* sanity checks */
- if (ELEM4(NULL, dst, src, dataPrefix, dataName))
+ if (ELEM(NULL, dst, src, dataPrefix, dataName))
return 0;
else if ((dataPrefix[0] == 0) || (dataName[0] == 0))
return 0;
@@ -522,17 +522,28 @@ bool calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, floa
/* only loop over keyframes to find extents for values if needed */
if (ymin || ymax) {
- BezTriple *bezt;
+ BezTriple *bezt, *prevbezt = NULL;
- for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) {
- if ((do_sel_only == false) || BEZSELECTED(bezt)) {
+ for (bezt = fcu->bezt, i = 0; i < fcu->totvert; prevbezt = bezt, bezt++, i++) {
+ if ((do_sel_only == false) || BEZSELECTED(bezt)) {
+ /* keyframe itself */
+ yminv = min_ff(yminv, bezt->vec[1][1]);
+ ymaxv = max_ff(ymaxv, bezt->vec[1][1]);
+
if (include_handles) {
- yminv = min_ffff(yminv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
- ymaxv = max_ffff(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
- }
- else {
- yminv = min_ff(yminv, bezt->vec[1][1]);
- ymaxv = max_ff(ymaxv, bezt->vec[1][1]);
+ /* left handle - only if applicable
+ * NOTE: for the very first keyframe, the left handle actually has no bearings on anything
+ */
+ if (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)) {
+ yminv = min_ff(yminv, bezt->vec[0][1]);
+ ymaxv = max_ff(ymaxv, bezt->vec[0][1]);
+ }
+
+ /* right handle - only if applicable */
+ if (bezt->ipo == BEZT_IPO_BEZ) {
+ yminv = min_ff(yminv, bezt->vec[2][1]);
+ ymaxv = max_ff(ymaxv, bezt->vec[2][1]);
+ }
}
foundvert = true;
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index 445acc850e6..4aa1b49ea13 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -187,7 +187,7 @@ FreestyleLineSet *BKE_freestyle_lineset_add(FreestyleConfig *config, const char
BLI_addtail(&config->linesets, (void *)lineset);
BKE_freestyle_lineset_set_active_index(config, lineset_index);
- lineset->linestyle = BKE_new_linestyle("LineStyle", NULL);
+ lineset->linestyle = BKE_linestyle_new("LineStyle", NULL);
lineset->flags |= FREESTYLE_LINESET_ENABLED;
lineset->selection = FREESTYLE_SEL_VISIBILITY | FREESTYLE_SEL_EDGE_TYPES | FREESTYLE_SEL_IMAGE_BORDER;
lineset->qi = FREESTYLE_QI_VISIBLE;
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index c381084cfd2..e226e9d9797 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -506,7 +506,7 @@ void gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
bGPDlayer *gpl;
/* error checking */
- if (ELEM3(NULL, gpd, gpd->layers.first, active))
+ if (ELEM(NULL, gpd, gpd->layers.first, active))
return;
/* loop over layers deactivating all */
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index 2e201a0b8e8..1b7a03ec80e 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -73,6 +73,8 @@ static IDType idtypes[] = {
{ ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE },
{ ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE },
{ ID_PA, "ParticleSettings", "particles", 0 },
+ { ID_PAL, "Palettes", "palettes", IDTYPE_FLAGS_ISLINKABLE },
+ { ID_PC, "PaintCurve", "paint_curves", IDTYPE_FLAGS_ISLINKABLE },
{ ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE },
{ ID_SCR, "Screen", "screens", 0 },
{ ID_SEQ, "Sequence", "sequences", 0 }, /* not actually ID data */
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 3188676fb6c..4dbd15a3774 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -64,7 +64,7 @@ static char idp_size_table[] = {
/** \name IDP Array API
* \{ */
-#define GETPROP(prop, i) (((IDProperty *)(prop)->data.pointer) + (i))
+#define GETPROP(prop, i) &(IDP_IDPArray(prop)[i])
/* --------- property array type -------------*/
@@ -251,7 +251,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen)
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
newsize = newlen;
- newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;\
+ newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
if (is_grow == false)
idp_resize_group_array(prop, newlen, prop->data.pointer);
@@ -821,7 +821,7 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
case IDP_INT:
return (IDP_Int(prop1) == IDP_Int(prop2));
case IDP_FLOAT:
-#if defined(DEBUG) && defined(WITH_PYTHON)
+#if !defined(NDEBUG) && defined(WITH_PYTHON)
{
float p1 = IDP_Float(prop1);
float p2 = IDP_Float(prop2);
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index db5c212d1db..805c1250c5d 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1257,7 +1257,7 @@ static bool do_add_image_extension(char *string, const char imtype, const ImageF
extension = extension_test;
}
#endif
- else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
+ else if (ELEM(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
if (!BLI_testextensie(string, extension_test = ".png"))
extension = extension_test;
}
@@ -1900,7 +1900,7 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
ibuf->ftype = RADHDR;
}
#endif
- else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
+ else if (ELEM(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
ibuf->ftype = PNG;
if (imtype == R_IMF_IMTYPE_PNG) {
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index 6682b1a9b2d..4d80256426d 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1804,6 +1804,7 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo
return 1;
}
+
int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors)
{
unsigned int i=0;
@@ -1888,10 +1889,8 @@ int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase *
//if (do_extra_solve)
// cloth_calc_helper_forces(ob, clmd, initial_cos, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
- for (i = 0; i < numverts; i++) {
-
- if (do_extra_solve) {
-
+ if (do_extra_solve) {
+ for (i = 0; i < numverts; i++) {
if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (verts [i].flags & CLOTH_VERT_FLAG_PINNED))
continue;
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 7385322ddeb..51cf26063c7 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1308,8 +1308,8 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i
* - they were degrees/10
* - we need radians for RNA to do the right thing
*/
- if ( ((icu->blocktype == ID_OB) && ELEM3(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) ||
- ((icu->blocktype == ID_PO) && ELEM3(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) )
+ if ( ((icu->blocktype == ID_OB) && ELEM(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) ||
+ ((icu->blocktype == ID_PO) && ELEM(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) )
{
const float fac = (float)M_PI / 18.0f; //10.0f * M_PI/180.0f;
@@ -1341,7 +1341,7 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i
DriverVar *dvar = fcu->driver->variables.first;
DriverTarget *dtar = &dvar->targets[0];
- if (ELEM3(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) {
+ if (ELEM(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) {
const float fac = (float)M_PI / 18.0f;
dst->vec[0][0] *= fac;
@@ -1388,7 +1388,7 @@ static void ipo_to_animato(ID *id, Ipo *ipo, char actname[], char constname[], S
IpoCurve *icu;
/* sanity check */
- if (ELEM3(NULL, ipo, anim, drivers))
+ if (ELEM(NULL, ipo, anim, drivers))
return;
if (G.debug & G_DEBUG) printf("ipo_to_animato\n");
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index ea55f32ea05..3f12e3efcc7 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -729,7 +729,8 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh
Curve *cu;
int a;
CurveDeform cd;
- int use_vgroups;
+ MDeformVert *dvert = NULL;
+ int defgrp_index = -1;
const bool is_neg_axis = (defaxis > 2);
if (cuOb->type != OB_CURVE)
@@ -750,75 +751,63 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh
cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 0.0f;
}
- /* check whether to use vertex groups (only possible if target is a Mesh)
- * we want either a Mesh with no derived data, or derived data with
- * deformverts
+ /* Check whether to use vertex groups (only possible if target is a Mesh or Lattice).
+ * We want either a Mesh/Lattice with no derived data, or derived data with deformverts.
*/
- if (target->type == OB_MESH) {
- /* if there's derived data without deformverts, don't use vgroups */
- if (dm) {
- use_vgroups = (dm->getVertData(dm, 0, CD_MDEFORMVERT) != NULL);
- }
- else {
- Mesh *me = target->data;
- use_vgroups = (me->dvert != NULL);
+ if (vgroup && vgroup[0] && ELEM(target->type, OB_MESH, OB_LATTICE)) {
+ defgrp_index = defgroup_name_index(target, vgroup);
+
+ if (defgrp_index != -1) {
+ /* if there's derived data without deformverts, don't use vgroups */
+ if (dm) {
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+ }
+ else if (target->type == OB_LATTICE) {
+ dvert = ((Lattice *)target->data)->dvert;
+ }
+ else {
+ dvert = ((Mesh *)target->data)->dvert;
+ }
}
}
- else {
- use_vgroups = false;
- }
-
- if (vgroup && vgroup[0] && use_vgroups) {
- Mesh *me = target->data;
- const int defgrp_index = defgroup_name_index(target, vgroup);
- if (defgrp_index != -1 && (me->dvert || dm)) {
- MDeformVert *dvert = me->dvert;
- float vec[3];
- float weight;
-
+ if (dvert) {
+ MDeformVert *dvert_iter;
+ float vec[3];
- if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
- dvert = me->dvert;
- for (a = 0; a < numVerts; a++, dvert++) {
- if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
- weight = defvert_find_weight(dvert, defgrp_index);
-
- if (weight > 0.0f) {
- mul_m4_v3(cd.curvespace, vertexCos[a]);
- copy_v3_v3(vec, vertexCos[a]);
- calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
- interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
- mul_m4_v3(cd.objectspace, vertexCos[a]);
- }
+ if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
+ for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
+ const float weight = defvert_find_weight(dvert_iter, defgrp_index);
+
+ if (weight > 0.0f) {
+ mul_m4_v3(cd.curvespace, vertexCos[a]);
+ copy_v3_v3(vec, vertexCos[a]);
+ calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
+ interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
+ mul_m4_v3(cd.objectspace, vertexCos[a]);
}
}
- else {
- /* set mesh min/max bounds */
- INIT_MINMAX(cd.dmin, cd.dmax);
-
- for (a = 0; a < numVerts; a++, dvert++) {
- if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
-
- if (defvert_find_weight(dvert, defgrp_index) > 0.0f) {
- mul_m4_v3(cd.curvespace, vertexCos[a]);
- minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]);
- }
+ }
+ else {
+ /* set mesh min/max bounds */
+ INIT_MINMAX(cd.dmin, cd.dmax);
+
+ for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
+ if (defvert_find_weight(dvert_iter, defgrp_index) > 0.0f) {
+ mul_m4_v3(cd.curvespace, vertexCos[a]);
+ minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]);
}
-
- dvert = me->dvert;
- for (a = 0; a < numVerts; a++, dvert++) {
- if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
-
- weight = defvert_find_weight(dvert, defgrp_index);
-
- if (weight > 0.0f) {
- /* already in 'cd.curvespace', prev for loop */
- copy_v3_v3(vec, vertexCos[a]);
- calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
- interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
- mul_m4_v3(cd.objectspace, vertexCos[a]);
- }
+ }
+
+ for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
+ const float weight = defvert_find_weight(dvert_iter, defgrp_index);
+
+ if (weight > 0.0f) {
+ /* already in 'cd.curvespace', prev for loop */
+ copy_v3_v3(vec, vertexCos[a]);
+ calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
+ interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
+ mul_m4_v3(cd.objectspace, vertexCos[a]);
}
}
}
@@ -1166,6 +1155,28 @@ void BKE_lattice_center_bounds(Lattice *lt, float cent[3])
mid_v3_v3v3(cent, min, max);
}
+void BKE_lattice_transform(Lattice *lt, float mat[4][4], bool do_keys)
+{
+ BPoint *bp = lt->def;
+ int i = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ while (i--) {
+ mul_m4_v3(mat, bp->vec);
+ bp++;
+ }
+
+ if (do_keys && lt->key) {
+ KeyBlock *kb;
+
+ for (kb = lt->key->block.first; kb; kb = kb->next) {
+ float *fp = kb->data;
+ for (i = kb->totelem; i--; fp += 3) {
+ mul_m4_v3(mat, fp);
+ }
+ }
+ }
+}
+
void BKE_lattice_translate(Lattice *lt, float offset[3], bool do_keys)
{
int i, numVerts;
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 1f3327b0dc4..515287de336 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -104,6 +104,7 @@
#include "BKE_mask.h"
#include "BKE_node.h"
#include "BKE_object.h"
+#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_packedFile.h"
#include "BKE_speaker.h"
@@ -382,7 +383,7 @@ bool id_copy(ID *id, ID **newid, bool test)
if (!test) *newid = (ID *)BKE_mask_copy((Mask *)id);
return true;
case ID_LS:
- if (!test) *newid = (ID *)BKE_copy_linestyle((FreestyleLineStyle *)id);
+ if (!test) *newid = (ID *)BKE_linestyle_copy((FreestyleLineStyle *)id);
return true;
}
@@ -515,6 +516,10 @@ ListBase *which_libbase(Main *mainlib, short type)
return &(mainlib->mask);
case ID_LS:
return &(mainlib->linestyle);
+ case ID_PAL:
+ return &(mainlib->palettes);
+ case ID_PC:
+ return &(mainlib->paintcurves);
}
return NULL;
}
@@ -596,6 +601,8 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[a++] = &(main->text);
lb[a++] = &(main->sound);
lb[a++] = &(main->group);
+ lb[a++] = &(main->palettes);
+ lb[a++] = &(main->paintcurves);
lb[a++] = &(main->brush);
lb[a++] = &(main->script);
lb[a++] = &(main->particle);
@@ -731,6 +738,12 @@ static ID *alloc_libblock_notest(short type)
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;
}
return id;
}
@@ -1005,7 +1018,13 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
BKE_mask_free(bmain, (Mask *)id);
break;
case ID_LS:
- BKE_free_linestyle((FreestyleLineStyle *)id);
+ BKE_linestyle_free((FreestyleLineStyle *)id);
+ break;
+ case ID_PAL:
+ BKE_palette_free((Palette *)id);
+ break;
+ case ID_PC:
+ BKE_paint_curve_free((PaintCurve *)id);
break;
}
@@ -1131,14 +1150,17 @@ void BKE_main_unlock(struct Main *bmain)
}
/* ***************** ID ************************ */
-
-
-ID *BKE_libblock_find_name(const short type, const char *name) /* type: "OB" or "MA" etc */
+ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name)
{
- ListBase *lb = which_libbase(G.main, type);
+ ListBase *lb = which_libbase(bmain, type);
BLI_assert(lb != NULL);
return BLI_findstring(lb, name, offsetof(ID, name) + 2);
}
+ID *BKE_libblock_find_name(const short type, const char *name)
+{
+ return BKE_libblock_find_name_ex(G.main, type, name);
+}
+
void id_sort_by_name(ListBase *lb, ID *id)
{
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index d92fa328e87..45695844101 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -43,6 +43,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BKE_context.h"
+#include "BKE_freestyle.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_linestyle.h"
@@ -51,6 +53,8 @@
#include "BKE_colortools.h"
#include "BKE_animsys.h"
+#include "RNA_access.h"
+
static const char *modifier_name[LS_MODIFIER_NUM] = {
NULL,
"Along Stroke",
@@ -99,12 +103,12 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle)
BLI_listbase_clear(&linestyle->thickness_modifiers);
BLI_listbase_clear(&linestyle->geometry_modifiers);
- BKE_add_linestyle_geometry_modifier(linestyle, NULL, LS_MODIFIER_SAMPLING);
+ BKE_linestyle_geometry_modifier_add(linestyle, NULL, LS_MODIFIER_SAMPLING);
linestyle->caps = LS_CAPS_BUTT;
}
-FreestyleLineStyle *BKE_new_linestyle(const char *name, struct Main *main)
+FreestyleLineStyle *BKE_linestyle_new(const char *name, struct Main *main)
{
FreestyleLineStyle *linestyle;
@@ -118,7 +122,7 @@ FreestyleLineStyle *BKE_new_linestyle(const char *name, struct Main *main)
return linestyle;
}
-void BKE_free_linestyle(FreestyleLineStyle *linestyle)
+void BKE_linestyle_free(FreestyleLineStyle *linestyle)
{
LineStyleModifier *m;
@@ -137,33 +141,33 @@ void BKE_free_linestyle(FreestyleLineStyle *linestyle)
BKE_free_animdata(&linestyle->id);
while ((m = (LineStyleModifier *)linestyle->color_modifiers.first))
- BKE_remove_linestyle_color_modifier(linestyle, m);
+ BKE_linestyle_color_modifier_remove(linestyle, m);
while ((m = (LineStyleModifier *)linestyle->alpha_modifiers.first))
- BKE_remove_linestyle_alpha_modifier(linestyle, m);
+ BKE_linestyle_alpha_modifier_remove(linestyle, m);
while ((m = (LineStyleModifier *)linestyle->thickness_modifiers.first))
- BKE_remove_linestyle_thickness_modifier(linestyle, m);
+ BKE_linestyle_thickness_modifier_remove(linestyle, m);
while ((m = (LineStyleModifier *)linestyle->geometry_modifiers.first))
- BKE_remove_linestyle_geometry_modifier(linestyle, m);
+ BKE_linestyle_geometry_modifier_remove(linestyle, m);
}
-FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle)
+FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle)
{
FreestyleLineStyle *new_linestyle;
LineStyleModifier *m;
int a;
- new_linestyle = BKE_new_linestyle(linestyle->id.name + 2, NULL);
- BKE_free_linestyle(new_linestyle);
+ new_linestyle = BKE_linestyle_new(linestyle->id.name + 2, NULL);
+ 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_copy_linestyle");
+ 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);
}
}
if (linestyle->nodetree) {
- linestyle->nodetree = ntreeCopyTree(linestyle->nodetree);
+ new_linestyle->nodetree = ntreeCopyTree(linestyle->nodetree);
}
new_linestyle->r = linestyle->r;
@@ -198,17 +202,29 @@ FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle)
new_linestyle->texstep = linestyle->texstep;
new_linestyle->pr_texture = linestyle->pr_texture;
for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next)
- BKE_copy_linestyle_color_modifier(new_linestyle, m);
+ BKE_linestyle_color_modifier_copy(new_linestyle, m);
for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next)
- BKE_copy_linestyle_alpha_modifier(new_linestyle, m);
+ BKE_linestyle_alpha_modifier_copy(new_linestyle, m);
for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next)
- BKE_copy_linestyle_thickness_modifier(new_linestyle, m);
+ BKE_linestyle_thickness_modifier_copy(new_linestyle, m);
for (m = (LineStyleModifier *)linestyle->geometry_modifiers.first; m; m = m->next)
- BKE_copy_linestyle_geometry_modifier(new_linestyle, m);
+ BKE_linestyle_geometry_modifier_copy(new_linestyle, m);
return new_linestyle;
}
+FreestyleLineStyle *BKE_linestyle_active_from_scene(Scene *scene)
+{
+ SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ FreestyleConfig *config = &actsrl->freestyleConfig;
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
+
+ if (lineset) {
+ return lineset->linestyle;
+ }
+ return NULL;
+}
+
static LineStyleModifier *new_modifier(const char *name, int type, size_t size)
{
LineStyleModifier *m;
@@ -255,7 +271,7 @@ static LineStyleModifier *alloc_color_modifier(const char *name, int type)
return new_modifier(name, type, size);
}
-LineStyleModifier *BKE_add_linestyle_color_modifier(FreestyleLineStyle *linestyle, const char *name, int type)
+LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type)
{
LineStyleModifier *m;
@@ -289,7 +305,7 @@ LineStyleModifier *BKE_add_linestyle_color_modifier(FreestyleLineStyle *linestyl
return m;
}
-LineStyleModifier *BKE_copy_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
LineStyleModifier *new_m;
@@ -344,7 +360,7 @@ LineStyleModifier *BKE_copy_linestyle_color_modifier(FreestyleLineStyle *linesty
return new_m;
}
-int BKE_remove_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+int BKE_linestyle_color_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
if (BLI_findindex(&linestyle->color_modifiers, m) == -1)
return -1;
@@ -389,7 +405,7 @@ static LineStyleModifier *alloc_alpha_modifier(const char *name, int type)
return new_modifier(name, type, size);
}
-LineStyleModifier *BKE_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, const char *name, int type)
+LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type)
{
LineStyleModifier *m;
@@ -435,7 +451,7 @@ LineStyleModifier *BKE_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyl
return m;
}
-LineStyleModifier *BKE_copy_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
LineStyleModifier *new_m;
@@ -493,7 +509,7 @@ LineStyleModifier *BKE_copy_linestyle_alpha_modifier(FreestyleLineStyle *linesty
return new_m;
}
-int BKE_remove_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+int BKE_linestyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
if (BLI_findindex(&linestyle->alpha_modifiers, m) == -1)
return -1;
@@ -542,7 +558,7 @@ static LineStyleModifier *alloc_thickness_modifier(const char *name, int type)
return new_modifier(name, type, size);
}
-LineStyleModifier *BKE_add_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, const char *name, int type)
+LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type)
{
LineStyleModifier *m;
@@ -604,7 +620,7 @@ LineStyleModifier *BKE_add_linestyle_thickness_modifier(FreestyleLineStyle *line
return m;
}
-LineStyleModifier *BKE_copy_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
LineStyleModifier *new_m;
@@ -681,7 +697,7 @@ LineStyleModifier *BKE_copy_linestyle_thickness_modifier(FreestyleLineStyle *lin
return new_m;
}
-int BKE_remove_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+int BKE_linestyle_thickness_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
if (BLI_findindex(&linestyle->thickness_modifiers, m) == -1)
return -1;
@@ -756,7 +772,7 @@ static LineStyleModifier *alloc_geometry_modifier(const char *name, int type)
return new_modifier(name, type, size);
}
-LineStyleModifier *BKE_add_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, const char *name, int type)
+LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type)
{
LineStyleModifier *m;
@@ -874,7 +890,7 @@ LineStyleModifier *BKE_add_linestyle_geometry_modifier(FreestyleLineStyle *lines
return m;
}
-LineStyleModifier *BKE_copy_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
LineStyleModifier *new_m;
@@ -1008,7 +1024,7 @@ LineStyleModifier *BKE_copy_linestyle_geometry_modifier(FreestyleLineStyle *line
return new_m;
}
-int BKE_remove_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+int BKE_linestyle_geometry_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
if (BLI_findindex(&linestyle->geometry_modifiers, m) == -1)
return -1;
@@ -1025,27 +1041,27 @@ static void move_modifier(ListBase *lb, LineStyleModifier *modifier, int directi
BLI_insertlinkafter(lb, modifier->next, modifier);
}
-void BKE_move_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+void BKE_linestyle_color_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
{
move_modifier(&linestyle->color_modifiers, modifier, direction);
}
-void BKE_move_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+void BKE_linestyle_alpha_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
{
move_modifier(&linestyle->alpha_modifiers, modifier, direction);
}
-void BKE_move_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+void BKE_linestyle_thickness_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
{
move_modifier(&linestyle->thickness_modifiers, modifier, direction);
}
-void BKE_move_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+void BKE_linestyle_geometry_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
{
move_modifier(&linestyle->geometry_modifiers, modifier, direction);
}
-void BKE_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase)
+void BKE_linestyle_modifier_list_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase)
{
LineStyleModifier *m;
ColorBand *color_ramp;
@@ -1076,7 +1092,7 @@ void BKE_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *list
}
}
-char *BKE_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *color_ramp)
+char *BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *color_ramp)
{
LineStyleModifier *m;
bool found = false;
@@ -1107,11 +1123,11 @@ char *BKE_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *c
return BLI_sprintfN("color_modifiers[\"%s\"].color_ramp", name_esc);
}
}
- printf("BKE_path_from_ID_to_color_ramp: No color ramps correspond to the given pointer.\n");
+ printf("BKE_linestyle_path_to_color_ramp: No color ramps correspond to the given pointer.\n");
return NULL;
}
-void BKE_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Object *ob)
+void BKE_linestyle_target_object_unlink(FreestyleLineStyle *linestyle, struct Object *ob)
{
LineStyleModifier *m;
@@ -1137,3 +1153,64 @@ void BKE_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Ob
}
}
}
+
+bool BKE_linestyle_use_textures(FreestyleLineStyle *linestyle, const bool use_shading_nodes)
+{
+ if (use_shading_nodes) {
+ if (linestyle && linestyle->use_nodes && linestyle->nodetree) {
+ bNode *node;
+
+ for (node = linestyle->nodetree->nodes.first; node; node = node->next) {
+ if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
+ return true;
+ }
+ }
+ }
+ }
+ else {
+ if (linestyle && (linestyle->flag & LS_TEXTURE)) {
+ return (linestyle->mtex[0] != NULL);
+ }
+ }
+ return false;
+}
+
+void BKE_linestyle_default_shader(const bContext *C, FreestyleLineStyle *linestyle)
+{
+ bNode *uv_along_stroke, *input_texure, *output_linestyle;
+ bNodeSocket *fromsock, *tosock;
+ bNodeTree *ntree;
+
+ BLI_assert(linestyle->nodetree == NULL);
+
+ ntree = ntreeAddTree(NULL, "stroke_shader", "ShaderNodeTree");
+
+ linestyle->nodetree = ntree;
+
+ uv_along_stroke = nodeAddStaticNode(C, ntree, SH_NODE_UVALONGSTROKE);
+ uv_along_stroke->locx = 0.0f;
+ uv_along_stroke->locy = 300.0f;
+ uv_along_stroke->custom1 = 0; // use_tips
+
+ input_texure = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
+ input_texure->locx = 200.0f;
+ input_texure->locy = 300.0f;
+
+ output_linestyle = nodeAddStaticNode(C, ntree, SH_NODE_OUTPUT_LINESTYLE);
+ output_linestyle->locx = 400.0f;
+ output_linestyle->locy = 300.0f;
+ output_linestyle->custom1 = MA_RAMP_BLEND;
+ output_linestyle->custom2 = 0; // use_clamp
+
+ nodeSetActive(ntree, input_texure);
+
+ fromsock = BLI_findlink(&uv_along_stroke->outputs, 0); // UV
+ tosock = BLI_findlink(&input_texure->inputs, 0); // UV
+ nodeAddLink(ntree, uv_along_stroke, fromsock, input_texure, tosock);
+
+ fromsock = BLI_findlink(&input_texure->outputs, 0); // Color
+ tosock = BLI_findlink(&output_linestyle->inputs, 0); // Color
+ nodeAddLink(ntree, input_texure, fromsock, output_linestyle, tosock);
+
+ ntreeUpdateTree(CTX_data_main(C), ntree);
+}
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 4147750c356..1c40446c217 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -1212,7 +1212,7 @@ void BKE_mask_point_parent_matrix_get(MaskSplinePoint *point, float ctime, float
}
invert_m3_m3(mask_to_clip_matrix, mask_from_clip_matrix);
- mul_serie_m3(parent_matrix, mask_to_clip_matrix, H, mask_from_clip_matrix, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(parent_matrix, mask_from_clip_matrix, H, mask_to_clip_matrix);
}
}
}
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 35207595103..4dc8ed21463 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -326,7 +326,7 @@ static void maskrasterize_spline_differentiate_point_outset(float (*diff_feather
* are to any of the triangle edges.
*/
static bool layer_bucket_isect_test(
- MaskRasterLayer *layer, unsigned int face_index,
+ const MaskRasterLayer *layer, unsigned int face_index,
const unsigned int bucket_x, const unsigned int bucket_y,
const float bucket_size_x, const float bucket_size_y,
const float bucket_max_rad_squared)
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 971db1997de..eeca60f7ef4 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -63,6 +63,7 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
+#include "BKE_scene.h"
#include "BKE_node.h"
#include "BKE_curve.h"
@@ -111,6 +112,9 @@ void BKE_material_free_ex(Material *ma, bool do_id_user)
MEM_freeN(ma->nodetree);
}
+ if (ma->texpaintslot)
+ MEM_freeN(ma->texpaintslot);
+
if (ma->gpumaterial.first)
GPU_material_free(ma);
}
@@ -269,7 +273,8 @@ Material *localize_material(Material *ma)
if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
-
+
+ man->texpaintslot = NULL;
man->preview = NULL;
if (ma->nodetree)
@@ -467,7 +472,7 @@ Material ***give_matarar(Object *ob)
me = ob->data;
return &(me->mat);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
cu = ob->data;
return &(cu->mat);
}
@@ -488,7 +493,7 @@ short *give_totcolp(Object *ob)
me = ob->data;
return &(me->totcol);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
cu = ob->data;
return &(cu->totcol);
}
@@ -1291,7 +1296,7 @@ bool object_remove_material_slot(Object *ob)
}
/* check indices from mesh */
- if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
material_data_index_remove_id((ID *)ob->data, actcol - 1);
if (ob->curve_cache) {
BKE_displist_free(&ob->curve_cache->disp);
@@ -1301,6 +1306,124 @@ bool object_remove_material_slot(Object *ob)
return true;
}
+static bool get_mtex_slot_valid_texpaint(struct MTex *mtex)
+{
+ return (mtex && (mtex->texco == TEXCO_UV) &&
+ mtex->tex && (mtex->tex->type == TEX_IMAGE) &&
+ mtex->tex->ima);
+}
+
+void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
+{
+ MTex **mtex;
+ short count = 0;
+ short index = 0, i;
+
+ bool use_nodes = BKE_scene_use_new_shading_nodes(scene);
+ bool is_bi = BKE_scene_uses_blender_internal(scene);
+
+ if (!ma)
+ return;
+
+ if (ma->texpaintslot) {
+ MEM_freeN(ma->texpaintslot);
+ ma->tot_slots = 0;
+ ma->texpaintslot = NULL;
+ }
+
+ if (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_IMAGE) {
+ ma->paint_active_slot = 0;
+ ma->paint_clone_slot = 0;
+ return;
+ }
+
+ if (use_nodes || ma->use_nodes) {
+ bNode *node, *active_node;
+
+ if (!(ma->nodetree)) {
+ ma->paint_active_slot = 0;
+ ma->paint_clone_slot = 0;
+ return;
+ }
+
+ for (node = ma->nodetree->nodes.first; node; node = node->next) {
+ if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id)
+ count++;
+ }
+
+ if (count == 0) {
+ ma->paint_active_slot = 0;
+ ma->paint_clone_slot = 0;
+ return;
+ }
+ ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
+
+ active_node = nodeGetActiveTexture(ma->nodetree);
+
+ for (node = ma->nodetree->nodes.first; node; node = node->next) {
+ if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) {
+ if (active_node == node)
+ ma->paint_active_slot = index;
+ ma->texpaintslot[index++].ima = (Image *)node->id;
+ }
+ }
+ }
+ else if (is_bi) {
+ for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) {
+ if (get_mtex_slot_valid_texpaint(*mtex)) {
+ count++;
+ }
+ }
+
+ if (count == 0) {
+ ma->paint_active_slot = 0;
+ ma->paint_clone_slot = 0;
+ return;
+ }
+
+ ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
+
+ for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) {
+ if (get_mtex_slot_valid_texpaint(*mtex)) {
+ ma->texpaintslot[index].ima = (*mtex)->tex->ima;
+ ma->texpaintslot[index].uvname = (*mtex)->uvname;
+ ma->texpaintslot[index].index = i;
+
+ index++;
+ }
+ }
+ }
+ else {
+ ma->paint_active_slot = 0;
+ ma->paint_clone_slot = 0;
+ return;
+ }
+
+
+ ma->tot_slots = count;
+
+
+ if (ma->paint_active_slot >= count) {
+ ma->paint_active_slot = count - 1;
+ }
+
+ if (ma->paint_clone_slot >= count) {
+ ma->paint_clone_slot = count - 1;
+ }
+
+ return;
+}
+
+void BKE_texpaint_slots_refresh_object(Scene *scene, struct Object *ob)
+{
+ int i;
+
+ for (i = 1; i < ob->totcol + 1; i++) {
+ Material *ma = give_current_material(ob, i);
+ BKE_texpaint_slot_refresh_cache(scene, ma);
+ }
+}
+
/* r_col = current value, col = new value, (fac == 0) is no change */
void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
@@ -1573,7 +1696,7 @@ void copy_matcopybuf(Material *ma)
matcopybuf.mtex[a] = MEM_dupallocN(mtex);
}
}
- matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, false);
+ matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, G.main, false);
matcopybuf.preview = NULL;
BLI_listbase_clear(&matcopybuf.gpumaterial);
matcopied = 1;
@@ -1626,7 +1749,7 @@ void paste_matcopybuf(Material *ma)
}
}
- ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, false);
+ ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, G.main, false);
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 43b19f0c869..453c6df6e3b 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -491,10 +491,7 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.');
- /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
- if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL))
- return;
-
+ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
if (ob->type == OB_MBALL) {
if (ob != active_object) {
@@ -537,23 +534,17 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis)
BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
- /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
- if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL))
- return NULL;
-
+ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
- if (ob->type == OB_MBALL) {
+ if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
if (ob != bob) {
BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
- /* object ob has to be in same "group" ... it means, that it has to have
- * same base of its name */
+ /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
if (strcmp(obname, basisname) == 0) {
if (obnr < basisnr) {
- if (!(ob->flag & OB_FROMDUPLI)) {
- basis = ob;
- basisnr = obnr;
- }
+ basis = ob;
+ basisnr = obnr;
}
}
}
@@ -2227,10 +2218,7 @@ static void mball_count(EvaluationContext *eval_ctx, PROCESS *process, Scene *sc
BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
process->totelem = 0;
- /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
- if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL))
- return;
-
+ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
if (ob->type == OB_MBALL) {
if (ob == bob) {
@@ -2454,6 +2442,30 @@ bool BKE_mball_center_bounds(MetaBall *mb, float r_cent[3])
return 0;
}
+void BKE_mball_transform(MetaBall *mb, float mat[4][4])
+{
+ MetaElem *me;
+ float quat[4];
+ const float scale = mat4_to_scale(mat);
+ const float scale_sqrt = sqrtf(scale);
+
+ mat4_to_quat(quat, mat);
+
+ 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);
+ }
+ }
+}
+
void BKE_mball_translate(MetaBall *mb, const float offset[3])
{
MetaElem *ml;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 2bf33b97a70..2e80379522c 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -115,16 +115,16 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
int i, i1 = 0, i2 = 0, tot, j;
for (i = 0; i < c1->totlayer; i++) {
- if (ELEM7(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
{
i1++;
}
}
for (i = 0; i < c2->totlayer; i++) {
- if (ELEM7(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
{
i2++;
}
@@ -135,16 +135,16 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
l1 = c1->layers; l2 = c2->layers;
tot = i1;
- i1 = 0; i2 = 0;
+ i1 = 0; i2 = 0;
for (i = 0; i < tot; i++) {
- while (i1 < c1->totlayer && !ELEM7(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ while (i1 < c1->totlayer && !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
{
i1++, l1++;
}
- while (i2 < c2->totlayer && !ELEM7(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ while (i2 < c2->totlayer && !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
{
i2++, l2++;
}
@@ -1869,6 +1869,27 @@ bool BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3])
return (me->totvert != 0);
}
+void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys)
+{
+ int i;
+ MVert *mvert = me->mvert;
+
+ for (i = 0; i < me->totvert; i++, mvert++)
+ mul_m4_v3(mat, mvert->co);
+
+ if (do_keys && me->key) {
+ KeyBlock *kb;
+ for (kb = me->key->block.first; kb; kb = kb->next) {
+ float *fp = kb->data;
+ for (i = kb->totelem; i--; fp += 3) {
+ mul_m4_v3(mat, fp);
+ }
+ }
+ }
+
+ /* don't update normals, caller can do this explicitly */
+}
+
void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
{
int i = me->totvert;
@@ -2041,7 +2062,7 @@ int BKE_mesh_mselect_find(Mesh *me, int index, int type)
{
int i;
- BLI_assert(ELEM3(type, ME_VSEL, ME_ESEL, ME_FSEL));
+ BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL));
for (i = 0; i < me->totselect; i++) {
if ((me->mselect[i].index == index) &&
@@ -2059,7 +2080,7 @@ int BKE_mesh_mselect_find(Mesh *me, int index, int type)
*/
int BKE_mesh_mselect_active_get(Mesh *me, int type)
{
- BLI_assert(ELEM3(type, ME_VSEL, ME_ESEL, ME_FSEL));
+ BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL));
if (me->totselect) {
if (me->mselect[me->totselect - 1].type == type) {
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index cb0386b1203..4c9e44682c3 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -567,6 +567,10 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg
copy_v3_v3(nor, lnor);
}
}
+ else {
+ /* We still have to clear the stack! */
+ while (BLI_SMALLSTACK_POP(normal));
+ }
}
ml_prev = ml_curr;
@@ -574,8 +578,6 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg
}
}
- BLI_SMALLSTACK_FREE(normal);
-
MEM_freeN(edge_to_loops);
MEM_freeN(loop_to_poly);
@@ -729,7 +731,7 @@ void BKE_mesh_loop_tangents(Mesh *mesh, const char *uvmap, float (*r_looptangent
}
BKE_mesh_loop_tangents_ex(mesh->mvert, mesh->totvert, mesh->mloop, r_looptangents,
- loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports);
+ loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports);
}
/** \} */
@@ -1096,6 +1098,125 @@ bool BKE_mesh_center_centroid(Mesh *me, float cent[3])
/* -------------------------------------------------------------------- */
+/** \name Mesh Volume Calculation
+ * \{ */
+
+static bool mesh_calc_center_centroid_ex(MVert *mverts, int UNUSED(numVerts),
+ MFace *mfaces, int numFaces,
+ float center[3])
+{
+ float totweight;
+ int f;
+
+ zero_v3(center);
+
+ if (numFaces == 0)
+ return false;
+
+ totweight = 0.0f;
+ for (f = 0; f < numFaces; ++f) {
+ MFace *face = &mfaces[f];
+ MVert *v1 = &mverts[face->v1];
+ MVert *v2 = &mverts[face->v2];
+ MVert *v3 = &mverts[face->v3];
+ MVert *v4 = &mverts[face->v4];
+ float area;
+
+ area = area_tri_v3(v1->co, v2->co, v3->co);
+ madd_v3_v3fl(center, v1->co, area);
+ madd_v3_v3fl(center, v2->co, area);
+ madd_v3_v3fl(center, v3->co, area);
+ totweight += area;
+
+ if (face->v4) {
+ area = area_tri_v3(v3->co, v4->co, v1->co);
+ madd_v3_v3fl(center, v3->co, area);
+ madd_v3_v3fl(center, v4->co, area);
+ madd_v3_v3fl(center, v1->co, area);
+ totweight += area;
+ }
+ }
+ if (totweight == 0.0f)
+ return false;
+
+ mul_v3_fl(center, 1.0f / (3.0f * totweight));
+
+ return true;
+}
+
+void BKE_mesh_calc_volume(MVert *mverts, int numVerts,
+ MFace *mfaces, int numFaces,
+ float *r_vol, float *r_com)
+{
+ float center[3];
+ float totvol;
+ int f;
+
+ if (r_vol) *r_vol = 0.0f;
+ if (r_com) zero_v3(r_com);
+
+ if (numFaces == 0)
+ return;
+
+ if (!mesh_calc_center_centroid_ex(mverts, numVerts, mfaces, numFaces, center))
+ return;
+
+ totvol = 0.0f;
+ for (f = 0; f < numFaces; ++f) {
+ MFace *face = &mfaces[f];
+ MVert *v1 = &mverts[face->v1];
+ MVert *v2 = &mverts[face->v2];
+ MVert *v3 = &mverts[face->v3];
+ MVert *v4 = &mverts[face->v4];
+ float vol;
+
+ vol = volume_tetrahedron_signed_v3(center, v1->co, v2->co, v3->co);
+ if (r_vol) {
+ totvol += vol;
+ }
+ if (r_com) {
+ /* averaging factor 1/4 is applied in the end */
+ madd_v3_v3fl(r_com, center, vol); // XXX could extract this
+ madd_v3_v3fl(r_com, v1->co, vol);
+ madd_v3_v3fl(r_com, v2->co, vol);
+ madd_v3_v3fl(r_com, v3->co, vol);
+ }
+
+ if (face->v4) {
+ vol = volume_tetrahedron_signed_v3(center, v3->co, v4->co, v1->co);
+
+ if (r_vol) {
+ totvol += vol;
+ }
+ if (r_com) {
+ /* averaging factor 1/4 is applied in the end */
+ madd_v3_v3fl(r_com, center, vol); // XXX could extract this
+ madd_v3_v3fl(r_com, v3->co, vol);
+ madd_v3_v3fl(r_com, v4->co, vol);
+ madd_v3_v3fl(r_com, v1->co, vol);
+ }
+ }
+ }
+
+ /* Note: Depending on arbitrary centroid position,
+ * totvol can become negative even for a valid mesh.
+ * The true value is always the positive value.
+ */
+ if (r_vol) {
+ *r_vol = fabsf(totvol);
+ }
+ if (r_com) {
+ /* Note: Factor 1/4 is applied once for all vertices here.
+ * This also automatically negates the vector if totvol is negative.
+ */
+ if (totvol != 0.0f)
+ mul_v3_fl(r_com, 0.25f / totvol);
+ }
+}
+
+
+/* -------------------------------------------------------------------- */
+
/** \name NGon Tessellation (NGon/Tessface Conversion)
* \{ */
@@ -2110,11 +2231,10 @@ void BKE_mesh_calc_relative_deform(
float tvec[3];
- barycentric_transform(
- tvec, vert_cos_dst[v_curr],
- vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next],
- vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next]
- );
+ transform_point_by_tri_v3(
+ tvec, vert_cos_dst[v_curr],
+ vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next],
+ vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next]);
add_v3_v3(vert_cos_new[v_curr], tvec);
vert_accum[v_curr] += 1;
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index 65c576dd6a0..82065750791 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -442,7 +442,7 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
/* Find contiguous smooth groups already assigned, these are the values we can't reuse! */
for (; i--; p++) {
int bit = poly_groups[*p];
- if (!ELEM3(bit, 0, poly_group_id, poly_group_id_overflowed) &&
+ if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) &&
!(bit_poly_group_mask & bit))
{
bit_poly_group_mask |= bit;
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 858fe83b43f..f3a9e894eb3 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -164,16 +164,20 @@ static int search_poly_cmp(const void *v1, const void *v2)
{
const SortPoly *sp1 = v1, *sp2 = v2;
const int max_idx = sp1->numverts > sp2->numverts ? sp2->numverts : sp1->numverts;
- int idx = 0;
+ int idx;
/* Reject all invalid polys at end of list! */
if (sp1->invalid || sp2->invalid)
- return sp1->invalid && sp2->invalid ? 0 : sp1->invalid ? 1 : -1;
- /* Else, sort on first non-egal verts (remember verts of valid polys are sorted). */
- while (idx < max_idx && sp1->verts[idx] == sp2->verts[idx])
- idx++;
- return sp1->verts[idx] > sp2->verts[idx] ? 1 : sp1->verts[idx] < sp2->verts[idx] ? -1 :
- sp1->numverts > sp2->numverts ? 1 : sp1->numverts < sp2->numverts ? -1 : 0;
+ return sp1->invalid ? (sp2->invalid ? 0 : 1) : -1;
+ /* Else, sort on first non-equal verts (remember verts of valid polys are sorted). */
+ for (idx = 0; idx < max_idx; idx++) {
+ const int v1 = sp1->verts[idx];
+ const int v2 = sp2->verts[idx];
+ if (v1 != v2) {
+ return (v1 > v2) ? 1 : -1;
+ }
+ }
+ return sp1->numverts > sp2->numverts ? 1 : sp1->numverts < sp2->numverts ? -1 : 0;
}
static int search_polyloop_cmp(const void *v1, const void *v2)
@@ -255,7 +259,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
do_edge_recalc = do_fixes;
}
- for (i = 1; i < totvert; i++, mv++) {
+ for (i = 0; i < totvert; i++, mv++) {
bool fix_normal = true;
for (j = 0; j < 3; j++) {
@@ -498,8 +502,9 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
PRINT_ERR("\tLoop %u has invalid vert reference (%u)\n", sp->loopstart + j, ml->v);
sp->invalid = true;
}
-
- mverts[ml->v].flag |= ME_VERT_TMP_TAG;
+ else {
+ mverts[ml->v].flag |= ME_VERT_TMP_TAG;
+ }
*v = ml->v;
}
@@ -909,8 +914,6 @@ static bool mesh_validate_customdata(CustomData *data, CustomDataMask mask,
return is_valid;
}
-#undef PRINT
-
/**
* \returns is_valid.
*/
@@ -1052,8 +1055,36 @@ void BKE_mesh_cd_validate(Mesh *me)
}
}
}
-/** \} */
+/**
+ * Check all material indices of polygons are valid, invalid ones are set to 0.
+ * \returns is_valid.
+ */
+int BKE_mesh_validate_material_indices(Mesh *me)
+{
+ MPoly *mp;
+ const int max_idx = max_ii(0, me->totcol - 1);
+ const int totpoly = me->totpoly;
+ int i;
+ bool is_valid = true;
+
+ for (mp = me->mpoly, i = 0; i < totpoly; i++, mp++) {
+ if (mp->mat_nr > max_idx) {
+ mp->mat_nr = 0;
+ is_valid = false;
+ }
+ }
+
+ if (!is_valid) {
+ DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 1c42603cf4a..a9e853c873e 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -171,11 +171,14 @@ bool modifier_isPreview(ModifierData *md)
{
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (!(mti->flags & eModifierTypeFlag_UsesPreview))
+ /* Constructive modifiers are highly likely to also modify data like vgroups or vcol! */
+ if (!((mti->flags & eModifierTypeFlag_UsesPreview) || (mti->type == eModifierTypeType_Constructive))) {
return false;
+ }
- if (md->mode & eModifierMode_Realtime)
+ if (md->mode & eModifierMode_Realtime) {
return true;
+ }
return false;
}
@@ -350,6 +353,7 @@ int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *r_lastPossibleC
/* Find the last modifier acting on the cage. */
for (i = 0; md; i++, md = md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ bool supports_mapping;
md->scene = scene;
@@ -357,16 +361,17 @@ int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *r_lastPossibleC
if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue;
if (md->mode & eModifierMode_DisableTemporary) continue;
+ supports_mapping = modifier_supportsMapping(md);
+ if (r_lastPossibleCageIndex && supports_mapping) {
+ *r_lastPossibleCageIndex = i;
+ }
+
if (!(md->mode & eModifierMode_Realtime)) continue;
if (!(md->mode & eModifierMode_Editmode)) continue;
- if (!modifier_supportsMapping(md))
+ if (!supports_mapping)
break;
- if (r_lastPossibleCageIndex) {
- *r_lastPossibleCageIndex = i;
- }
-
if (md->mode & eModifierMode_OnCage)
cageIndex = i;
}
@@ -409,13 +414,12 @@ bool modifier_isEnabled(struct Scene *scene, ModifierData *md, int required_mode
md->scene = scene;
- if ((md->mode & required_mode) != required_mode) return 0;
- if (mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return 0;
- if (md->mode & eModifierMode_DisableTemporary) return 0;
- if (required_mode & eModifierMode_Editmode)
- if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) return 0;
+ if ((md->mode & required_mode) != required_mode) return false;
+ if (mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return false;
+ if (md->mode & eModifierMode_DisableTemporary) return false;
+ if ((required_mode & eModifierMode_Editmode) && !(mti->flags & eModifierTypeFlag_SupportsEditmode)) return false;
- return 1;
+ return true;
}
CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierData *md,
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 1d5bbbe1aeb..246ef8a33f5 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -112,7 +112,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden,
/* assumed to be at hi_level (or
* null) */
- BLI_bitmap *prev_hidden)
+ const BLI_bitmap *prev_hidden)
{
BLI_bitmap *subd;
int hi_gridsize = BKE_ccg_gridsize(hi_level);
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index d0114d52a06..19e45142960 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -430,7 +430,7 @@ static float nlastrip_get_frame_actionclip(NlaStrip *strip, float cframe, short
return (strip->end + (strip->actstart * scale - cframe)) / scale;
}
else { /* if (mode == NLATIME_CONVERT_EVAL) */
- if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) {
+ if (IS_EQF((float)cframe, strip->end) && IS_EQF(strip->repeat, floorf(strip->repeat))) {
/* this case prevents the motion snapping back to the first frame at the end of the strip
* by catching the case where repeats is a whole number, which means that the end of the strip
* could also be interpreted as the end of the start of a repeat
@@ -453,7 +453,7 @@ static float nlastrip_get_frame_actionclip(NlaStrip *strip, float cframe, short
return strip->actstart + (cframe - strip->start) / scale;
}
else { /* if (mode == NLATIME_CONVERT_EVAL) */
- if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) {
+ if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, floorf(strip->repeat))) {
/* this case prevents the motion snapping back to the first frame at the end of the strip
* by catching the case where repeats is a whole number, which means that the end of the strip
* could also be interpreted as the end of the start of a repeat
@@ -1637,7 +1637,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
}
}
- if (ELEM3(NULL, activeTrack, activeStrip, activeStrip->act)) {
+ if (ELEM(NULL, activeTrack, activeStrip, activeStrip->act)) {
if (G.debug & G_DEBUG) {
printf("NLA tweakmode enter - neither active requirement found\n");
printf("\tactiveTrack = %p, activeStrip = %p\n", (void *)activeTrack, (void *)activeStrip);
@@ -1744,7 +1744,7 @@ static void UNUSED_FUNCTION(BKE_nla_bake) (Scene *scene, ID *UNUSED(id), AnimDat
* 1) Scene and AnimData must be provided
* 2) there must be tracks to merge...
*/
- if (ELEM3(NULL, scene, adt, adt->nla_tracks.first))
+ if (ELEM(NULL, scene, adt, adt->nla_tracks.first))
return;
/* if animdata currently has an action, 'push down' this onto the stack first */
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 56a76a54955..0f86b551092 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1205,13 +1205,13 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool do_
return newtree;
}
-bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const bool do_id_user)
+bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, Main *bmain, const bool do_id_user)
{
- return ntreeCopyTree_internal(ntree, G.main, do_id_user, true, true);
+ return ntreeCopyTree_internal(ntree, bmain, do_id_user, true, true);
}
bNodeTree *ntreeCopyTree(bNodeTree *ntree)
{
- return ntreeCopyTree_ex(ntree, true);
+ return ntreeCopyTree_ex(ntree, G.main, true);
}
/* use when duplicating scenes */
@@ -3406,6 +3406,7 @@ static void registerCompositNodes(void)
register_node_type_cmp_inpaint();
register_node_type_cmp_despeckle();
register_node_type_cmp_defocus();
+ register_node_type_cmp_sunbeams();
register_node_type_cmp_valtorgb();
register_node_type_cmp_rgbtobw();
@@ -3528,10 +3529,12 @@ static void registerShaderNodes(void)
register_node_type_sh_mix_shader();
register_node_type_sh_add_shader();
register_node_type_sh_uvmap();
+ register_node_type_sh_uvalongstroke();
register_node_type_sh_output_lamp();
register_node_type_sh_output_material();
register_node_type_sh_output_world();
+ register_node_type_sh_output_linestyle();
register_node_type_sh_tex_image();
register_node_type_sh_tex_environment();
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 3490bb9ffbd..b09016506e3 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -42,6 +42,7 @@
#include "DNA_constraint_types.h"
#include "DNA_group_types.h"
#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
#include "DNA_material_types.h"
#include "DNA_meta_types.h"
@@ -180,7 +181,7 @@ void BKE_object_free_curve_cache(Object *ob)
{
if (ob->curve_cache) {
BKE_displist_free(&ob->curve_cache->disp);
- BLI_freelistN(&ob->curve_cache->bev);
+ BKE_curve_bevelList_free(&ob->curve_cache->bev);
if (ob->curve_cache->path) {
free_path(ob->curve_cache->path);
}
@@ -246,7 +247,7 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
ModifierData *md;
BKE_object_free_modifiers(ob_dst);
- if (!ELEM5(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
+ if (!ELEM(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
/* only objects listed above can have modifiers and linking them to objects
* which doesn't have modifiers stack is quite silly */
return;
@@ -255,11 +256,11 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
for (md = ob_src->modifiers.first; md; md = md->next) {
ModifierData *nmd = NULL;
- if (ELEM4(md->type,
- eModifierType_Hook,
- eModifierType_Softbody,
- eModifierType_ParticleInstance,
- eModifierType_Collision))
+ if (ELEM(md->type,
+ eModifierType_Hook,
+ eModifierType_Softbody,
+ eModifierType_ParticleInstance,
+ eModifierType_Collision))
{
continue;
}
@@ -296,7 +297,7 @@ void BKE_object_free_derived_caches(Object *ob)
me->bb->flag |= BOUNDBOX_DIRTY;
}
}
- else if (ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
+ else if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
Curve *cu = ob->data;
if (cu->bb) {
@@ -322,7 +323,7 @@ void BKE_object_free_derived_caches(Object *ob)
if (ob->curve_cache) {
BKE_displist_free(&ob->curve_cache->disp);
- BLI_freelistN(&ob->curve_cache->bev);
+ BKE_curve_bevelList_free(&ob->curve_cache->bev);
if (ob->curve_cache->path) {
free_path(ob->curve_cache->path);
ob->curve_cache->path = NULL;
@@ -408,7 +409,7 @@ void BKE_object_free_ex(Object *ob, bool do_id_user)
/* Free runtime curves data. */
if (ob->curve_cache) {
- BLI_freelistN(&ob->curve_cache->bev);
+ BKE_curve_bevelList_free(&ob->curve_cache->bev);
if (ob->curve_cache->path)
free_path(ob->curve_cache->path);
MEM_freeN(ob->curve_cache);
@@ -709,7 +710,7 @@ void BKE_object_unlink(Object *ob)
lineset; lineset = lineset->next)
{
if (lineset->linestyle) {
- BKE_unlink_linestyle_target_object(lineset->linestyle, ob);
+ BKE_linestyle_target_object_unlink(lineset->linestyle, ob);
}
}
}
@@ -873,9 +874,9 @@ bool BKE_object_is_in_wpaint_select_vert(Object *ob)
{
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
- return ( (ob->mode & OB_MODE_WEIGHT_PAINT) &&
- (me->edit_btmesh == NULL) &&
- (ME_EDIT_PAINT_SEL_MODE(me) == SCE_SELECT_VERTEX) );
+ return ((ob->mode & OB_MODE_WEIGHT_PAINT) &&
+ (me->edit_btmesh == NULL) &&
+ (ME_EDIT_PAINT_SEL_MODE(me) == SCE_SELECT_VERTEX));
}
return false;
@@ -977,7 +978,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
ob->empty_drawtype = OB_PLAINAXES;
ob->empty_drawsize = 1.0;
- if (ELEM3(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ if (ELEM(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
ob->trackflag = OB_NEGZ;
ob->upflag = OB_POSY;
}
@@ -1526,6 +1527,18 @@ Object *BKE_object_copy(Object *ob)
return BKE_object_copy_ex(G.main, ob, false);
}
+static void extern_local_object__modifiersForeachIDLink(
+ void *UNUSED(userData), Object *UNUSED(ob),
+ ID **idpoin)
+{
+ if (*idpoin) {
+ /* intentionally omit ID_OB */
+ if (ELEM(GS((*idpoin)->name), ID_IM, ID_TE)) {
+ id_lib_extern(*idpoin);
+ }
+ }
+}
+
static void extern_local_object(Object *ob)
{
ParticleSystem *psys;
@@ -1539,6 +1552,8 @@ static void extern_local_object(Object *ob)
for (psys = ob->particlesystem.first; psys; psys = psys->next)
id_lib_extern((ID *)psys->part);
+
+ modifiers_foreachIDLink(ob, extern_local_object__modifiersForeachIDLink, NULL);
}
void BKE_object_make_local(Object *ob)
@@ -1778,6 +1793,55 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
ob->dt = target->dt;
}
+/**
+ * Use with newly created objects to set their size
+ * (used to apply scene-scale).
+ */
+void BKE_object_obdata_size_init(struct Object *ob, const float size)
+{
+ /* apply radius as a scale to types that support it */
+ switch (ob->type) {
+ case OB_EMPTY:
+ {
+ ob->empty_drawsize *= size;
+ break;
+ }
+ case OB_FONT:
+ {
+ Curve *cu = ob->data;
+ cu->fsize *= size;
+ break;
+ }
+ case OB_CAMERA:
+ {
+ Camera *cam = ob->data;
+ cam->drawsize *= size;
+ break;
+ }
+ case OB_LAMP:
+ {
+ Lamp *lamp = ob->data;
+ lamp->dist *= size;
+ lamp->area_size *= size;
+ lamp->area_sizey *= size;
+ lamp->area_sizez *= size;
+ break;
+ }
+ /* Only lattice (not mesh, curve, mball...),
+ * because its got data when newly added */
+ case OB_LATTICE:
+ {
+ struct Lattice *lt = ob->data;
+ float mat[4][4];
+
+ unit_m4(mat);
+ scale_m4_fl(mat, size);
+
+ BKE_lattice_transform(lt, (float (*)[4])mat, false);
+ break;
+ }
+ }
+}
/* *************** CALC ****************** */
@@ -1978,7 +2042,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
unit_m4(mat);
cu = par->data;
- if (ELEM3(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */
+ if (ELEM(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */
BKE_displist_make_curveTypes(scene, par, 0);
if (par->curve_cache->path == NULL) return;
@@ -1994,17 +2058,20 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
* we divide the curvetime calculated in the previous step by the length of the path, to get a time
* factor, which then gets clamped to lie within 0.0 - 1.0 range
*/
- if (IS_EQF(cu->pathlen, 0.0f) == 0)
+ if (cu->pathlen) {
ctime = cu->ctime / cu->pathlen;
- else
+ }
+ else {
ctime = cu->ctime;
+ }
CLAMP(ctime, 0.0f, 1.0f);
}
else {
ctime = BKE_scene_frame_get(scene);
- if (IS_EQF(cu->pathlen, 0.0f) == 0)
+ if (cu->pathlen) {
ctime /= cu->pathlen;
+ }
CLAMP(ctime, 0.0f, 1.0f);
}
@@ -2289,7 +2356,7 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat
int a;
/* include framerate */
- fac1 = (1.0f / (1.0f + fabsf(ob->sf)) );
+ fac1 = (1.0f / (1.0f + fabsf(ob->sf)));
if (fac1 >= 1.0f) return 0;
fac2 = 1.0f - fac1;
@@ -2466,6 +2533,20 @@ void BKE_boundbox_init_from_minmax(BoundBox *bb, const float min[3], const float
bb->vec[1][2] = bb->vec[2][2] = bb->vec[5][2] = bb->vec[6][2] = max[2];
}
+void BKE_boundbox_calc_center_aabb(const BoundBox *bb, float r_cent[3])
+{
+ r_cent[0] = 0.5f * (bb->vec[0][0] + bb->vec[4][0]);
+ r_cent[1] = 0.5f * (bb->vec[0][1] + bb->vec[2][1]);
+ r_cent[2] = 0.5f * (bb->vec[0][2] + bb->vec[1][2]);
+}
+
+void BKE_boundbox_calc_size_aabb(const BoundBox *bb, float r_size[3])
+{
+ r_size[0] = 0.5f * fabsf(bb->vec[0][0] - bb->vec[4][0]);
+ r_size[1] = 0.5f * fabsf(bb->vec[0][1] - bb->vec[2][1]);
+ r_size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]);
+}
+
BoundBox *BKE_object_boundbox_get(Object *ob)
{
BoundBox *bb = NULL;
@@ -2473,7 +2554,7 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
if (ob->type == OB_MESH) {
bb = BKE_mesh_boundbox_get(ob);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
bb = BKE_curve_boundbox_get(ob);
}
else if (ob->type == OB_MBALL) {
@@ -2483,7 +2564,7 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
}
/* used to temporally disable/enable boundbox */
-void BKE_object_boundbox_flag(Object *ob, int flag, int set)
+void BKE_object_boundbox_flag(Object *ob, int flag, const bool set)
{
BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
@@ -3126,8 +3207,10 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc,
* Test a bounding box for ray intersection
* assumes the ray is already local to the boundbox space
*/
-bool BKE_boundbox_ray_hit_check(struct BoundBox *bb, const float ray_start[3], const float ray_normal[3],
- float *r_lambda)
+bool BKE_boundbox_ray_hit_check(
+ const struct BoundBox *bb,
+ const float ray_start[3], const float ray_normal[3],
+ float *r_lambda)
{
const int triangle_indexes[12][3] = {
{0, 1, 2}, {0, 2, 3},
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 707438bc673..0d82c6e89a1 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -754,14 +754,14 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj
if (orco) {
int j;
- for (j = 0; j < mpoly->totloop; j++) {
+ for (j = 0; j < mp->totloop; j++) {
madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w);
}
}
if (mloopuv) {
int j;
- for (j = 0; j < mpoly->totloop; j++) {
+ for (j = 0; j < mp->totloop; j++) {
madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j].uv, w);
}
}
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 9a144b5461a..4382d74f34e 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -45,8 +45,10 @@
#include "BLI_bitmap.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
+#include "BLI_listbase.h"
#include "BKE_brush.h"
+#include "BKE_main.h"
#include "BKE_context.h"
#include "BKE_crazyspace.h"
#include "BKE_depsgraph.h"
@@ -269,6 +271,105 @@ void BKE_paint_brush_set(Paint *p, Brush *br)
}
}
+void BKE_paint_curve_free(PaintCurve *pc)
+{
+ if (pc->points) {
+ MEM_freeN(pc->points);
+ pc->points = NULL;
+ pc->tot_points = 0;
+ }
+}
+
+PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name)
+{
+ PaintCurve *pc;
+
+ pc = BKE_libblock_alloc(bmain, ID_PC, name);
+
+ return pc;
+}
+
+Palette *BKE_paint_palette(Paint *p)
+{
+ return p ? p->palette : NULL;
+}
+
+void BKE_paint_palette_set(Paint *p, Palette *palette)
+{
+ if (p) {
+ id_us_min((ID *)p->palette);
+ id_us_plus((ID *)palette);
+ p->palette = palette;
+ }
+}
+
+void BKE_paint_curve_set(Brush *br, PaintCurve *pc)
+{
+ if (br) {
+ id_us_min((ID *)br->paint_curve);
+ id_us_plus((ID *)pc);
+ br->paint_curve = pc;
+ }
+}
+
+/* remove colour from palette. Must be certain color is inside the palette! */
+void BKE_palette_color_remove(Palette *palette, PaletteColor *color)
+{
+ BLI_remlink(&palette->colors, color);
+ BLI_addhead(&palette->deleted, color);
+}
+
+void BKE_palette_cleanup(Palette *palette)
+{
+ BLI_freelistN(&palette->deleted);
+}
+
+
+Palette *BKE_palette_add(Main *bmain, const char *name)
+{
+ Palette *palette;
+
+ palette = BKE_libblock_alloc(bmain, ID_PAL, name);
+
+ /* enable fake user by default */
+ palette->id.flag |= LIB_FAKEUSER;
+
+ return palette;
+}
+
+void BKE_palette_free(Palette *palette)
+{
+ BLI_freelistN(&palette->colors);
+}
+
+PaletteColor *BKE_palette_color_add(Palette *palette)
+{
+ PaletteColor *color = MEM_callocN(sizeof(*color), "Pallete Color");
+ BLI_addtail(&palette->colors, color);
+ palette->active_color = BLI_countlist(&palette->colors) - 1;
+ return color;
+}
+
+void BKE_palette_color_delete(struct Palette *palette)
+{
+ PaletteColor *color = BLI_findlink(&palette->colors, palette->active_color);
+
+ if (color) {
+ if ((color == palette->colors.last) && (palette->colors.last != palette->colors.first))
+ palette->active_color--;
+
+ BLI_remlink(&palette->colors, color);
+ BLI_addhead(&palette->deleted, color);
+ }
+}
+
+
+bool BKE_palette_is_empty(const struct Palette *palette)
+{
+ return BLI_listbase_is_empty(&palette->colors);
+}
+
+
/* are we in vertex paint or weight pain face select mode? */
bool BKE_paint_select_face_test(Object *ob)
{
@@ -318,6 +419,7 @@ void BKE_paint_init(Paint *p, const char col[3])
void BKE_paint_free(Paint *paint)
{
id_us_min((ID *)paint->brush);
+ id_us_min((ID *)paint->palette);
}
/* called when copying scene settings, so even if 'src' and 'tar' are the same
@@ -328,6 +430,7 @@ void BKE_paint_copy(Paint *src, Paint *tar)
{
tar->brush = src->brush;
id_us_plus((ID *)tar->brush);
+ id_us_plus((ID *)tar->palette);
}
/* returns non-zero if any of the face's vertices
@@ -378,7 +481,7 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level,
return gpm->data[(y * factor) * gridsize + (x * factor)];
}
-/* threshhold to move before updating the brush rotation */
+/* threshold to move before updating the brush rotation */
#define RAKE_THRESHHOLD 20
void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_pos[2])
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 8161f9d8875..27d346f65b9 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -1657,11 +1657,14 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const f
index_mp_to_orig = NULL;
}
+ totface = dm->getNumTessFaces(dm);
+ if (!totface) {
+ return DMCACHE_NOTFOUND;
+ }
+
mpoly = dm->getPolyArray(dm);
osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE);
- totface = dm->getNumTessFaces(dm);
-
if (osface == NULL || index_mf_to_mpoly == NULL) {
/* Assume we don't need osface data */
if (index < totface) {
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 06ac9db0b16..09e20c02691 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -117,7 +117,7 @@ static int particles_are_dynamic(ParticleSystem *psys)
if (psys->part->type == PART_HAIR)
return psys->flag & PSYS_HAIR_DYNAMICS;
else
- return ELEM3(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
+ return ELEM(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
}
float psys_get_current_display_percentage(ParticleSystem *psys)
@@ -399,7 +399,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
}
}
- if (origindex_final != ORIGINDEX_NONE) {
+ if (origindex_final != ORIGINDEX_NONE && origindex_final < totelem) {
if (nodearray[origindex_final]) {
/* prepend */
node->next = nodearray[origindex_final];
@@ -507,7 +507,7 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
sub_v3_v3v3(delta, max, min);
/* determine major axis */
- axis = (delta[0]>=delta[1]) ? 0 : ((delta[1]>=delta[2]) ? 1 : 2);
+ axis = axis_dominant_v3_single(delta);
d = delta[axis]/(float)res;
@@ -1079,7 +1079,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
float *element_weight=NULL,*element_sum=NULL,*jitter_offset=NULL, *vweight=NULL;
float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3];
- if (ELEM3(NULL, ob, psys, psys->part))
+ if (ELEM(NULL, ob, psys, psys->part))
return 0;
part=psys->part;
@@ -2638,7 +2638,7 @@ static void sph_particle_courant(SPHData *sphdata, SPHRangeData *pfr)
mul_v3_v3fl(sphdata->flow, flow, 1.0f / pfr->tot_neighbors);
}
else {
- sphdata->element_size = MAXFLOAT;
+ sphdata->element_size = FLT_MAX;
copy_v3_v3(sphdata->flow, flow);
}
}
@@ -3153,7 +3153,7 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f
extrotfac = 0.0f;
}
- if ((part->flag & PART_ROT_DYN) && ELEM3(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) {
+ if ((part->flag & PART_ROT_DYN) && ELEM(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) {
float angle;
float len1 = len_v3(pa->prev_state.vel);
float len2 = len_v3(pa->state.vel);
@@ -4012,6 +4012,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
if (!psys->clmd) {
psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth);
psys->clmd->sim_parms->goalspring = 0.0f;
+ psys->clmd->sim_parms->vel_damping = 1.0f;
psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
}
@@ -4846,13 +4847,13 @@ void psys_changed_type(Object *ob, ParticleSystem *psys)
psys->flag &= ~PSYS_KEYED;
if (part->type == PART_HAIR) {
- if (ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0)
+ if (ELEM(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0)
part->ren_as = PART_DRAW_PATH;
if (part->distr == PART_DISTR_GRID)
part->distr = PART_DISTR_JIT;
- if (ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
+ if (ELEM(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
part->draw_as = PART_DRAW_REND;
CLAMP(part->path_start, 0.0f, 100.0f);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 1a815cf0dee..3e763016efb 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -50,6 +50,15 @@
#define STACK_FIXED_DEPTH 100
+/* Setting zero so we can catch bugs in OpenMP/PBVH. */
+#ifdef _OPENMP
+# ifdef DEBUG
+# define PBVH_OMP_LIMIT 0
+# else
+# define PBVH_OMP_LIMIT 8
+# endif
+#endif
+
typedef struct PBVHStack {
PBVHNode *node;
int revisiting;
@@ -965,7 +974,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
* can only update vertices marked with ME_VERT_PBVH_UPDATE.
*/
-#pragma omp parallel for private(n) schedule(static)
+#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
@@ -1009,7 +1018,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
}
}
-#pragma omp parallel for private(n) schedule(static)
+#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
@@ -1046,7 +1055,7 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
int n;
/* update BB, redraw flag */
-#pragma omp parallel for private(n) schedule(static)
+#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index 90b5d8cf1a1..b2178fe69b3 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -284,7 +284,7 @@ Report *BKE_reports_last_displayable(ReportList *reports)
Report *report;
for (report = reports->list.last; report; report = report->prev) {
- if (ELEM3(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO))
+ if (ELEM(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO))
return report;
}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 09293503ad5..3d61b0bdefb 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -57,6 +57,7 @@
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_library.h"
+#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_pointcache.h"
#include "BKE_rigidbody.h"
@@ -287,10 +288,10 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
DM_ensure_tessface(dm);
- mvert = (dm) ? dm->getVertArray(dm) : NULL;
- totvert = (dm) ? dm->getNumVerts(dm) : 0;
- mface = (dm) ? dm->getTessFaceArray(dm) : NULL;
- totface = (dm) ? dm->getNumTessFaces(dm) : 0;
+ mvert = dm->getVertArray(dm);
+ totvert = dm->getNumVerts(dm);
+ mface = dm->getTessFaceArray(dm);
+ totface = dm->getNumTessFaces(dm);
/* sanity checking - potential case when no data will be present */
if ((totvert == 0) || (totface == 0)) {
@@ -344,7 +345,7 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
}
/* cleanup temp data */
- if (dm && ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
+ if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
dm->release(dm);
}
}
@@ -394,7 +395,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
}
mul_v3_fl(size, 0.5f);
- if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
+ if (ELEM(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
/* take radius as largest x/y dimension, and height as z-dimension */
radius = MAX2(size[0], size[1]);
height = size[2];
@@ -455,6 +456,182 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
/* --------------------- */
+/* helper function to calculate volume of rigidbody object */
+// TODO: allow a parameter to specify method used to calculate this?
+void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
+{
+ RigidBodyOb *rbo = ob->rigidbody_object;
+
+ float size[3] = {1.0f, 1.0f, 1.0f};
+ float radius = 1.0f;
+ float height = 1.0f;
+
+ float volume = 0.0f;
+
+ /* if automatically determining dimensions, use the Object's boundbox
+ * - assume that all quadrics are standing upright on local z-axis
+ * - assume even distribution of mass around the Object's pivot
+ * (i.e. Object pivot is centralized in boundbox)
+ * - boundbox gives full width
+ */
+ // XXX: all dimensions are auto-determined now... later can add stored settings for this
+ BKE_object_dimensions_get(ob, size);
+
+ if (ELEM(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
+ /* take radius as largest x/y dimension, and height as z-dimension */
+ radius = MAX2(size[0], size[1]) * 0.5f;
+ height = size[2];
+ }
+ else if (rbo->shape == RB_SHAPE_SPHERE) {
+ /* take radius to the the largest dimension to try and encompass everything */
+ radius = max_fff(size[0], size[1], size[2]) * 0.5f;
+ }
+
+ /* calculate volume as appropriate */
+ switch (rbo->shape) {
+ case RB_SHAPE_BOX:
+ volume = size[0] * size[1] * size[2];
+ break;
+
+ case RB_SHAPE_SPHERE:
+ volume = 4.0f / 3.0f * (float)M_PI * radius * radius * radius;
+ break;
+
+ /* for now, assume that capsule is close enough to a cylinder... */
+ case RB_SHAPE_CAPSULE:
+ case RB_SHAPE_CYLINDER:
+ volume = (float)M_PI * radius * radius * height;
+ break;
+
+ case RB_SHAPE_CONE:
+ volume = (float)M_PI / 3.0f * radius * radius * height;
+ break;
+
+ case RB_SHAPE_CONVEXH:
+ case RB_SHAPE_TRIMESH:
+ {
+ if (ob->type == OB_MESH) {
+ DerivedMesh *dm = rigidbody_get_mesh(ob);
+ MVert *mvert;
+ MFace *mface;
+ int totvert, totface;
+
+ /* ensure mesh validity, then grab data */
+ if (dm == NULL)
+ return;
+
+ DM_ensure_tessface(dm);
+
+ mvert = dm->getVertArray(dm);
+ totvert = dm->getNumVerts(dm);
+ mface = dm->getTessFaceArray(dm);
+ totface = dm->getNumTessFaces(dm);
+
+ if (totvert > 0 && totface > 0) {
+ BKE_mesh_calc_volume(mvert, totvert, mface, totface, &volume, NULL);
+ }
+
+ /* cleanup temp data */
+ if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
+ dm->release(dm);
+ }
+ }
+ else {
+ /* rough estimate from boundbox as fallback */
+ /* XXX could implement other types of geometry here (curves, etc.) */
+ volume = size[0] * size[1] * size[2];
+ }
+ break;
+ }
+
+#if 0 // XXX: not defined yet
+ case RB_SHAPE_COMPOUND:
+ volume = 0.0f;
+ break;
+#endif
+ }
+
+ /* return the volume calculated */
+ if (r_vol) *r_vol = volume;
+}
+
+void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3])
+{
+ RigidBodyOb *rbo = ob->rigidbody_object;
+
+ float size[3] = {1.0f, 1.0f, 1.0f};
+ float height = 1.0f;
+
+ zero_v3(r_com);
+
+ /* if automatically determining dimensions, use the Object's boundbox
+ * - assume that all quadrics are standing upright on local z-axis
+ * - assume even distribution of mass around the Object's pivot
+ * (i.e. Object pivot is centralized in boundbox)
+ * - boundbox gives full width
+ */
+ // XXX: all dimensions are auto-determined now... later can add stored settings for this
+ BKE_object_dimensions_get(ob, size);
+
+ /* calculate volume as appropriate */
+ switch (rbo->shape) {
+ case RB_SHAPE_BOX:
+ case RB_SHAPE_SPHERE:
+ case RB_SHAPE_CAPSULE:
+ case RB_SHAPE_CYLINDER:
+ break;
+
+ case RB_SHAPE_CONE:
+ /* take radius as largest x/y dimension, and height as z-dimension */
+ height = size[2];
+ /* cone is geometrically centered on the median,
+ * center of mass is 1/4 up from the base
+ */
+ r_com[2] = -0.25f * height;
+ break;
+
+ case RB_SHAPE_CONVEXH:
+ case RB_SHAPE_TRIMESH:
+ {
+ if (ob->type == OB_MESH) {
+ DerivedMesh *dm = rigidbody_get_mesh(ob);
+ MVert *mvert;
+ MFace *mface;
+ int totvert, totface;
+
+ /* ensure mesh validity, then grab data */
+ if (dm == NULL)
+ return;
+
+ DM_ensure_tessface(dm);
+
+ mvert = dm->getVertArray(dm);
+ totvert = dm->getNumVerts(dm);
+ mface = dm->getTessFaceArray(dm);
+ totface = dm->getNumTessFaces(dm);
+
+ if (totvert > 0 && totface > 0) {
+ BKE_mesh_calc_volume(mvert, totvert, mface, totface, NULL, r_com);
+ }
+
+ /* cleanup temp data */
+ if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
+ dm->release(dm);
+ }
+ }
+ break;
+ }
+
+#if 0 // XXX: not defined yet
+ case RB_SHAPE_COMPOUND:
+ volume = 0.0f;
+ break;
+#endif
+ }
+}
+
+/* --------------------- */
+
/**
* Create physics sim representation of object given RigidBody settings
*
@@ -543,7 +720,7 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
return;
}
- if (ELEM4(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
+ if (ELEM(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
if (rbc->physics_constraint) {
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
RB_constraint_delete(rbc->physics_constraint);
@@ -1414,6 +1591,8 @@ struct RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) { return NULL; }
struct RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) { return NULL; }
void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc) {}
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_com[3]) { zero_v3(r_com); }
struct RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) { return NULL; }
struct RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw) { return NULL; }
void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw) {}
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index 1310162483e..4be75344133 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -392,6 +392,7 @@ void init_actuator(bActuator *act)
bSteeringActuator *sta;
bArmatureActuator *arma;
bMouseActuator *ma;
+ bEditObjectActuator *eoa;
if (act->data) MEM_freeN(act->data);
act->data= NULL;
@@ -430,6 +431,9 @@ void init_actuator(bActuator *act)
break;
case ACT_EDIT_OBJECT:
act->data= MEM_callocN(sizeof(bEditObjectActuator), "editobact");
+ eoa = act->data;
+ eoa->upflag= ACT_TRACK_UP_Z;
+ eoa->trackflag= ACT_TRACK_TRAXIS_Y;
break;
case ACT_CONSTRAINT:
act->data= MEM_callocN(sizeof(bConstraintActuator), "cons act");
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index f8ce31f1b8a..eb98e381222 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -39,6 +39,7 @@
#include "DNA_anim_types.h"
#include "DNA_group_types.h"
#include "DNA_linestyle_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
@@ -46,6 +47,8 @@
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -62,6 +65,7 @@
#include "BKE_action.h"
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
+#include "BKE_editmesh.h"
#include "BKE_fcurve.h"
#include "BKE_freestyle.h"
#include "BKE_global.h"
@@ -78,6 +82,7 @@
#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
+#include "BKE_unit.h"
#include "BKE_world.h"
#include "RE_engine.h"
@@ -86,6 +91,8 @@
#include "IMB_colormanagement.h"
+#include "bmesh.h"
+
//XXX #include "BIF_previewrender.h"
//XXX #include "BIF_editseq.h"
@@ -253,6 +260,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint);
ts->imapaint.paintcursor = NULL;
+ id_us_plus((ID *)ts->imapaint.stencil);
ts->particle.paintcursor = NULL;
}
@@ -510,6 +518,8 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->r.border.ymin = 0.0f;
sce->r.border.xmax = 1.0f;
sce->r.border.ymax = 1.0f;
+
+ sce->r.preview_start_resolution = 64;
sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct");
sce->toolsettings->doublimit = 0.001;
@@ -553,6 +563,8 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->toolsettings->proportional_size = 1.0f;
sce->toolsettings->imapaint.paint.flags |= PAINT_SHOW_BRUSH;
+ sce->toolsettings->imapaint.normal_angle = 80;
+ sce->toolsettings->imapaint.seam_bleed = 2;
sce->physics_settings.gravity[0] = 0.0f;
sce->physics_settings.gravity[1] = 0.0f;
@@ -719,14 +731,14 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
/* called from creator.c */
Scene *BKE_scene_set_name(Main *bmain, const char *name)
{
- Scene *sce = (Scene *)BKE_libblock_find_name(ID_SCE, name);
+ Scene *sce = (Scene *)BKE_libblock_find_name_ex(bmain, ID_SCE, name);
if (sce) {
BKE_scene_set_background(bmain, sce);
- printf("Scene switch: '%s' in file: '%s'\n", name, G.main->name);
+ printf("Scene switch: '%s' in file: '%s'\n", name, bmain->name);
return sce;
}
- printf("Can't find scene: '%s' in file: '%s'\n", name, G.main->name);
+ printf("Can't find scene: '%s' in file: '%s'\n", name, bmain->name);
return NULL;
}
@@ -804,9 +816,7 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
BKE_libblock_free(bmain, sce);
}
-/* used by metaballs
- * doesn't return the original duplicated object, only dupli's
- */
+/* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */
int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
Scene **scene, int val, Base **base, Object **ob)
{
@@ -817,11 +827,12 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
iter->phase = F_START;
iter->dupob = NULL;
iter->duplilist = NULL;
+ iter->dupli_refob = NULL;
}
else {
/* run_again is set when a duplilist has been ended */
while (run_again) {
- run_again = 0;
+ run_again = false;
/* the first base */
if (iter->phase == F_START) {
@@ -879,34 +890,46 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
iter->dupob = iter->duplilist->first;
- if (!iter->dupob)
+ if (!iter->dupob) {
free_object_duplilist(iter->duplilist);
+ iter->duplilist = NULL;
+ }
+ iter->dupli_refob = NULL;
}
}
}
/* handle dupli's */
if (iter->dupob) {
-
- copy_m4_m4(iter->omat, iter->dupob->ob->obmat);
- copy_m4_m4(iter->dupob->ob->obmat, iter->dupob->mat);
-
(*base)->flag |= OB_FROMDUPLI;
*ob = iter->dupob->ob;
iter->phase = F_DUPLI;
-
+
+ if (iter->dupli_refob != *ob) {
+ if (iter->dupli_refob) {
+ /* Restore previous object's real matrix. */
+ copy_m4_m4(iter->dupli_refob->obmat, iter->omat);
+ }
+ /* Backup new object's real matrix. */
+ iter->dupli_refob = *ob;
+ copy_m4_m4(iter->omat, iter->dupli_refob->obmat);
+ }
+ copy_m4_m4((*ob)->obmat, iter->dupob->mat);
+
iter->dupob = iter->dupob->next;
}
else if (iter->phase == F_DUPLI) {
iter->phase = F_SCENE;
(*base)->flag &= ~OB_FROMDUPLI;
- for (iter->dupob = iter->duplilist->first; iter->dupob; iter->dupob = iter->dupob->next) {
- copy_m4_m4(iter->dupob->ob->obmat, iter->omat);
+ if (iter->dupli_refob) {
+ /* Restore last object's real matrix. */
+ copy_m4_m4(iter->dupli_refob->obmat, iter->omat);
+ iter->dupli_refob = NULL;
}
free_object_duplilist(iter->duplilist);
iter->duplilist = NULL;
- run_again = 1;
+ run_again = true;
}
}
}
@@ -1118,11 +1141,6 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra)
double intpart;
scene->r.subframe = modf(cfra, &intpart);
scene->r.cfra = (int)intpart;
-
- if (cfra < 0.0) {
- scene->r.cfra -= 1;
- scene->r.subframe = 1.0f + scene->r.subframe;
- }
}
/* drivers support/hacks
@@ -1541,6 +1559,53 @@ static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bma
}
+static bool check_rendered_viewport_visible(Main *bmain)
+{
+ wmWindowManager *wm = bmain->wm.first;
+ wmWindow *window;
+ for (window = wm->windows.first; window != NULL; window = window->next) {
+ bScreen *screen = window->screen;
+ ScrArea *area;
+ for (area = screen->areabase.first; area != NULL; area = area->next) {
+ View3D *v3d = area->spacedata.first;
+ if (area->spacetype != SPACE_VIEW3D) {
+ continue;
+ }
+ if (v3d->drawtype == OB_RENDER) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
+{
+ /* This is needed to prepare mesh to be used by the render
+ * engine from the viewport rendering. We do loading here
+ * so all the objects which shares the same mesh datablock
+ * are nicely tagged for update and updated.
+ *
+ * This makes it so viewport render engine doesn't need to
+ * call loading of the edit data for the mesh objects.
+ */
+
+ Object *obedit = scene->obedit;
+ if (obedit) {
+ Mesh *mesh = obedit->data;
+ /* TODO(sergey): Check object recalc flags as well? */
+ if ((obedit->type == OB_MESH) &&
+ (mesh->id.flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA)))
+ {
+ if (check_rendered_viewport_visible(bmain)) {
+ BMesh *bm = mesh->edit_btmesh->bm;
+ BM_mesh_bm_to_me(bm, mesh, false);
+ DAG_id_tag_update(&mesh->id, 0);
+ }
+ }
+ }
+}
+
void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene)
{
Scene *sce_iter;
@@ -1552,6 +1617,9 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set)
DAG_scene_relations_update(bmain, sce_iter);
+ /* flush editing data if needed */
+ prepare_mesh_for_viewport_render(bmain, scene);
+
/* flush recalc flags to dependencies */
DAG_ids_flush_tagged(bmain);
@@ -1832,6 +1900,12 @@ bool BKE_scene_use_new_shading_nodes(Scene *scene)
return (type && type->flag & RE_USE_SHADING_NODES);
}
+bool BKE_scene_uses_blender_internal(struct Scene *scene)
+{
+ return strcmp("BLENDER_RENDER", scene->r.engine) == 0;
+}
+
+
void BKE_scene_base_flag_to_objects(struct Scene *scene)
{
Base *base = scene->base.first;
@@ -1903,3 +1977,29 @@ int BKE_scene_num_threads(const Scene *scene)
{
return BKE_render_num_threads(&scene->r);
}
+
+/* Apply the needed correction factor to value, based on unit_type (only length-related are affected currently)
+ * and unit->scale_length.
+ */
+double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, double value)
+{
+ if (unit->system == USER_UNIT_NONE) {
+ /* Never apply scale_length when not using a unit setting! */
+ return value;
+ }
+
+ switch (unit_type) {
+ case B_UNIT_LENGTH:
+ return value * (double)unit->scale_length;
+ case B_UNIT_CAMERA:
+ return value * (double)unit->scale_length;
+ case B_UNIT_AREA:
+ return value * pow(unit->scale_length, 2);
+ case B_UNIT_VOLUME:
+ return value * pow(unit->scale_length, 3);
+ case B_UNIT_MASS:
+ return value * pow(unit->scale_length, 3);
+ default:
+ return value;
+ }
+}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 9d40ee6e667..b2296151cf7 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -425,6 +425,32 @@ ScrArea *BKE_screen_find_big_area(bScreen *sc, const int spacetype, const short
return big;
}
+/**
+ * Utility function to get the active layer to use when adding new objects.
+ */
+unsigned int BKE_screen_view3d_layer_active_ex(const View3D *v3d, const Scene *scene, bool use_localvd)
+{
+ unsigned int lay;
+ if ((v3d == NULL) || (v3d->scenelock && !v3d->localvd)) {
+ lay = scene->layact;
+ }
+ else {
+ lay = v3d->layact;
+ }
+
+ if (use_localvd) {
+ if (v3d && v3d->localvd) {
+ lay |= v3d->lay;
+ }
+ }
+
+ return lay;
+}
+unsigned int BKE_screen_view3d_layer_active(const struct View3D *v3d, const struct Scene *scene)
+{
+ return BKE_screen_view3d_layer_active_ex(v3d, scene, true);
+}
+
void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene)
{
int bit;
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 2b14b92217b..d2dc9da47f9 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -52,6 +52,11 @@
#include "RNA_access.h"
+/* TODO(sergey): Could be considered a bad level call, but
+ * need this for gaussian table.
+ */
+#include "RE_pipeline.h"
+
static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
const ImBuf *ibuf3, const ImBuf *out, int start_line, unsigned char **rect1,
unsigned char **rect2, unsigned char **rect3, unsigned char **rect_out)
@@ -2579,6 +2584,295 @@ static void do_overdrop_effect(const SeqRenderData *context, Sequence *UNUSED(se
}
}
+/*********************** Gaussian Blur *************************/
+
+/* NOTE: This gaussian blur implementation accumulates values in the square
+ * kernel rather that doing X direction and then Y direction because of the
+ * lack of using multiple-staged filters.
+ *
+ * Once we can we'll implement a way to apply filter as multiple stages we
+ * can optimize hell of a lot in here.
+ */
+
+static void init_gaussian_blur_effect(Sequence *seq)
+{
+ if (seq->effectdata)
+ MEM_freeN(seq->effectdata);
+
+ seq->effectdata = MEM_callocN(sizeof(WipeVars), "wipevars");
+}
+
+static int num_inputs_gaussian_blur(void)
+{
+ return 1;
+}
+
+static void free_gaussian_blur_effect(Sequence *seq)
+{
+ if (seq->effectdata)
+ MEM_freeN(seq->effectdata);
+
+ seq->effectdata = NULL;
+}
+
+static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src)
+{
+ dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+static int early_out_gaussian_blur(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
+{
+ GaussianBlurVars *data = seq->effectdata;
+ if (data->size_x == 0.0f && data->size_y == 0) {
+ return EARLY_USE_INPUT_1;
+ }
+ return EARLY_DO_EFFECT;
+}
+
+/* TODO(sergey): De-duplicate with compositor. */
+static float *make_gaussian_blur_kernel(float rad, int size)
+{
+ float *gausstab, sum, val;
+ float fac;
+ int i, n;
+
+ n = 2 * size + 1;
+
+ gausstab = (float *)MEM_mallocN(sizeof(float) * n, __func__);
+
+ sum = 0.0f;
+ fac = (rad > 0.0f ? 1.0f / rad : 0.0f);
+ for (i = -size; i <= size; i++) {
+ val = RE_filter_value(R_FILTER_GAUSS, (float)i * fac);
+ sum += val;
+ gausstab[i + size] = val;
+ }
+
+ sum = 1.0f / sum;
+ for (i = 0; i < n; i++)
+ gausstab[i] *= sum;
+
+ return gausstab;
+}
+
+static void do_gaussian_blur_effect_byte(Sequence *seq,
+ int start_line,
+ int x, int y,
+ int frame_width, int frame_height,
+ unsigned char *rect,
+ unsigned char *out)
+{
+#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
+ GaussianBlurVars *data = seq->effectdata;
+ const int size_x = (int) (data->size_x + 0.5f),
+ size_y = (int) (data->size_y + 0.5f);
+ int i, j;
+
+ /* Make gaussian weight tabke. */
+ float *gausstab_x, *gausstab_y;
+ gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
+ if (data->size_x == data->size_y) {
+ gausstab_y = gausstab_x;
+ }
+ else {
+ gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
+ }
+
+ for (i = 0; i < y; ++i) {
+ for (j = 0; j < x; ++j) {
+ int out_index = INDEX(j, i);
+ int current_x, current_y;
+ float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float accum_weight = 0.0f;
+ for (current_y = i - size_y;
+ current_y <= i + size_y;
+ ++current_y)
+ {
+ if (current_y < -start_line ||
+ current_y + start_line >= frame_height)
+ {
+ /* Out of bounds. */
+ continue;
+ }
+
+ for (current_x = j - size_x;
+ current_x <= j + size_x;
+ ++current_x)
+ {
+ float weight;
+ int index = INDEX(current_x, current_y + start_line);
+ if (current_x < 0 || current_x >= frame_width) {
+ /* Out of bounds. */
+ continue;
+ }
+ BLI_assert(index >= 0);
+ BLI_assert(index < frame_width * frame_height * 4);
+
+ if (size_x != 0 && size_y != 0) {
+ weight = gausstab_x[current_x - j + size_x] *
+ gausstab_y[current_y - i + size_y];
+ }
+ else if (size_x == 0) {
+ weight = gausstab_y[current_y - i + size_y];
+ }
+ else {
+ weight = gausstab_x[current_x - j + size_x];
+ }
+ accum[0] += rect[index] * weight;
+ accum[1] += rect[index + 1] * weight;
+ accum[2] += rect[index + 2] * weight;
+ accum[3] += rect[index + 3] * weight;
+ accum_weight += weight;
+ }
+ }
+ out[out_index + 0] = accum[0] / accum_weight;
+ out[out_index + 1] = accum[1] / accum_weight;
+ out[out_index + 2] = accum[2] / accum_weight;
+ out[out_index + 3] = accum[3] / accum_weight;
+ }
+ }
+
+ MEM_freeN(gausstab_x);
+ if (gausstab_x != gausstab_y) {
+ MEM_freeN(gausstab_y);
+ }
+#undef INDEX
+}
+
+static void do_gaussian_blur_effect_float(Sequence *seq,
+ int start_line,
+ int x, int y,
+ int frame_width, int frame_height,
+ float *rect,
+ float *out)
+{
+#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
+ GaussianBlurVars *data = seq->effectdata;
+ const int size_x = (int) (data->size_x + 0.5f),
+ size_y = (int) (data->size_y + 0.5f);
+ int i, j;
+
+ /* Make gaussian weight tabke. */
+ float *gausstab_x, *gausstab_y;
+ gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
+ if (data->size_x == data->size_y) {
+ gausstab_y = gausstab_x;
+ }
+ else {
+ gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
+ }
+
+ for (i = 0; i < y; ++i) {
+ for (j = 0; j < x; ++j) {
+ int out_index = INDEX(j, i);
+ int current_x, current_y;
+ float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float accum_weight = 0.0f;
+ for (current_y = i - size_y;
+ current_y <= i + size_y;
+ ++current_y)
+ {
+ float weight;
+ if (current_y < -start_line ||
+ current_y + start_line >= frame_height)
+ {
+ /* Out of bounds. */
+ continue;
+ }
+
+ for (current_x = j - size_x;
+ current_x <= j + size_x;
+ ++current_x)
+ {
+ int index = INDEX(current_x, current_y + start_line);
+ if (current_x < 0 || current_x >= frame_width) {
+ /* Out of bounds. */
+ continue;
+ }
+
+ if (size_x != 0 && size_y != 0) {
+ weight = gausstab_x[current_x - j + size_x] *
+ gausstab_y[current_y - i + size_y];
+ }
+ else if (size_x == 0) {
+ weight = gausstab_y[current_y - i + size_y];
+ }
+ else {
+ weight = gausstab_x[current_x - j + size_x];
+ }
+ madd_v4_v4fl(accum, &rect[index], weight);
+ accum_weight += weight;
+ }
+ }
+ mul_v4_v4fl(&out[out_index], accum, 1.0f / accum_weight);
+ }
+ }
+
+ MEM_freeN(gausstab_x);
+ if (gausstab_x != gausstab_y) {
+ MEM_freeN(gausstab_y);
+ }
+#undef INDEX
+}
+
+static void do_gaussian_blur_effect(const SeqRenderData *context,
+ Sequence *seq,
+ float UNUSED(cfra),
+ float UNUSED(facf0),
+ float UNUSED(facf1),
+ ImBuf *ibuf1,
+ ImBuf *ibuf2,
+ ImBuf *UNUSED(ibuf3),
+ int start_line,
+ int total_lines,
+ ImBuf *out)
+{
+ if (out->rect_float) {
+ float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
+
+ slice_get_float_buffers(context,
+ ibuf1, ibuf2,
+ NULL,
+ out,
+ start_line,
+ &rect1,
+ &rect2,
+ NULL,
+ &rect_out);
+
+ do_gaussian_blur_effect_float(seq,
+ start_line,
+ context->rectx,
+ total_lines,
+ context->rectx,
+ context->recty,
+ ibuf1->rect_float,
+ rect_out);
+ }
+ else {
+ unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
+
+ slice_get_byte_buffers(context,
+ ibuf1, ibuf2,
+ NULL,
+ out,
+ start_line,
+ &rect1,
+ &rect2,
+ NULL,
+ &rect_out);
+
+ do_gaussian_blur_effect_byte(seq,
+ start_line,
+ context->rectx,
+ total_lines,
+ context->rectx,
+ context->recty,
+ (unsigned char *) ibuf1->rect,
+ rect_out);
+ }
+}
+
/*********************** sequence effect factory *************************/
static void init_noop(Sequence *UNUSED(seq))
@@ -2767,6 +3061,15 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
rval.early_out = early_out_adjustment;
rval.execute = do_adjustment;
break;
+ case SEQ_TYPE_GAUSSIAN_BLUR:
+ rval.multithreaded = true;
+ rval.init = init_gaussian_blur_effect;
+ rval.num_inputs = num_inputs_gaussian_blur;
+ rval.free = free_gaussian_blur_effect;
+ rval.copy = copy_gaussian_blur_effect;
+ rval.early_out = early_out_gaussian_blur;
+ rval.execute_slice = do_gaussian_blur_effect;
+ break;
}
return rval;
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index f5efe04951f..c9647b05ce7 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -758,7 +758,7 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r
int prev_startdisp = 0, prev_enddisp = 0;
/* note: don't rename the strip, will break animation curves */
- if (ELEM7(seq->type,
+ if (ELEM(seq->type,
SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM,
SEQ_TYPE_SCENE, SEQ_TYPE_META, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) == 0)
{
@@ -994,28 +994,29 @@ void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq)
static const char *give_seqname_by_type(int type)
{
switch (type) {
- case SEQ_TYPE_META: return "Meta";
- case SEQ_TYPE_IMAGE: return "Image";
- case SEQ_TYPE_SCENE: return "Scene";
- case SEQ_TYPE_MOVIE: return "Movie";
- case SEQ_TYPE_MOVIECLIP: return "Clip";
- case SEQ_TYPE_MASK: return "Mask";
- case SEQ_TYPE_SOUND_RAM: return "Audio";
- case SEQ_TYPE_CROSS: return "Cross";
- case SEQ_TYPE_GAMCROSS: return "Gamma Cross";
- case SEQ_TYPE_ADD: return "Add";
- case SEQ_TYPE_SUB: return "Sub";
- case SEQ_TYPE_MUL: return "Mul";
- case SEQ_TYPE_ALPHAOVER: return "Alpha Over";
- case SEQ_TYPE_ALPHAUNDER: return "Alpha Under";
- case SEQ_TYPE_OVERDROP: return "Over Drop";
- case SEQ_TYPE_WIPE: return "Wipe";
- case SEQ_TYPE_GLOW: return "Glow";
- case SEQ_TYPE_TRANSFORM: return "Transform";
- case SEQ_TYPE_COLOR: return "Color";
- case SEQ_TYPE_MULTICAM: return "Multicam";
- case SEQ_TYPE_ADJUSTMENT: return "Adjustment";
- case SEQ_TYPE_SPEED: return "Speed";
+ case SEQ_TYPE_META: return "Meta";
+ case SEQ_TYPE_IMAGE: return "Image";
+ case SEQ_TYPE_SCENE: return "Scene";
+ case SEQ_TYPE_MOVIE: return "Movie";
+ case SEQ_TYPE_MOVIECLIP: return "Clip";
+ case SEQ_TYPE_MASK: return "Mask";
+ case SEQ_TYPE_SOUND_RAM: return "Audio";
+ case SEQ_TYPE_CROSS: return "Cross";
+ case SEQ_TYPE_GAMCROSS: return "Gamma Cross";
+ case SEQ_TYPE_ADD: return "Add";
+ case SEQ_TYPE_SUB: return "Sub";
+ case SEQ_TYPE_MUL: return "Mul";
+ case SEQ_TYPE_ALPHAOVER: return "Alpha Over";
+ case SEQ_TYPE_ALPHAUNDER: return "Alpha Under";
+ case SEQ_TYPE_OVERDROP: return "Over Drop";
+ case SEQ_TYPE_WIPE: return "Wipe";
+ case SEQ_TYPE_GLOW: return "Glow";
+ case SEQ_TYPE_TRANSFORM: return "Transform";
+ case SEQ_TYPE_COLOR: return "Color";
+ case SEQ_TYPE_MULTICAM: return "Multicam";
+ case SEQ_TYPE_ADJUSTMENT: return "Adjustment";
+ case SEQ_TYPE_SPEED: return "Speed";
+ case SEQ_TYPE_GAUSSIAN_BLUR: return "Gaussian Blur";
default:
return NULL;
}
@@ -2224,7 +2225,7 @@ static ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh, con
init_data.out = out;
IMB_processor_apply_threaded(out->y, sizeof(RenderEffectThread), &init_data,
- render_effect_execute_init_handle, render_effect_execute_do_thread);
+ render_effect_execute_init_handle, render_effect_execute_do_thread);
return out;
}
@@ -2808,7 +2809,7 @@ static ImBuf *seq_render_strip(const SeqRenderData *context, Sequence *seq, floa
float nr = give_stripelem_index(seq, cfra);
/* all effects are handled similarly with the exception of speed effect */
int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type;
- bool is_preprocessed = !ELEM3(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE);
+ bool is_preprocessed = !ELEM(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE);
ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
@@ -2875,7 +2876,7 @@ static bool seq_must_swap_input_in_blend_mode(Sequence *seq)
/* bad hack, to fix crazy input ordering of
* those two effects */
- if (ELEM3(seq->blend_mode, SEQ_TYPE_ALPHAOVER, SEQ_TYPE_ALPHAUNDER, SEQ_TYPE_OVERDROP)) {
+ if (ELEM(seq->blend_mode, SEQ_TYPE_ALPHAOVER, SEQ_TYPE_ALPHAUNDER, SEQ_TYPE_OVERDROP)) {
swap_input = true;
}
@@ -2960,7 +2961,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq
/* Some of the blend modes are unclear how to apply with only single input,
* or some of them will just produce an empty result..
*/
- if (ELEM3(seq->blend_mode, SEQ_BLEND_REPLACE, SEQ_TYPE_CROSS, SEQ_TYPE_ALPHAOVER)) {
+ if (ELEM(seq->blend_mode, SEQ_BLEND_REPLACE, SEQ_TYPE_CROSS, SEQ_TYPE_ALPHAOVER)) {
int early_out;
if (seq->blend_mode == SEQ_BLEND_REPLACE) {
early_out = EARLY_NO_INPUT;
@@ -3512,16 +3513,28 @@ bool BKE_sequence_single_check(Sequence *seq)
}
/* check if the selected seq's reference unselected seq's */
-bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase)
+bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase, bool one_only)
{
Sequence *seq;
- /* is there more than 1 select */
+ /* is there a valid selection select */
bool ok = false;
+ /* is there one selected already? */
+ bool first = false;
for (seq = seqbase->first; seq; seq = seq->next) {
if (seq->flag & SELECT) {
- ok = true;
- break;
+ if (one_only) {
+ ok = true;
+ break;
+ }
+ else {
+ if (first) {
+ ok = true;
+ break;
+ }
+ else
+ first = true;
+ }
}
}
@@ -3688,7 +3701,7 @@ Sequence *BKE_sequencer_foreground_frame_get(Scene *scene, int frame)
if (seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame)
continue;
/* only use elements you can see - not */
- if (ELEM5(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR)) {
+ if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR)) {
if (seq->machine > best_machine) {
best_seq = seq;
best_machine = seq->machine;
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index e2cc7b84f95..d2a4d15a2c6 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -50,6 +50,7 @@
#include "BKE_lattice.h"
#include "BKE_deform.h"
+#include "BKE_mesh.h" /* for OMP limits. */
#include "BKE_subsurf.h"
#include "BKE_editmesh.h"
@@ -65,57 +66,6 @@
/* Util macros */
#define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n"))
-/* get derived mesh */
-/* TODO is anyfunction that does this? returning the derivedFinal without we caring if its in edit mode or not? */
-DerivedMesh *object_get_derived_final(Object *ob, bool for_render)
-{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_btmesh;
-
- if (for_render) {
- /* TODO(sergey): use proper derived render here in the future. */
- return ob->derivedFinal;
- }
-
- if (em) {
- DerivedMesh *dm = em->derivedFinal;
- return dm;
- }
-
- return ob->derivedFinal;
-}
-
-/* Space transform */
-void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float target[4][4])
-{
- float itarget[4][4];
- invert_m4_m4(itarget, target);
- mul_m4_m4m4(data->local2target, itarget, local);
- invert_m4_m4(data->target2local, data->local2target);
-}
-
-void space_transform_apply(const SpaceTransform *data, float co[3])
-{
- mul_v3_m4v3(co, ((SpaceTransform *)data)->local2target, co);
-}
-
-void space_transform_invert(const SpaceTransform *data, float co[3])
-{
- mul_v3_m4v3(co, ((SpaceTransform *)data)->target2local, co);
-}
-
-static void space_transform_apply_normal(const SpaceTransform *data, float no[3])
-{
- mul_mat3_m4_v3(((SpaceTransform *)data)->local2target, no);
- normalize_v3(no); /* TODO: could we just determine de scale value from the matrix? */
-}
-
-static void space_transform_invert_normal(const SpaceTransform *data, float no[3])
-{
- mul_mat3_m4_v3(((SpaceTransform *)data)->target2local, no);
- normalize_v3(no); /* TODO: could we just determine de scale value from the matrix? */
-}
-
/*
* Shrinkwrap to the nearest vertex
*
@@ -135,12 +85,12 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
OUT_OF_MEMORY();
return;
}
-
+
/* Setup nearest */
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
#ifndef __APPLE__
-#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static)
+#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static) if(calc->numVerts > BKE_MESH_OMP_LIMIT)
#endif
for (i = 0; i < calc->numVerts; ++i) {
float *co = calc->vertexCos[i];
@@ -158,7 +108,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
else {
copy_v3_v3(tmp_co, co);
}
- space_transform_apply(&calc->local2target, tmp_co);
+ BLI_space_transform_apply(&calc->local2target, tmp_co);
/* Use local proximity heuristics (to reduce the nearest search)
*
@@ -184,7 +134,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
/* Convert the coordinates back to mesh coordinates */
copy_v3_v3(tmp_co, nearest.co);
- space_transform_invert(&calc->local2target, tmp_co);
+ BLI_space_transform_invert(&calc->local2target, tmp_co);
interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */
}
@@ -223,11 +173,11 @@ bool BKE_shrinkwrap_project_normal(
/* Apply space transform (TODO readjust dist) */
if (transf) {
copy_v3_v3(tmp_co, vert);
- space_transform_apply(transf, tmp_co);
+ BLI_space_transform_apply(transf, tmp_co);
co = tmp_co;
copy_v3_v3(tmp_no, dir);
- space_transform_apply_normal(transf, tmp_no);
+ BLI_space_transform_apply_normal(transf, tmp_no);
no = tmp_no;
#ifdef USE_DIST_CORRECT
@@ -246,7 +196,7 @@ bool BKE_shrinkwrap_project_normal(
if (hit_tmp.index != -1) {
/* invert the normal first so face culling works on rotated objects */
if (transf) {
- space_transform_invert_normal(transf, hit_tmp.no);
+ BLI_space_transform_invert_normal(transf, hit_tmp.no);
}
if (options & (MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE | MOD_SHRINKWRAP_CULL_TARGET_BACKFACE)) {
@@ -261,7 +211,7 @@ bool BKE_shrinkwrap_project_normal(
if (transf) {
/* Inverting space transform (TODO make coeherent with the initial dist readjust) */
- space_transform_invert(transf, hit_tmp.co);
+ BLI_space_transform_invert(transf, hit_tmp.co);
#ifdef USE_DIST_CORRECT
hit_tmp.dist = len_v3v3(vert, hit_tmp.co);
#endif
@@ -326,7 +276,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
auxMesh = object_get_derived_final(calc->smd->auxTarget, for_render);
if (!auxMesh)
return;
- SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget);
+ BLI_SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget);
}
/* After sucessufuly build the trees, start projection vertexs */
@@ -335,7 +285,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
{
#ifndef __APPLE__
-#pragma omp parallel for private(i, hit) schedule(static)
+#pragma omp parallel for private(i, hit) schedule(static) if (calc->numVerts > BKE_MESH_OMP_LIMIT)
#endif
for (i = 0; i < calc->numVerts; ++i) {
float *co = calc->vertexCos[i];
@@ -445,7 +395,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
/* Find the nearest vertex */
#ifndef __APPLE__
-#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static)
+#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static) if(calc->numVerts > BKE_MESH_OMP_LIMIT)
#endif
for (i = 0; i < calc->numVerts; ++i) {
float *co = calc->vertexCos[i];
@@ -460,7 +410,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
else {
copy_v3_v3(tmp_co, co);
}
- space_transform_apply(&calc->local2target, tmp_co);
+ BLI_space_transform_apply(&calc->local2target, tmp_co);
/* Use local proximity heuristics (to reduce the nearest search)
*
@@ -494,7 +444,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
}
/* Convert the coordinates back to mesh coordinates */
- space_transform_invert(&calc->local2target, tmp_co);
+ BLI_space_transform_invert(&calc->local2target, tmp_co);
interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */
}
}
@@ -537,7 +487,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
/* TODO there might be several "bugs" on non-uniform scales matrixs
* because it will no longer be nearest surface, not sphere projection
* because space has been deformed */
- SPACE_TRANSFORM_SETUP(&calc.local2target, ob, smd->target);
+ BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, ob, smd->target);
/* TODO: smd->keepDist is in global units.. must change to local */
calc.keepDist = smd->keepDist;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 12a19381e9d..0bd9517dcfd 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -41,6 +41,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@@ -2290,18 +2291,23 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
DMSetDrawOptionsTex drawParams,
DMSetDrawOptions drawParamsMapped,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag flag)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ MTFace *tf_stencil_base = NULL;
+ MTFace *tf_stencil = NULL;
+ MTFace *tf_base;
short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
DMFlagMat *faceFlags = ccgdm->faceFlags;
DMDrawOption draw_option;
int i, totface, gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
+ int gridOffset = 0;
+ int mat_nr_cache = -1;
(void) compareDrawOptions;
@@ -2315,6 +2321,12 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
mcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
totface = ccgSubSurf_getNumFaces(ss);
+
+ if (flag & DM_DRAW_USE_TEXPAINT_UV) {
+ int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
+ tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+ }
+
for (i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
@@ -2333,6 +2345,18 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
mat_nr = 0;
}
+ /* texture painting, handle the correct uv layer here */
+ if (flag & DM_DRAW_USE_TEXPAINT_UV) {
+ if (mat_nr != mat_nr_cache) {
+ tf_base = DM_paint_uvlayer_active_get(dm, mat_nr);
+
+ mat_nr_cache = mat_nr;
+ }
+ tf = tf_base + gridOffset;
+ tf_stencil = tf_stencil_base + gridOffset;
+ gridOffset += gridFaces * gridFaces * numVerts;
+ }
+
if (drawParams)
draw_option = drawParams(tf, (mcol != NULL), mat_nr);
else if (index != ORIGINDEX_NONE)
@@ -2373,26 +2397,31 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
float *d_co = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
if (tf) glTexCoord2fv(tf->uv[1]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
glNormal3sv(ln[0][1]);
glVertex3fv(d_co);
if (tf) glTexCoord2fv(tf->uv[2]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
glNormal3sv(ln[0][2]);
glVertex3fv(c_co);
if (tf) glTexCoord2fv(tf->uv[3]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
glNormal3sv(ln[0][3]);
glVertex3fv(b_co);
if (tf) glTexCoord2fv(tf->uv[0]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
glNormal3sv(ln[0][0]);
glVertex3fv(a_co);
if (tf) tf++;
+ if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
ln++;
}
@@ -2408,17 +2437,20 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
if (tf) glTexCoord2fv(tf->uv[0]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
glNormal3fv(CCG_elem_no(&key, a));
glVertex3fv(CCG_elem_co(&key, a));
if (tf) glTexCoord2fv(tf->uv[1]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
glNormal3fv(CCG_elem_no(&key, b));
glVertex3fv(CCG_elem_co(&key, b));
if (x != gridFaces - 1) {
if (tf) tf++;
+ if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
}
}
@@ -2427,16 +2459,19 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
if (tf) glTexCoord2fv(tf->uv[3]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
glNormal3fv(CCG_elem_no(&key, a));
glVertex3fv(CCG_elem_co(&key, a));
if (tf) glTexCoord2fv(tf->uv[2]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
glNormal3fv(CCG_elem_no(&key, b));
glVertex3fv(CCG_elem_co(&key, b));
if (tf) tf++;
+ if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
glEnd();
@@ -2455,22 +2490,27 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
ccgDM_glNormalFast(a_co, b_co, c_co, d_co);
if (tf) glTexCoord2fv(tf->uv[1]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
glVertex3fv(d_co);
if (tf) glTexCoord2fv(tf->uv[2]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
glVertex3fv(c_co);
if (tf) glTexCoord2fv(tf->uv[3]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
glVertex3fv(b_co);
if (tf) glTexCoord2fv(tf->uv[0]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(a_co);
if (tf) tf++;
+ if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
}
}
@@ -2483,17 +2523,17 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
static void ccgDM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag flag)
{
- ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
+ ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag);
}
static void ccgDM_drawMappedFacesTex(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag flag)
{
- ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
+ ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
}
static void ccgDM_drawUVEdges(DerivedMesh *dm)
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 90687ef9916..4cd85fb342e 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -1286,6 +1286,19 @@ void txt_sel_all(Text *text)
text->selc = text->sell->len;
}
+/**
+ * Reverse of #txt_pop_sel
+ * Clears the selection and ensures the cursor is located
+ * at the selection (where the cursor is visually while editing).
+ */
+void txt_sel_clear(Text *text)
+{
+ if (text->sell) {
+ text->curl = text->sell;
+ text->curc = text->selc;
+ }
+}
+
void txt_sel_line(Text *text)
{
if (!text) return;
@@ -2697,7 +2710,7 @@ void txt_indent(Text *text)
/* hardcoded: TXT_TABSIZE = 4 spaces: */
int spaceslen = TXT_TABSIZE;
- if (ELEM3(NULL, text, text->curl, text->sell)) {
+ if (ELEM(NULL, text, text->curl, text->sell)) {
return;
}
@@ -2764,7 +2777,7 @@ void txt_unindent(Text *text)
/* hardcoded: TXT_TABSIZE = 4 spaces: */
int spaceslen = TXT_TABSIZE;
- if (ELEM3(NULL, text, text->curl, text->sell)) {
+ if (ELEM(NULL, text, text->curl, text->sell)) {
return;
}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index bb956cb085c..b1981a3a804 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -41,6 +41,7 @@
#include "BLI_math.h"
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
+#include "BLI_math_color.h"
#include "DNA_key_types.h"
#include "DNA_object_types.h"
@@ -145,12 +146,12 @@ void init_tex_mapping(TexMapping *texmap)
if (texmap->type == TEXMAP_TYPE_TEXTURE) {
/* to transform a texture, the inverse transform needs
* to be applied to the texture coordinate */
- mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0);
+ mul_m4_series(texmap->mat, tmat, rmat, smat);
invert_m4(texmap->mat);
}
else if (texmap->type == TEXMAP_TYPE_POINT) {
/* forward transform */
- mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0);
+ mul_m4_series(texmap->mat, tmat, rmat, smat);
}
else if (texmap->type == TEXMAP_TYPE_VECTOR) {
/* no translation for vectors */
@@ -237,7 +238,7 @@ void init_colorband(ColorBand *coba, bool rangetype)
}
coba->tot = 2;
-
+ coba->color_mode = COLBAND_BLEND_RGB;
}
ColorBand *add_colorband(bool rangetype)
@@ -252,106 +253,209 @@ ColorBand *add_colorband(bool rangetype)
/* ------------------------------------------------------------------------- */
+static float colorband_hue_interp(
+ const int ipotype_hue,
+ const float mfac, const float fac,
+ float h1, float h2)
+{
+ float h_interp;
+ int mode = 0;
+
+#define HUE_INTERP(h_a, h_b) ((mfac * (h_a)) + (fac * (h_b)))
+#define HUE_MOD(h) (((h) < 1.0f) ? (h) : (h) - 1.0f)
+
+ h1 = HUE_MOD(h1);
+ h2 = HUE_MOD(h2);
+
+ BLI_assert(h1 >= 0.0f && h1 < 1.0f);
+ BLI_assert(h2 >= 0.0f && h2 < 1.0f);
+
+ switch (ipotype_hue) {
+ case COLBAND_HUE_NEAR:
+ {
+ if ((h1 < h2) && (h2 - h1) > +0.5f) mode = 1;
+ else if ((h1 > h2) && (h2 - h1) < -0.5f) mode = 2;
+ else mode = 0;
+ break;
+ }
+ case COLBAND_HUE_FAR:
+ {
+ if ((h1 < h2) && (h2 - h1) < +0.5f) mode = 1;
+ else if ((h1 > h2) && (h2 - h1) > -0.5f) mode = 2;
+ else mode = 0;
+ break;
+ }
+ case COLBAND_HUE_CCW:
+ {
+ if (h1 > h2) mode = 2;
+ else mode = 0;
+ break;
+ }
+ case COLBAND_HUE_CW:
+ {
+ if (h1 < h2) mode = 1;
+ else mode = 0;
+ break;
+ }
+ }
+
+ switch (mode) {
+ case 0:
+ h_interp = HUE_INTERP(h1, h2);
+ break;
+ case 1:
+ h_interp = HUE_INTERP(h1 + 1.0f, h2);
+ h_interp = HUE_MOD(h_interp);
+ break;
+ case 2:
+ h_interp = HUE_INTERP(h1, h2 + 1.0f);
+ h_interp = HUE_MOD(h_interp);
+ break;
+ }
+
+ BLI_assert(h_interp >= 0.0f && h_interp < 1.0f);
+
+#undef HUE_INTERP
+#undef HUE_MOD
+
+ return h_interp;
+}
+
bool do_colorband(const ColorBand *coba, float in, float out[4])
{
const CBData *cbd1, *cbd2, *cbd0, *cbd3;
- float fac, mfac, t[4];
+ float fac;
+ int ipotype;
int a;
if (coba == NULL || coba->tot == 0) return 0;
cbd1 = coba->data;
+
+ ipotype = (coba->color_mode == COLBAND_BLEND_RGB) ? coba->ipotype : COLBAND_INTERP_LINEAR;
+
if (coba->tot == 1) {
out[0] = cbd1->r;
out[1] = cbd1->g;
out[2] = cbd1->b;
out[3] = cbd1->a;
}
+ else if ((in <= cbd1->pos) && ELEM(ipotype, COLBAND_INTERP_LINEAR, COLBAND_INTERP_EASE)) {
+ out[0] = cbd1->r;
+ out[1] = cbd1->g;
+ out[2] = cbd1->b;
+ out[3] = cbd1->a;
+ }
else {
- if (in <= cbd1->pos && coba->ipotype < 2) {
+ CBData left, right;
+
+ /* we're looking for first pos > in */
+ for (a = 0; a < coba->tot; a++, cbd1++) if (cbd1->pos > in) break;
+
+ if (a == coba->tot) {
+ cbd2 = cbd1 - 1;
+ right = *cbd2;
+ right.pos = 1.0f;
+ cbd1 = &right;
+ }
+ else if (a == 0) {
+ left = *cbd1;
+ left.pos = 0.0f;
+ cbd2 = &left;
+ }
+ else {
+ cbd2 = cbd1 - 1;
+ }
+
+ if ((in >= cbd1->pos) && ELEM(ipotype, COLBAND_INTERP_LINEAR, COLBAND_INTERP_EASE)) {
out[0] = cbd1->r;
out[1] = cbd1->g;
out[2] = cbd1->b;
out[3] = cbd1->a;
}
else {
- CBData left, right;
-
- /* we're looking for first pos > in */
- for (a = 0; a < coba->tot; a++, cbd1++) if (cbd1->pos > in) break;
-
- if (a == coba->tot) {
- cbd2 = cbd1 - 1;
- right = *cbd2;
- right.pos = 1.0f;
- cbd1 = &right;
- }
- else if (a == 0) {
- left = *cbd1;
- left.pos = 0.0f;
- cbd2 = &left;
+
+ if (cbd2->pos != cbd1->pos) {
+ fac = (in - cbd1->pos) / (cbd2->pos - cbd1->pos);
}
else {
- cbd2 = cbd1 - 1;
+ /* was setting to 0.0 in 2.56 & previous, but this
+ * is incorrect for the last element, see [#26732] */
+ fac = (a != coba->tot) ? 0.0f : 1.0f;
}
-
- if (in >= cbd1->pos && coba->ipotype < 2) {
- out[0] = cbd1->r;
- out[1] = cbd1->g;
- out[2] = cbd1->b;
- out[3] = cbd1->a;
+
+ if (ipotype == COLBAND_INTERP_CONSTANT) {
+ /* constant */
+ out[0] = cbd2->r;
+ out[1] = cbd2->g;
+ out[2] = cbd2->b;
+ out[3] = cbd2->a;
}
- else {
-
- if (cbd2->pos != cbd1->pos)
- fac = (in - cbd1->pos) / (cbd2->pos - cbd1->pos);
+ else if (ipotype >= COLBAND_INTERP_B_SPLINE) {
+ /* ipo from right to left: 3 2 1 0 */
+ float t[4];
+
+ if (a >= coba->tot - 1) cbd0 = cbd1;
+ else cbd0 = cbd1 + 1;
+ if (a < 2) cbd3 = cbd2;
+ else cbd3 = cbd2 - 1;
+
+ CLAMP(fac, 0.0f, 1.0f);
+
+ if (ipotype == COLBAND_INTERP_CARDINAL) {
+ key_curve_position_weights(fac, t, KEY_CARDINAL);
+ }
else {
- /* was setting to 0.0 in 2.56 & previous, but this
- * is incorrect for the last element, see [#26732] */
- fac = (a != coba->tot) ? 0.0f : 1.0f;
+ key_curve_position_weights(fac, t, KEY_BSPLINE);
+ }
+
+ out[0] = t[3] * cbd3->r + t[2] * cbd2->r + t[1] * cbd1->r + t[0] * cbd0->r;
+ out[1] = t[3] * cbd3->g + t[2] * cbd2->g + t[1] * cbd1->g + t[0] * cbd0->g;
+ out[2] = t[3] * cbd3->b + t[2] * cbd2->b + t[1] * cbd1->b + t[0] * cbd0->b;
+ out[3] = t[3] * cbd3->a + t[2] * cbd2->a + t[1] * cbd1->a + t[0] * cbd0->a;
+ CLAMP(out[0], 0.0f, 1.0f);
+ CLAMP(out[1], 0.0f, 1.0f);
+ CLAMP(out[2], 0.0f, 1.0f);
+ CLAMP(out[3], 0.0f, 1.0f);
+ }
+ else {
+ float mfac;
+
+ if (ipotype == COLBAND_INTERP_EASE) {
+ mfac = fac * fac;
+ fac = 3.0f * mfac - 2.0f * mfac * fac;
}
-
- if (coba->ipotype == 4) {
- /* constant */
- out[0] = cbd2->r;
- out[1] = cbd2->g;
- out[2] = cbd2->b;
- out[3] = cbd2->a;
- return 1;
+
+ mfac = 1.0f - fac;
+
+ if (UNLIKELY(coba->color_mode == COLBAND_BLEND_HSV)) {
+ float col1[3], col2[3];
+
+ rgb_to_hsv_v(&cbd1->r, col1);
+ rgb_to_hsv_v(&cbd2->r, col2);
+
+ out[0] = colorband_hue_interp(coba->ipotype_hue, mfac, fac, col1[0], col2[0]);
+ out[1] = mfac * col1[1] + fac * col2[1];
+ out[2] = mfac * col1[2] + fac * col2[2];
+ out[3] = mfac * cbd1->a + fac * cbd2->a;
+
+ hsv_to_rgb_v(out, out);
}
-
- if (coba->ipotype >= 2) {
- /* ipo from right to left: 3 2 1 0 */
-
- if (a >= coba->tot - 1) cbd0 = cbd1;
- else cbd0 = cbd1 + 1;
- if (a < 2) cbd3 = cbd2;
- else cbd3 = cbd2 - 1;
-
- CLAMP(fac, 0.0f, 1.0f);
-
- if (coba->ipotype == 3)
- key_curve_position_weights(fac, t, KEY_CARDINAL);
- else
- key_curve_position_weights(fac, t, KEY_BSPLINE);
-
- out[0] = t[3] * cbd3->r + t[2] * cbd2->r + t[1] * cbd1->r + t[0] * cbd0->r;
- out[1] = t[3] * cbd3->g + t[2] * cbd2->g + t[1] * cbd1->g + t[0] * cbd0->g;
- out[2] = t[3] * cbd3->b + t[2] * cbd2->b + t[1] * cbd1->b + t[0] * cbd0->b;
- out[3] = t[3] * cbd3->a + t[2] * cbd2->a + t[1] * cbd1->a + t[0] * cbd0->a;
- CLAMP(out[0], 0.0f, 1.0f);
- CLAMP(out[1], 0.0f, 1.0f);
- CLAMP(out[2], 0.0f, 1.0f);
- CLAMP(out[3], 0.0f, 1.0f);
+ else if (UNLIKELY(coba->color_mode == COLBAND_BLEND_HSL)) {
+ float col1[3], col2[3];
+
+ rgb_to_hsl_v(&cbd1->r, col1);
+ rgb_to_hsl_v(&cbd2->r, col2);
+
+ out[0] = colorband_hue_interp(coba->ipotype_hue, mfac, fac, col1[0], col2[0]);
+ out[1] = mfac * col1[1] + fac * col2[1];
+ out[2] = mfac * col1[2] + fac * col2[2];
+ out[3] = mfac * cbd1->a + fac * cbd2->a;
+
+ hsl_to_rgb_v(out, out);
}
else {
-
- if (coba->ipotype == 1) { /* EASE */
- mfac = fac * fac;
- fac = 3.0f * mfac - 2.0f * mfac * fac;
- }
- mfac = 1.0f - fac;
-
+ /* COLBAND_BLEND_RGB */
out[0] = mfac * cbd1->r + fac * cbd2->r;
out[1] = mfac * cbd1->g + fac * cbd2->g;
out[2] = mfac * cbd1->b + fac * cbd2->b;
@@ -408,19 +512,18 @@ CBData *colorband_element_add(struct ColorBand *coba, float position)
if (coba->tot == MAXCOLORBAND) {
return NULL;
}
- else if (coba->tot > 0) {
+ else {
CBData *xnew;
- float col[4];
-
- do_colorband(coba, position, col);
xnew = &coba->data[coba->tot];
xnew->pos = position;
- xnew->r = col[0];
- xnew->g = col[1];
- xnew->b = col[2];
- xnew->a = col[3];
+ if (coba->tot != 0) {
+ do_colorband(coba, position, &xnew->r);
+ }
+ else {
+ zero_v4(&xnew->r);
+ }
}
coba->tot++;
@@ -474,7 +577,8 @@ void BKE_texture_free(Tex *tex)
void default_tex(Tex *tex)
{
- tex->type = TEX_CLOUDS;
+ tex->type = TEX_IMAGE;
+ tex->ima = NULL;
tex->stype = 0;
tex->flag = TEX_CHECKER_ODD;
tex->imaflag = TEX_INTERPOL | TEX_MIPMAP | TEX_USEALPHA;
@@ -592,7 +696,7 @@ Tex *add_texture(Main *bmain, const char *name)
void default_mtex(MTex *mtex)
{
- mtex->texco = TEXCO_ORCO;
+ mtex->texco = TEXCO_UV;
mtex->mapto = MAP_COL;
mtex->object = NULL;
mtex->projx = PROJ_X;
@@ -747,8 +851,7 @@ Tex *localize_texture(Tex *tex)
{
Tex *texn;
- texn = BKE_libblock_copy(&tex->id);
- BLI_remlink(&G.main->tex, texn);
+ texn = BKE_libblock_copy_nolib(&tex->id, false);
/* image texture: BKE_texture_free also doesn't decrease */
diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c
index 76b7ad5d982..6300e29f516 100644
--- a/source/blender/blenkernel/intern/tracking_region_tracker.c
+++ b/source/blender/blenkernel/intern/tracking_region_tracker.c
@@ -501,7 +501,7 @@ static void tracking_scale_marker_search(const MovieTrackingMarker *old_marker,
static void tracking_insert_new_marker(MovieTrackingContext *context, MovieTrackingTrack *track,
const MovieTrackingMarker *old_marker, int curfra, bool tracked,
int frame_width, int frame_height,
- double dst_pixel_x[5], double dst_pixel_y[5])
+ const double dst_pixel_x[5], const double dst_pixel_y[5])
{
MovieTrackingMarker new_marker;
int frame_delta = context->backwards ? -1 : 1;
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index ffbdf5cb486..eb224020977 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -82,7 +82,7 @@ static bool stabilization_median_point_get(MovieTracking *tracking, int framenr,
* NOTE: frame number should be in clip space, not scene space
*/
static void stabilization_calculate_data(MovieTracking *tracking, int framenr, int width, int height,
- float firstmedian[2], float median[2],
+ const float firstmedian[2], const float median[2],
float translation[2], float *scale, float *angle)
{
MovieTrackingStabilization *stab = &tracking->stabilization;
@@ -439,6 +439,6 @@ void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect
rotate_m4(rotation_mat, 'Z', angle); /* rotation matrix */
/* compose transformation matrix */
- mul_serie_m4(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat,
- scale_mat, inv_center_mat, NULL);
+ mul_m4_series(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat,
+ scale_mat, inv_center_mat);
}
diff --git a/source/blender/blenkernel/intern/treehash.c b/source/blender/blenkernel/intern/treehash.c
index fb55e3d2137..a65bd28da97 100644
--- a/source/blender/blenkernel/intern/treehash.c
+++ b/source/blender/blenkernel/intern/treehash.c
@@ -59,7 +59,7 @@ static TseGroup *tse_group_create(void)
static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem)
{
- if (tse_group->size == tse_group->allocated) {
+ if (UNLIKELY(tse_group->size == tse_group->allocated)) {
tse_group->allocated *= 2;
tse_group->elems = MEM_reallocN(tse_group->elems, sizeof(TreeStoreElem *) * tse_group->allocated);
}
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 8aca9f78702..5a2c77b5619 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -41,6 +41,8 @@
# include "BLI_winstuff.h"
#endif
+/* no BKE or DNA includes! */
+
#define TEMP_STR_SIZE 256
#define SEP_CHR '#'
@@ -349,7 +351,7 @@ static void unit_dual_convert(double value, bUnitCollection *usys, bUnitDef **un
static size_t unit_as_string(char *str, int len_max, double value, int prec, bUnitCollection *usys,
/* non exposed options */
- bUnitDef *unit, char pad)
+ const bUnitDef *unit, char pad)
{
double value_conv;
size_t len, i;
@@ -456,7 +458,7 @@ size_t bUnit_AsString(char *str, int len_max, double value, int prec, int system
return unit_as_string(str, len_max, value, prec, usys, NULL, pad ? ' ' : '\0');
}
-BLI_INLINE int isalpha_or_utf8(const int ch)
+BLI_INLINE bool isalpha_or_utf8(const int ch)
{
return (ch >= 128 || isalpha(ch));
}
@@ -493,11 +495,11 @@ static const char *unit_find_str(const char *str, const char *substr)
*
* "1m1cm+2mm" - Original value
* "1*1#1*0.01#+2*0.001#" - Replace numbers
- * "1*1,1*0.01 +2*0.001 " - Add comma's if ( - + * / % ^ < > ) not found in between
+ * "1*1+1*0.01 +2*0.001 " - Add add signs if ( + - * / | & ~ < > ^ ! = % ) not found in between
*
*/
-/* not too strict, (- = * /) are most common */
+/* not too strict, (+ - * /) are most common */
static bool ch_is_op(char op)
{
switch (op) {
@@ -514,9 +516,11 @@ static bool ch_is_op(char op)
case '!':
case '=':
case '%':
- return 1;
+ return true;
+ break;
default:
- return 0;
+ return false;
+ break;
}
}
@@ -579,14 +583,42 @@ static int unit_replace(char *str, int len_max, char *str_tmp, double scale_pref
return ofs;
}
-static int unit_find(const char *str, bUnitDef *unit)
+static bool unit_find(const char *str, bUnitDef *unit)
{
- if (unit_find_str(str, unit->name_short)) return 1;
- if (unit_find_str(str, unit->name_plural)) return 1;
- if (unit_find_str(str, unit->name_alt)) return 1;
- if (unit_find_str(str, unit->name)) return 1;
+ if (unit_find_str(str, unit->name_short)) return true;
+ if (unit_find_str(str, unit->name_plural)) return true;
+ if (unit_find_str(str, unit->name_alt)) return true;
+ if (unit_find_str(str, unit->name)) return true;
- return 0;
+ return false;
+}
+
+static bUnitDef *unit_detect_from_str(bUnitCollection *usys, const char *str, const char *str_prev)
+{
+ /* Try to find a default unit from current or previous string.
+ * This allows us to handle cases like 2 + 2mm, people would expect to get 4mm, not 2.002m!
+ * Note this does not handle corner cases like 2 + 2cm + 1 + 2.5mm... We can't support everything. */
+ bUnitDef *unit = NULL;
+
+ /* see which units the new value has */
+ for (unit = usys->units; unit->name; unit++) {
+ if (unit_find(str, unit))
+ break;
+ }
+ /* Else, try to infer the default unit from the previous string. */
+ if (str_prev && (unit == NULL || unit->name == NULL)) {
+ /* see which units the original value had */
+ for (unit = usys->units; unit->name; unit++) {
+ if (unit_find(str_prev, unit))
+ break;
+ }
+ }
+ /* Else, fall back to default unit. */
+ if (unit == NULL || unit->name == NULL) {
+ unit = unit_default(usys);
+ }
+
+ return unit;
}
/* make a copy of the string that replaces the units with numbers
@@ -597,37 +629,58 @@ static int unit_find(const char *str, bUnitDef *unit)
* 10.1km -> 10.1*1000.0
* ...will be resolved by python.
*
- * values will be split by a comma's
- * 5'2" -> 5*0.3048, 2*0.0254
+ * values will be split by an add sign
+ * 5'2" -> 5*0.3048 + 2*0.0254
*
* str_prev is optional, when valid it is used to get a base unit when none is set.
*
* return true of a change was made.
*/
-int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type)
+bool bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type)
{
bUnitCollection *usys = unit_get_system(system, type);
- bUnitDef *unit;
+ bUnitDef *unit = NULL, *default_unit;
+ double scale_pref_base = scale_pref;
char str_tmp[TEMP_STR_SIZE];
- int changed = 0;
+ bool changed = false;
if (usys == NULL || usys->units[0].name == NULL) {
- return 0;
+ return changed;
}
/* make lowercase */
BLI_ascii_strtolower(str, len_max);
+ /* Try to find a default unit from current or previous string. */
+ default_unit = unit_detect_from_str(usys, str, str_prev);
+
+ /* We apply the default unit to the whole expression (default unit is now the reference '1.0' one). */
+ scale_pref_base *= default_unit->scalar;
+
+ /* Apply the default unit on the whole expression, this allows to handle nasty cases like '2+2in'. */
+ if (BLI_snprintf(str_tmp, sizeof(str_tmp), "(%s)*%.9g", str, default_unit->scalar) < sizeof(str_tmp)) {
+ strncpy(str, str_tmp, len_max);
+ }
+ else {
+ /* BLI_snprintf would not fit into str_tmp, cant do much in this case
+ * check for this because otherwise bUnit_ReplaceString could call its self forever */
+ return changed;
+ }
+
for (unit = usys->units; unit->name; unit++) {
/* in case there are multiple instances */
- while (unit_replace(str, len_max, str_tmp, scale_pref, unit))
+ while (unit_replace(str, len_max, str_tmp, scale_pref_base, unit))
changed = true;
}
unit = NULL;
{
/* try other unit systems now, so we can evaluate imperial when metric is set for eg. */
+ /* Note that checking other systems at that point means we do not support their units as 'default' one.
+ * In other words, when in metrics, typing '2+2in' will give 2 meters 2 inches, not 4 inches.
+ * I do think this is the desired behavior!
+ */
bUnitCollection *usys_iter;
int system_iter;
@@ -638,7 +691,7 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca
for (unit = usys_iter->units; unit->name; unit++) {
int ofs = 0;
/* in case there are multiple instances */
- while ((ofs = unit_replace(str + ofs, len_max - ofs, str_tmp, scale_pref, unit)))
+ while ((ofs = unit_replace(str + ofs, len_max - ofs, str_tmp, scale_pref_base, unit)))
changed = true;
}
}
@@ -647,35 +700,9 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca
}
unit = NULL;
- if (changed == 0) {
- /* no units given so infer a unit from the previous string or default */
- if (str_prev) {
- /* see which units the original value had */
- for (unit = usys->units; unit->name; unit++) {
- if (unit_find(str_prev, unit))
- break;
- }
- }
-
- if (unit == NULL || unit->name == NULL)
- unit = unit_default(usys);
-
- /* add the unit prefix and re-run, use brackets in case there was an expression given */
- if (BLI_snprintf(str_tmp, sizeof(str_tmp), "(%s)%s", str, unit->name) < sizeof(str_tmp)) {
- strncpy(str, str_tmp, len_max);
- return bUnit_ReplaceString(str, len_max, NULL, scale_pref, system, type);
- }
- else {
- /* BLI_snprintf would not fit into str_tmp, cant do much in this case
- * check for this because otherwise bUnit_ReplaceString could call its self forever */
- return 0;
- }
-
- }
-
- /* replace # with commas when there is no operator between it and the next number
+ /* replace # with add sign when there is no operator between it and the next number
*
- * "1*1# 3*100# * 3" -> "1 *1, 3 *100 * 3"
+ * "1*1# 3*100# * 3" -> "1*1+ 3*100 * 3"
*
* */
{
@@ -683,25 +710,19 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca
const char *ch = str;
while ((str_found = strchr(str_found, SEP_CHR))) {
+ bool op_found = false;
- int op_found = 0;
- /* any operators after this?*/
+ /* any operators after this? */
for (ch = str_found + 1; *ch != '\0'; ch++) {
-
if (*ch == ' ' || *ch == '\t') {
- /* do nothing */
- }
- else if (ch_is_op(*ch) || *ch == ',') { /* found an op, no need to insert a ',' */
- op_found = 1;
- break;
- }
- else { /* found a non-op character */
- op_found = 0;
- break;
+ continue;
}
+ op_found = (ch_is_op(*ch) || ELEM(*ch, ',', ')'));
+ break;
}
- *str_found++ = op_found ? ' ' : ',';
+ /* If found an op, comma or closing parenthesis, no need to insert a '+', else we need it. */
+ *str_found++ = op_found ? ' ' : '+';
}
}
@@ -771,7 +792,7 @@ double bUnit_BaseScalar(int system, int type)
}
/* external access */
-int bUnit_IsValid(int system, int type)
+bool bUnit_IsValid(int system, int type)
{
return !(system < 0 || system > UNIT_SYSTEM_TOT || type < 0 || type > B_UNIT_TYPE_TOT);
}
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 5065c3ae04f..8e3c92314e6 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -142,8 +142,7 @@ World *localize_world(World *wrld)
World *wrldn;
int a;
- wrldn = BKE_libblock_copy(&wrld->id);
- BLI_remlink(&G.main->world, wrldn);
+ wrldn = BKE_libblock_copy_nolib(&wrld->id, false);
for (a = 0; a < MAX_MTEX; a++) {
if (wrld->mtex[a]) {
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index a9f040b8650..aef44993912 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -110,7 +110,7 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
}
#endif
#ifdef WITH_FFMPEG
- if (ELEM4(imtype, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_XVID, R_IMF_IMTYPE_THEORA)) {
+ if (ELEM(imtype, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_XVID, R_IMF_IMTYPE_THEORA)) {
mh.start_movie = BKE_ffmpeg_start;
mh.append_movie = BKE_ffmpeg_append;
mh.end_movie = BKE_ffmpeg_end;
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 00dfae9e72a..ca21180000d 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -30,13 +30,6 @@
#include <string.h>
#include <stdio.h>
-#if defined(_WIN32) && defined(DEBUG) && !defined(__MINGW32__) && !defined(__CYGWIN__)
-/* This does not seem necessary or present on MSVC 8, but may be needed in earlier versions? */
-# if _MSC_VER < 1400
-# include <stdint.h>
-# endif
-#endif
-
#include <stdlib.h>
#include <libavformat/avformat.h>
@@ -708,7 +701,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
* you have various implementations around. float samples in particular are not always supported.
*/
const enum AVSampleFormat *p = codec->sample_fmts;
- for (; *p!=-1; p++) {
+ for (; *p != -1; p++) {
if (*p == st->codec->sample_fmt)
break;
}
diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h
index f8e23629429..3a9d013f796 100644
--- a/source/blender/blenlib/BLI_array.h
+++ b/source/blender/blenlib/BLI_array.h
@@ -97,8 +97,7 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
(void)0 /* do nothing */ : \
_bli_array_grow_func((void **)&(arr), _##arr##_static, \
sizeof(*(arr)), _##arr##_count, num, \
- "BLI_array." #arr), \
- (void)0) /* msvc2008 needs this */ \
+ "BLI_array." #arr)) \
), \
/* increment the array count, all conditions above are accounted for. */ \
(_##arr##_count += num))
@@ -144,7 +143,7 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
/* set the count of the array, doesn't actually increase the allocated array
* size. don't use this unless you know what you're doing. */
-#define BLI_array_length_set(arr, count) \
+#define BLI_array_count_set(arr, count) \
{ _##arr##_count = (count); }(void)0
/* only to prevent unused warnings */
@@ -182,5 +181,8 @@ void _bli_array_wrap(void *arr, unsigned int arr_len, size_t arr_stride, int dir
#define BLI_array_wrap(arr, arr_len, dir) \
_bli_array_wrap(arr, arr_len, sizeof(*(arr)), dir)
+int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p);
+#define BLI_array_findindex(arr, arr_len, p) \
+ _bli_array_findindex(arr, arr_len, sizeof(*(arr)), p)
#endif /* __BLI_ARRAY_H__ */
diff --git a/source/blender/blenlib/BLI_callbacks.h b/source/blender/blenlib/BLI_callbacks.h
index 8d5ea91c422..2f963cfac51 100644
--- a/source/blender/blenlib/BLI_callbacks.h
+++ b/source/blender/blenlib/BLI_callbacks.h
@@ -29,12 +29,20 @@ struct bContext;
struct Main;
struct ID;
+/**
+ * Common suffix uses:
+ * - ``_PRE/_POST``:
+ * For handling discrete non-interactive events.
+ * - ``_INIT/_COMPLETE/_CANCEL``:
+ * For handling jobs (which may in turn cause other handlers to be called).
+ */
typedef enum {
BLI_CB_EVT_FRAME_CHANGE_PRE,
BLI_CB_EVT_FRAME_CHANGE_POST,
BLI_CB_EVT_RENDER_PRE,
BLI_CB_EVT_RENDER_POST,
BLI_CB_EVT_RENDER_STATS,
+ BLI_CB_EVT_RENDER_INIT,
BLI_CB_EVT_RENDER_COMPLETE,
BLI_CB_EVT_RENDER_CANCEL,
BLI_CB_EVT_LOAD_PRE,
@@ -45,6 +53,7 @@ typedef enum {
BLI_CB_EVT_SCENE_UPDATE_POST,
BLI_CB_EVT_GAME_PRE,
BLI_CB_EVT_GAME_POST,
+ BLI_CB_EVT_VERSION_UPDATE,
BLI_CB_EVT_TOT
} eCbEvent;
diff --git a/source/blender/blenlib/BLI_dial.h b/source/blender/blenlib/BLI_dial.h
new file mode 100644
index 00000000000..c8b57e803d2
--- /dev/null
+++ b/source/blender/blenlib/BLI_dial.h
@@ -0,0 +1,59 @@
+/*
+ * ***** 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_DIAL_H__
+#define __BLI_DIAL_H__
+
+/** \file BLI_dial.h
+ * \ingroup bli
+ *
+ * \note dials act similar to old rotation based phones and output an angle.
+ *
+ * They just are initialized with the center of the dial and a threshold value as input.
+ *
+ * When the distance of the current position of the dial from the center
+ * exceeds the threshold, this position is used to calculate the initial direction.
+ * After that, the angle from the initial direction is calculated based on
+ * current and previous directions of the digit, and returned to the user.
+ *
+ * Usage examples:
+ * \code
+ * float start_position[2] = {0.0f, 0.0f};
+ * float current_position[2];
+ * float threshold = 0.5f;
+ * float angle;
+ * Dial *dial;
+ *
+ * dial = BLI_dial_initialize(start_position, threshold);
+ *
+ * angle = BLI_dial_angle(dial, curent_position);
+ *
+ * MEM_freeN(dial);
+ *
+ * \endcode
+ */
+
+typedef struct Dial Dial;
+
+Dial *BLI_dial_initialize(float start_position[2], float threshold);
+
+float BLI_dial_angle(Dial *dial, float current_position[2]);
+
+#endif /* __BLI_DIAL_H__ */
diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h
index 484cddd0039..7aa1c30e449 100644
--- a/source/blender/blenlib/BLI_dynstr.h
+++ b/source/blender/blenlib/BLI_dynstr.h
@@ -54,7 +54,7 @@ void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len) ATT
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format, ...) ATTR_PRINTF_FORMAT(2, 3) ATTR_NONNULL(1, 2);
void BLI_dynstr_vappendf(DynStr *__restrict ds, const char *__restrict format, va_list args) ATTR_PRINTF_FORMAT(2, 0) ATTR_NONNULL(1, 2);
-int BLI_dynstr_get_len(DynStr *ds) ATTR_NONNULL();
+int BLI_dynstr_get_len(DynStr *ds) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
char *BLI_dynstr_get_cstring(DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BLI_dynstr_get_cstring_ex(DynStr *__restrict ds, char *__restrict str) ATTR_NONNULL();
diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h
index c0529d9032d..a0455489d24 100644
--- a/source/blender/blenlib/BLI_edgehash.h
+++ b/source/blender/blenlib/BLI_edgehash.h
@@ -106,6 +106,8 @@ bool BLI_edgeset_add(EdgeSet *es, unsigned int v0, unsigned int v1);
void BLI_edgeset_insert(EdgeSet *es, unsigned int v0, unsigned int v1);
bool BLI_edgeset_haskey(EdgeSet *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
void BLI_edgeset_free(EdgeSet *es);
+void BLI_edgeset_flag_set(EdgeSet *es, unsigned int flag);
+void BLI_edgeset_flag_clear(EdgeSet *es, unsigned int flag);
/* rely on inline api for now */
BLI_INLINE EdgeSetIterator *BLI_edgesetIterator_new(EdgeSet *gs) { return (EdgeSetIterator *)BLI_edgehashIterator_new((EdgeHash *)gs); }
@@ -114,5 +116,9 @@ BLI_INLINE void BLI_edgesetIterator_getKey(EdgeSetIterator *esi, unsigned int *r
BLI_INLINE void BLI_edgesetIterator_step(EdgeSetIterator *esi) { BLI_edgehashIterator_step((EdgeHashIterator *)esi); }
BLI_INLINE bool BLI_edgesetIterator_isDone(EdgeSetIterator *esi) { return BLI_edgehashIterator_isDone((EdgeHashIterator *)esi); }
+#ifdef DEBUG
+double BLI_edgehash_calc_quality(EdgeHash *eh);
+double BLI_edgeset_calc_quality(EdgeSet *es);
+#endif
#endif /* __BLI_EDGEHASH_H__ */
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index 2d1e1d84882..4f451a6c741 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -62,7 +62,7 @@ int BLI_create_symlink(const char *path, const char *to);
/* keep in sync with the definition of struct direntry in BLI_fileops_types.h */
#ifdef WIN32
-# if (defined(_MSC_VER) && (_MSC_VER >= 1500)) || defined(__MINGW64__)
+# if defined(_MSC_VER) || defined(__MINGW64__)
typedef struct _stat64 BLI_stat_t;
# elif defined(__MINGW32__)
typedef struct _stati64 BLI_stat_t;
@@ -101,7 +101,9 @@ int BLI_access(const char *filename, int mode);
bool BLI_file_is_writable(const char *file);
bool BLI_file_touch(const char *file);
+#if 0 /* UNUSED */
int BLI_file_gzip(const char *from, const char *to);
+#endif
char *BLI_file_ungzip_to_mem(const char *from_file, int *r_size);
size_t BLI_file_descriptor_size(int file);
diff --git a/source/blender/blenlib/BLI_fileops_types.h b/source/blender/blenlib/BLI_fileops_types.h
index 53c9fa16b70..0e6eab687ad 100644
--- a/source/blender/blenlib/BLI_fileops_types.h
+++ b/source/blender/blenlib/BLI_fileops_types.h
@@ -46,7 +46,7 @@ struct direntry {
char *relname;
char *path;
#ifdef WIN32 /* keep in sync with the definition of BLI_stat_t in BLI_fileops.h */
-# if (defined(_MSC_VER) && (_MSC_VER >= 1500)) || defined(__MINGW64__)
+# if defined(_MSC_VER) || defined(__MINGW64__)
struct _stat64 s;
# elif defined(__MINGW32__)
struct _stati64 s;
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index a59023d4f9b..dd3f62cd6d3 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -139,6 +139,9 @@ unsigned int BLI_ghashutil_uinthash(unsigned int key);
unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]);
#define BLI_ghashutil_inthash_v4_p \
((GSetHashFP)BLI_ghashutil_uinthash_v4)
+int BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b);
+#define BLI_ghashutil_inthash_v4_cmp \
+ BLI_ghashutil_uinthash_v4_cmp
unsigned int BLI_ghashutil_inthash_p(const void *ptr);
int BLI_ghashutil_intcmp(const void *a, const void *b);
@@ -189,6 +192,8 @@ GSet *BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info,
const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
int BLI_gset_size(GSet *gs) ATTR_WARN_UNUSED_RESULT;
+void BLI_gset_flag_set(GSet *gs, unsigned int flag);
+void BLI_gset_flag_clear(GSet *gs, unsigned int flag);
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp);
void BLI_gset_insert(GSet *gh, void *key);
bool BLI_gset_add(GSet *gs, void *key);
@@ -224,6 +229,11 @@ BLI_INLINE bool BLI_gsetIterator_done(GSetIterator *gsi) { return BLI_ghashItera
BLI_gsetIterator_done(&gs_iter_) == false; \
BLI_gsetIterator_step(&gs_iter_), i_++)
+#ifdef DEBUG
+double BLI_ghash_calc_quality(GHash *gh);
+double BLI_gset_calc_quality(GSet *gs);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_gsqueue.h b/source/blender/blenlib/BLI_gsqueue.h
index d17897df665..4600d6f6325 100644
--- a/source/blender/blenlib/BLI_gsqueue.h
+++ b/source/blender/blenlib/BLI_gsqueue.h
@@ -30,8 +30,6 @@
/** \file BLI_gsqueue.h
* \ingroup bli
- * \brief A generic structure queue (a queue for fixed length
- * (generally small) structures.
*/
typedef struct _GSQueue GSQueue;
@@ -46,4 +44,3 @@ void BLI_gsqueue_pushback(GSQueue *gq, const void *item);
void BLI_gsqueue_free(GSQueue *gq);
#endif /* __BLI_GSQUEUE_H__ */
-
diff --git a/source/blender/blenlib/BLI_heap.h b/source/blender/blenlib/BLI_heap.h
index 8a157f5e8db..ac9edfd46a2 100644
--- a/source/blender/blenlib/BLI_heap.h
+++ b/source/blender/blenlib/BLI_heap.h
@@ -35,31 +35,31 @@ typedef void (*HeapFreeFP)(void *ptr);
/* Creates a new heap. BLI_memarena is used for allocating nodes. Removed nodes
* are recycled, so memory usage will not shrink. */
-Heap *BLI_heap_new_ex(unsigned int tot_reserve);
-Heap *BLI_heap_new(void);
-void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp);
+Heap *BLI_heap_new_ex(unsigned int tot_reserve) ATTR_WARN_UNUSED_RESULT;
+Heap *BLI_heap_new(void) ATTR_WARN_UNUSED_RESULT;
+void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1);
/* Insert heap node with a value (often a 'cost') and pointer into the heap,
* duplicate values are allowed. */
-HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr);
+HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr) ATTR_NONNULL(1);
/* Remove a heap node. */
-void BLI_heap_remove(Heap *heap, HeapNode *node);
+void BLI_heap_remove(Heap *heap, HeapNode *node) ATTR_NONNULL(1, 2);
/* Return 0 if the heap is empty, 1 otherwise. */
-bool BLI_heap_is_empty(Heap *heap);
+bool BLI_heap_is_empty(Heap *heap) ATTR_NONNULL(1);
/* Return the size of the heap. */
-unsigned int BLI_heap_size(Heap *heap);
+unsigned int BLI_heap_size(Heap *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
/* Return the top node of the heap. This is the node with the lowest value. */
-HeapNode *BLI_heap_top(Heap *heap);
+HeapNode *BLI_heap_top(Heap *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
/* Pop the top node off the heap and return it's pointer. */
-void *BLI_heap_popmin(Heap *heap);
+void *BLI_heap_popmin(Heap *heap) ATTR_NONNULL(1);
/* Return the value or pointer of a heap node. */
-float BLI_heap_node_value(HeapNode *heap);
-void *BLI_heap_node_ptr(HeapNode *heap);
+float BLI_heap_node_value(HeapNode *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+void *BLI_heap_node_ptr(HeapNode *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
#endif /* __BLI_HEAP_H__ */
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
index 7b00fd90bf6..99a5fad397a 100644
--- a/source/blender/blenlib/BLI_kdopbvh.h
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -93,7 +93,7 @@ int BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const f
void BLI_bvhtree_update_tree(BVHTree *tree);
/* collision/overlap: check two trees if they overlap, alloc's *overlap with length of the int return value */
-BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int *result);
+BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int *r_overlap_tot);
float BLI_bvhtree_getepsilon(const BVHTree *tree);
diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h
index 84e7130a962..17d40e068b3 100644
--- a/source/blender/blenlib/BLI_linklist_stack.h
+++ b/source/blender/blenlib/BLI_linklist_stack.h
@@ -116,6 +116,9 @@
# define _BLI_SMALLSTACK_CAST(var)
#endif
+#define _BLI_SMALLSTACK_FAKEUSER(var) \
+ (void)(&(_##var##_type))
+
#define BLI_SMALLSTACK_DECLARE(var, type) \
LinkNode *_##var##_stack = NULL, *_##var##_free = NULL, *_##var##_temp = NULL; \
type _##var##_type
@@ -133,11 +136,14 @@
_##var##_temp->next = _##var##_stack; \
_##var##_temp->link = data; \
_##var##_stack = _##var##_temp; \
+ _BLI_SMALLSTACK_FAKEUSER(var); \
} (void)0
/* internal use, no null check */
#define _BLI_SMALLSTACK_DEL_EX(var_src, var_dst) \
- (void)((_##var_src##_temp = _##var_src##_stack->next), \
+ (void)(_BLI_SMALLSTACK_FAKEUSER(var_src), \
+ _BLI_SMALLSTACK_FAKEUSER(var_dst), \
+ (_##var_src##_temp = _##var_src##_stack->next), \
(_##var_src##_stack->next = _##var_dst##_free), \
(_##var_dst##_free = _##var_src##_stack), \
(_##var_src##_stack = _##var_src##_temp)) \
@@ -180,10 +186,6 @@
SWAP(LinkNode *, _##var_a##_free, _##var_b##_free); \
} (void)0
-#define BLI_SMALLSTACK_FREE(var) { \
- (void)&(_##var##_type); \
-} (void)0
-
/** \} */
#endif /* __BLI_LINKLIST_STACK_H__ */
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index b900b5f21a5..697ba863603 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -76,8 +76,8 @@ void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1, 2);
void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1, 2);
void BLI_listbase_reverse(struct ListBase *lb) ATTR_NONNULL(1);
-void BLI_rotatelist_first(struct ListBase *lb, void *vlink) ATTR_NONNULL(1, 2);
-void BLI_rotatelist_last(struct ListBase *lb, void *vlink) ATTR_NONNULL(1, 2);
+void BLI_listbase_rotate_first(struct ListBase *lb, void *vlink) ATTR_NONNULL(1, 2);
+void BLI_listbase_rotate_last(struct ListBase *lb, void *vlink) ATTR_NONNULL(1, 2);
/**
* Utility functions to avoid first/last references inline all over.
@@ -95,27 +95,27 @@ struct LinkData *BLI_genericNodeN(void *data);
*
* \code{.c}
*
- * LISTBASE_CIRCULAR_FORWARD_BEGIN (listbase, item, item_init) {
+ * BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN (listbase, item, item_init) {
* ...operate on marker...
* }
- * LISTBASE_CIRCULAR_FORWARD_END (listbase, item, item_init);
+ * BLI_LISTBASE_CIRCULAR_FORWARD_END (listbase, item, item_init);
*
* \endcode
*/
-#define LISTBASE_CIRCULAR_FORWARD_BEGIN(lb, lb_iter, lb_init) \
+#define BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN(lb, lb_iter, lb_init) \
if ((lb)->first && (lb_init || (lb_init = (lb)->first))) { \
lb_iter = lb_init; \
do {
-#define LISTBASE_CIRCULAR_FORWARD_END(lb, lb_iter, lb_init) \
+#define BLI_LISTBASE_CIRCULAR_FORWARD_END(lb, lb_iter, lb_init) \
} while ((lb_iter = (lb_iter)->next ? (lb_iter)->next : (lb)->first), \
(lb_iter != lb_init)); \
}
-#define LISTBASE_CIRCULAR_BACKWARD_BEGIN(lb, lb_iter, lb_init) \
+#define BLI_LISTBASE_CIRCULAR_BACKWARD_BEGIN(lb, lb_iter, lb_init) \
if ((lb)->last && (lb_init || (lb_init = (lb)->last))) { \
lb_iter = lb_init; \
do {
-#define LISTBASE_CIRCULAR_BACKWARD_END(lb, lb_iter, lb_init) \
+#define BLI_LISTBASE_CIRCULAR_BACKWARD_END(lb, lb_iter, lb_init) \
} while ((lb_iter = (lb_iter)->prev ? (lb_iter)->prev : (lb)->last), \
(lb_iter != lb_init)); \
}
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index 54e9349f1f8..5f94f04e0a8 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -75,11 +75,6 @@
#define M_LN10 2.30258509299404568402
#endif
-/* non-standard defines, used in some places */
-#ifndef MAXFLOAT
-#define MAXFLOAT ((float)3.40282347e+38)
-#endif
-
#if defined(__GNUC__)
# define NAN_FLT __builtin_nanf("")
#else
@@ -147,13 +142,7 @@ static const int NAN_INT = 0x7FC00000;
#ifdef WIN32
# if defined(_MSC_VER)
-# if (_MSC_VER < 1800) && !defined(isnan)
-# define isnan(n) _isnan(n)
-# endif
# define finite(n) _finite(n)
-# if (_MSC_VER < 1800) && !defined(hypot)
-# define hypot(a, b) _hypot(a, b)
-# endif
# endif
#endif
@@ -163,7 +152,7 @@ static const int NAN_INT = 0x7FC00000;
#ifndef CHECK_TYPE
#ifdef __GNUC__
#define CHECK_TYPE(var, type) { \
- __typeof(var) *__tmp; \
+ typeof(var) *__tmp; \
__tmp = (type *)NULL; \
(void)__tmp; \
} (void)0
@@ -241,11 +230,6 @@ MINLINE int mod_i(int i, int n);
MINLINE unsigned int highest_order_bit_i(unsigned int n);
MINLINE unsigned short highest_order_bit_s(unsigned short n);
-#if defined(_MSC_VER) && (_MSC_VER < 1800)
-extern double copysign(double x, double y);
-extern double round(double x);
-#endif
-
double double_round(double x, int ndigits);
#ifdef BLI_MATH_GCC_WARN_PRAGMA
diff --git a/source/blender/blenlib/BLI_math_color_blend.h b/source/blender/blenlib/BLI_math_color_blend.h
index d7e9bf50eae..2535a31ccc4 100644
--- a/source/blender/blenlib/BLI_math_color_blend.h
+++ b/source/blender/blenlib/BLI_math_color_blend.h
@@ -49,6 +49,24 @@ MINLINE void blend_color_lighten_byte(unsigned char dst[4], const unsigned char
MINLINE void blend_color_darken_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]);
MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]);
MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]);
+
+MINLINE void blend_color_overlay_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_hardlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_burn_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_linearburn_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_dodge_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_screen_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_softlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_pinlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_linearlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_vividlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_difference_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_exclusion_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_color_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_hue_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_saturation_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_luminosity_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+
MINLINE void blend_color_interpolate_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4], float t);
MINLINE void blend_color_mix_float(float dst[4], const float src1[4], const float src2[4]);
@@ -59,6 +77,24 @@ MINLINE void blend_color_lighten_float(float dst[4], const float src1[4], const
MINLINE void blend_color_darken_float(float dst[4], const float src1[4], const float src2[4]);
MINLINE void blend_color_erase_alpha_float(float dst[4], const float src1[4], const float src2[4]);
MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], const float src2[4]);
+
+MINLINE void blend_color_overlay_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_burn_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_linearburn_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_dodge_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_screen_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_softlight_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_pinlight_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_linearlight_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_vividlight_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_difference_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_exclusion_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_color_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_hue_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_saturation_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_luminosity_float(float dst[4], const float src1[4], const float src2[2]);
+
MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t);
#if BLI_MATH_DO_INLINE
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index f4bcc810846..81ca2908619 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -72,6 +72,7 @@ MINLINE float plane_point_side_v3(const float plane[4], const float co[3]);
/********************************* Volume **********************************/
float volume_tetrahedron_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
+float volume_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
@@ -85,8 +86,11 @@ float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const
float dist_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2]);
void closest_to_line_segment_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2]);
-float dist_squared_to_plane_v3(const float p[3], const float plane[4]);
-float dist_to_plane_v3(const float p[3], const float plane[4]);
+float dist_signed_squared_to_plane_v3(const float p[3], const float plane[4]);
+float dist_squared_to_plane_v3(const float p[3], const float plane[4]);
+float dist_signed_to_plane_v3(const float p[3], const float plane[4]);
+float dist_to_plane_v3(const float p[3], const float plane[4]);
+
float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]);
float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]);
float dist_squared_to_line_v3(const float p[3], const float l1[3], const float l2[3]);
@@ -126,9 +130,14 @@ int isect_line_sphere_v2(const float l1[2], const float l2[2], const float sp[2]
int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[2], const float v4[2], float vi[2]);
bool isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
-int isect_line_line_v3(const float v1[3], const float v2[3],
- const float v3[3], const float v4[3],
- float i1[3], float i2[3]);
+int isect_line_line_epsilon_v3(
+ const float v1[3], const float v2[3],
+ const float v3[3], const float v4[3], float i1[3], float i2[3],
+ const float epsilon);
+int isect_line_line_v3(
+ const float v1[3], const float v2[3],
+ const float v3[3], const float v4[3],
+ float i1[3], float i2[3]);
bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
const float v3[3], const float v4[3],
float vi[3], float *r_lambda);
@@ -168,6 +177,8 @@ int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2],
bool isect_point_tri_v2_cw(const float pt[2], const float v1[2], const float v2[2], const float v3[2]);
int isect_point_tri_v2_int(const int x1, const int y1, const int x2, const int y2, const int a, const int b);
bool isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3]);
+bool isect_point_tri_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3],
+ float r_vi[3]);
/* axis-aligned bounding box */
bool isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3]);
@@ -209,9 +220,14 @@ void interp_cubic_v3(float x[3], float v[3],
int interp_sparse_array(float *array, const int list_size, const float invalid);
-void barycentric_transform(float pt_tar[3], float const pt_src[3],
- const float tri_tar_p1[3], const float tri_tar_p2[3], const float tri_tar_p3[3],
- const float tri_src_p1[3], const float tri_src_p2[3], const float tri_src_p3[3]);
+void transform_point_by_tri_v3(
+ float pt_tar[3], float const pt_src[3],
+ const float tri_tar_p1[3], const float tri_tar_p2[3], const float tri_tar_p3[3],
+ const float tri_src_p1[3], const float tri_src_p2[3], const float tri_src_p3[3]);
+void transform_point_by_seg_v3(
+ float p_dst[3], const float p_src[3],
+ const float l_dst_p1[3], const float l_dst_p2[3],
+ const float l_src_p1[3], const float l_src_p2[3]);
void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2],
const float co[2], float w[3]);
diff --git a/source/blender/blenlib/BLI_math_interp.h b/source/blender/blenlib/BLI_math_interp.h
index 43ef64214ad..d2ec7b80d86 100644
--- a/source/blender/blenlib/BLI_math_interp.h
+++ b/source/blender/blenlib/BLI_math_interp.h
@@ -45,4 +45,24 @@ void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width
void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height,
int components, float u, float v);
+#define EWA_MAXIDX 255
+extern const float EWA_WTS[EWA_MAXIDX + 1];
+
+typedef void (*ewa_filter_read_pixel_cb) (void *userdata, int x, int y, float result[4]);
+
+void BLI_ewa_imp2radangle(float A, float B, float C, float F, float *a, float *b, float *th, float *ecc);
+
+/* TODO(sergey): Consider making this function inlined, so the pixel read callback
+ * could also be inlined in order to avoid per-pixel function calls.
+ */
+void BLI_ewa_filter(const int width, const int height,
+ const bool intpol,
+ const bool use_alpha,
+ const float uv[2],
+ const float du[2],
+ const float dv[2],
+ ewa_filter_read_pixel_cb read_pixel_cb,
+ void *customdata,
+ float result[4]);
+
#endif /* __BLI_MATH_INTERP_H__ */
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 5550a1c9fd9..5868912e762 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -34,14 +34,19 @@
extern "C" {
#endif
+#include "BLI_compiler_attrs.h"
+
/********************************* Init **************************************/
+void zero_m2(float R[2][2]);
void zero_m3(float R[3][3]);
void zero_m4(float R[4][4]);
+void unit_m2(float R[2][2]);
void unit_m3(float R[3][3]);
void unit_m4(float R[4][4]);
+void copy_m2_m2(float R[2][2], float A[2][2]);
void copy_m3_m3(float R[3][3], float A[3][3]);
void copy_m4_m4(float R[4][4], float A[4][4]);
void copy_m3_m4(float R[3][3], float A[4][4]);
@@ -67,6 +72,7 @@ void mul_m4_m4m3(float R[4][4], float A[4][4], float B[3][3]);
void mul_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
void mul_m3_m3m4(float R[3][3], float A[4][4], float B[3][3]);
+
void mul_m4_m4m4_q(float m1[4][4], float m3[4][4], float m2[4][4]);
void mul_m4_m3m4_q(float m1[4][4], float m3[4][4], float m2[3][3]);
@@ -76,6 +82,33 @@ void mul_serie_m3(float R[3][3],
void mul_serie_m4(float R[4][4],
float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
float M5[4][4], float M6[4][4], float M7[4][4], float M8[4][4]);
+/* mul_m3_series */
+void _va_mul_m3_series_3(float R[3][3], float M1[3][3], float M2[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_4(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_5(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_6(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
+ float M5[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_7(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
+ float M5[3][3], float M6[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_8(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
+ float M5[3][3], float M6[3][3], float M7[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_9(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
+ float M5[3][3], float M6[3][3], float M7[3][3], float M8[3][3]) ATTR_NONNULL();
+/* mul_m4_series */
+void _va_mul_m4_series_3(float R[4][4], float M1[4][4], float M2[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_4(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_5(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_6(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
+ float M5[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_7(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
+ float M5[4][4], float M6[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_8(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
+ float M5[4][4], float M6[4][4], float M7[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_9(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
+ float M5[4][4], float M6[4][4], float M7[4][4], float M8[4][4]) ATTR_NONNULL();
+
+#define mul_m3_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m3_series_, __VA_ARGS__)
+#define mul_m4_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m4_series_, __VA_ARGS__)
void mul_m4_v3(float M[4][4], float r[3]);
void mul_v3_m4v3(float r[3], float M[4][4], const float v[3]);
@@ -216,6 +249,23 @@ void mat4_frustum_set(float m[4][4], float left, float right, float bottom, floa
void mat4_look_from_origin(float m[4][4], float lookdir[3], float camup[3]);
+/* SpaceTransform helper */
+typedef struct SpaceTransform {
+ float local2target[4][4];
+ float target2local[4][4];
+
+} SpaceTransform;
+
+void BLI_space_transform_from_matrices(struct SpaceTransform *data, float local[4][4], float target[4][4]);
+void BLI_space_transform_apply(const struct SpaceTransform *data, float co[3]);
+void BLI_space_transform_invert(const struct SpaceTransform *data, float co[3]);
+void BLI_space_transform_apply_normal(const struct SpaceTransform *data, float no[3]);
+void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float no[3]);
+
+#define BLI_SPACE_TRANSFORM_SETUP(data, local, target) \
+ BLI_space_transform_from_matrices((data), (local)->obmat, (target)->obmat)
+
+
/*********************************** Other ***********************************/
void print_m3(const char *str, float M[3][3]);
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index fdad16adb7d..34e65e61981 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -65,6 +65,7 @@ MINLINE void swap_v4_v4(float a[4], float b[4]);
MINLINE void copy_v2_v2_char(char r[2], const char a[2]);
MINLINE void copy_v3_v3_char(char r[3], const char a[3]);
MINLINE void copy_v4_v4_char(char r[4], const char a[4]);
+
/* short */
MINLINE void copy_v2_v2_short(short r[2], const short a[2]);
MINLINE void copy_v3_v3_short(short r[3], const short a[3]);
@@ -231,6 +232,7 @@ MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_R
MINLINE bool compare_v2v2(const float a[2], const float b[2], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool compare_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool compare_len_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool compare_len_squared_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool compare_v4v4(const float a[4], const float b[4], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 244c308a05c..3d82480d050 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -111,6 +111,7 @@ const char *BLI_last_slash(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_R
int BLI_add_slash(char *string) ATTR_NONNULL();
void BLI_del_slash(char *string) ATTR_NONNULL();
const char *BLI_first_slash(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+void BLI_path_native_slash(char *path) ATTR_NONNULL();
void BLI_getlastdir(const char *dir, char *last, const size_t maxlen);
bool BLI_testextensie(const char *str, const char *ext) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
@@ -128,9 +129,6 @@ int BLI_stringdec(const char *string, char *head, char *start, unsigned short *n
void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic);
int BLI_split_name_num(char *left, int *nr, const char *name, const char delim);
-/* make sure path separators conform to system one */
-void BLI_clean(char *path) ATTR_NONNULL();
-
/**
* dir can be any input, like from buttons, and this function
* converts it to a regular full path.
diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h
index 50ab50e449a..c86b3aea503 100644
--- a/source/blender/blenlib/BLI_rand.h
+++ b/source/blender/blenlib/BLI_rand.h
@@ -42,33 +42,33 @@ typedef struct RNG RNG;
struct RNG *BLI_rng_new(unsigned int seed);
struct RNG *BLI_rng_new_srandom(unsigned int seed);
-void BLI_rng_free(struct RNG *rng);
+void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1);
-void BLI_rng_seed(struct RNG *rng, unsigned int seed);
-void BLI_rng_srandom(struct RNG *rng, unsigned int seed);
-int BLI_rng_get_int(struct RNG *rng);
-unsigned int BLI_rng_get_uint(struct RNG *rng);
-double BLI_rng_get_double(struct RNG *rng);
-float BLI_rng_get_float(struct RNG *rng);
-void BLI_rng_get_float_unit_v2(struct RNG *rng, float v[2]);
-void BLI_rng_get_float_unit_v3(struct RNG *rng, float v[3]);
-void BLI_rng_shuffle_array(struct RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_tot);
+void BLI_rng_seed(struct RNG *rng, unsigned int seed) ATTR_NONNULL(1);
+void BLI_rng_srandom(struct RNG *rng, unsigned int seed) ATTR_NONNULL(1);
+int BLI_rng_get_int(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+unsigned int BLI_rng_get_uint(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+double BLI_rng_get_double(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+void BLI_rng_get_float_unit_v2(struct RNG *rng, float v[2]) ATTR_NONNULL(1, 2);
+void BLI_rng_get_float_unit_v3(struct RNG *rng, float v[3]) ATTR_NONNULL(1, 2);
+void BLI_rng_shuffle_array(struct RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_tot) ATTR_NONNULL(1, 2);
/** Note that skipping is as slow as generating n numbers! */
-void BLI_rng_skip(struct RNG *rng, int n);
+void BLI_rng_skip(struct RNG *rng, int n) ATTR_NONNULL(1);
/** Seed for the random number generator, using noise.c hash[] */
void BLI_srandom(unsigned int seed);
/** Return a pseudo-random number N where 0<=N<(2^31) */
-int BLI_rand(void);
+int BLI_rand(void) ATTR_WARN_UNUSED_RESULT;
/** Return a pseudo-random number N where 0.0f<=N<1.0f */
-float BLI_frand(void);
+float BLI_frand(void) ATTR_WARN_UNUSED_RESULT;
void BLI_frand_unit_v3(float v[3]);
/** Return a pseudo-random (hash) float from an integer value */
-float BLI_hash_frand(unsigned int seed);
+float BLI_hash_frand(unsigned int seed) ATTR_WARN_UNUSED_RESULT;
/** Shuffle an array randomly using the given seed.
* contents. This routine does not use nor modify
@@ -83,10 +83,10 @@ void BLI_thread_srandom(int thread, unsigned int seed);
/** Return a pseudo-random number N where 0<=N<(2^31) */
/** Allows up to BLENDER_MAX_THREADS threads to address */
-int BLI_thread_rand(int thread);
+int BLI_thread_rand(int thread) ATTR_WARN_UNUSED_RESULT;
/** Return a pseudo-random number N where 0.0f<=N<1.0f */
/** Allows up to BLENDER_MAX_THREADS threads to address */
-float BLI_thread_frand(int thread);
+float BLI_thread_frand(int thread) ATTR_WARN_UNUSED_RESULT;
#endif /* __BLI_RAND_H__ */
diff --git a/source/blender/blenlib/BLI_smallhash.h b/source/blender/blenlib/BLI_smallhash.h
index b2fec6f870c..b80044bccff 100644
--- a/source/blender/blenlib/BLI_smallhash.h
+++ b/source/blender/blenlib/BLI_smallhash.h
@@ -70,4 +70,8 @@ void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key) ATTR_NONNUL
void *BLI_smallhash_iternew(SmallHash *sh, SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
/* void BLI_smallhash_print(SmallHash *sh); */ /* UNUSED */
+#ifdef DEBUG
+double BLI_smallhash_calc_quality(SmallHash *sh);
+#endif
+
#endif /* __BLI_SMALLHASH_H__ */
diff --git a/source/blender/blenlib/BLI_stack.h b/source/blender/blenlib/BLI_stack.h
index d65c8f02462..1e0b29bc7e8 100644
--- a/source/blender/blenlib/BLI_stack.h
+++ b/source/blender/blenlib/BLI_stack.h
@@ -34,16 +34,20 @@ typedef struct BLI_Stack BLI_Stack;
BLI_Stack *BLI_stack_new_ex(
const size_t elem_size, const char *description,
- const size_t chunk_size) ATTR_NONNULL();
+ const size_t chunk_size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_Stack *BLI_stack_new(
- const size_t elem_size, const char *description) ATTR_NONNULL();
+ const size_t elem_size, const char *description) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL();
-void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL();
+void *BLI_stack_push_r(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL();
+void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n) ATTR_NONNULL();
void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL();
-bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_NONNULL();
+size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-#endif
+bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+#endif /* __BLI_STACK_H__ */
diff --git a/source/blender/blenlib/BLI_stackdefines.h b/source/blender/blenlib/BLI_stackdefines.h
index 24cb043cd43..da9bf5ea04c 100644
--- a/source/blender/blenlib/BLI_stackdefines.h
+++ b/source/blender/blenlib/BLI_stackdefines.h
@@ -36,7 +36,7 @@
# define _STACK_SWAP_TOTALLOC(stack_a, stack_b) SWAP(unsigned int, _##stack_a##_totalloc, _##stack_b##_totalloc)
#else
# define STACK_DECLARE(stack) unsigned int _##stack##_index
-# define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)(tot))
+# define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)(0 ? tot : 0))
# define _STACK_SIZETEST(stack, off) (void)(stack), (void)(off)
# define _STACK_SWAP_TOTALLOC(stack_a, stack_b) (void)(stack_a), (void)(stack_b)
#endif
@@ -57,9 +57,12 @@
#define STACK_PEEK_PTR(stack) (BLI_assert(_##stack##_index), &((stack)[_##stack##_index - 1]))
/** remove any item from the stack, take care, re-orders */
#define STACK_REMOVE(stack, i) \
- _STACK_BOUNDSTEST(stack, i); \
- if (--_##stack##_index != i) { \
- stack[i] = stack[_##stack##_index]; \
+ { \
+ const unsigned int _i = i; \
+ _STACK_BOUNDSTEST(stack, _i); \
+ if (--_##stack##_index != _i) { \
+ stack[_i] = stack[_##stack##_index]; \
+ } \
} (void)0
#ifdef __GNUC__
#define STACK_SWAP(stack_a, stack_b) { \
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index 786e5e9d9d8..b249bc720c6 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -64,6 +64,8 @@ char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT A
size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL();
+size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL();
+
int BLI_strcaseeq(const char *a, const char *b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
char *BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
diff --git a/source/blender/blenlib/BLI_sys_types.h b/source/blender/blenlib/BLI_sys_types.h
index fcbed1daf66..c9cf33f2f69 100644
--- a/source/blender/blenlib/BLI_sys_types.h
+++ b/source/blender/blenlib/BLI_sys_types.h
@@ -47,127 +47,7 @@
extern "C" {
#endif
-/* MSVC 2010 and 2012 (>=1600) have stdint.h so we should use this for consistency */
-#if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER <= 1500
-
-/* The __intXX are built-in types of the visual compiler! So we don't
- * need to include anything else here. */
-
-
-typedef signed __int8 int8_t;
-typedef signed __int16 int16_t;
-typedef signed __int32 int32_t;
-typedef signed __int64 int64_t;
-
-typedef unsigned __int8 uint8_t;
-typedef unsigned __int16 uint16_t;
-typedef unsigned __int32 uint32_t;
-typedef unsigned __int64 uint64_t;
-
-// 7.18.2 Limits of specified-width integer types
-
-#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
-
-// 7.18.2.1 Limits of exact-width integer types
-#define INT8_MIN ((int8_t)_I8_MIN)
-#define INT8_MAX _I8_MAX
-#define INT16_MIN ((int16_t)_I16_MIN)
-#define INT16_MAX _I16_MAX
-#define INT32_MIN ((int32_t)_I32_MIN)
-#define INT32_MAX _I32_MAX
-#define INT64_MIN ((int64_t)_I64_MIN)
-#define INT64_MAX _I64_MAX
-#define UINT8_MAX _UI8_MAX
-#define UINT16_MAX _UI16_MAX
-#define UINT32_MAX _UI32_MAX
-#define UINT64_MAX _UI64_MAX
-
-// 7.18.2.2 Limits of minimum-width integer types
-#define INT_LEAST8_MIN INT8_MIN
-#define INT_LEAST8_MAX INT8_MAX
-#define INT_LEAST16_MIN INT16_MIN
-#define INT_LEAST16_MAX INT16_MAX
-#define INT_LEAST32_MIN INT32_MIN
-#define INT_LEAST32_MAX INT32_MAX
-#define INT_LEAST64_MIN INT64_MIN
-#define INT_LEAST64_MAX INT64_MAX
-#define UINT_LEAST8_MAX UINT8_MAX
-#define UINT_LEAST16_MAX UINT16_MAX
-#define UINT_LEAST32_MAX UINT32_MAX
-#define UINT_LEAST64_MAX UINT64_MAX
-
-// 7.18.2.3 Limits of fastest minimum-width integer types
-#define INT_FAST8_MIN INT8_MIN
-#define INT_FAST8_MAX INT8_MAX
-#define INT_FAST16_MIN INT16_MIN
-#define INT_FAST16_MAX INT16_MAX
-#define INT_FAST32_MIN INT32_MIN
-#define INT_FAST32_MAX INT32_MAX
-#define INT_FAST64_MIN INT64_MIN
-#define INT_FAST64_MAX INT64_MAX
-#define UINT_FAST8_MAX UINT8_MAX
-#define UINT_FAST16_MAX UINT16_MAX
-#define UINT_FAST32_MAX UINT32_MAX
-#define UINT_FAST64_MAX UINT64_MAX
-
-// 7.18.2.4 Limits of integer types capable of holding object pointers
-#ifdef _WIN64 // [
-# define INTPTR_MIN INT64_MIN
-# define INTPTR_MAX INT64_MAX
-# define UINTPTR_MAX UINT64_MAX
-#else // _WIN64 ][
-# define INTPTR_MIN INT32_MIN
-# define INTPTR_MAX INT32_MAX
-# define UINTPTR_MAX UINT32_MAX
-#endif // _WIN64 ]
-
-// 7.18.2.5 Limits of greatest-width integer types
-#define INTMAX_MIN INT64_MIN
-#define INTMAX_MAX INT64_MAX
-#define UINTMAX_MAX UINT64_MAX
-
-// 7.18.3 Limits of other integer types
-
-#ifdef _WIN64 // [
-# define PTRDIFF_MIN _I64_MIN
-# define PTRDIFF_MAX _I64_MAX
-#else // _WIN64 ][
-# define PTRDIFF_MIN _I32_MIN
-# define PTRDIFF_MAX _I32_MAX
-#endif // _WIN64 ]
-
-#define SIG_ATOMIC_MIN INT_MIN
-#define SIG_ATOMIC_MAX INT_MAX
-
-#ifndef SIZE_MAX // [
-# ifdef _WIN64 // [
-# define SIZE_MAX _UI64_MAX
-# else // _WIN64 ][
-# define SIZE_MAX _UI32_MAX
-# endif // _WIN64 ]
-#endif // SIZE_MAX ]
-
-#endif // __STDC_LIMIT_MACROS ]
-
-#ifndef _INTPTR_T_DEFINED
-#ifdef _WIN64
-typedef __int64 intptr_t;
-#else
-typedef long intptr_t;
-#endif
-#define _INTPTR_T_DEFINED
-#endif
-
-#ifndef _UINTPTR_T_DEFINED
-#ifdef _WIN64
-typedef unsigned __int64 uintptr_t;
-#else
-typedef unsigned long uintptr_t;
-#endif
-#define _UINTPTR_T_DEFINED
-#endif
-
-#elif defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
+#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
/* Linux-i386, Linux-Alpha, Linux-ppc */
#include <stdint.h>
@@ -186,7 +66,7 @@ typedef uint64_t u_int64_t;
#include <inttypes.h>
/* MinGW and MSVC >= 2010 */
-#elif defined(FREE_WINDOWS) || (defined(_MSC_VER) && _MSC_VER >= 1600)
+#elif defined(FREE_WINDOWS) || defined(_MSC_VER)
#include <stdint.h>
#else
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index 56931a45495..63a6b2a1943 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -40,6 +40,25 @@
#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_, \
+ count, ...) count
+#define _VA_NARGS_EXPAND(args) _VA_NARGS_RETURN_COUNT args
+#define _VA_NARGS_COUNT_MAX32(...) _VA_NARGS_EXPAND((__VA_ARGS__, \
+ 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_MAX32(__VA_ARGS__)), (__VA_ARGS__))
+
/* useful for finding bad use of min/max */
#if 0
/* gcc only */
@@ -137,20 +156,20 @@
* ... the compiler optimizes away the temp var */
#ifdef __GNUC__
#define CHECK_TYPE(var, type) { \
- __typeof(var) *__tmp; \
+ 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; \
+ typeof(var_a) *__tmp; \
+ __tmp = (typeof(var_b) *)NULL; \
(void)__tmp; \
} (void)0
#define CHECK_TYPE_PAIR_INLINE(var_a, var_b) ((void)({ \
- __typeof(var_a) *__tmp; \
- __tmp = (__typeof(var_b) *)NULL; \
+ typeof(var_a) *__tmp; \
+ __tmp = (typeof(var_b) *)NULL; \
(void)__tmp; \
}))
@@ -161,8 +180,19 @@
#endif
/* can be used in simple macros */
-#define CHECK_TYPE_INLINE(val, type) \
- ((void)(((type)0) != (val)))
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+# define CHECK_TYPE_INLINE(val, type) \
+ (void)((void)(((type)0) != (0 ? (val) : ((type)0))), \
+ _Generic((val), type: 0, const type: 0))
+#else
+# define CHECK_TYPE_INLINE(val, type) \
+ ((void)(((type)0) != (0 ? (val) : ((type)0))))
+#endif
+
+#define CHECK_TYPE_NONCONST(var) { \
+ void *non_const = 0 ? (var) : NULL; \
+ (void)non_const; \
+} (void)0
#define SWAP(type, a, b) { \
type sw_ap; \
@@ -182,17 +212,42 @@
(b) = (tval); \
} (void)0
-/* ELEM#(a, ...): is the first arg equal any of the others */
-#define ELEM(a, b, c) ((a) == (b) || (a) == (c))
-#define ELEM3(a, b, c, d) (ELEM(a, b, c) || (a) == (d) )
-#define ELEM4(a, b, c, d, e) (ELEM(a, b, c) || ELEM(a, d, e) )
-#define ELEM5(a, b, c, d, e, f) (ELEM(a, b, c) || ELEM3(a, d, e, f) )
-#define ELEM6(a, b, c, d, e, f, g) (ELEM(a, b, c) || ELEM4(a, d, e, f, g) )
-#define ELEM7(a, b, c, d, e, f, g, h) (ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) )
-#define ELEM8(a, b, c, d, e, f, g, h, i) (ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) )
-#define ELEM9(a, b, c, d, e, f, g, h, i, j) (ELEM4(a, b, c, d, e) || ELEM5(a, f, g, h, i, j) )
-#define ELEM10(a, b, c, d, e, f, g, h, i, j, k) (ELEM4(a, b, c, d, e) || ELEM6(a, f, g, h, i, j, k) )
-#define ELEM11(a, b, c, d, e, f, g, h, i, j, k, l) (ELEM4(a, b, c, d, e) || ELEM7(a, f, g, h, i, j, k, l) )
+/* ELEM#(v, ...): is the first arg equal any others? */
+/* internal helpers*/
+#define _VA_ELEM3(v, a, b) \
+ (((v) == (a)) || ((v) == (b)))
+#define _VA_ELEM4(v, a, b, c) \
+ (_VA_ELEM3(v, a, b) || ((v) == (c)))
+#define _VA_ELEM5(v, a, b, c, d) \
+ (_VA_ELEM4(v, a, b, c) || ((v) == (d)))
+#define _VA_ELEM6(v, a, b, c, d, e) \
+ (_VA_ELEM5(v, a, b, c, d) || ((v) == (e)))
+#define _VA_ELEM7(v, a, b, c, d, e, f) \
+ (_VA_ELEM6(v, a, b, c, d, e) || ((v) == (f)))
+#define _VA_ELEM8(v, a, b, c, d, e, f, g) \
+ (_VA_ELEM7(v, a, b, c, d, e, f) || ((v) == (g)))
+#define _VA_ELEM9(v, a, b, c, d, e, f, g, h) \
+ (_VA_ELEM8(v, a, b, c, d, e, f, g) || ((v) == (h)))
+#define _VA_ELEM10(v, a, b, c, d, e, f, g, h, i) \
+ (_VA_ELEM9(v, a, b, c, d, e, f, g, h) || ((v) == (i)))
+#define _VA_ELEM11(v, a, b, c, d, e, f, g, h, i, j) \
+ (_VA_ELEM10(v, a, b, c, d, e, f, g, h, i) || ((v) == (j)))
+#define _VA_ELEM12(v, a, b, c, d, e, f, g, h, i, j, k) \
+ (_VA_ELEM11(v, a, b, c, d, e, f, g, h, i, j) || ((v) == (k)))
+#define _VA_ELEM13(v, a, b, c, d, e, f, g, h, i, j, k, l) \
+ (_VA_ELEM12(v, a, b, c, d, e, f, g, h, i, j, k) || ((v) == (l)))
+#define _VA_ELEM14(v, a, b, c, d, e, f, g, h, i, j, k, l, m) \
+ (_VA_ELEM13(v, a, b, c, d, e, f, g, h, i, j, k, l) || ((v) == (m)))
+#define _VA_ELEM15(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n) \
+ (_VA_ELEM14(v, a, b, c, d, e, f, g, h, i, j, k, l, m) || ((v) == (n)))
+#define _VA_ELEM16(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
+ (_VA_ELEM15(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n) || ((v) == (o)))
+#define _VA_ELEM17(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
+ (_VA_ELEM16(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) || ((v) == (p)))
+
+/* reusable ELEM macro */
+#define ELEM(...) VA_NARGS_CALL_OVERLOAD(_VA_ELEM, __VA_ARGS__)
+
/* shift around elements */
#define SHIFT3(type, a, b, c) { \
@@ -346,13 +401,13 @@
#define IN_RANGE_INCL(a, b, c) ((b < c) ? ((b <= a && a <= c) ? 1 : 0) : ((c <= a && a <= b) ? 1 : 0))
/* unpack vector for args */
-#define UNPACK2(a) ((a)[0]), ((a)[1])
-#define UNPACK3(a) ((a)[0]), ((a)[1]), ((a)[2])
-#define UNPACK4(a) ((a)[0]), ((a)[1]), ((a)[2]), ((a)[3])
-/* op may be '&' or '*' */
-#define UNPACK2OP(op, a) op((a)[0]), op((a)[1])
-#define UNPACK3OP(op, a) op((a)[0]), op((a)[1]), op((a)[2])
-#define UNPACK4OP(op, a) op((a)[0]), op((a)[1]), op((a)[2]), op((a)[3])
+#define UNPACK2(a) ((a)[0]), ((a)[1])
+#define UNPACK3(a) UNPACK2(a), ((a)[2])
+#define UNPACK4(a) UNPACK3(a), ((a)[3])
+/* pre may be '&', '*' or func, post may be '->member' */
+#define UNPACK2_EX(pre, a, post) (pre((a)[0])post), (pre((a)[1])post)
+#define UNPACK3_EX(pre, a, post) UNPACK2_EX(pre, a, post), (pre((a)[2])post)
+#define UNPACK4_EX(pre, a, post) UNPACK3_EX(pre, a, post), (pre((a)[3])post)
/* array helpers */
#define ARRAY_LAST_ITEM(arr_start, arr_dtype, tot) \
@@ -385,8 +440,7 @@
/* memcpy, skipping the first part of a struct,
* ensures 'struct_dst' isn't const and that the offset can be computed at compile time */
#define MEMCPY_STRUCT_OFS(struct_dst, struct_src, member) { \
- void *_not_const = struct_dst; \
- (void)_not_const; \
+ CHECK_TYPE_NONCONST(struct_dst); \
((void)(struct_dst == struct_src), \
memcpy((char *)(struct_dst) + OFFSETOF_STRUCT(struct_dst, member), \
(char *)(struct_src) + OFFSETOF_STRUCT(struct_dst, member), \
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 0c1c5f1d774..dd02bcf22a9 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -42,6 +42,7 @@ set(INC_SYS
set(SRC
intern/BLI_args.c
intern/BLI_array.c
+ intern/BLI_dial.c
intern/BLI_dynstr.c
intern/BLI_ghash.c
intern/BLI_heap.c
@@ -118,6 +119,7 @@ set(SRC
BLI_compiler_attrs.h
BLI_compiler_compat.h
BLI_convexhull2d.h
+ BLI_dial.h
BLI_dlrbTree.h
BLI_dynlib.h
BLI_dynstr.h
diff --git a/source/blender/blenlib/intern/BLI_array.c b/source/blender/blenlib/intern/BLI_array.c
index 21d7a5a6d10..da2eef8ab6a 100644
--- a/source/blender/blenlib/intern/BLI_array.c
+++ b/source/blender/blenlib/intern/BLI_array.c
@@ -137,3 +137,18 @@ void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int d
BLI_assert(0);
}
}
+
+/**
+ * \note Not efficient, use for error checks/asserts.
+ */
+int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p)
+{
+ const char *arr_step = (const char *)arr;
+ unsigned int i;
+ for (i = 0; i < arr_len; i++, arr_step += arr_stride) {
+ if (memcmp(arr_step, p, arr_stride) == 0) {
+ return (int)i;
+ }
+ }
+ return -1;
+}
diff --git a/source/blender/blenlib/intern/BLI_dial.c b/source/blender/blenlib/intern/BLI_dial.c
new file mode 100644
index 00000000000..cfbb52847fd
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_dial.c
@@ -0,0 +1,100 @@
+/*
+ * ***** 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 "BLI_dial.h"
+#include "BLI_math.h"
+
+#include "MEM_guardedalloc.h"
+
+struct Dial {
+ /* center of the dial */
+ float center[2];
+
+ /* threshold of the dial. Distance of current position has to be greater
+ * than the threshold to be used in any calculations */
+ float threshold_squared;
+
+ /* the direction of the first dial position exceeding the threshold. This
+ * is later used as the basis against which rotation angle is calculated */
+ float initial_direction[2];
+
+ /* cache the last angle to detect rotations bigger than -/+ PI */
+ float last_angle;
+
+ /* number of full rotations */
+ int rotations;
+
+ /* has initial_direction been initialized */
+ bool initialized;
+};
+
+
+Dial *BLI_dial_initialize(float start_position[2], float threshold)
+{
+ Dial *dial = MEM_callocN(sizeof(Dial), "dial");
+
+ copy_v2_v2(dial->center, start_position);
+ dial->threshold_squared = threshold * threshold;
+
+ return dial;
+}
+
+float BLI_dial_angle(Dial *dial, float current_position[2])
+{
+ float current_direction[2];
+
+ sub_v2_v2v2(current_direction, current_position, dial->center);
+
+ /* only update when we have enough precision, by having the mouse adequately away from center */
+ if (len_squared_v2(current_direction) > dial->threshold_squared) {
+ float angle;
+ float cosval, sinval;
+
+ normalize_v2(current_direction);
+
+ if (!dial->initialized) {
+ copy_v2_v2(dial->initial_direction, current_direction);
+ dial->initialized = true;
+ }
+
+ /* calculate mouse angle between initial and final mouse position */
+ cosval = dot_v2v2(current_direction, dial->initial_direction);
+ sinval = cross_v2v2(current_direction, dial->initial_direction);
+
+ /* clamp to avoid nans in acos */
+ angle = atan2f(sinval, cosval);
+
+ /* change of sign, we passed the 180 degree threshold. This means we need to add a turn.
+ * to distinguish between transition from 0 to -1 and -PI to +PI, use comparison with PI/2 */
+ if ((angle * dial->last_angle < 0.0f) &&
+ (fabsf(dial->last_angle) > (float)M_PI_2))
+ {
+ if (dial->last_angle < 0.0f)
+ dial->rotations--;
+ else
+ dial->rotations++;
+ }
+ dial->last_angle = angle;
+
+ return angle + 2.0f * (float)M_PI * dial->rotations;
+ }
+
+ return dial->last_angle;
+}
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index b30553d0b5e..74d7fdc88cb 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -399,7 +399,7 @@ void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default)
* \param key The key to lookup.
* \returns the pointer to value for \a key or NULL.
*
- * \note This has 2 main benifits over #BLI_ghash_lookup.
+ * \note This has 2 main benefits over #BLI_ghash_lookup.
* - A NULL return always means that \a key isn't in \a gh.
* - The value can be modified in-place without further function calls (faster).
*/
@@ -570,12 +570,12 @@ void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh)
ghi->curEntry = NULL;
ghi->curBucket = UINT_MAX; /* wraps to zero */
if (gh->nentries) {
- while (!ghi->curEntry) {
+ do {
ghi->curBucket++;
if (UNLIKELY(ghi->curBucket == ghi->gh->nbuckets))
break;
ghi->curEntry = ghi->gh->buckets[ghi->curBucket];
- }
+ } while (!ghi->curEntry);
}
}
@@ -704,6 +704,11 @@ unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4])
return hash;
}
+int BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b)
+{
+ return memcmp(a, b, sizeof(unsigned int[4]));
+}
+
unsigned int BLI_ghashutil_uinthash(unsigned int key)
{
key += ~(key << 16);
@@ -967,6 +972,17 @@ void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
{
BLI_ghash_free((GHash *)gs, keyfreefp, NULL);
}
+
+void BLI_gset_flag_set(GSet *gs, unsigned int flag)
+{
+ ((GHash *)gs)->flag |= flag;
+}
+
+void BLI_gset_flag_clear(GSet *gs, unsigned int flag)
+{
+ ((GHash *)gs)->flag &= ~flag;
+}
+
/** \} */
@@ -996,3 +1012,41 @@ GSet *BLI_gset_pair_new(const char *info)
}
/** \} */
+
+
+/** \name Debugging & Introspection
+ * \{ */
+#ifdef DEBUG
+
+/**
+ * Measure how well the hash function performs
+ * (1.0 is approx as good as random distribution).
+ *
+ * Smaller is better!
+ */
+double BLI_ghash_calc_quality(GHash *gh)
+{
+ uint64_t sum = 0;
+ unsigned int i;
+
+ if (gh->nentries == 0)
+ return -1.0;
+
+ for (i = 0; i < gh->nbuckets; i++) {
+ uint64_t count = 0;
+ Entry *e;
+ for (e = gh->buckets[i]; e; e = e->next) {
+ count += 1;
+ }
+ sum += count * (count + 1);
+ }
+ return ((double)sum * (double)gh->nbuckets /
+ ((double)gh->nentries * (gh->nentries + 2 * gh->nbuckets - 1)));
+}
+double BLI_gset_calc_quality(GSet *gs)
+{
+ return BLI_ghash_calc_quality((GHash *)gs);
+}
+
+#endif
+/** \} */
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 6b1fbe855a1..dbacb0f3451 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -34,6 +34,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
+#include "BLI_stack.h"
#include "BLI_kdopbvh.h"
#include "BLI_math.h"
#include "BLI_strict_flags.h"
@@ -42,14 +43,30 @@
#include <omp.h>
#endif
+/* used for iterative_raycast */
+// #define USE_SKIP_LINKS
+
#define MAX_TREETYPE 32
+/* Setting zero so we can catch bugs in OpenMP/KDOPBVH.
+ * TODO(sergey): Deduplicate the limits with PBVH from BKE.
+ */
+#ifdef _OPENMP
+# ifdef DEBUG
+# define KDOPBVH_OMP_LIMIT 0
+# else
+# define KDOPBVH_OMP_LIMIT 1024
+# endif
+#endif
+
typedef unsigned char axis_t;
typedef struct BVHNode {
struct BVHNode **children;
struct BVHNode *parent; /* some user defined traversed need that */
+#ifdef USE_SKIP_LINKS
struct BVHNode *skip[2];
+#endif
float *bv; /* Bounding volume of all nodes, max 13 axis */
int index; /* face, edge, vertex index */
char totnode; /* how many nodes are used, used for speedup */
@@ -77,9 +94,7 @@ BLI_STATIC_ASSERT((sizeof(void *) == 8 && sizeof(BVHTree) <= 48) ||
typedef struct BVHOverlapData {
BVHTree *tree1, *tree2;
- BVHTreeOverlap *overlap;
- unsigned int i;
- unsigned int max_overlap; /* i is number of overlaps */
+ struct BLI_Stack *overlap; /* store BVHTreeOverlap */
axis_t start_axis, stop_axis;
} BVHOverlapData;
@@ -375,7 +390,7 @@ static int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int a
return n;
}
-/* --- */
+#ifdef USE_SKIP_LINKS
static void build_skip_links(BVHTree *tree, BVHNode *node, BVHNode *left, BVHNode *right)
{
int i;
@@ -392,6 +407,7 @@ static void build_skip_links(BVHTree *tree, BVHNode *node, BVHNode *left, BVHNod
left = node->children[i];
}
}
+#endif
/*
* BVHTree bounding volumes functions
@@ -670,7 +686,7 @@ static int implicit_leafs_index(BVHBuildHelper *data, int depth, int child_index
/* This functions returns the number of branches needed to have the requested number of leafs. */
static int implicit_needed_branches(int tree_type, int leafs)
{
- return max_ii(1, (leafs + tree_type - 3) / (tree_type - 1) );
+ return max_ii(1, (leafs + tree_type - 3) / (tree_type - 1));
}
/**
@@ -750,7 +766,8 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array,
int j;
/* Loop all branches on this level */
-#pragma omp parallel for private(j) schedule(static)
+
+#pragma omp parallel for private(j) schedule(static) if (num_leafs > KDOPBVH_OMP_LIMIT)
for (j = i; j < end_j; j++) {
int k;
const int parent_level_index = j - i;
@@ -931,7 +948,10 @@ void BLI_bvhtree_balance(BVHTree *tree)
for (i = 0; i < tree->totbranch; i++)
tree->nodes[tree->totleaf + i] = branches_array + i;
+#ifdef USE_SKIP_LINKS
build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL);
+#endif
+
/* bvhtree_info(tree); */
}
@@ -1038,27 +1058,16 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2)
if (!node1->totnode) {
/* check if node2 is a leaf */
if (!node2->totnode) {
+ BVHTreeOverlap *overlap;
- if (node1 == node2) {
+ if (UNLIKELY(node1 == node2)) {
return;
}
- if (data->i >= data->max_overlap) {
- /* try to make alloc'ed memory bigger */
- data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap) * (size_t)data->max_overlap * 2);
-
- if (!data->overlap) {
- printf("Out of Memory in traverse\n");
- return;
- }
- data->max_overlap *= 2;
- }
-
/* both leafs, insert overlap! */
- data->overlap[data->i].indexA = node1->index;
- data->overlap[data->i].indexB = node2->index;
-
- data->i++;
+ overlap = BLI_stack_push_r(data->overlap);
+ overlap->indexA = node1->index;
+ overlap->indexB = node2->index;
}
else {
for (j = 0; j < data->tree2->tree_type; j++) {
@@ -1077,16 +1086,21 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2)
return;
}
-BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int *result)
+BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int *r_overlap_tot)
{
int j;
- unsigned int total = 0;
+ size_t total = 0;
BVHTreeOverlap *overlap = NULL, *to = NULL;
BVHOverlapData **data;
/* check for compatibility of both trees (can't compare 14-DOP with 18-DOP) */
- if ((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) && (tree1->axis == 18 || tree2->axis == 18))
+ if (UNLIKELY((tree1->axis != tree2->axis) &&
+ (tree1->axis == 14 || tree2->axis == 14) &&
+ (tree1->axis == 18 || tree2->axis == 18)))
+ {
+ BLI_assert(0);
return NULL;
+ }
/* fast check root nodes for collision before doing big splitting + traversal */
if (!tree_overlap(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf],
@@ -1096,43 +1110,42 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int
return NULL;
}
- data = MEM_callocN(sizeof(BVHOverlapData *) * tree1->tree_type, "BVHOverlapData_star");
+ data = MEM_mallocN(sizeof(BVHOverlapData *) * tree1->tree_type, "BVHOverlapData_star");
for (j = 0; j < tree1->tree_type; j++) {
- data[j] = MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData");
+ data[j] = MEM_mallocN(sizeof(BVHOverlapData), "BVHOverlapData");
/* init BVHOverlapData */
- data[j]->overlap = malloc(sizeof(BVHTreeOverlap) * (size_t)max_ii(tree1->totleaf, tree2->totleaf));
+ data[j]->overlap = BLI_stack_new(sizeof(BVHTreeOverlap), __func__);
data[j]->tree1 = tree1;
data[j]->tree2 = tree2;
- data[j]->max_overlap = (unsigned int)max_ii(tree1->totleaf, tree2->totleaf);
- data[j]->i = 0;
data[j]->start_axis = min_axis(tree1->start_axis, tree2->start_axis);
data[j]->stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis);
}
-#pragma omp parallel for private(j) schedule(static)
+#pragma omp parallel for private(j) schedule(static) if (tree1->totleaf > KDOPBVH_OMP_LIMIT)
for (j = 0; j < MIN2(tree1->tree_type, tree1->nodes[tree1->totleaf]->totnode); j++) {
traverse(data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]);
}
for (j = 0; j < tree1->tree_type; j++)
- total += data[j]->i;
+ total += BLI_stack_count(data[j]->overlap);
- to = overlap = MEM_callocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap");
+ to = overlap = MEM_mallocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap");
for (j = 0; j < tree1->tree_type; j++) {
- memcpy(to, data[j]->overlap, data[j]->i * sizeof(BVHTreeOverlap));
- to += data[j]->i;
+ unsigned int count = (unsigned int)BLI_stack_count(data[j]->overlap);
+ BLI_stack_pop_n(data[j]->overlap, to, count);
+ BLI_stack_free(data[j]->overlap);
+ to += count;
}
for (j = 0; j < tree1->tree_type; j++) {
- free(data[j]->overlap);
MEM_freeN(data[j]);
}
MEM_freeN(data);
- (*result) = total;
+ *r_overlap_tot = (unsigned int)total;
return overlap;
}
@@ -1172,13 +1185,6 @@ static float calc_nearest_point_squared(const float proj[3], BVHNode *node, floa
return len_squared_v3v3(proj, nearest);
}
-
-typedef struct NodeDistance {
- BVHNode *node;
- float dist;
-
-} NodeDistance;
-
/* TODO: use a priority queue to reduce the number of nodes looked on */
static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node)
{
@@ -1226,6 +1232,12 @@ static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node)
#if 0
+typedef struct NodeDistance {
+ BVHNode *node;
+ float dist;
+
+} NodeDistance;
+
#define DEFAULT_FIND_NEAREST_HEAP_SIZE 1024
#define NodeDistance_priority(a, b) ((a).dist < (b).dist)
diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c
index 66fcfd21fbb..a0b61e7945c 100644
--- a/source/blender/blenlib/intern/BLI_linklist.c
+++ b/source/blender/blenlib/intern/BLI_linklist.c
@@ -38,17 +38,12 @@
int BLI_linklist_length(LinkNode *list)
{
- if (0) {
- return list ? (1 + BLI_linklist_length(list->next)) : 0;
- }
- else {
- int len;
+ int len;
- for (len = 0; list; list = list->next)
- len++;
-
- return len;
- }
+ for (len = 0; list; list = list->next)
+ len++;
+
+ return len;
}
int BLI_linklist_index(LinkNode *list, void *ptr)
diff --git a/source/blender/blenlib/intern/callbacks.c b/source/blender/blenlib/intern/callbacks.c
index 719809e6bcd..191be49263c 100644
--- a/source/blender/blenlib/intern/callbacks.c
+++ b/source/blender/blenlib/intern/callbacks.c
@@ -37,7 +37,7 @@ void BLI_callback_exec(struct Main *main, struct ID *self, eCbEvent evt)
ListBase *lb = &callback_slots[evt];
bCallbackFuncStore *funcstore;
- for (funcstore = (bCallbackFuncStore *)lb->first; funcstore; funcstore = (bCallbackFuncStore *)funcstore->next) {
+ for (funcstore = lb->first; funcstore; funcstore = funcstore->next) {
funcstore->func(main, self, funcstore->arg);
}
}
@@ -61,8 +61,8 @@ void BLI_callback_global_finalize(void)
ListBase *lb = &callback_slots[evt];
bCallbackFuncStore *funcstore;
bCallbackFuncStore *funcstore_next;
- for (funcstore = (bCallbackFuncStore *)lb->first; funcstore; funcstore = funcstore_next) {
- funcstore_next = (bCallbackFuncStore *)funcstore->next;
+ for (funcstore = lb->first; funcstore; funcstore = funcstore_next) {
+ funcstore_next = funcstore->next;
BLI_remlink(lb, funcstore);
if (funcstore->alloc) {
MEM_freeN(funcstore);
diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c
index 173d2a5a590..4ed82f8a473 100644
--- a/source/blender/blenlib/intern/edgehash.c
+++ b/source/blender/blenlib/intern/edgehash.c
@@ -93,7 +93,7 @@ BLI_INLINE unsigned int edgehash_keyhash(EdgeHash *eh, unsigned int v0, unsigned
{
BLI_assert(v0 < v1);
- return ((v0 * 39) ^ (v1 * 31)) % eh->nbuckets;
+ return ((v0 * 65) ^ (v1 * 31)) % eh->nbuckets;
}
/**
@@ -270,7 +270,7 @@ static void edgehash_free_cb(EdgeHash *eh, EdgeHashFreeFP valfreefp)
for (e = eh->buckets[i]; e; ) {
EdgeEntry *e_next = e->next;
- if (valfreefp) valfreefp(e->val);
+ valfreefp(e->val);
e = e_next;
}
@@ -463,14 +463,14 @@ void BLI_edgehashIterator_init(EdgeHashIterator *ehi, EdgeHash *eh)
ehi->curEntry = NULL;
ehi->curBucket = UINT_MAX; /* wraps to zero */
if (eh->nentries) {
- while (!ehi->curEntry) {
+ do {
ehi->curBucket++;
if (UNLIKELY(ehi->curBucket == ehi->eh->nbuckets)) {
break;
}
ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
- }
+ } while (!ehi->curEntry);
}
}
@@ -622,4 +622,49 @@ void BLI_edgeset_free(EdgeSet *es)
BLI_edgehash_free((EdgeHash *)es, NULL);
}
+void BLI_edgeset_flag_set(EdgeSet *es, unsigned int flag)
+{
+ ((EdgeHash *)es)->flag |= flag;
+}
+
+void BLI_edgeset_flag_clear(EdgeSet *es, unsigned int flag)
+{
+ ((EdgeHash *)es)->flag &= ~flag;
+}
+
+/** \} */
+
+/** \name Debugging & Introspection
+ * \{ */
+#ifdef DEBUG
+
+/**
+ * Measure how well the hash function performs
+ * (1.0 is approx as good as random distribution).
+ */
+double BLI_edgehash_calc_quality(EdgeHash *eh)
+{
+ uint64_t sum = 0;
+ unsigned int i;
+
+ if (eh->nentries == 0)
+ return -1.0;
+
+ for (i = 0; i < eh->nbuckets; i++) {
+ uint64_t count = 0;
+ EdgeEntry *e;
+ for (e = eh->buckets[i]; e; e = e->next) {
+ count += 1;
+ }
+ sum += count * (count + 1);
+ }
+ return ((double)sum * (double)eh->nbuckets /
+ ((double)eh->nentries * (eh->nentries + 2 * eh->nbuckets - 1)));
+}
+double BLI_edgeset_calc_quality(EdgeSet *es)
+{
+ return BLI_edgehash_calc_quality((EdgeHash *)es);
+}
+
+#endif
/** \} */
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index 0893c3e380f..f6bbd3273f9 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -66,7 +66,7 @@
#include "BLI_fileops.h"
#include "BLI_sys_types.h" // for intptr_t support
-
+#if 0 /* UNUSED */
/* gzip the file in from and write it to "to".
* return -1 if zlib fails, -2 if the originating file does not exist
* note: will remove the "from" file
@@ -111,6 +111,7 @@ int BLI_file_gzip(const char *from, const char *to)
return rval;
}
+#endif
/* gzip the file in from_file and write it to memory to_mem, at most size bytes.
* return the unziped size
diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c
index 67703c3f033..94d18ce3c77 100644
--- a/source/blender/blenlib/intern/gsqueue.c
+++ b/source/blender/blenlib/intern/gsqueue.c
@@ -27,6 +27,12 @@
/** \file blender/blenlib/intern/gsqueue.c
* \ingroup bli
+ *
+ * \brief A generic structure queue
+ * (a queue for fixed length generally small) structures.
+ *
+ * \note Only use this if you need (first-in-first-out),
+ * otherwise #BLI_stack is more efficient (first-in-last-out).
*/
#include <string.h>
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index b0c24899bd1..abf15d57cf7 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -354,7 +354,7 @@ int BLI_countlist(const ListBase *listbase)
}
/**
- * Returns the nth element of \a listbase, numbering from 1.
+ * Returns the nth element of \a listbase, numbering from 0.
*/
void *BLI_findlink(const ListBase *listbase, int number)
{
@@ -372,7 +372,7 @@ void *BLI_findlink(const ListBase *listbase, int number)
}
/**
- * Returns the nth-last element of \a listbase, numbering from 1.
+ * Returns the nth-last element of \a listbase, numbering from 0.
*/
void *BLI_rfindlink(const ListBase *listbase, int number)
{
@@ -390,7 +390,7 @@ void *BLI_rfindlink(const ListBase *listbase, int number)
}
/**
- * Returns the position of \a vlink within \a listbase, numbering from 1, or -1 if not found.
+ * Returns the position of \a vlink within \a listbase, numbering from 0, or -1 if not found.
*/
int BLI_findindex(const ListBase *listbase, const void *vlink)
{
@@ -599,7 +599,7 @@ void BLI_listbase_reverse(ListBase *lb)
/**
* \param vlink Link to make first.
*/
-void BLI_rotatelist_first(ListBase *lb, void *vlink)
+void BLI_listbase_rotate_first(ListBase *lb, void *vlink)
{
/* make circular */
((Link *)lb->first)->prev = lb->last;
@@ -615,7 +615,7 @@ void BLI_rotatelist_first(ListBase *lb, void *vlink)
/**
* \param vlink Link to make last.
*/
-void BLI_rotatelist_last(ListBase *lb, void *vlink)
+void BLI_listbase_rotate_last(ListBase *lb, void *vlink)
{
/* make circular */
((Link *)lb->first)->prev = lb->last;
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index 57a48bb5fa8..3ed7230b1d2 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -37,112 +37,38 @@
void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
{
- if (s != 0.0f) {
- float i, f, p;
- h = (h - floorf(h)) * 6.0f;
-
- i = floorf(h);
- f = h - i;
-
- /* avoid computing q/t when not needed */
- p = (v * (1.0f - s));
-#define q (v * (1.0f - (s * f)))
-#define t (v * (1.0f - (s * (1.0f - f))))
-
- /* faster to compare floats then int conversion */
- if (i < 1.0f) {
- *r = v;
- *g = t;
- *b = p;
- }
- else if (i < 2.0f) {
- *r = q;
- *g = v;
- *b = p;
- }
- else if (i < 3.0f) {
- *r = p;
- *g = v;
- *b = t;
- }
- else if (i < 4.0f) {
- *r = p;
- *g = q;
- *b = v;
- }
- else if (i < 5.0f) {
- *r = t;
- *g = p;
- *b = v;
- }
- else {
- *r = v;
- *g = p;
- *b = q;
- }
+ float nr, ng, nb;
-#undef q
-#undef t
+ nr = fabsf(h * 6.0f - 3.0f) - 1.0f;
+ ng = 2.0f - fabsf(h * 6.0f - 2.0f);
+ nb = 2.0f - fabsf(h * 6.0f - 4.0f);
- }
- else {
- *r = v;
- *g = v;
- *b = v;
- }
+ CLAMP(nr, 0.0f, 1.0f);
+ CLAMP(nb, 0.0f, 1.0f);
+ CLAMP(ng, 0.0f, 1.0f);
+
+ *r = ((nr - 1.0f) * s + 1.0f) * v;
+ *g = ((ng - 1.0f) * s + 1.0f) * v;
+ *b = ((nb - 1.0f) * s + 1.0f) * v;
}
-/* HSL to rgb conversion from https://en.wikipedia.org/wiki/HSL_and_HSV */
void hsl_to_rgb(float h, float s, float l, float *r, float *g, float *b)
{
- float i, f, c;
- h = (h - floorf(h)) * 6.0f;
- c = (l > 0.5f) ? (2.0f * (1.0f - l) * s) : (2.0f * l * s);
- i = floorf(h);
- f = h - i;
+ float nr, ng, nb, chroma;
-#define x2 (c * f)
-#define x1 (c * (1.0f - f))
+ nr = fabsf(h * 6.0f - 3.0f) - 1.0f;
+ ng = 2.0f - fabsf(h * 6.0f - 2.0f);
+ nb = 2.0f - fabsf(h * 6.0f - 4.0f);
- /* faster to compare floats then int conversion */
- if (i < 1.0f) {
- *r = c;
- *g = x2;
- *b = 0;
- }
- else if (i < 2.0f) {
- *r = x1;
- *g = c;
- *b = 0;
- }
- else if (i < 3.0f) {
- *r = 0;
- *g = c;
- *b = x2;
- }
- else if (i < 4.0f) {
- *r = 0;
- *g = x1;
- *b = c;
- }
- else if (i < 5.0f) {
- *r = x2;
- *g = 0;
- *b = c;
- }
- else {
- *r = c;
- *g = 0;
- *b = x1;
- }
+ CLAMP(nr, 0.0f, 1.0f);
+ CLAMP(nb, 0.0f, 1.0f);
+ CLAMP(ng, 0.0f, 1.0f);
-#undef x1
-#undef x2
+ chroma = (1.0f - fabsf(2.0f * l - 1.0f)) * s;
- f = l - 0.5f * c;
- *r += f;
- *g += f;
- *b += f;
+ *r = (nr - 0.5f) * chroma + l;
+ *g = (ng - 0.5f) * chroma + l;
+ *b = (nb - 0.5f) * chroma + l;
}
/* convenience function for now */
@@ -152,9 +78,9 @@ void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
}
/* convenience function for now */
-void hsl_to_rgb_v(const float hcl[3], float r_rgb[3])
+void hsl_to_rgb_v(const float hsl[3], float r_rgb[3])
{
- hsl_to_rgb(hcl[0], hcl[1], hcl[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]);
+ hsl_to_rgb(hsl[0], hsl[1], hsl[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]);
}
void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv)
@@ -187,7 +113,7 @@ void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb)
void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace)
{
float sr, sg, sb;
- float y = 128.f, cr = 128.f, cb = 128.f;
+ float y = 128.0f, cr = 128.0f, cb = 128.0f;
sr = 255.0f * r;
sg = 255.0f * g;
@@ -226,7 +152,7 @@ void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, in
/* FIXME comment above must be wrong because BLI_YCC_ITU_BT601 y 16.0 cr 16.0 -> r -0.7009 */
void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace)
{
- float r = 128.f, g = 128.f, b = 128.f;
+ float r = 128.0f, g = 128.0f, b = 128.0f;
switch (colorspace) {
case BLI_YCC_ITU_BT601:
@@ -284,57 +210,26 @@ void hex_to_rgb(char *hexcol, float *r, float *g, float *b)
void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv)
{
- float h, s, v;
- float cmax, cmin;
-
- cmax = r;
- cmin = r;
- cmax = (g > cmax ? g : cmax);
- cmin = (g < cmin ? g : cmin);
- cmax = (b > cmax ? b : cmax);
- cmin = (b < cmin ? b : cmin);
-
- v = cmax; /* value */
- if (cmax != 0.0f) {
- float cdelta;
-
- cdelta = cmax - cmin;
- s = cdelta / cmax;
-
- if (s != 0.0f) {
- float rc, gc, bc;
-
- rc = (cmax - r) / cdelta;
- gc = (cmax - g) / cdelta;
- bc = (cmax - b) / cdelta;
-
- if (r == cmax) {
- h = bc - gc;
- if (h < 0.0f) {
- h += 6.0f;
- }
- }
- else if (g == cmax) {
- h = 2.0f + rc - bc;
- }
- else {
- h = 4.0f + gc - rc;
- }
-
- h *= (1.0f / 6.0f);
- }
- else {
- h = 0.0f;
- }
+ float k = 0.0f;
+ float chroma;
+ float min_gb;
+
+ if (g < b) {
+ SWAP(float, g, b);
+ k = -1.0f;
}
- else {
- h = 0.0f;
- s = 0.0f;
+ min_gb = b;
+ if (r < g) {
+ SWAP(float, r, g);
+ k = -2.0f / 6.0f - k;
+ min_gb = min_ff(g, b);
}
- *lh = h;
- *ls = s;
- *lv = v;
+ chroma = r - min_gb;
+
+ *lh = fabsf(k + (g - b) / (6.0f * chroma + 1e-20f));
+ *ls = chroma / (r + 1e-20f);
+ *lv = r;
}
/* convenience function for now */
@@ -374,8 +269,8 @@ void rgb_to_hsl(float r, float g, float b, float *lh, float *ls, float *ll)
void rgb_to_hsl_compat(float r, float g, float b, float *lh, float *ls, float *ll)
{
- float orig_s = *ls;
- float orig_h = *lh;
+ const float orig_s = *ls;
+ const float orig_h = *lh;
rgb_to_hsl(r, g, b, lh, ls, ll);
@@ -407,8 +302,8 @@ void rgb_to_hsl_v(const float rgb[3], float r_hsl[3])
void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv)
{
- float orig_h = *lh;
- float orig_s = *ls;
+ const float orig_h = *lh;
+ const float orig_s = *ls;
rgb_to_hsv(r, g, b, lh, ls, lv);
@@ -703,11 +598,12 @@ static float index_to_float(const unsigned short i)
void BLI_init_srgb_conversion(void)
{
- static int initialized = 0;
+ static bool initialized = false;
unsigned int i, b;
- if (initialized) return;
- initialized = 1;
+ if (initialized)
+ return;
+ initialized = true;
/* Fill in the lookup table to convert floats to bytes: */
for (i = 0; i < 0x10000; i++) {
@@ -736,6 +632,9 @@ static float inverse_srgb_companding(float v)
}
}
+/**
+ * \note Does sRGB to linear conversion
+ */
void rgb_to_xyz(float r, float g, float b, float *x, float *y, float *z)
{
r = inverse_srgb_companding(r) * 100.0f;
@@ -762,13 +661,13 @@ static float xyz_to_lab_component(float v)
void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b)
{
- float xr = x / 95.047f;
- float yr = y / 100.0f;
- float zr = z / 108.883f;
+ const float xr = x / 95.047f;
+ const float yr = y / 100.0f;
+ const float zr = z / 108.883f;
- float fx = xyz_to_lab_component(xr);
- float fy = xyz_to_lab_component(yr);
- float fz = xyz_to_lab_component(zr);
+ const float fx = xyz_to_lab_component(xr);
+ const float fy = xyz_to_lab_component(yr);
+ const float fz = xyz_to_lab_component(zr);
*l = 116.0f * fy - 16.0f;
*a = 500.0f * (fx - fy);
diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c
index 4810fe757fa..2522fe5f6c9 100644
--- a/source/blender/blenlib/intern/math_color_blend_inline.c
+++ b/source/blender/blenlib/intern/math_color_blend_inline.c
@@ -30,11 +30,16 @@
#include "BLI_math_base.h"
#include "BLI_math_color.h"
#include "BLI_math_color_blend.h"
+#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
#ifndef __MATH_COLOR_BLEND_INLINE_C__
#define __MATH_COLOR_BLEND_INLINE_C__
+/* don't add any saturation to a completly black and white image */
+#define EPS_SATURATION 0.0005f
+#define EPS_ALPHA 0.0005f
+
/***************************** Color Blending ********************************
*
* - byte colors are assumed to be straight alpha
@@ -67,10 +72,7 @@ MINLINE void blend_color_mix_byte(unsigned char dst[4], const unsigned char src1
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -92,10 +94,7 @@ MINLINE void blend_color_add_byte(unsigned char dst[4], const unsigned char src1
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -117,10 +116,7 @@ MINLINE void blend_color_sub_byte(unsigned char dst[4], const unsigned char src1
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -143,10 +139,7 @@ MINLINE void blend_color_mul_byte(unsigned char dst[4], const unsigned char src1
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -169,10 +162,7 @@ MINLINE void blend_color_lighten_byte(unsigned char dst[4], const unsigned char
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -195,10 +185,7 @@ MINLINE void blend_color_darken_byte(unsigned char dst[4], const unsigned char s
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -215,10 +202,7 @@ MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], const unsigned c
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -235,11 +219,391 @@ MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], const unsigned cha
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+MINLINE void blend_color_overlay_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = (int)src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ int temp;
+
+ if (src1[i] > 127) {
+ temp = 255 - ((255 - 2 * (src1[i] - 127)) * (255 - src2[i]) / 255);
+ }
+ else {
+ temp = (2 * src1[i] * src2[i]) >> 8;
+ }
+ dst[i] = (unsigned char)min_ii((temp * fac + src1[i] * mfac) / 255, 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_hardlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = (int)src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ int temp;
+
+ if (src2[i] > 127) {
+ temp = 255 - ((255 - 2 * (src2[i] - 127)) * (255 - src1[i]) / 255);
+ }
+ else {
+ temp = (2 * src2[i] * src1[i]) >> 8;
+ }
+ dst[i] = (unsigned char)min_ii((temp * fac + src1[i] * mfac) / 255, 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_burn_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ const int temp = (src2[i] == 0) ? 0 : max_ii(255 - ((255 - src1[i]) * 255) / src2[i], 0);
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_linearburn_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ const int temp = max_ii(src1[i] + src2[i] - 255, 0);
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_dodge_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ const int temp = (src2[i] == 255) ? 255 : min_ii((src1[i] * 255) / (255 - src2[i]), 255);
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+MINLINE void blend_color_screen_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ const int temp = max_ii(255 - (((255 - src1[i]) * (255 - src2[i])) / 255), 0);
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_softlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ int temp;
+
+ if (src1[i] < 127) {
+ temp = ((2 * ((src2[i] / 2) + 64)) * src1[i]) / 255;
+ }
+ else {
+ temp = 255 - (2 * (255 - ((src2[i] / 2) + 64)) * (255 - src1[i]) / 255);
+ }
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_pinlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ int temp;
+
+ if (src2[i] > 127) {
+ temp = max_ii(2 * (src2[i] - 127), src1[i]);
+ }
+ else {
+ temp = min_ii(2 * src2[i], src1[i]);
+ }
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_linearlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ int temp;
+
+ if (src2[i] > 127) {
+ temp = min_ii(src1[i] + 2 * (src2[i] - 127), 255);
+ }
+ else {
+ temp = max_ii(src1[i] + 2 * src2[i] - 255, 0);
+ }
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_vividlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ int temp;
+
+ if (src2[i] == 255) {
+ temp = 255;
+ }
+ else if (src2[i] == 0) {
+ temp = 0;
+ }
+ else if (src2[i] > 127) {
+ temp = min_ii(((src1[i]) * 255) / (2 * (255 - src2[i])), 255);
+ }
+ else {
+ temp = max_ii(255 - ((255 - src1[i]) * 255 / (2 * src2[i])), 0);
+ }
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+
+MINLINE void blend_color_difference_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ const int temp = abs(src1[i] - src2[i]);
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_exclusion_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ const int temp = 127 - ((2 * (src1[i] - 127) * (src2[i] - 127)) / 255);
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+MINLINE void blend_color_color_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2);
+
+
+ h1 = h2;
+ s1 = s2;
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
+ dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
+ dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+MINLINE void blend_color_hue_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2);
+
+
+ h1 = h2;
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
+ dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
+ dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+
+}
+
+MINLINE void blend_color_saturation_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2);
+
+ if (s1 > EPS_SATURATION) {
+ s1 = s2;
+ }
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
+ dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
+ dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+MINLINE void blend_color_luminosity_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2);
+
+ v1 = v2;
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
+ dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
+ dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
+
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
+
}
MINLINE void blend_color_interpolate_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4], float ft)
@@ -257,10 +621,7 @@ MINLINE void blend_color_interpolate_byte(unsigned char dst[4], const unsigned c
dst[3] = (unsigned char)divide_round_i(tmp, 255);
}
else {
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -280,10 +641,7 @@ MINLINE void blend_color_mix_float(float dst[4], const float src1[4], const floa
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -298,10 +656,7 @@ MINLINE void blend_color_add_float(float dst[4], const float src1[4], const floa
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -316,10 +671,7 @@ MINLINE void blend_color_sub_float(float dst[4], const float src1[4], const floa
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -337,10 +689,7 @@ MINLINE void blend_color_mul_float(float dst[4], const float src1[4], const floa
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -360,10 +709,7 @@ MINLINE void blend_color_lighten_float(float dst[4], const float src1[4], const
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -383,10 +729,7 @@ MINLINE void blend_color_darken_float(float dst[4], const float src1[4], const f
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -397,8 +740,9 @@ MINLINE void blend_color_erase_alpha_float(float dst[4], const float src1[4], co
float alpha = max_ff(src1[3] - src2[3], 0.0f);
float map_alpha;
- if (alpha <= 0.0005f)
+ if (alpha <= EPS_ALPHA) {
alpha = 0.0f;
+ }
map_alpha = alpha / src1[3];
@@ -409,10 +753,7 @@ MINLINE void blend_color_erase_alpha_float(float dst[4], const float src1[4], co
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -423,8 +764,9 @@ MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], cons
float alpha = min_ff(src1[3] + src2[3], 1.0f);
float map_alpha;
- if (alpha >= 1.0f - 0.0005f)
+ if (alpha >= 1.0f - EPS_ALPHA) {
alpha = 1.0f;
+ }
map_alpha = (src1[3] > 0.0f) ? alpha / src1[3] : 1.0f;
@@ -435,17 +777,390 @@ MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], cons
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_overlay_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ float temp;
+
+ if (src1[i] > 0.5f) {
+ temp = 1.0f - (1.0f - 2.0f * (src1[i] - 0.5f)) * (1.0f - src2[i]);
+ }
+ else {
+ temp = 2.0f * src1[i] * src2[i];
+ }
+ dst[i] = min_ff(temp * fac + src1[i] * mfac, 1.0f);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+
+MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[2])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ float temp;
+
+ if (src2[i] > 0.5f) {
+ temp = 1.0f - ((1.0f - 2.0f * (src2[i] - 0.5f)) * (1.0f - src1[i]));
+ }
+ else {
+ temp = 2.0f * src2[i] * src1[i];
+ }
+ dst[i] = min_ff((temp * fac + src1[i] * mfac) / 1.0f, 1.0f);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_burn_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ const float temp = (src2[i] == 0.0f) ? 0.0f : max_ff(1.0f - ((1.0f - src1[i]) / src2[i]), 0.0f);
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_linearburn_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ const float temp = max_ff(src1[i] + src2[i] - 1.0f, 0.0f);
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+
+MINLINE void blend_color_dodge_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ const float temp = (src2[i] >= 1.0f) ? 1.0f : min_ff(src1[i] / (1.0f - src2[i]), 1.0f);
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_screen_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ const float temp = max_ff(1.0f - ((1.0f - src1[i]) * (1.0f - src2[i])), 0.0f);
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_softlight_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ float temp;
+
+ if (src1[i] < 0.5f) {
+ temp = (src2[i] + 0.5f) * src1[i];
+ }
+ else {
+ temp = 1.0f - ((1.0f - (src2[i] + 0.5f)) * (1.0f - src1[i]));
+ }
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_pinlight_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ float temp;
+
+ if (src2[i] > 0.5f) {
+ temp = max_ff(2.0f * (src2[i] - 0.5f), src1[i]);
+ }
+ else {
+ temp = min_ff(2.0f * src2[i], src1[i]);
+ }
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+
+MINLINE void blend_color_linearlight_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ float temp;
+
+ if (src2[i] > 0.5f) {
+ temp = min_ff(src1[i] + 2.0f * (src2[i] - 0.5f), 1.0f);
+ }
+ else {
+ temp = max_ff(src1[i] + 2.0f * src2[i] - 1.0f, 0.0f);
+ }
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+
+MINLINE void blend_color_vividlight_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ float temp;
+
+ if (src2[i] == 1.0f) {
+ temp = 1.0f;
+ }
+ else if (src2[i] == 0.0f) {
+ temp = 0.0f;
+ }
+ else if (src2[i] > 0.5f) {
+ temp = min_ff(((src1[i]) * 1.0f) / (2.0f * (1.0f - src2[i])), 1.0f);
+ }
+ else {
+ temp = max_ff(1.0f - ((1.0f - src1[i]) * 1.0f / (2.0f * src2[i])), 0.0f);
+ }
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_difference_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ dst[i] = (fabsf(src1[i] - src2[i]) * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
}
}
+
+MINLINE void blend_color_exclusion_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ const float temp = 0.5f - ((2 * (src1[i] - 0.5f) * (src2[i] - 0.5f)));
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+
+}
+
+MINLINE void blend_color_color_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+
+ rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1);
+ rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2);
+
+ h1 = h2;
+ s1 = s2;
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (r * fac + src1[0] * mfac);
+ dst[1] = (g * fac + src1[1] * mfac);
+ dst[2] = (b * fac + src1[2] * mfac);
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+
+MINLINE void blend_color_hue_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+
+ rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1);
+ rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2);
+
+ h1 = h2;
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (r * fac + src1[0] * mfac);
+ dst[1] = (g * fac + src1[1] * mfac);
+ dst[2] = (b * fac + src1[2] * mfac);
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_saturation_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+
+ rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1);
+ rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2);
+
+ if (s1 > EPS_SATURATION) {
+ s1 = s2;
+ }
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (r * fac + src1[0] * mfac);
+ dst[1] = (g * fac + src1[1] * mfac);
+ dst[2] = (b * fac + src1[2] * mfac);
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_luminosity_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+
+ rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1);
+ rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2);
+
+ v1 = v2;
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (r * fac + src1[0] * mfac);
+ dst[1] = (g * fac + src1[1] * mfac);
+ dst[2] = (b * fac + src1[2] * mfac);
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+
MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t)
{
/* interpolation, colors are premultiplied so it goes fine */
- float mt = 1.0f - t;
+ const float mt = 1.0f - t;
dst[0] = mt * src1[0] + t * src2[0];
dst[1] = mt * src1[1] + t * src2[1];
@@ -453,4 +1168,7 @@ MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], co
dst[3] = mt * src1[3] + t * src2[3];
}
+#undef EPS_SATURATION
+#undef EPS_ALPHA
+
#endif /* __MATH_COLOR_BLEND_INLINE_C__ */
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index bb2201541d9..9233749d5df 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -255,11 +255,11 @@ MINLINE float rgb_to_luma_y(const float rgb[3])
MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char col_b[3], const int limit)
{
- int r = (int)col_a[0] - (int)col_b[0];
+ const int r = (int)col_a[0] - (int)col_b[0];
if (ABS(r) < limit) {
- int g = (int)col_a[1] - (int)col_b[1];
+ const int g = (int)col_a[1] - (int)col_b[1];
if (ABS(g) < limit) {
- int b = (int)col_a[2] - (int)col_b[2];
+ const int b = (int)col_a[2] - (int)col_b[2];
if (ABS(b) < limit) {
return 1;
}
@@ -280,7 +280,7 @@ MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4])
straight[3] = premul[3];
}
else {
- float alpha_inv = 1.0f / premul[3];
+ const float alpha_inv = 1.0f / premul[3];
straight[0] = premul[0] * alpha_inv;
straight[1] = premul[1] * alpha_inv;
straight[2] = premul[2] * alpha_inv;
@@ -295,7 +295,7 @@ MINLINE void premul_to_straight_v4(float color[4])
MINLINE void straight_to_premul_v4_v4(float premul[4], const float straight[4])
{
- float alpha = straight[3];
+ const float alpha = straight[3];
premul[0] = straight[0] * alpha;
premul[1] = straight[1] * alpha;
premul[2] = straight[2] * alpha;
@@ -309,8 +309,8 @@ MINLINE void straight_to_premul_v4(float color[4])
MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4])
{
- float alpha = color[3] * (1.0f / 255.0f);
- float fac = alpha * (1.0f / 255.0f);
+ const float alpha = color[3] * (1.0f / 255.0f);
+ const float fac = alpha * (1.0f / 255.0f);
result[0] = color[0] * fac;
result[1] = color[1] * fac;
@@ -327,7 +327,7 @@ MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float c
result[3] = FTOCHAR(color[3]);
}
else {
- float alpha_inv = 1.0f / color[3];
+ const float alpha_inv = 1.0f / color[3];
/* hopefully this would be optimized */
result[0] = FTOCHAR(color[0] * alpha_inv);
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 5f3ab5eb73e..1cd1d1875fc 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -238,6 +238,18 @@ float volume_tetrahedron_v3(const float v1[3], const float v2[3], const float v3
return fabsf(determinant_m3_array(m)) / 6.0f;
}
+/**
+ * The volume from a tetrahedron, normal pointing inside gives negative volume
+ */
+float volume_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
+{
+ float m[3][3];
+ sub_v3_v3v3(m[0], v1, v2);
+ sub_v3_v3v3(m[1], v2, v3);
+ sub_v3_v3v3(m[2], v3, v4);
+ return determinant_m3_array(m) / 6.0f;
+}
+
/********************************* Distance **********************************/
@@ -364,24 +376,36 @@ void closest_to_plane_v3(float r_close[3], const float plane[4], const float pt[
madd_v3_v3v3fl(r_close, pt, plane, -side / len_sq);
}
-float dist_squared_to_plane_v3(const float pt[3], const float plane[4])
+float dist_signed_squared_to_plane_v3(const float pt[3], const float plane[4])
{
const float len_sq = len_squared_v3(plane);
const float side = plane_point_side_v3(plane, pt);
const float fac = side / len_sq;
return copysignf(len_sq * (fac * fac), side);
}
+float dist_squared_to_plane_v3(const float pt[3], const float plane[4])
+{
+ const float len_sq = len_squared_v3(plane);
+ const float side = plane_point_side_v3(plane, pt);
+ const float fac = side / len_sq;
+ /* only difference to code above - no 'copysignf' */
+ return len_sq * (fac * fac);
+}
/**
* Return the signed distance from the point to the plane.
*/
-float dist_to_plane_v3(const float pt[3], const float plane[4])
+float dist_signed_to_plane_v3(const float pt[3], const float plane[4])
{
const float len_sq = len_squared_v3(plane);
const float side = plane_point_side_v3(plane, pt);
const float fac = side / len_sq;
return sqrtf(len_sq) * fac;
}
+float dist_to_plane_v3(const float pt[3], const float plane[4])
+{
+ return fabsf(dist_signed_to_plane_v3(pt, plane));
+}
/* distance v1 to line-piece l1-l2 in 3D */
float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3])
@@ -556,7 +580,7 @@ int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[
{
float a1, a2, b1, b2, c1, c2, d;
float u, v;
- const float eps = 0.000001f;
+ const float eps = 1e-6f;
const float eps_sq = eps * eps;
a1 = v2[0] - v1[0];
@@ -953,7 +977,7 @@ bool isect_line_tri_v3(const float p1[3], const float p2[3],
cross_v3_v3v3(p, d, e2);
a = dot_v3v3(e1, p);
- if ((a > -0.000001f) && (a < 0.000001f)) return 0;
+ if (a == 0.0f) return 0;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
@@ -992,7 +1016,7 @@ bool isect_line_tri_epsilon_v3(const float p1[3], const float p2[3],
cross_v3_v3v3(p, d, e2);
a = dot_v3v3(e1, p);
- if ((a > -0.000001f) && (a < 0.000001f)) return 0;
+ if (a == 0.0f) return 0;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
@@ -1266,13 +1290,13 @@ bool isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3],
static bool getLowestRoot(const float a, const float b, const float c, const float maxR, float *root)
{
/* Check if a solution exists */
- float determinant = b * b - 4.0f * a * c;
+ const float determinant = b * b - 4.0f * a * c;
/* If determinant is negative it means no solutions. */
if (determinant >= 0.0f) {
/* calculate the two roots: (if determinant == 0 then
* x1==x2 but lets disregard that slight optimization) */
- float sqrtD = sqrtf(determinant);
+ const float sqrtD = sqrtf(determinant);
float r1 = (-b - sqrtD) / (2.0f * a);
float r2 = (-b + sqrtD) / (2.0f * a);
@@ -1283,18 +1307,18 @@ static bool getLowestRoot(const float a, const float b, const float c, const flo
/* Get lowest root: */
if (r1 > 0.0f && r1 < maxR) {
*root = r1;
- return 1;
+ return true;
}
/* It is possible that we want x2 - this can happen */
/* if x1 < 0 */
if (r2 > 0.0f && r2 < maxR) {
*root = r2;
- return 1;
+ return true;
}
}
/* No (valid) solutions */
- return 0;
+ return false;
}
bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius,
@@ -1323,7 +1347,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
if (fabsf(nordotv) < 0.000001f) {
if (fabsf(a) >= radius) {
- return 0;
+ return false;
}
}
else {
@@ -1365,7 +1389,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
//(((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y))) & 0x80000000) {
*r_lambda = t0;
copy_v3_v3(ipoint, point);
- return 1;
+ return true;
}
}
@@ -1382,7 +1406,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) {
copy_v3_v3(ipoint, v0);
- found_by_sweep = 1;
+ found_by_sweep = true;
}
/*v1*/
@@ -1392,7 +1416,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) {
copy_v3_v3(ipoint, v1);
- found_by_sweep = 1;
+ found_by_sweep = true;
}
/*v2*/
@@ -1402,7 +1426,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) {
copy_v3_v3(ipoint, v2);
- found_by_sweep = 1;
+ found_by_sweep = true;
}
/*---test edges---*/
@@ -1428,7 +1452,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
copy_v3_v3(ipoint, e1);
mul_v3_fl(ipoint, e);
add_v3_v3(ipoint, v0);
- found_by_sweep = 1;
+ found_by_sweep = true;
}
}
@@ -1450,7 +1474,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
copy_v3_v3(ipoint, e2);
mul_v3_fl(ipoint, e);
add_v3_v3(ipoint, v0);
- found_by_sweep = 1;
+ found_by_sweep = true;
}
}
@@ -1477,7 +1501,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
copy_v3_v3(ipoint, e3);
mul_v3_fl(ipoint, e);
add_v3_v3(ipoint, v1);
- found_by_sweep = 1;
+ found_by_sweep = true;
}
}
@@ -1496,10 +1520,10 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
return isect_line_tri_v3(p1, p2, v0, v1, v2, lambda);
/* first a simple bounding box test */
- if (min_fff(v0[a1], v1[a1], v2[a1]) > p1[a1]) return 0;
- if (min_fff(v0[a2], v1[a2], v2[a2]) > p1[a2]) return 0;
- if (max_fff(v0[a1], v1[a1], v2[a1]) < p1[a1]) return 0;
- if (max_fff(v0[a2], v1[a2], v2[a2]) < p1[a2]) return 0;
+ if (min_fff(v0[a1], v1[a1], v2[a1]) > p1[a1]) return false;
+ if (min_fff(v0[a2], v1[a2], v2[a2]) > p1[a2]) return false;
+ if (max_fff(v0[a1], v1[a1], v2[a1]) < p1[a1]) return false;
+ if (max_fff(v0[a2], v1[a2], v2[a2]) < p1[a2]) return false;
/* then a full intersection test */
#endif
@@ -1509,7 +1533,7 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
sub_v3_v3v3(p, v0, p1);
f = (e2[a1] * e1[a2] - e2[a2] * e1[a1]);
- if ((f > -0.000001f) && (f < 0.000001f)) return 0;
+ if ((f > -0.000001f) && (f < 0.000001f)) return false;
v = (p[a2] * e1[a1] - p[a1] * e1[a2]) / f;
if ((v < 0.0f) || (v > 1.0f)) return 0;
@@ -1517,7 +1541,7 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
f = e1[a1];
if ((f > -0.000001f) && (f < 0.000001f)) {
f = e1[a2];
- if ((f > -0.000001f) && (f < 0.000001f)) return 0;
+ if ((f > -0.000001f) && (f < 0.000001f)) return false;
u = (-p[a2] - v * e2[a2]) / f;
}
else
@@ -1527,9 +1551,9 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
*r_lambda = (p[a0] + u * e1[a0] + v * e2[a0]) / (p2[a0] - p1[a0]);
- if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return 0;
+ if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return false;
- return 1;
+ return true;
}
/**
@@ -1538,7 +1562,10 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
* 1 - lines are coplanar, i1 is set to intersection
* 2 - i1 and i2 are the nearest points on line 1 (v1, v2) and line 2 (v3, v4) respectively
*/
-int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float i1[3], float i2[3])
+int isect_line_line_epsilon_v3(
+ const float v1[3], const float v2[3],
+ const float v3[3], const float v4[3], float i1[3], float i2[3],
+ const float epsilon)
{
float a[3], b[3], c[3], ab[3], cb[3], dir1[3], dir2[3];
float d, div;
@@ -1564,7 +1591,7 @@ int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3],
return 0;
}
/* test if the two lines are coplanar */
- else if (d > -0.000001f && d < 0.000001f) {
+ else if (UNLIKELY(fabsf(d) <= epsilon)) {
cross_v3_v3v3(cb, c, b);
mul_v3_fl(a, dot_v3v3(cb, ab) / div);
@@ -1604,9 +1631,17 @@ int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3],
}
}
-/* Intersection point strictly between the two lines
- * 0 when no intersection is found
- * */
+int isect_line_line_v3(
+ const float v1[3], const float v2[3],
+ const float v3[3], const float v4[3], float i1[3], float i2[3])
+{
+ const float epsilon = 0.000001f;
+ return isect_line_line_epsilon_v3(v1, v2, v3, v4, i1, i2, epsilon);
+}
+
+/** Intersection point strictly between the two lines
+ * \return false when no intersection is found
+ */
bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
const float v3[3], const float v4[3],
float vi[3], float *r_lambda)
@@ -1623,7 +1658,7 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
d = dot_v3v3(dir1, dir2);
if (d == 1.0f || d == -1.0f || d == 0) {
/* colinear or one vector is zero-length*/
- return 0;
+ return false;
}
cross_v3_v3v3(ab, a, b);
@@ -1632,7 +1667,7 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
/* test zero length line */
if (UNLIKELY(div == 0.0f)) {
- return 0;
+ return false;
}
/* test if the two lines are coplanar */
else if (d > -0.000001f && d < 0.000001f) {
@@ -1651,14 +1686,14 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
if (r_lambda) *r_lambda = f1;
- return 1; /* intersection found */
+ return true; /* intersection found */
}
else {
- return 0;
+ return false;
}
}
else {
- return 0;
+ return false;
}
}
@@ -1676,9 +1711,9 @@ void isect_ray_aabb_initialize(IsectRayAABBData *data, const float ray_start[3],
data->ray_inv_dir[1] = 1.0f / ray_direction[1];
data->ray_inv_dir[2] = 1.0f / ray_direction[2];
- data->sign[0] = data->ray_inv_dir[0] < 0;
- data->sign[1] = data->ray_inv_dir[1] < 0;
- data->sign[2] = data->ray_inv_dir[2] < 0;
+ data->sign[0] = data->ray_inv_dir[0] < 0.0f;
+ data->sign[1] = data->ray_inv_dir[1] < 0.0f;
+ data->sign[2] = data->ray_inv_dir[2] < 0.0f;
}
/* Adapted from http://www.gamedev.net/community/forums/topic.asp?topic_id=459973 */
@@ -1796,8 +1831,9 @@ float line_plane_factor_v3(const float plane_co[3], const float plane_no[3],
return (dot != 0.0f) ? -dot_v3v3(plane_no, h) / dot : 0.0f;
}
-/* ensure the distance between these points is no greater then 'dist'
- * if it is, scale then both into the center */
+/** Ensure the distance between these points is no greater then 'dist'.
+ * If it is, scale then both into the center.
+ */
void limit_dist_v3(float v1[3], float v2[3], const float dist)
{
const float dist_old = len_v3v3(v1, v2);
@@ -1862,8 +1898,7 @@ static bool point_in_slice(const float p[3], const float v1[3], const float l1[3
sub_v3_v3v3(rp, p, v1);
h = dot_v3v3(q, rp) / dot_v3v3(q, q);
- if (h < 0.0f || h > 1.0f) return 0;
- return 1;
+ return (h < 0.0f || h > 1.0f) ? false : true;
}
#if 0
@@ -1892,10 +1927,43 @@ static int point_in_slice_m(float p[3], float origin[3], float normal[3], float
bool isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3])
{
- if (!point_in_slice(p, v1, v2, v3)) return 0;
- if (!point_in_slice(p, v2, v3, v1)) return 0;
- if (!point_in_slice(p, v3, v1, v2)) return 0;
- return 1;
+ if (!point_in_slice(p, v1, v2, v3)) return false;
+ if (!point_in_slice(p, v2, v3, v1)) return false;
+ if (!point_in_slice(p, v3, v1, v2)) return false;
+ return true;
+}
+
+/**
+ * \param r_vi The point \a p projected onto the triangle.
+ * \return True when \a p is inside the triangle.
+ * \note Its up to the caller to check the distance between \a p and \a r_vi against an error margin.
+ */
+bool isect_point_tri_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3],
+ float r_vi[3])
+{
+ if (isect_point_tri_prism_v3(p, v1, v2, v3)) {
+ float no[3], n1[3], n2[3];
+
+ /* Could use normal_tri_v3, but doesn't have to be unit-length */
+ sub_v3_v3v3(n1, v1, v2);
+ sub_v3_v3v3(n2, v2, v3);
+ cross_v3_v3v3(no, n1, n2);
+
+ if (LIKELY(len_squared_v3(no) != 0.0f)) {
+ float plane[4];
+ plane_from_point_normal_v3(plane, v1, no);
+ closest_to_plane_v3(r_vi, plane, p);
+ }
+ else {
+ /* degenerate */
+ copy_v3_v3(r_vi, p);
+ }
+
+ return true;
+ }
+ else {
+ return false;
+ }
}
bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4])
@@ -1906,7 +1974,7 @@ bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4])
div = dot_v3v3(dp, plane);
if (div == 0.0f) /* parallel */
- return 1;
+ return true;
t = -plane_point_side_v3(plane, p1) / div;
@@ -1915,34 +1983,34 @@ bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4])
if (t >= 1.0f) {
zero_v3(p1);
zero_v3(p2);
- return 0;
+ return false;
}
/* intersect plane */
if (t > 0.0f) {
madd_v3_v3v3fl(pc, p1, dp, t);
copy_v3_v3(p1, pc);
- return 1;
+ return true;
}
- return 1;
+ return true;
}
else {
/* behind plane, completely clipped */
if (t <= 0.0f) {
zero_v3(p1);
zero_v3(p2);
- return 0;
+ return false;
}
/* intersect plane */
if (t < 1.0f) {
madd_v3_v3v3fl(pc, p1, dp, t);
copy_v3_v3(p2, pc);
- return 1;
+ return true;
}
- return 1;
+ return true;
}
}
@@ -2171,12 +2239,12 @@ static bool barycentric_weights(const float v1[3], const float v2[3], const floa
if (fabsf(wtot) > FLT_EPSILON) {
mul_v3_fl(w, 1.0f / wtot);
- return 0;
+ return false;
}
else {
/* zero area triangle */
copy_v3_fl(w, 1.0f / 3.0f);
- return 1;
+ return true;
}
}
@@ -2227,8 +2295,9 @@ void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], co
}
}
}
- else
+ else {
barycentric_weights(v1, v2, v3, co, n, w);
+ }
}
}
@@ -2254,11 +2323,11 @@ int barycentric_inside_triangle_v2(const float w[3])
/* returns 0 for degenerated triangles */
bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
{
- float x = co[0], y = co[1];
- float x1 = v1[0], y1 = v1[1];
- float x2 = v2[0], y2 = v2[1];
- float x3 = v3[0], y3 = v3[1];
- float det = (y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3);
+ const float x = co[0], y = co[1];
+ const float x1 = v1[0], y1 = v1[1];
+ const float x2 = v2[0], y2 = v2[1];
+ const float x3 = v3[0], y3 = v3[1];
+ const float det = (y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3);
if (fabsf(det) > FLT_EPSILON) {
w[0] = ((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3)) / det;
@@ -2307,8 +2376,9 @@ void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const fl
if (wtot != 0.0f) {
mul_v3_fl(w, 1.0f / wtot);
}
- else /* dummy values for zero area face */
+ else { /* dummy values for zero area face */
w[0] = w[1] = w[2] = 1.0f / 3.0f;
+ }
}
/* same as #barycentric_weights_v2 but works with a quad,
@@ -2343,8 +2413,7 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo
if (UNLIKELY(lens[0] < FLT_EPSILON)) { w[0] = 1.0f; w[1] = w[2] = w[3] = 0.0f; }
else if (UNLIKELY(lens[1] < FLT_EPSILON)) { w[1] = 1.0f; w[0] = w[2] = w[3] = 0.0f; }
else if (UNLIKELY(lens[2] < FLT_EPSILON)) { w[2] = 1.0f; w[0] = w[1] = w[3] = 0.0f; }
- else if (UNLIKELY(lens[3] < FLT_EPSILON)) { w[3] = 1.0f; w[0] = w[1] = w[2] = 0.0f;
- }
+ else if (UNLIKELY(lens[3] < FLT_EPSILON)) { w[3] = 1.0f; w[0] = w[1] = w[2] = 0.0f; }
else {
float wtot, area;
@@ -2388,9 +2457,10 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo
/* given 2 triangles in 3D space, and a point in relation to the first triangle.
* calculate the location of a point in relation to the second triangle.
* Useful for finding relative positions with geometry */
-void barycentric_transform(float pt_tar[3], float const pt_src[3],
- const float tri_tar_p1[3], const float tri_tar_p2[3], const float tri_tar_p3[3],
- const float tri_src_p1[3], const float tri_src_p2[3], const float tri_src_p3[3])
+void transform_point_by_tri_v3(
+ float pt_tar[3], float const pt_src[3],
+ const float tri_tar_p1[3], const float tri_tar_p2[3], const float tri_tar_p3[3],
+ const float tri_src_p1[3], const float tri_src_p2[3], const float tri_src_p3[3])
{
/* this works by moving the source triangle so its normal is pointing on the Z
* axis where its barycentric weights can be calculated in 2D and its Z offset can
@@ -2427,6 +2497,19 @@ void barycentric_transform(float pt_tar[3], float const pt_src[3],
madd_v3_v3v3fl(pt_tar, pt_tar, no_tar, (z_ofs_src / area_src) * area_tar);
}
+/**
+ * Simply re-interpolates,
+ * assumes p_src is between \a l_src_p1-l_src_p2
+ */
+void transform_point_by_seg_v3(
+ float p_dst[3], const float p_src[3],
+ const float l_dst_p1[3], const float l_dst_p2[3],
+ const float l_src_p1[3], const float l_src_p2[3])
+{
+ float t = line_point_factor_v3(p_src, l_src_p1, l_src_p2);
+ interp_v3_v3v3(p_dst, l_dst_p1, l_dst_p2, t);
+}
+
/* given an array with some invalid values this function interpolates valid values
* replacing the invalid ones */
int interp_sparse_array(float *array, const int list_size, const float skipval)
@@ -2551,7 +2634,7 @@ static float mean_value_half_tan_v2(const float v1[2], const float v2[2], const
void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[3])
{
- const float eps = 0.00001f; /* take care, low values cause [#36105] */
+ const float eps = 1e-5f; /* take care, low values cause [#36105] */
const float eps_sq = eps * eps;
const float *v_curr, *v_next;
float ht_prev, ht; /* half tangents */
@@ -2620,7 +2703,7 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[
void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[2])
{
- const float eps = 0.00001f; /* take care, low values cause [#36105] */
+ const float eps = 1e-5f; /* take care, low values cause [#36105] */
const float eps_sq = eps * eps;
const float *v_curr, *v_next;
float ht_prev, ht; /* half tangents */
@@ -2690,8 +2773,8 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[
void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3], const float x2[3], const float v2[3], const float t)
{
float a[3], b[3];
- float t2 = t * t;
- float t3 = t2 * t;
+ const float t2 = t * t;
+ const float t3 = t2 * t;
/* cubic interpolation */
a[0] = v1[0] + v2[0] + 2 * (x1[0] - x2[0]);
@@ -2916,11 +2999,9 @@ void orthographic_m4(float matrix[4][4], const float left, const float right, co
void perspective_m4(float mat[4][4], const float left, const float right, const float bottom, const float top,
const float nearClip, const float farClip)
{
- float Xdelta, Ydelta, Zdelta;
-
- Xdelta = right - left;
- Ydelta = top - bottom;
- Zdelta = farClip - nearClip;
+ const float Xdelta = right - left;
+ const float Ydelta = top - bottom;
+ const float Zdelta = farClip - nearClip;
if (Xdelta == 0.0f || Ydelta == 0.0f || Zdelta == 0.0f) {
return;
@@ -2934,7 +3015,7 @@ void perspective_m4(float mat[4][4], const float left, const float right, const
mat[3][2] = (-2.0f * nearClip * farClip) / Zdelta;
mat[0][1] = mat[0][2] = mat[0][3] =
mat[1][0] = mat[1][2] = mat[1][3] =
- mat[3][0] = mat[3][1] = mat[3][3] = 0.0;
+ mat[3][0] = mat[3][1] = mat[3][3] = 0.0f;
}
@@ -2983,7 +3064,6 @@ static void i_multmatrix(float icand[4][4], float Vm[4][4])
void polarview_m4(float Vm[4][4], float dist, float azimuth, float incidence, float twist)
{
-
unit_m4(Vm);
translate_m4(Vm, 0.0, 0.0, -dist);
@@ -3005,16 +3085,16 @@ void lookat_m4(float mat[4][4], float vx, float vy, float vz, float px, float py
dx = px - vx;
dy = py - vy;
dz = pz - vz;
- hyp = dx * dx + dz * dz; /* hyp squared */
+ hyp = dx * dx + dz * dz; /* hyp squared */
hyp1 = sqrtf(dy * dy + hyp);
- hyp = sqrtf(hyp); /* the real hyp */
+ hyp = sqrtf(hyp); /* the real hyp */
- if (hyp1 != 0.0f) { /* rotate X */
+ if (hyp1 != 0.0f) { /* rotate X */
sine = -dy / hyp1;
cosine = hyp / hyp1;
}
else {
- sine = 0;
+ sine = 0.0f;
cosine = 1.0f;
}
mat1[1][1] = cosine;
@@ -3024,16 +3104,16 @@ void lookat_m4(float mat[4][4], float vx, float vy, float vz, float px, float py
i_multmatrix(mat1, mat);
- mat1[1][1] = mat1[2][2] = 1.0f; /* be careful here to reinit */
- mat1[1][2] = mat1[2][1] = 0.0; /* those modified by the last */
+ mat1[1][1] = mat1[2][2] = 1.0f; /* be careful here to reinit */
+ mat1[1][2] = mat1[2][1] = 0.0f; /* those modified by the last */
- /* paragraph */
- if (hyp != 0.0f) { /* rotate Y */
+ /* paragraph */
+ if (hyp != 0.0f) { /* rotate Y */
sine = dx / hyp;
cosine = -dz / hyp;
}
else {
- sine = 0;
+ sine = 0.0f;
cosine = 1.0f;
}
mat1[0][0] = cosine;
@@ -3214,10 +3294,10 @@ void accumulate_vertex_normals_poly(float **vertnos, const float polyno[3],
void tangent_from_uv(float uv1[2], float uv2[2], float uv3[3], float co1[3], float co2[3], float co3[3], float n[3], float tang[3])
{
- float s1 = uv2[0] - uv1[0];
- float s2 = uv3[0] - uv1[0];
- float t1 = uv2[1] - uv1[1];
- float t2 = uv3[1] - uv1[1];
+ const float s1 = uv2[0] - uv1[0];
+ const float s2 = uv3[0] - uv1[0];
+ const float t1 = uv2[1] - uv1[1];
+ const float t2 = uv3[1] - uv1[1];
float det = (s1 * t2 - s2 * t1);
if (det != 0.0f) { /* otherwise 'tang' becomes nan */
@@ -3242,7 +3322,7 @@ void tangent_from_uv(float uv1[2], float uv2[2], float uv3[3], float co1[3], flo
}
}
else {
- tang[0] = tang[1] = tang[2] = 0.0;
+ tang[0] = tang[1] = tang[2] = 0.0f;
}
}
@@ -3275,7 +3355,8 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, fl
float lloc[3], float rloc[3], float lrot[3][3], float lscale[3][3])
{
float accu_com[3] = {0.0f, 0.0f, 0.0f}, accu_rcom[3] = {0.0f, 0.0f, 0.0f};
- float accu_weight = 0.0f, accu_rweight = 0.0f, eps = 0.000001f;
+ float accu_weight = 0.0f, accu_rweight = 0.0f;
+ const float eps = 1e-6f;
int a;
/* first set up a nice default response */
@@ -3369,7 +3450,7 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, fl
/* this is pretty much Polardecompose 'inline' the algo based on Higham's thesis */
/* without the far case ... but seems to work here pretty neat */
- odet = 0.f;
+ odet = 0.0f;
ndet = determinant_m3_array(q);
while ((odet - ndet) * (odet - ndet) > eps && i < imax) {
invert_m3_m3(qi, q);
@@ -3410,9 +3491,8 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
float q0[3], float q1[3], float q2[3], float q3[3])
{
static const float epsilon = 1e-6f;
- float c, sd[3];
-
- c = dot_v3v3(n, p);
+ float sd[3];
+ const float c = dot_v3v3(n, p);
/* signed distances from the vertices to the plane. */
sd[0] = dot_v3v3(n, v0) - c;
@@ -3423,16 +3503,16 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
if (fabsf(sd[1]) < epsilon) sd[1] = 0.0f;
if (fabsf(sd[2]) < epsilon) sd[2] = 0.0f;
- if (sd[0] > 0) {
- if (sd[1] > 0) {
- if (sd[2] > 0) {
+ if (sd[0] > 0.0f) {
+ if (sd[1] > 0.0f) {
+ if (sd[2] > 0.0f) {
/* +++ */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* ++- */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
@@ -3447,15 +3527,15 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
copy_v3_v3(q3, q2);
}
}
- else if (sd[1] < 0) {
- if (sd[2] > 0) {
+ else if (sd[1] < 0.0f) {
+ if (sd[2] > 0.0f) {
/* +-+ */
copy_v3_v3(q0, v0);
vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1])));
vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2])));
copy_v3_v3(q3, v2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* +-- */
copy_v3_v3(q0, v0);
vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1])));
@@ -3471,14 +3551,14 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
}
}
else {
- if (sd[2] > 0) {
+ if (sd[2] > 0.0f) {
/* +0+ */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* +0- */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
@@ -3494,16 +3574,16 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
}
}
}
- else if (sd[0] < 0) {
- if (sd[1] > 0) {
- if (sd[2] > 0) {
+ else if (sd[0] < 0.0f) {
+ if (sd[1] > 0.0f) {
+ if (sd[2] > 0.0f) {
/* -++ */
vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1])));
copy_v3_v3(q1, v1);
copy_v3_v3(q2, v2);
vec_add_dir(q3, v0, v2, (sd[0] / (sd[0] - sd[2])));
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* -+- */
vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1])));
copy_v3_v3(q1, v1);
@@ -3518,15 +3598,15 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
copy_v3_v3(q3, q2);
}
}
- else if (sd[1] < 0) {
- if (sd[2] > 0) {
+ else if (sd[1] < 0.0f) {
+ if (sd[2] > 0.0f) {
/* --+ */
vec_add_dir(q0, v0, v2, (sd[0] / (sd[0] - sd[2])));
vec_add_dir(q1, v1, v2, (sd[1] / (sd[1] - sd[2])));
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* --- */
return false;
}
@@ -3536,14 +3616,14 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
}
}
else {
- if (sd[2] > 0) {
+ if (sd[2] > 0.0f) {
/* -0+ */
vec_add_dir(q0, v0, v2, (sd[0] / (sd[0] - sd[2])));
copy_v3_v3(q1, v1);
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* -0- */
return false;
}
@@ -3554,15 +3634,15 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
}
}
else {
- if (sd[1] > 0) {
- if (sd[2] > 0) {
+ if (sd[1] > 0.0f) {
+ if (sd[2] > 0.0f) {
/* 0++ */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* 0+- */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
@@ -3577,15 +3657,15 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
copy_v3_v3(q3, q2);
}
}
- else if (sd[1] < 0) {
- if (sd[2] > 0) {
+ else if (sd[1] < 0.0f) {
+ if (sd[2] > 0.0f) {
/* 0-+ */
copy_v3_v3(q0, v0);
vec_add_dir(q1, v1, v2, (sd[1] / (sd[1] - sd[2])));
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* 0-- */
return false;
}
@@ -3595,14 +3675,14 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
}
}
else {
- if (sd[2] > 0) {
+ if (sd[2] > 0.0f) {
/* 00+ */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* 00- */
return false;
}
@@ -3757,7 +3837,7 @@ static void ff_normalize(float n[3])
d = dot_v3v3(n, n);
- if (d > 1.0e-35F) {
+ if (d > 1.0e-35f) {
d = 1.0f / sqrtf(d);
n[0] *= d;
diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c
index 9af1c8677df..4feb954a31a 100644
--- a/source/blender/blenlib/intern/math_interp.c
+++ b/source/blender/blenlib/intern/math_interp.c
@@ -62,7 +62,11 @@ static float P(float k)
/* older, slower function, works the same as above */
static float P(float k)
{
- return (float)(1.0f / 6.0f) * (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f * pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f * pow(MAX2(k, 0), 3.0f) - 4.0f * pow(MAX2(k - 1.0f, 0), 3.0f));
+ return (float)(1.0f / 6.0f) *
+ (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f *
+ pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f *
+ pow(MAX2(k, 0), 3.0f) - 4.0f *
+ pow(MAX2(k - 1.0f, 0), 3.0f));
}
#endif
@@ -366,3 +370,192 @@ void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char
{
bilinear_interpolation(buffer, NULL, output, NULL, width, height, components, u, v);
}
+
+/**************************************************************************
+ * Filtering method based on
+ * "Creating raster omnimax images from multiple perspective views using the elliptical weighted average filter"
+ * by Ned Greene and Paul S. Heckbert (1986)
+ ***************************************************************************/
+
+/* table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2
+ * used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible */
+#define EWA_MAXIDX 255
+const float EWA_WTS[EWA_MAXIDX + 1] = {
+ 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f,
+ 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f,
+ 0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f,
+ 0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f,
+ 0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f,
+ 0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f,
+ 0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f,
+ 0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f,
+ 0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f,
+ 0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f,
+ 0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f,
+ 0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f,
+ 0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f,
+ 0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f,
+ 0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f,
+ 0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f,
+ 0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f,
+ 0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f,
+ 0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f,
+ 0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f,
+ 0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f,
+ 0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f,
+ 0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f,
+ 0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f,
+ 0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f,
+ 0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f,
+ 0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f,
+ 0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f,
+ 0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f,
+ 0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f,
+ 0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f,
+ 0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f
+};
+
+static void radangle2imp(float a2, float b2, float th, float *A, float *B, float *C, float *F)
+{
+ float ct2 = cosf(th);
+ const float st2 = 1.0f - ct2 * ct2; /* <- sin(th)^2 */
+ ct2 *= ct2;
+ *A = a2 * st2 + b2 * ct2;
+ *B = (b2 - a2) * sinf(2.0f * th);
+ *C = a2 * ct2 + b2 * st2;
+ *F = a2 * b2;
+}
+
+/* all tests here are done to make sure possible overflows are hopefully minimized */
+void BLI_ewa_imp2radangle(float A, float B, float C, float F, float *a, float *b, float *th, float *ecc)
+{
+ if (F <= 1e-5f) { /* use arbitrary major radius, zero minor, infinite eccentricity */
+ *a = sqrtf(A > C ? A : C);
+ *b = 0.0f;
+ *ecc = 1e10f;
+ *th = 0.5f * (atan2f(B, A - C) + (float)M_PI);
+ }
+ else {
+ const float AmC = A - C, ApC = A + C, F2 = F * 2.0f;
+ const float r = sqrtf(AmC * AmC + B * B);
+ float d = ApC - r;
+ *a = (d <= 0.0f) ? sqrtf(A > C ? A : C) : sqrtf(F2 / d);
+ d = ApC + r;
+ if (d <= 0.0f) {
+ *b = 0.0f;
+ *ecc = 1e10f;
+ }
+ else {
+ *b = sqrtf(F2 / d);
+ *ecc = *a / *b;
+ }
+ /* incr theta by 0.5*pi (angle of major axis) */
+ *th = 0.5f * (atan2f(B, AmC) + (float)M_PI);
+ }
+}
+
+void BLI_ewa_filter(const int width, const int height,
+ const bool intpol,
+ const bool use_alpha,
+ const float uv[2],
+ const float du[2],
+ const float dv[2],
+ ewa_filter_read_pixel_cb read_pixel_cb,
+ void *userdata,
+ float result[4])
+{
+ /* scaling dxt/dyt by full resolution can cause overflow because of huge A/B/C and esp. F values,
+ * scaling by aspect ratio alone does the opposite, so try something in between instead... */
+ const float ff2 = (float)width, ff = sqrtf(ff2), q = (float)height / ff;
+ const float Ux = du[0] * ff, Vx = dv[0] * q, Uy = du[1] * ff, Vy = dv[1] * q;
+ float A = Vx * Vx + Vy * Vy;
+ float B = -2.0f * (Ux * Vx + Uy * Vy);
+ float C = Ux * Ux + Uy * Uy;
+ float F = A * C - B * B * 0.25f;
+ float a, b, th, ecc, a2, b2, ue, ve, U0, V0, DDQ, U, ac1, ac2, BU, d;
+ int u, v, u1, u2, v1, v2;
+
+ /* The so-called 'high' quality ewa method simply adds a constant of 1 to both A & C,
+ * so the ellipse always covers at least some texels. But since the filter is now always larger,
+ * it also means that everywhere else it's also more blurry then ideally should be the case.
+ * So instead here the ellipse radii are modified instead whenever either is too low.
+ * Use a different radius based on interpolation switch, just enough to anti-alias when interpolation is off,
+ * and slightly larger to make result a bit smoother than bilinear interpolation when interpolation is on
+ * (minimum values: const float rmin = intpol ? 1.f : 0.5f;) */
+ const float rmin = (intpol ? 1.5625f : 0.765625f) / ff2;
+ BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
+ if ((b2 = b * b) < rmin) {
+ if ((a2 = a * a) < rmin) {
+ B = 0.0f;
+ A = C = rmin;
+ F = A * C;
+ }
+ else {
+ b2 = rmin;
+ radangle2imp(a2, b2, th, &A, &B, &C, &F);
+ }
+ }
+
+ ue = ff * sqrtf(C);
+ ve = ff * sqrtf(A);
+ d = (float)(EWA_MAXIDX + 1) / (F * ff2);
+ A *= d;
+ B *= d;
+ C *= d;
+
+ U0 = uv[0] * (float)width;
+ V0 = uv[1] * (float)height;
+ u1 = (int)(floorf(U0 - ue));
+ u2 = (int)(ceilf(U0 + ue));
+ v1 = (int)(floorf(V0 - ve));
+ v2 = (int)(ceilf(V0 + ve));
+
+ /* sane clamping to avoid unnecessarily huge loops */
+ /* note: if eccentricity gets clamped (see above),
+ * the ue/ve limits can also be lowered accordingly
+ */
+ if (U0 - (float)u1 > EWA_MAXIDX) u1 = (int)U0 - EWA_MAXIDX;
+ if ((float)u2 - U0 > EWA_MAXIDX) u2 = (int)U0 + EWA_MAXIDX;
+ if (V0 - (float)v1 > EWA_MAXIDX) v1 = (int)V0 - EWA_MAXIDX;
+ if ((float)v2 - V0 > EWA_MAXIDX) v2 = (int)V0 + EWA_MAXIDX;
+
+ /* Early output check for cases the whole region is outside of the buffer. */
+ if ((u2 < 0 || u1 >= width) || (v2 < 0 || v1 >= height)) {
+ zero_v4(result);
+ return;
+ }
+
+ U0 -= 0.5f;
+ V0 -= 0.5f;
+ DDQ = 2.0f * A;
+ U = (float)u1 - U0;
+ ac1 = A * (2.0f * U + 1.0f);
+ ac2 = A * U * U;
+ BU = B * U;
+
+ d = 0.0f;
+ zero_v4(result);
+ for (v = v1; v <= v2; ++v) {
+ const float V = (float)v - V0;
+ float DQ = ac1 + B * V;
+ float Q = (C * V + BU) * V + ac2;
+ for (u = u1; u <= u2; ++u) {
+ if (Q < (float)(EWA_MAXIDX + 1)) {
+ float tc[4];
+ const float wt = EWA_WTS[(Q < 0.0f) ? 0 : (unsigned int)Q];
+ read_pixel_cb(userdata, u, v, tc);
+ madd_v3_v3fl(result, tc, wt);
+ result[3] += use_alpha ? tc[3] * wt : 0.0f;
+ d += wt;
+ }
+ Q += DQ;
+ DQ += DDQ;
+ }
+ }
+
+ /* d should hopefully never be zero anymore */
+ d = 1.0f / d;
+ mul_v3_fl(result, d);
+ /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */
+ result[3] = use_alpha ? result[3] * d : 1.0f;
+}
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index eb73aba6aa8..228bb1008b1 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -35,42 +35,59 @@
/********************************* Init **************************************/
+void zero_m2(float m[2][2])
+{
+ memset(m, 0, sizeof(float[2][2]));
+}
+
void zero_m3(float m[3][3])
{
- memset(m, 0, 3 * 3 * sizeof(float));
+ memset(m, 0, sizeof(float[3][3]));
}
void zero_m4(float m[4][4])
{
- memset(m, 0, 4 * 4 * sizeof(float));
+ memset(m, 0, sizeof(float[4][4]));
+}
+
+void unit_m2(float m[2][2])
+{
+ m[0][0] = m[1][1] = 1.0f;
+ m[0][1] = 0.0f;
+ m[1][0] = 0.0f;
}
void unit_m3(float m[3][3])
{
- m[0][0] = m[1][1] = m[2][2] = 1.0;
- m[0][1] = m[0][2] = 0.0;
- m[1][0] = m[1][2] = 0.0;
- m[2][0] = m[2][1] = 0.0;
+ m[0][0] = m[1][1] = m[2][2] = 1.0f;
+ m[0][1] = m[0][2] = 0.0f;
+ m[1][0] = m[1][2] = 0.0f;
+ m[2][0] = m[2][1] = 0.0f;
}
void unit_m4(float m[4][4])
{
- m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0;
- m[0][1] = m[0][2] = m[0][3] = 0.0;
- m[1][0] = m[1][2] = m[1][3] = 0.0;
- m[2][0] = m[2][1] = m[2][3] = 0.0;
- m[3][0] = m[3][1] = m[3][2] = 0.0;
+ 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;
+}
+
+void copy_m2_m2(float m1[2][2], float m2[2][2])
+{
+ memcpy(m1, m2, sizeof(float[2][2]));
}
void copy_m3_m3(float m1[3][3], float m2[3][3])
{
/* destination comes first: */
- memcpy(&m1[0], &m2[0], 9 * sizeof(float));
+ memcpy(m1, m2, sizeof(float[3][3]));
}
void copy_m4_m4(float m1[4][4], float m2[4][4])
{
- memcpy(m1, m2, 4 * 4 * sizeof(float));
+ memcpy(m1, m2, sizeof(float[4][4]));
}
void copy_m3_m4(float m1[3][3], float m2[4][4])
@@ -103,14 +120,14 @@ void copy_m4_m3(float m1[4][4], float m2[3][3]) /* no clear */
m1[2][2] = m2[2][2];
/* Reevan's Bugfix */
- m1[0][3] = 0.0F;
- m1[1][3] = 0.0F;
- m1[2][3] = 0.0F;
+ m1[0][3] = 0.0f;
+ m1[1][3] = 0.0f;
+ m1[2][3] = 0.0f;
- m1[3][0] = 0.0F;
- m1[3][1] = 0.0F;
- m1[3][2] = 0.0F;
- m1[3][3] = 1.0F;
+ m1[3][0] = 0.0f;
+ m1[3][1] = 0.0f;
+ m1[3][2] = 0.0f;
+ m1[3][3] = 1.0f;
}
@@ -338,38 +355,147 @@ void mul_serie_m3(float answ[3][3],
}
}
-void mul_serie_m4(float answ[4][4], float m1[4][4],
- float m2[4][4], float m3[4][4], float m4[4][4],
- float m5[4][4], float m6[4][4], float m7[4][4],
- float m8[4][4])
-{
- float temp[4][4];
-
- if (m1 == NULL || m2 == NULL) return;
-
- mul_m4_m4m4(answ, m1, m2);
- if (m3) {
- mul_m4_m4m4(temp, answ, m3);
- if (m4) {
- mul_m4_m4m4(answ, temp, m4);
- if (m5) {
- mul_m4_m4m4(temp, answ, m5);
- if (m6) {
- mul_m4_m4m4(answ, temp, m6);
- if (m7) {
- mul_m4_m4m4(temp, answ, m7);
- if (m8) {
- mul_m4_m4m4(answ, temp, m8);
- }
- else copy_m4_m4(answ, temp);
- }
- }
- else copy_m4_m4(answ, temp);
- }
- }
- else copy_m4_m4(answ, temp);
- }
-}
+/** \name Macro helpers for: mul_m3_series
+ * \{ */
+void _va_mul_m3_series_3(
+ float r[3][3],
+ float m1[3][3], float m2[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+}
+void _va_mul_m3_series_4(
+ float r[3][3],
+ float m1[3][3], float m2[3][3], float m3[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+ mul_m3_m3m3(r, r, m3);
+}
+void _va_mul_m3_series_5(
+ float r[3][3],
+ float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+ mul_m3_m3m3(r, r, m3);
+ mul_m3_m3m3(r, r, m4);
+}
+void _va_mul_m3_series_6(
+ float r[3][3],
+ float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3],
+ float m5[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+ mul_m3_m3m3(r, r, m3);
+ mul_m3_m3m3(r, r, m4);
+ mul_m3_m3m3(r, r, m5);
+}
+void _va_mul_m3_series_7(
+ float r[3][3],
+ float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3],
+ float m5[3][3], float m6[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+ mul_m3_m3m3(r, r, m3);
+ mul_m3_m3m3(r, r, m4);
+ mul_m3_m3m3(r, r, m5);
+ mul_m3_m3m3(r, r, m6);
+}
+void _va_mul_m3_series_8(
+ float r[3][3],
+ float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3],
+ float m5[3][3], float m6[3][3], float m7[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+ mul_m3_m3m3(r, r, m3);
+ mul_m3_m3m3(r, r, m4);
+ mul_m3_m3m3(r, r, m5);
+ mul_m3_m3m3(r, r, m6);
+ mul_m3_m3m3(r, r, m7);
+}
+void _va_mul_m3_series_9(
+ float r[3][3],
+ float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3],
+ float m5[3][3], float m6[3][3], float m7[3][3], float m8[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+ mul_m3_m3m3(r, r, m3);
+ mul_m3_m3m3(r, r, m4);
+ mul_m3_m3m3(r, r, m5);
+ mul_m3_m3m3(r, r, m6);
+ mul_m3_m3m3(r, r, m7);
+ mul_m3_m3m3(r, r, m8);
+}
+/** \} */
+
+/** \name Macro helpers for: mul_m4_series
+ * \{ */
+void _va_mul_m4_series_3(
+ float r[4][4],
+ float m1[4][4], float m2[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+}
+void _va_mul_m4_series_4(
+ float r[4][4],
+ float m1[4][4], float m2[4][4], float m3[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+ mul_m4_m4m4(r, r, m3);
+}
+void _va_mul_m4_series_5(
+ float r[4][4],
+ float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+ mul_m4_m4m4(r, r, m3);
+ mul_m4_m4m4(r, r, m4);
+}
+void _va_mul_m4_series_6(
+ float r[4][4],
+ float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4],
+ float m5[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+ mul_m4_m4m4(r, r, m3);
+ mul_m4_m4m4(r, r, m4);
+ mul_m4_m4m4(r, r, m5);
+}
+void _va_mul_m4_series_7(
+ float r[4][4],
+ float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4],
+ float m5[4][4], float m6[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+ mul_m4_m4m4(r, r, m3);
+ mul_m4_m4m4(r, r, m4);
+ mul_m4_m4m4(r, r, m5);
+ mul_m4_m4m4(r, r, m6);
+}
+void _va_mul_m4_series_8(
+ float r[4][4],
+ float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4],
+ float m5[4][4], float m6[4][4], float m7[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+ mul_m4_m4m4(r, r, m3);
+ mul_m4_m4m4(r, r, m4);
+ mul_m4_m4m4(r, r, m5);
+ mul_m4_m4m4(r, r, m6);
+ mul_m4_m4m4(r, r, m7);
+}
+void _va_mul_m4_series_9(
+ float r[4][4],
+ float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4],
+ float m5[4][4], float m6[4][4], float m7[4][4], float m8[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+ mul_m4_m4m4(r, r, m3);
+ mul_m4_m4m4(r, r, m4);
+ mul_m4_m4m4(r, r, m5);
+ mul_m4_m4m4(r, r, m6);
+ mul_m4_m4m4(r, r, m7);
+ mul_m4_m4m4(r, r, m8);
+}
+/** \} */
void mul_v2_m3v2(float r[2], float m[3][3], float v[2])
{
@@ -391,10 +517,9 @@ void mul_m3_v2(float m[3][3], float r[2])
void mul_m4_v3(float mat[4][4], float vec[3])
{
- float x, y;
+ const float x = vec[0];
+ const float y = vec[1];
- x = vec[0];
- y = vec[1];
vec[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
vec[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
@@ -402,10 +527,9 @@ void mul_m4_v3(float mat[4][4], float vec[3])
void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3])
{
- float x, y;
+ const float x = vec[0];
+ const float y = vec[1];
- x = vec[0];
- y = vec[1];
r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
@@ -413,18 +537,16 @@ void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3])
void mul_v2_m4v3(float r[2], float mat[4][4], const float vec[3])
{
- float x;
+ const float x = vec[0];
- x = vec[0];
r[0] = x * mat[0][0] + vec[1] * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
r[1] = x * mat[0][1] + vec[1] * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
}
void mul_v2_m2v2(float r[2], float mat[2][2], const float vec[2])
{
- float x;
+ const float x = vec[0];
- x = vec[0];
r[0] = mat[0][0] * x + mat[1][0] * vec[1];
r[1] = mat[0][1] * x + mat[1][1] * vec[1];
}
@@ -453,10 +575,9 @@ void mul_v3_m4v3_q(float out[3], float mat[][4], const float vec[3])
/* same as mul_m4_v3() but doesnt apply translation component */
void mul_mat3_m4_v3(float mat[4][4], float vec[3])
{
- float x, y;
+ const float x = vec[0];
+ const float y = vec[1];
- x = vec[0];
- y = vec[1];
vec[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2];
vec[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2];
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
@@ -483,11 +604,9 @@ void mul_v2_project_m4_v3(float r[2], float mat[4][4], const float vec[3])
void mul_v4_m4v4(float r[4], float mat[4][4], const float v[4])
{
- float x, y, z;
-
- x = v[0];
- y = v[1];
- z = v[2];
+ const float x = v[0];
+ const float y = v[1];
+ const float z = v[2];
r[0] = x * mat[0][0] + y * mat[1][0] + z * mat[2][0] + mat[3][0] * v[3];
r[1] = x * mat[0][1] + y * mat[1][1] + z * mat[2][1] + mat[3][1] * v[3];
@@ -502,11 +621,9 @@ void mul_m4_v4(float mat[4][4], float r[4])
void mul_v4d_m4v4d(double r[4], float mat[4][4], double v[4])
{
- double x, y, z;
-
- x = v[0];
- y = v[1];
- z = v[2];
+ const double x = v[0];
+ const double y = v[1];
+ const double z = v[2];
r[0] = x * (double)mat[0][0] + y * (double)mat[1][0] + z * (double)mat[2][0] + (double)mat[3][0] * v[3];
r[1] = x * (double)mat[0][1] + y * (double)mat[1][1] + z * (double)mat[2][1] + (double)mat[3][1] * v[3];
@@ -546,10 +663,9 @@ void mul_m3_v3(float M[3][3], float r[3])
void mul_transposed_m3_v3(float mat[3][3], float vec[3])
{
- float x, y;
+ const float x = vec[0];
+ const float y = vec[1];
- x = vec[0];
- y = vec[1];
vec[0] = x * mat[0][0] + y * mat[0][1] + mat[0][2] * vec[2];
vec[1] = x * mat[1][0] + y * mat[1][1] + mat[1][2] * vec[2];
vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2];
@@ -557,10 +673,9 @@ void mul_transposed_m3_v3(float mat[3][3], float vec[3])
void mul_transposed_mat3_m4_v3(float mat[4][4], float vec[3])
{
- float x, y;
+ const float x = vec[0];
+ const float y = vec[1];
- x = vec[0];
- y = vec[1];
vec[0] = x * mat[0][0] + y * mat[0][1] + mat[0][2] * vec[2];
vec[1] = x * mat[1][0] + y * mat[1][1] + mat[1][2] * vec[2];
vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2];
@@ -613,10 +728,9 @@ void negate_m4(float m[4][4])
void mul_m3_v3_double(float mat[3][3], double vec[3])
{
- double x, y;
+ const double x = vec[0];
+ const double y = vec[1];
- x = vec[0];
- y = vec[1];
vec[0] = x * (double)mat[0][0] + y * (double)mat[1][0] + (double)mat[2][0] * vec[2];
vec[1] = x * (double)mat[0][1] + y * (double)mat[1][1] + (double)mat[2][1] * vec[2];
vec[2] = x * (double)mat[0][2] + y * (double)mat[1][2] + (double)mat[2][2] * vec[2];
@@ -668,11 +782,9 @@ float determinant_m3_array(float m[3][3])
bool invert_m3_ex(float m[3][3], const float epsilon)
{
float tmp[3][3];
- bool success;
+ const bool success = invert_m3_m3_ex(tmp, m, epsilon);
- success = invert_m3_m3_ex(tmp, m, epsilon);
copy_m3_m3(m, tmp);
-
return success;
}
@@ -706,11 +818,9 @@ bool invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon)
bool invert_m3(float m[3][3])
{
float tmp[3][3];
- bool success;
+ const bool success = invert_m3_m3(tmp, m);
- success = invert_m3_m3(tmp, m);
copy_m3_m3(m, tmp);
-
return success;
}
@@ -743,11 +853,9 @@ bool invert_m3_m3(float m1[3][3], float m2[3][3])
bool invert_m4(float m[4][4])
{
float tmp[4][4];
- bool success;
+ const bool success = invert_m4_m4(tmp, m);
- success = invert_m4_m4(tmp, m);
copy_m4_m4(m, tmp);
-
return success;
}
@@ -1348,7 +1456,7 @@ float mat3_to_scale(float mat[3][3])
{
/* unit length vector */
float unit_vec[3];
- copy_v3_fl(unit_vec, 0.577350269189626f);
+ copy_v3_fl(unit_vec, (float)(1.0 / M_SQRT3));
mul_m3_v3(mat, unit_vec);
return len_v3(unit_vec);
}
@@ -1357,7 +1465,7 @@ float mat4_to_scale(float mat[4][4])
{
/* unit length vector */
float unit_vec[3];
- copy_v3_fl(unit_vec, 0.577350269189626f);
+ copy_v3_fl(unit_vec, (float)(1.0 / M_SQRT3));
mul_mat3_m4_v3(mat, unit_vec);
return len_v3(unit_vec);
}
@@ -2224,7 +2332,7 @@ void pseudoinverse_m4_m4(float Ainv[4][4], float A[4][4], float epsilon)
transpose_m4(V);
- mul_serie_m4(Ainv, U, Wm, V, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(Ainv, U, Wm, V);
}
void mat4_ortho_set(float m[][4], float left, float right, float bottom, float top, float nearVal, float farVal)
@@ -2300,3 +2408,51 @@ void invert_m4_m4_safe(float Ainv[4][4], float A[4][4])
}
}
}
+
+/**
+ * SpaceTransform struct encapsulates all needed data to convert between two coordinate spaces
+ * (where conversion can be represented by a matrix multiplication).
+ *
+ * A SpaceTransform is initialized using:
+ * BLI_SPACE_TRANSFORM_SETUP(&data, ob1, ob2)
+ *
+ * After that the following calls can be used:
+ * BLI_space_transform_apply(&data, co); // converts a coordinate in ob1 space to the corresponding ob2 space
+ * BLI_space_transform_invert(&data, co); // converts a coordinate in ob2 space to the corresponding ob1 space
+ *
+ * Same concept as BLI_space_transform_apply and BLI_space_transform_invert, but no is normalized after conversion
+ * (and not translated at all!):
+ * BLI_space_transform_apply_normal(&data, no);
+ * BLI_space_transform_invert_normal(&data, no);
+ *
+ */
+
+void BLI_space_transform_from_matrices(SpaceTransform *data, float local[4][4], float target[4][4])
+{
+ float itarget[4][4];
+ invert_m4_m4(itarget, target);
+ mul_m4_m4m4(data->local2target, itarget, local);
+ invert_m4_m4(data->target2local, data->local2target);
+}
+
+void BLI_space_transform_apply(const SpaceTransform *data, float co[3])
+{
+ mul_v3_m4v3(co, ((SpaceTransform *)data)->local2target, co);
+}
+
+void BLI_space_transform_invert(const SpaceTransform *data, float co[3])
+{
+ mul_v3_m4v3(co, ((SpaceTransform *)data)->target2local, co);
+}
+
+void BLI_space_transform_apply_normal(const SpaceTransform *data, float no[3])
+{
+ mul_mat3_m4_v3(((SpaceTransform *)data)->local2target, no);
+ normalize_v3(no);
+}
+
+void BLI_space_transform_invert_normal(const SpaceTransform *data, float no[3])
+{
+ mul_mat3_m4_v3(((SpaceTransform *)data)->target2local, no);
+ normalize_v3(no);
+}
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index dce2e9d54e3..141f9201689 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -139,7 +139,7 @@ float dot_qtqt(const float q1[4], const float q2[4])
void invert_qt(float q[4])
{
- float f = dot_qtqt(q, q);
+ const float f = dot_qtqt(q, q);
if (f == 0.0f)
return;
@@ -380,9 +380,8 @@ void mat3_to_quat_is_ok(float q[4], float wmat[3][3])
float normalize_qt(float q[4])
{
- float len;
+ const float len = sqrtf(dot_qtqt(q, q));
- len = sqrtf(dot_qtqt(q, q));
if (len != 0.0f) {
mul_qt_fl(q, 1.0f / len);
}
@@ -520,7 +519,7 @@ float angle_qtqt(const float q1[4], const float q2[4])
void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
{
- const float eps = 0.0001f;
+ const float eps = 1e-4f;
float nor[3], tvec[3];
float angle, si, co, len;
@@ -669,7 +668,7 @@ void QuatInterpolW(float *result, float quat1[4], float quat2[4], float t)
*/
void interp_dot_slerp(const float t, const float cosom, float r_w[2])
{
- const float eps = 0.0001f;
+ const float eps = 1e-4f;
BLI_assert(IN_RANGE_INCL(cosom, -1.0001f, 1.0001f));
@@ -783,9 +782,8 @@ void tri_to_quat_ex(float quat[4], const float v1[3], const float v2[3], const f
float tri_to_quat(float quat[4], const float v1[3], const float v2[3], const float v3[3])
{
float vec[3];
- float len;
+ const float len = normal_tri_v3(vec, v1, v2, v3);
- len = normal_tri_v3(vec, v1, v2, v3);
tri_to_quat_ex(quat, v1, v2, v3, vec);
return len;
}
@@ -1606,7 +1604,7 @@ void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4])
mul_m4_m4m4(S, baseRinv, baseRS);
/* set scaling part */
- mul_serie_m4(dq->scale, basemat, S, baseinv, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(dq->scale, basemat, S, baseinv);
dq->scale_weight = 1.0f;
}
else {
@@ -1658,7 +1656,7 @@ void add_weighted_dq_dq(DualQuat *dqsum, const DualQuat *dq, float weight)
/* make sure we interpolate quats in the right direction */
if (dot_qtqt(dq->quat, dqsum->quat) < 0) {
- flipped = 1;
+ flipped = true;
weight = -weight;
}
@@ -1689,7 +1687,7 @@ void add_weighted_dq_dq(DualQuat *dqsum, const DualQuat *dq, float weight)
void normalize_dq(DualQuat *dq, float totweight)
{
- float scale = 1.0f / totweight;
+ const float scale = 1.0f / totweight;
mul_qt_fl(dq->quat, scale);
mul_qt_fl(dq->trans, scale);
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 38cbb39f36d..c904b963e54 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -35,7 +35,7 @@
void interp_v2_v2v2(float target[2], const float a[2], const float b[2], const float t)
{
- float s = 1.0f - t;
+ const float s = 1.0f - t;
target[0] = s * a[0] + t * b[0];
target[1] = s * a[1] + t * b[1];
@@ -51,7 +51,7 @@ void interp_v2_v2v2v2(float p[2], const float v1[2], const float v2[2], const fl
void interp_v3_v3v3(float target[3], const float a[3], const float b[3], const float t)
{
- float s = 1.0f - t;
+ const float s = 1.0f - t;
target[0] = s * a[0] + t * b[0];
target[1] = s * a[1] + t * b[1];
@@ -60,7 +60,7 @@ void interp_v3_v3v3(float target[3], const float a[3], const float b[3], const f
void interp_v4_v4v4(float target[4], const float a[4], const float b[4], const float t)
{
- float s = 1.0f - t;
+ const float s = 1.0f - t;
target[0] = s * a[0] + t * b[0];
target[1] = s * a[1] + t * b[1];
@@ -119,8 +119,7 @@ bool interp_v2_v2v2_slerp(float target[2], const float a[2], const float b[2], c
}
/**
- * Same as #interp_v3_v3v3_slerp buy uses fallback values
- * for opposite vectors.
+ * Same as #interp_v3_v3v3_slerp but uses fallback values for opposite vectors.
*/
void interp_v3_v3v3_slerp_safe(float target[3], const float a[3], const float b[3], const float t)
{
@@ -208,7 +207,7 @@ void interp_v3_v3v3v3_uv(float p[3], const float v1[3], const float v2[3], const
void interp_v3_v3v3_uchar(char unsigned target[3], const unsigned char a[3], const unsigned char b[3], const float t)
{
- float s = 1.0f - t;
+ const float s = 1.0f - t;
target[0] = (char)floorf(s * a[0] + t * b[0]);
target[1] = (char)floorf(s * a[1] + t * b[1]);
@@ -221,7 +220,7 @@ void interp_v3_v3v3_char(char target[3], const char a[3], const char b[3], const
void interp_v4_v4v4_uchar(char unsigned target[4], const unsigned char a[4], const unsigned char b[4], const float t)
{
- float s = 1.0f - t;
+ const float s = 1.0f - t;
target[0] = (char)floorf(s * a[0] + t * b[0]);
target[1] = (char)floorf(s * a[1] + t * b[1]);
@@ -550,8 +549,7 @@ void angle_poly_v3(float *angles, const float *verts[3], int len)
/* Project v1 on v2 */
void project_v2_v2v2(float c[2], const float v1[2], const float v2[2])
{
- float mul;
- mul = dot_v2v2(v1, v2) / dot_v2v2(v2, v2);
+ const float mul = dot_v2v2(v1, v2) / dot_v2v2(v2, v2);
c[0] = mul * v2[0];
c[1] = mul * v2[1];
@@ -560,8 +558,7 @@ void project_v2_v2v2(float c[2], const float v1[2], const float v2[2])
/* Project v1 on v2 */
void project_v3_v3v3(float c[3], const float v1[3], const float v2[3])
{
- float mul;
- mul = dot_v3v3(v1, v2) / dot_v3v3(v2, v2);
+ const float mul = dot_v3v3(v1, v2) / dot_v3v3(v2, v2);
c[0] = mul * v2[0];
c[1] = mul * v2[1];
@@ -837,7 +834,7 @@ double len_squared_vn(const float *array, const int size)
float normalize_vn_vn(float *array_tar, const float *array_src, const int size)
{
- double d = len_squared_vn(array_src, size);
+ const double d = len_squared_vn(array_src, size);
float d_sqrt;
if (d > 1.0e-35) {
d_sqrt = (float)sqrt(d);
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 2639767fcb1..3ed4a561698 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -479,7 +479,7 @@ MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3])
}
/**
- * Has the effect of mul_m3_v3(), on a single axis.
+ * Has the effect of #mul_m3_v3(), on a single axis.
*/
MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3])
{
@@ -495,7 +495,8 @@ MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3])
}
/**
- * Almost like mul_m4_v3(), misses adding translation.
+ * Has the effect of #mul_mat3_m4_v3(), on a single axis.
+ * (no adding translation)
*/
MINLINE float dot_m4_v3_row_x(float M[4][4], const float a[3])
{
@@ -863,17 +864,17 @@ MINLINE void normal_float_to_short_v3(short out[3], const float in[3])
MINLINE bool is_zero_v2(const float v[2])
{
- return (v[0] == 0 && v[1] == 0);
+ return (v[0] == 0.0f && v[1] == 0.0f);
}
MINLINE bool is_zero_v3(const float v[3])
{
- return (v[0] == 0 && v[1] == 0 && v[2] == 0);
+ return (v[0] == 0.0f && v[1] == 0.0f && v[2] == 0.0f);
}
MINLINE bool is_zero_v4(const float v[4])
{
- return (v[0] == 0 && v[1] == 0 && v[2] == 0 && v[3] == 0);
+ return (v[0] == 0.0f && v[1] == 0.0f && v[2] == 0.0f && v[3] == 0.0f);
}
MINLINE bool is_finite_v2(const float v[2])
@@ -893,9 +894,15 @@ MINLINE bool is_finite_v4(const float v[4])
MINLINE bool is_one_v3(const float v[3])
{
- return (v[0] == 1 && v[1] == 1 && v[2] == 1);
+ return (v[0] == 1.0f && v[1] == 1.0f && v[2] == 1.0f);
}
+
+/** \name Vector Comparison
+ *
+ * \note use ``value <= limit``, so a limit of zero doesn't fail on an exact match.
+ * \{ */
+
MINLINE bool equals_v2v2(const float v1[2], const float v2[2])
{
return ((v1[0] == v2[0]) && (v1[1] == v2[1]));
@@ -913,8 +920,8 @@ MINLINE bool equals_v4v4(const float v1[4], const float v2[4])
MINLINE bool compare_v2v2(const float v1[2], const float v2[2], const float limit)
{
- if (fabsf(v1[0] - v2[0]) < limit)
- if (fabsf(v1[1] - v2[1]) < limit)
+ if (fabsf(v1[0] - v2[0]) <= limit)
+ if (fabsf(v1[1] - v2[1]) <= limit)
return true;
return false;
@@ -922,9 +929,9 @@ MINLINE bool compare_v2v2(const float v1[2], const float v2[2], const float limi
MINLINE bool compare_v3v3(const float v1[3], const float v2[3], const float limit)
{
- if (fabsf(v1[0] - v2[0]) < limit)
- if (fabsf(v1[1] - v2[1]) < limit)
- if (fabsf(v1[2] - v2[2]) < limit)
+ if (fabsf(v1[0] - v2[0]) <= limit)
+ if (fabsf(v1[1] - v2[1]) <= limit)
+ if (fabsf(v1[2] - v2[2]) <= limit)
return true;
return false;
@@ -938,15 +945,26 @@ MINLINE bool compare_len_v3v3(const float v1[3], const float v2[3], const float
y = v1[1] - v2[1];
z = v1[2] - v2[2];
- return ((x * x + y * y + z * z) < (limit * limit));
+ return ((x * x + y * y + z * z) <= (limit * limit));
+}
+
+MINLINE bool compare_len_squared_v3v3(const float v1[3], const float v2[3], const float limit_sq)
+{
+ float x, y, z;
+
+ x = v1[0] - v2[0];
+ y = v1[1] - v2[1];
+ z = v1[2] - v2[2];
+
+ return ((x * x + y * y + z * z) <= limit_sq);
}
MINLINE bool compare_v4v4(const float v1[4], const float v2[4], const float limit)
{
- if (fabsf(v1[0] - v2[0]) < limit)
- if (fabsf(v1[1] - v2[1]) < limit)
- if (fabsf(v1[2] - v2[2]) < limit)
- if (fabsf(v1[3] - v2[3]) < limit)
+ if (fabsf(v1[0] - v2[0]) <= limit)
+ if (fabsf(v1[1] - v2[1]) <= limit)
+ if (fabsf(v1[2] - v2[2]) <= limit)
+ if (fabsf(v1[3] - v2[3]) <= limit)
return true;
return false;
@@ -958,4 +976,6 @@ MINLINE float line_point_side_v2(const float l1[2], const float l2[2], const flo
((l2[0] - pt[0]) * (l1[1] - pt[1])));
}
+/** \} */
+
#endif /* __MATH_VECTOR_INLINE_C__ */
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 0b89ec1f0d0..a7fa443cfc4 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1175,7 +1175,13 @@ static bool get_path_local(char *targetpath, const char *folder_name, const char
}
/* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
+#ifdef __APPLE__
+ static char osx_resourses[FILE_MAX]; /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */
+ sprintf(osx_resourses, "%s../Resources", bprogdir);
+ return test_path(targetpath, osx_resourses, blender_version_decimal(ver), relfolder);
+#else
return test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder);
+#endif
}
/**
@@ -1415,7 +1421,7 @@ const char *BLI_get_folder_create(int folder_id, const char *subfolder)
const char *path;
/* only for user folders */
- if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
+ if (!ELEM(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
return NULL;
path = BLI_get_folder(folder_id, subfolder);
@@ -1515,21 +1521,6 @@ void BLI_setenv_if_new(const char *env, const char *val)
BLI_setenv(env, val);
}
-
-/**
- * Changes to the path separators to the native ones for this OS.
- */
-void BLI_clean(char *path)
-{
-#ifdef WIN32
- if (path && BLI_strnlen(path, 3) > 2) {
- BLI_char_switch(path + 2, '/', '\\');
- }
-#else
- BLI_char_switch(path + BLI_path_unc_prefix_len(path), '\\', '/');
-#endif
-}
-
/**
* Change every \a from in \a string into \a to. The
* result will be in \a string
@@ -1681,7 +1672,7 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, c
strcat(string, file);
/* Push all slashes to the system preferred direction */
- BLI_clean(string);
+ BLI_path_native_slash(string);
}
static bool testextensie_ex(const char *str, const size_t str_len,
@@ -1783,7 +1774,7 @@ bool BLI_replace_extension(char *path, size_t maxlen, const char *ext)
ssize_t a;
for (a = path_len - 1; a >= 0; a--) {
- if (ELEM3(path[a], '.', '/', '\\')) {
+ if (ELEM(path[a], '.', '/', '\\')) {
break;
}
}
@@ -2146,6 +2137,20 @@ void BLI_del_slash(char *string)
}
/**
+ * Changes to the path separators to the native ones for this OS.
+ */
+void BLI_path_native_slash(char *path)
+{
+#ifdef WIN32
+ if (path && BLI_strnlen(path, 3) > 2) {
+ BLI_char_switch(path + 2, '/', '\\');
+ }
+#else
+ BLI_char_switch(path + BLI_path_unc_prefix_len(path), '\\', '/');
+#endif
+}
+
+/**
* Tries appending each of the semicolon-separated extensions in the PATHEXT
* environment variable (Windows-only) onto *name in turn until such a file is found.
* Returns success/failure.
diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c
index 71cda92842a..dd829e5d80a 100644
--- a/source/blender/blenlib/intern/polyfill2d.c
+++ b/source/blender/blenlib/intern/polyfill2d.c
@@ -387,7 +387,7 @@ static bool kdtree2d_isect_tri_recursive(
(span_tri_v2_sign(tri_coords[1], tri_coords[2], co) != CONCAVE) &&
(span_tri_v2_sign(tri_coords[2], tri_coords[0], co) != CONCAVE))
{
- if (!ELEM3(node->index, tri_index[0], tri_index[1], tri_index[2])) {
+ if (!ELEM(node->index, tri_index[0], tri_index[1], tri_index[2])) {
return true;
}
}
diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c
index 410f98897ce..3dff0b31091 100644
--- a/source/blender/blenlib/intern/rand.c
+++ b/source/blender/blenlib/intern/rand.c
@@ -95,15 +95,20 @@ void BLI_rng_srandom(RNG *rng, unsigned int seed)
BLI_rng_seed(rng, seed + hash[seed & 255]);
}
-int BLI_rng_get_int(RNG *rng)
+BLI_INLINE void rng_step(RNG *rng)
{
rng->X = (MULTIPLIER * rng->X + ADDEND) & MASK;
+}
+
+int BLI_rng_get_int(RNG *rng)
+{
+ rng_step(rng);
return (int) (rng->X >> 17);
}
unsigned int BLI_rng_get_uint(RNG *rng)
{
- rng->X = (MULTIPLIER * rng->X + ADDEND) & MASK;
+ rng_step(rng);
return (unsigned int) (rng->X >> 17);
}
@@ -167,10 +172,9 @@ void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsig
void BLI_rng_skip(RNG *rng, int n)
{
- int i;
-
- for (i = 0; i < n; i++)
- BLI_rng_get_int(rng);
+ while (n--) {
+ rng_step(rng);
+ }
}
/***/
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index 05e4984d9a3..cf0d8cff870 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -865,6 +865,9 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const
/* Newell's Method */
/* Similar code used elsewhere, but this checks for double ups
* which historically this function supports so better not change */
+
+ /* warning: this only gives stable direction with single polygons,
+ * ideally we'd calculate connectivity and each polys normal, see T41047 */
const float *v_prev;
zero_v3(n);
diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c
index d6b2383bd47..0cf9f69b9ae 100644
--- a/source/blender/blenlib/intern/smallhash.c
+++ b/source/blender/blenlib/intern/smallhash.c
@@ -44,8 +44,6 @@
*
* Note that the values and keys are often pointers or index values,
* use the maximum values to avoid real pointers colliding with magic numbers.
- *
- * \note these have the SMHASH prefix because we may want to make them public.
*/
#include <string.h>
@@ -86,6 +84,11 @@ BLI_INLINE bool smallhash_val_is_used(const void *val)
extern const unsigned int hashsizes[];
+BLI_INLINE unsigned int smallhash_key(const uintptr_t key)
+{
+ return (unsigned int)key;
+}
+
/**
* Check if the number of items in the smallhash is large enough to require more buckets.
*/
@@ -118,7 +121,7 @@ BLI_INLINE void smallhash_buckets_reserve(SmallHash *sh, const unsigned int nent
BLI_INLINE SmallHashEntry *smallhash_lookup(SmallHash *sh, const uintptr_t key)
{
SmallHashEntry *e;
- unsigned int h = (unsigned int)key;
+ unsigned int h = smallhash_key(key);
unsigned int hoff = 1;
BLI_assert(key != SMHASH_KEY_UNUSED);
@@ -142,7 +145,7 @@ BLI_INLINE SmallHashEntry *smallhash_lookup(SmallHash *sh, const uintptr_t key)
BLI_INLINE SmallHashEntry *smallhash_lookup_first_free(SmallHash *sh, const uintptr_t key)
{
SmallHashEntry *e;
- unsigned int h = (unsigned int)key;
+ unsigned int h = smallhash_key(key);
unsigned int hoff = 1;
for (e = &sh->buckets[h % sh->nbuckets];
@@ -312,6 +315,9 @@ void *BLI_smallhash_iternew(SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
return BLI_smallhash_iternext(iter, key);
}
+/** \name Debugging & Introspection
+ * \{ */
+
/* note, this was called _print_smhash in knifetool.c
* it may not be intended for general use - campbell */
#if 0
@@ -345,3 +351,41 @@ void BLI_smallhash_print(SmallHash *sh)
fflush(stdout);
}
#endif
+
+#ifdef DEBUG
+/**
+ * Measure how well the hash function performs
+ * (1.0 is perfect - no stepping needed).
+ *
+ * Smaller is better!
+ */
+double BLI_smallhash_calc_quality(SmallHash *sh)
+{
+ uint64_t sum = 0;
+ unsigned int i;
+
+ if (sh->nentries == 0)
+ return -1.0;
+
+ for (i = 0; i < sh->nbuckets; i++) {
+ if (sh->buckets[i].key != SMHASH_KEY_UNUSED) {
+ uint64_t count = 0;
+ SmallHashEntry *e, *e_final = &sh->buckets[i];
+ unsigned int h = smallhash_key(e_final->key);
+ unsigned int hoff = 1;
+
+ for (e = &sh->buckets[h % sh->nbuckets];
+ e != e_final;
+ h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets])
+ {
+ count += 1;
+ }
+
+ sum += count;
+ }
+ }
+ return ((double)(sh->nentries + sum) / (double)sh->nentries);
+}
+#endif
+
+/** \} */
diff --git a/source/blender/blenlib/intern/stack.c b/source/blender/blenlib/intern/stack.c
index c2ee73d9693..58029120de9 100644
--- a/source/blender/blenlib/intern/stack.c
+++ b/source/blender/blenlib/intern/stack.c
@@ -35,7 +35,7 @@
#include "BLI_strict_flags.h"
-// #define USE_TOTELEM
+#define USE_TOTELEM
#define CHUNK_EMPTY ((size_t)-1)
/* target chunks size: 64kb */
@@ -135,7 +135,7 @@ void BLI_stack_free(BLI_Stack *stack)
* Copies the source value onto the stack (note that it copies
* elem_size bytes from 'src', the pointer itself is not stored)
*/
-void BLI_stack_push(BLI_Stack *stack, const void *src)
+void *BLI_stack_push_r(BLI_Stack *stack)
{
stack->chunk_index++;
@@ -161,8 +161,14 @@ void BLI_stack_push(BLI_Stack *stack, const void *src)
stack->totelem++;
#endif
- /* Copy source to end of stack */
- memcpy(CHUNK_LAST_ELEM(stack), src, stack->elem_size);
+ /* Return end of stack */
+ return CHUNK_LAST_ELEM(stack);
+}
+
+void BLI_stack_push(BLI_Stack *stack, const void *src)
+{
+ void *dst = BLI_stack_push_r(stack);
+ memcpy(dst, src, stack->elem_size);
}
/**
@@ -175,29 +181,62 @@ void BLI_stack_pop(BLI_Stack *stack, void *dst)
{
BLI_assert(BLI_stack_is_empty(stack) == false);
- if (!BLI_stack_is_empty(stack)) {
- memcpy(dst, CHUNK_LAST_ELEM(stack), stack->elem_size);
+ memcpy(dst, CHUNK_LAST_ELEM(stack), stack->elem_size);
#ifdef USE_TOTELEM
- stack->totelem--;
+ stack->totelem--;
#endif
- if (--stack->chunk_index == CHUNK_EMPTY) {
- struct StackChunk *chunk_free;
+ if (UNLIKELY(--stack->chunk_index == CHUNK_EMPTY)) {
+ struct StackChunk *chunk_free;
- chunk_free = stack->chunk_curr;
- stack->chunk_curr = stack->chunk_curr->next;
+ chunk_free = stack->chunk_curr;
+ stack->chunk_curr = stack->chunk_curr->next;
- chunk_free->next = stack->chunk_free;
- stack->chunk_free = chunk_free;
+ chunk_free->next = stack->chunk_free;
+ stack->chunk_free = chunk_free;
- stack->chunk_index = stack->chunk_elem_max - 1;
- }
+ stack->chunk_index = stack->chunk_elem_max - 1;
+ }
+}
+
+void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n)
+{
+ BLI_assert(n <= BLI_stack_count(stack));
+
+ while (n--) {
+ BLI_stack_pop(stack, dst);
+ dst = (void *)((char *)dst + stack->elem_size);
}
}
+size_t BLI_stack_count(const BLI_Stack *stack)
+{
+#ifdef USE_TOTELEM
+ return stack->totelem;
+#else
+ struct StackChunk *data = stack->chunk_curr;
+ size_t totelem = stack->chunk_index + 1;
+ size_t i;
+ if (totelem != stack->chunk_elem_max) {
+ data = data->next;
+ }
+ else {
+ totelem = 0;
+ }
+ for (i = 0; data; data = data->next) {
+ i++;
+ }
+ totelem += stack->chunk_elem_max * i;
+ return totelem;
+#endif
+}
+
/**
* Returns true if the stack is empty, false otherwise
*/
bool BLI_stack_is_empty(const BLI_Stack *stack)
{
+#ifdef USE_TOTELEM
+ BLI_assert((stack->chunk_curr == NULL) == (stack->totelem == 0));
+#endif
return (stack->chunk_curr == NULL);
}
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 453b0cc939f..f3ecc799e1e 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -515,7 +515,7 @@ int BLI_stat(const char *path, BLI_stat_t *buffer)
int BLI_wstat(const wchar_t *path, BLI_stat_t *buffer)
{
-#if (defined(_MSC_VER) && (_MSC_VER >= 1500)) || defined(__MINGW64__)
+#if defined(_MSC_VER) || defined(__MINGW64__)
return _wstat64(path, buffer);
#elif defined(__MINGW32__)
return _wstati64(path, buffer);
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index f396abbeb8d..eeafc1a9e8f 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -648,7 +648,7 @@ int BLI_str_rstrip_float_zero(char *str, const char pad)
* \param str_array_len The length of the array, or -1 for a NULL-terminated array.
* \return The index of str in str_array or -1.
*/
-int BLI_str_index_in_array_n(const char *str, const char **str_array, const int str_array_len)
+int BLI_str_index_in_array_n(const char *__restrict str, const char **__restrict str_array, const int str_array_len)
{
int index;
const char **str_iter = str_array;
@@ -668,7 +668,7 @@ int BLI_str_index_in_array_n(const char *str, const char **str_array, const int
* \param str_array Array of strings, (must be NULL-terminated).
* \return The index of str in str_array or -1.
*/
-int BLI_str_index_in_array(const char *str, const char **str_array)
+int BLI_str_index_in_array(const char *__restrict str, const char **__restrict str_array)
{
int index;
const char **str_iter = str_array;
@@ -741,3 +741,38 @@ size_t BLI_str_partition_ex(const char *str, const char delim[], char **sep, cha
return strlen(str);
}
+
+/**
+ * Format ints with decimal grouping.
+ * 1000 -> 1,000
+ *
+ * \param dst The resulting string
+ * \param num Number to format
+ * \return The length of \a dst
+ */
+size_t BLI_str_format_int_grouped(char dst[16], int num)
+{
+ char src[16];
+ char *p_src = src;
+ char *p_dst = dst;
+
+ const char separator = ',';
+ int num_len, commas;
+
+ num_len = sprintf(src, "%d", num);
+
+ if (*p_src == '-') {
+ *p_dst++ = *p_src++;
+ num_len--;
+ }
+
+ for (commas = 2 - num_len % 3; *p_src; commas = (commas + 1) % 3) {
+ *p_dst++ = *p_src++;
+ if (commas == 1) {
+ *p_dst++ = separator;
+ }
+ }
+ *--p_dst = '\0';
+
+ return (size_t)(p_dst - dst);
+}
diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c
index 65ded37eb7b..a67e116969e 100644
--- a/source/blender/blenlib/intern/winstuff.c
+++ b/source/blender/blenlib/intern/winstuff.c
@@ -92,6 +92,7 @@ void RegisterBlendExtension(void)
const char *ThumbHandlerDLL;
char RegCmd[MAX_PATH * 2];
char MBox[256];
+ char *blender_app;
#ifndef WIN64
BOOL IsWOW64;
#endif
@@ -99,6 +100,12 @@ void RegisterBlendExtension(void)
printf("Registering file extension...");
GetModuleFileName(0, BlPath, MAX_PATH);
+ /* Replace the actual app name with the wrapper. */
+ blender_app = strstr(BlPath, "blender-app.exe");
+ if (blender_app != NULL) {
+ strcpy(blender_app, "blender.exe");
+ }
+
/* root is HKLM by default */
lresult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Classes", 0, KEY_ALL_ACCESS, &root);
if (lresult != ERROR_SUCCESS) {
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 4fb983c119b..4b7b9cecb17 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -275,7 +275,8 @@ void BLO_main_expander(void (*expand_doit_func)(void *, struct Main *, void *));
*/
void BLO_expand_main(void *fdhandle, struct Main *mainvar);
-/* Update defaults in startup.blend, without having to save and embed it */
+/* Update defaults in startup.blend & userprefs.blend, without having to save and embed it */
+void BLO_update_defaults_userpref_blend(void);
void BLO_update_defaults_startup_blend(struct Main *mainvar);
#ifdef __cplusplus
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 91753158d02..b2e49be1a5e 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -434,8 +434,7 @@ void blo_join_main(ListBase *mainlist)
while ((tojoin = mainl->next)) {
add_main_to_main(mainl, tojoin);
BLI_remlink(mainlist, tojoin);
- MEM_freeN(tojoin->eval_ctx);
- MEM_freeN(tojoin);
+ BKE_main_free(tojoin);
}
}
@@ -1824,6 +1823,7 @@ static void lib_link_brush(FileData *fd, Main *main)
brush->mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mtex.tex);
brush->mask_mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mask_mtex.tex);
brush->clone.image = newlibadr_us(fd, brush->id.lib, brush->clone.image);
+ brush->paint_curve = newlibadr_us(fd, brush->id.lib, brush->paint_curve);
}
}
}
@@ -1834,6 +1834,8 @@ static void direct_link_brush(FileData *fd, Brush *brush)
/* fallof curve */
brush->curve = newdataadr(fd, brush->curve);
+ brush->gradient = newdataadr(fd, brush->gradient);
+
if (brush->curve)
direct_link_curvemapping(fd, brush->curve);
else
@@ -1843,6 +1845,43 @@ static void direct_link_brush(FileData *fd, Brush *brush)
brush->icon_imbuf = NULL;
}
+/* ************ READ Palette *************** */
+static void lib_link_palette(FileData *UNUSED(fd), Main *main)
+{
+ Palette *palette;
+
+ /* only link ID pointers */
+ for (palette = main->palettes.first; palette; palette = palette->id.next) {
+ if (palette->id.flag & LIB_NEED_LINK) {
+ palette->id.flag -= LIB_NEED_LINK;
+ }
+ }
+}
+
+static void direct_link_palette(FileData *fd, Palette *palette)
+{
+ /* palette itself has been read */
+ link_list(fd, &palette->colors);
+}
+
+static void lib_link_paint_curve(FileData *UNUSED(fd), Main *main)
+{
+ PaintCurve *pc;
+
+ /* only link ID pointers */
+ for (pc = main->paintcurves.first; pc; pc = pc->id.next) {
+ if (pc->id.flag & LIB_NEED_LINK) {
+ pc->id.flag -= LIB_NEED_LINK;
+ }
+ }
+}
+
+static void direct_link_paint_curve(FileData *fd, PaintCurve *pc)
+{
+ pc->points = newdataadr(fd, pc->points);
+}
+
+
static void direct_link_script(FileData *UNUSED(fd), Script *script)
{
script->id.us = 1;
@@ -2664,9 +2703,9 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
}
}
else if (ntree->type==NTREE_COMPOSIT) {
- if (ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
+ if (ELEM(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
direct_link_curvemapping(fd, node->storage);
- else if (ELEM3(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
+ else if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
((ImageUser *)node->storage)->ok = 1;
}
else if ( ntree->type==NTREE_TEXTURE) {
@@ -3516,7 +3555,8 @@ static void direct_link_material(FileData *fd, Material *ma)
for (a = 0; a < MAX_MTEX; a++) {
ma->mtex[a] = newdataadr(fd, ma->mtex[a]);
}
-
+ ma->texpaintslot = NULL;
+
ma->ramp_col = newdataadr(fd, ma->ramp_col);
ma->ramp_spec = newdataadr(fd, ma->ramp_spec);
@@ -5059,6 +5099,7 @@ static void link_paint(FileData *fd, Scene *sce, Paint *p)
{
if (p) {
p->brush = newlibadr_us(fd, sce->id.lib, p->brush);
+ p->palette = newlibadr_us(fd, sce->id.lib, p->palette);
p->paint_cursor = NULL;
}
}
@@ -5107,6 +5148,18 @@ static void lib_link_scene(FileData *fd, Main *main)
sce->toolsettings->sculpt->gravity_object =
newlibadr_us(fd, sce->id.lib, sce->toolsettings->sculpt->gravity_object);
+ if (sce->toolsettings->imapaint.stencil)
+ sce->toolsettings->imapaint.stencil =
+ newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.stencil);
+
+ if (sce->toolsettings->imapaint.clone)
+ sce->toolsettings->imapaint.clone =
+ newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.clone);
+
+ if (sce->toolsettings->imapaint.canvas)
+ sce->toolsettings->imapaint.canvas =
+ newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.canvas);
+
sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template);
for (base = sce->base.first; base; base = next) {
@@ -5355,7 +5408,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
if (seq->strip && seq->strip->done==0) {
seq->strip->done = true;
- if (ELEM4(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
+ if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
seq->strip->stripdata = newdataadr(fd, seq->strip->stripdata);
}
else {
@@ -5789,9 +5842,9 @@ static void lib_link_screen(FileData *fd, Main *main)
/* how to handle user count on pointer restore */
typedef enum ePointerUserMode {
- USER_IGNORE, /* ignore user count */
- USER_ONE, /* ensure at least one user (fake also counts) */
- USER_REAL /* ensure at least one real user (fake user ignored) */
+ USER_IGNORE = 0, /* ignore user count */
+ USER_ONE = 1, /* ensure at least one user (fake also counts) */
+ USER_REAL = 2, /* ensure at least one real user (fake user ignored) */
} ePointerUserMode;
static bool restore_pointer(ID *id, ID *newid, ePointerUserMode user)
@@ -5816,9 +5869,9 @@ static bool restore_pointer(ID *id, ID *newid, ePointerUserMode user)
* Only for undo files, or to restore a screen after reading without UI...
*
* user
- * - 0: no usercount change
- * - 1: ensure a user
- * - 2: ensure a real user (even if a fake one is set)
+ * - USER_IGNORE: no usercount change
+ * - USER_ONE: ensure a user
+ * - USER_REAL: ensure a real user (even if a fake one is set)
*/
static void *restore_pointer_by_name(Main *mainp, ID *id, ePointerUserMode user)
{
@@ -5915,8 +5968,12 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
v3d->ob_centre = restore_pointer_by_name(newmain, (ID *)v3d->ob_centre, USER_ONE);
for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next) {
- bgpic->ima = restore_pointer_by_name(newmain, (ID *)bgpic->ima, USER_ONE);
- bgpic->clip = restore_pointer_by_name(newmain, (ID *)bgpic->clip, USER_ONE);
+ if ((bgpic->ima = restore_pointer_by_name(newmain, (ID *)bgpic->ima, USER_IGNORE))) {
+ id_us_plus((ID *)bgpic->ima);
+ }
+ if ((bgpic->clip = restore_pointer_by_name(newmain, (ID *)bgpic->clip, USER_IGNORE))) {
+ id_us_plus((ID *)bgpic->clip);
+ }
}
if (v3d->localvd) {
/*Base *base;*/
@@ -6290,6 +6347,9 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
else if (sa->spacetype == SPACE_VIEW3D)
blo_do_versions_view3d_split_250(sa->spacedata.first, &sa->regionbase);
+ /* incase we set above */
+ sa->butspacetype = sa->spacetype;
+
for (sl = sa->spacedata.first; sl; sl = sl->next) {
link_list(fd, &(sl->regionbase));
@@ -7138,6 +7198,8 @@ static const char *dataname(short id_code)
case ID_NT: return "Data from NT";
case ID_BR: return "Data from BR";
case ID_PA: return "Data from PA";
+ case ID_PAL: return "Data from PAL";
+ case ID_PC: return "Data from PCRV";
case ID_GD: return "Data from GD";
case ID_WM: return "Data from WM";
case ID_MC: return "Data from MC";
@@ -7323,6 +7385,12 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
case ID_LS:
direct_link_linestyle(fd, (FreestyleLineStyle *)id);
break;
+ case ID_PAL:
+ direct_link_palette(fd, (Palette *)id);
+ break;
+ case ID_PC:
+ direct_link_paint_curve(fd, (PaintCurve *)id);
+ break;
}
oldnewmap_free_unused(fd->datamap);
@@ -7487,8 +7555,9 @@ static void lib_link_all(FileData *fd, Main *main)
/* No load UI for undo memfiles */
if (fd->memfile == NULL) {
lib_link_windowmanager(fd, main);
- lib_link_screen(fd, main);
}
+ /* DO NOT skip screens here, 3Dview may contains pointers to other ID data (like bgpic)! See T41411. */
+ lib_link_screen(fd, main);
lib_link_scene(fd, main);
lib_link_object(fd, main);
lib_link_curve(fd, main);
@@ -7511,6 +7580,8 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_vfont(fd, main);
lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */
lib_link_brush(fd, main);
+ lib_link_palette(fd, main);
+ lib_link_paint_curve(fd, main);
lib_link_particlesettings(fd, main);
lib_link_movieclip(fd, main);
lib_link_mask(fd, main);
@@ -8050,6 +8121,7 @@ static void expand_brush(FileData *fd, Main *mainvar, Brush *brush)
expand_doit(fd, mainvar, brush->mtex.tex);
expand_doit(fd, mainvar, brush->mask_mtex.tex);
expand_doit(fd, mainvar, brush->clone.image);
+ expand_doit(fd, mainvar, brush->paint_curve);
}
static void expand_material(FileData *fd, Main *mainvar, Material *ma)
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 3890e07bb65..7c6b6ec7249 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -2454,9 +2454,9 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
if (sl->spacetype == SPACE_OUTLINER) {
SpaceOops *so = (SpaceOops *)sl;
- if (!ELEM11(so->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_SELECTED, SO_ACTIVE,
- SO_SAME_TYPE, SO_GROUPS, SO_LIBRARIES, SO_SEQUENCE, SO_DATABLOCKS,
- SO_USERDEF))
+ if (!ELEM(so->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_SELECTED, SO_ACTIVE,
+ SO_SAME_TYPE, SO_GROUPS, SO_LIBRARIES, SO_SEQUENCE, SO_DATABLOCKS,
+ SO_USERDEF))
{
so->outlinevis = SO_ALL_SCENES;
}
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index 103f9b76ba7..8e760a9c9f6 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -34,6 +34,8 @@
/* allow readfile to use deprecated functionality */
#define DNA_DEPRECATED_ALLOW
+#include "DNA_brush_types.h"
+#include "DNA_cloth_types.h"
#include "DNA_constraint_types.h"
#include "DNA_sdna_types.h"
#include "DNA_space_types.h"
@@ -41,7 +43,9 @@
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
+#include "DNA_particle_types.h"
#include "DNA_linestyle_types.h"
+#include "DNA_actuator_types.h"
#include "DNA_genfile.h"
@@ -308,6 +312,44 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
mat->line_col[3] = mat->alpha;
}
}
+
+ if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "int", "preview_start_resolution")) {
+ Scene *scene;
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ scene->r.preview_start_resolution = 64;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 271, 2)) {
+ /* init up & track axis property of trackto actuators */
+ Object *ob;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ bActuator *act;
+ for (act = ob->actuators.first; act; act = act->next) {
+ if (act->type == ACT_EDIT_OBJECT) {
+ bEditObjectActuator *eoact = act->data;
+ eoact->trackflag = ob->trackflag;
+ /* if trackflag is pointing +-Z axis then upflag should point Y axis.
+ * Rest of trackflag cases, upflag should be point z axis */
+ if ((ob->trackflag == OB_POSZ) || (ob->trackflag == OB_NEGZ)) {
+ eoact->upflag = 1;
+ }
+ else {
+ eoact->upflag = 2;
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 271, 3)) {
+ Brush *br;
+
+ for (br = main->brush.first; br; br = br->id.next) {
+ br->fill_threshold = 0.2f;
+ }
}
if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "int", "preview_start_resolution")) {
@@ -316,4 +358,20 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
scene->r.preview_start_resolution = 64;
}
}
+
+ if (!MAIN_VERSION_ATLEAST(main, 271, 6)) {
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_ParticleSystem) {
+ ParticleSystemModifierData *pmd = (ParticleSystemModifierData *)md;
+ if (pmd->psys && pmd->psys->clmd) {
+ pmd->psys->clmd->sim_parms->vel_damping = 1.0f;
+ }
+ }
+ }
+ }
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index fdedd3f4edd..217d1f0821f 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -26,8 +26,10 @@
*/
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "DNA_brush_types.h"
#include "DNA_freestyle_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_scene_types.h"
@@ -36,14 +38,34 @@
#include "DNA_userdef_types.h"
#include "DNA_mesh_types.h"
#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "BKE_brush.h"
+#include "BKE_library.h"
#include "BKE_main.h"
#include "BLO_readfile.h"
-/* Update defaults in startup.blend, without having to save and embed the file.
+
+/**
+ * Override values in in-memory startup.blend, avoids resaving for small changes.
+ */
+void BLO_update_defaults_userpref_blend(void)
+{
+ /* defaults from T37518 */
+
+ U.uiflag |= USER_ZBUF_CURSOR;
+ U.uiflag |= USER_QUIT_PROMPT;
+ U.uiflag |= USER_CONTINUOUS_MOUSE;
+
+ U.versions = 1;
+ U.savetime = 2;
+}
+
+/**
+ * Update defaults in startup.blend, without having to save and embed the file.
* This function can be emptied each time the startup.blend is updated. */
-void BLO_update_defaults_startup_blend(Main *main)
+void BLO_update_defaults_startup_blend(Main *bmain)
{
Scene *scene;
SceneRenderLayer *srl;
@@ -51,7 +73,7 @@ void BLO_update_defaults_startup_blend(Main *main)
Mesh *me;
Material *mat;
- for (scene = main->scene.first; scene; scene = scene->id.next) {
+ for (scene = bmain->scene.first; scene; scene = scene->id.next) {
scene->r.im_format.planes = R_IMF_PLANES_RGBA;
scene->r.im_format.compress = 15;
@@ -59,9 +81,20 @@ void BLO_update_defaults_startup_blend(Main *main)
srl->freestyleConfig.sphere_radius = 0.1f;
srl->pass_alpha_threshold = 0.5f;
}
+
+ if (scene->toolsettings) {
+ ToolSettings *ts = scene->toolsettings;
+
+ if (ts->sculpt) {
+ Sculpt *sculpt = ts->sculpt;
+ sculpt->paint.symmetry_flags |= PAINT_SYMM_X;
+ sculpt->flags |= SCULPT_DYNTOPO_COLLAPSE;
+ sculpt->detail_size = 12;
+ }
+ }
}
- for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
+ for (linestyle = bmain->linestyle.first; linestyle; linestyle = linestyle->id.next) {
linestyle->flag = LS_SAME_OBJECT | LS_NO_SORTING | LS_TEXTURE;
linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA;
linestyle->integration_type = LS_INTEGRATION_MEAN;
@@ -71,27 +104,48 @@ void BLO_update_defaults_startup_blend(Main *main)
{
bScreen *screen;
- for (screen = main->screen.first; screen; screen = screen->id.next) {
+ for (screen = bmain->screen.first; screen; screen = screen->id.next) {
ScrArea *area;
for (area = screen->areabase.first; area; area = area->next) {
SpaceLink *space_link;
+ ARegion *ar;
+
for (space_link = area->spacedata.first; space_link; space_link = space_link->next) {
if (space_link->spacetype == SPACE_CLIP) {
SpaceClip *space_clip = (SpaceClip *) space_link;
space_clip->flag &= ~SC_MANUAL_CALIBRATION;
}
}
+
+ /* Remove all stored panels, we want to use defaults (order, open/closed) as defined by UI code here! */
+ for (ar = area->regionbase.first; ar; ar = ar->next) {
+ BLI_freelistN(&ar->panels);
+ }
}
}
}
- for (me = main->mesh.first; me; me = me->id.next) {
+ for (me = bmain->mesh.first; me; me = me->id.next) {
me->smoothresh = DEG2RADF(180.0f);
+ me->flag &= ~ME_TWOSIDED;
}
- for (mat = main->mat.first; mat; mat = mat->id.next) {
+ for (mat = bmain->mat.first; mat; mat = mat->id.next) {
mat->line_col[0] = mat->line_col[1] = mat->line_col[2] = 0.0f;
mat->line_col[3] = 1.0f;
}
+
+ {
+ Brush *br;
+ br = BKE_brush_add(bmain, "Fill");
+ br->imagepaint_tool = PAINT_TOOL_FILL;
+ br->ob_mode = OB_MODE_TEXTURE_PAINT;
+
+ br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Mask");
+ if (br) {
+ br->imagepaint_tool = PAINT_TOOL_MASK;
+ br->ob_mode |= OB_MODE_TEXTURE_PAINT;
+ }
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 572c6d0a02d..557cc147f19 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -473,7 +473,7 @@ static void do_version_ntree_242_2(bNodeTree *ntree)
if (ntree->type == NTREE_COMPOSIT) {
for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM3(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
/* only image had storage */
if (node->storage) {
NodeImageAnim *nia = node->storage;
@@ -2232,7 +2232,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
}
if (sce->r.mode & R_PANORAMA) {
- /* all these checks to ensure saved files with svn version keep working... */
+ /* all these checks to ensure saved files between released versions keep working... */
if (sce->r.xsch < sce->r.ysch) {
Object *obc = blo_do_versions_newlibadr(fd, lib, sce->camera);
if (obc && obc->type == OB_CAMERA) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index a0198a687a2..59f12657703 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -183,6 +183,114 @@
#define MYWRITE_BUFFER_SIZE 100000
#define MYWRITE_MAX_CHUNK 32768
+
+
+/** \name Small API to handle compression.
+ * \{ */
+
+typedef enum {
+ WW_WRAP_NONE = 1,
+ WW_WRAP_ZLIB,
+} eWriteWrapType;
+
+typedef struct WriteWrap WriteWrap;
+struct WriteWrap {
+ /* callbacks */
+ bool (*open)(WriteWrap *ww, const char *filepath);
+ bool (*close)(WriteWrap *ww);
+ size_t (*write)(WriteWrap *ww, const char *data, size_t data_len);
+
+ /* internal */
+ union {
+ int file_handle;
+ gzFile gz_handle;
+ } _user_data;
+};
+
+/* none */
+#define FILE_HANDLE(ww) \
+ (ww)->_user_data.file_handle
+
+static bool ww_open_none(WriteWrap *ww, const char *filepath)
+{
+ int file;
+
+ file = BLI_open(filepath, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666);
+
+ if (file != -1) {
+ FILE_HANDLE(ww) = file;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+static bool ww_close_none(WriteWrap *ww)
+{
+ return (close(FILE_HANDLE(ww)) != -1);
+}
+static size_t ww_write_none(WriteWrap *ww, const char *buf, size_t buf_len)
+{
+ return write(FILE_HANDLE(ww), buf, buf_len);
+}
+#undef FILE_HANDLE
+
+/* zlib */
+#define FILE_HANDLE(ww) \
+ (ww)->_user_data.gz_handle
+
+static bool ww_open_zlib(WriteWrap *ww, const char *filepath)
+{
+ gzFile file;
+
+ file = BLI_gzopen(filepath, "wb1");
+
+ if (file != Z_NULL) {
+ FILE_HANDLE(ww) = file;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+static bool ww_close_zlib(WriteWrap *ww)
+{
+ return (gzclose(FILE_HANDLE(ww)) == Z_OK);
+}
+static size_t ww_write_zlib(WriteWrap *ww, const char *buf, size_t buf_len)
+{
+ return gzwrite(FILE_HANDLE(ww), buf, buf_len);
+}
+#undef FILE_HANDLE
+
+/* --- end compression types --- */
+
+static void ww_handle_init(eWriteWrapType ww_type, WriteWrap *r_ww)
+{
+ memset(r_ww, 0, sizeof(*r_ww));
+
+ switch (ww_type) {
+ case WW_WRAP_ZLIB:
+ {
+ r_ww->open = ww_open_zlib;
+ r_ww->close = ww_close_zlib;
+ r_ww->write = ww_write_zlib;
+ break;
+ }
+ default:
+ {
+ r_ww->open = ww_open_none;
+ r_ww->close = ww_close_none;
+ r_ww->write = ww_write_none;
+ break;
+ }
+ }
+}
+
+/** \} */
+
+
+
typedef struct {
struct SDNA *sdna;
@@ -192,12 +300,17 @@ typedef struct {
int tot, count, error, memsize;
+ /* Wrap writing, so we can use zlib or
+ * other compression types later, see: G_FILE_COMPRESS
+ * Will be NULL for UNDO. */
+ WriteWrap *ww;
+
#ifdef USE_BMESH_SAVE_AS_COMPAT
char use_mesh_compat; /* option to save with older mesh format */
#endif
} WriteData;
-static WriteData *writedata_new(int file)
+static WriteData *writedata_new(WriteWrap *ww)
{
WriteData *wd= MEM_callocN(sizeof(*wd), "writedata");
@@ -209,7 +322,7 @@ static WriteData *writedata_new(int file)
wd->sdna = DNA_sdna_from_data(DNAstr, DNAlen, false);
- wd->file= file;
+ wd->ww = ww;
wd->buf= MEM_mallocN(MYWRITE_BUFFER_SIZE, "wd->buf");
@@ -226,9 +339,9 @@ static void writedata_do_write(WriteData *wd, const void *mem, int memlen)
add_memfilechunk(NULL, wd->current, mem, memlen);
}
else {
- if (write(wd->file, mem, memlen) != memlen)
- wd->error= 1;
-
+ if (wd->ww->write(wd->ww, mem, memlen) != memlen) {
+ wd->error = 1;
+ }
}
}
@@ -302,9 +415,9 @@ static void mywrite(WriteData *wd, const void *adr, int len)
* \param current The current memory file (can be NULL).
* \warning Talks to other functions with global parameters
*/
-static WriteData *bgnwrite(int file, MemFile *compare, MemFile *current)
+static WriteData *bgnwrite(WriteWrap *ww, MemFile *compare, MemFile *current)
{
- WriteData *wd= writedata_new(file);
+ WriteData *wd= writedata_new(ww);
if (wd == NULL) return NULL;
@@ -767,7 +880,7 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
writedata(wd, DATA, strlen(nss->bytecode)+1, nss->bytecode);
writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
- else if (ntree->type==NTREE_COMPOSIT && ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
+ else if (ntree->type==NTREE_COMPOSIT && ELEM(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
write_curvemapping(wd, node->storage);
else if (ntree->type==NTREE_TEXTURE && (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME) )
write_curvemapping(wd, node->storage);
@@ -2256,6 +2369,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
case SEQ_TYPE_TRANSFORM:
writestruct(wd, DATA, "TransformVars", 1, seq->effectdata);
break;
+ case SEQ_TYPE_GAUSSIAN_BLUR:
+ writestruct(wd, DATA, "GaussianBlurVars", 1, seq->effectdata);
+ break;
}
}
@@ -2921,6 +3037,38 @@ static void write_brushes(WriteData *wd, ListBase *idbase)
if (brush->curve)
write_curvemapping(wd, brush->curve);
+ if (brush->curve)
+ writestruct(wd, DATA, "ColorBand", 1, brush->gradient);
+ }
+ }
+}
+
+static void write_palettes(WriteData *wd, ListBase *idbase)
+{
+ Palette *palette;
+
+ for (palette = idbase->first; palette; palette = palette->id.next) {
+ if (palette->id.us > 0 || wd->current) {
+ PaletteColor *color;
+ writestruct(wd, ID_PAL, "Palette", 1, palette);
+ if (palette->id.properties) IDP_WriteProperty(palette->id.properties, wd);
+
+ for (color = palette->colors.first; color; color= color->next)
+ writestruct(wd, DATA, "PaletteColor", 1, color);
+ }
+ }
+}
+
+static void write_paintcurves(WriteData *wd, ListBase *idbase)
+{
+ PaintCurve *pc;
+
+ for (pc = idbase->first; pc; pc = pc->id.next) {
+ if (pc->id.us > 0 || wd->current) {
+ writestruct(wd, ID_PC, "PaintCurve", 1, pc);
+
+ writestruct(wd, DATA, "PaintCurvePoint", pc->tot_points, pc->points);
+ if (pc->id.properties) IDP_WriteProperty(pc->id.properties, wd);
}
}
}
@@ -3334,8 +3482,11 @@ static void write_thumb(WriteData *wd, const int *img)
}
/* if MemFile * there's filesave to memory */
-static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFile *current,
- int write_user_block, int write_flags, const int *thumb)
+static int write_file_handle(
+ Main *mainvar,
+ WriteWrap *ww,
+ MemFile *compare, MemFile *current,
+ int write_user_block, int write_flags, const int *thumb)
{
BHead bhead;
ListBase mainlist;
@@ -3344,7 +3495,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
blo_split_main(&mainlist, mainvar);
- wd= bgnwrite(handle, compare, current);
+ wd = bgnwrite(ww, compare, current);
#ifdef USE_BMESH_SAVE_AS_COMPAT
wd->use_mesh_compat = (write_flags & G_FILE_MESH_COMPAT) != 0;
@@ -3396,6 +3547,8 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
write_particlesettings(wd, &mainvar->particle);
write_nodetrees(wd, &mainvar->nodetree);
write_brushes (wd, &mainvar->brush);
+ write_palettes (wd, &mainvar->palettes);
+ write_paintcurves (wd, &mainvar->paintcurves);
write_scripts (wd, &mainvar->script);
write_gpencils (wd, &mainvar->gpencil);
write_linestyles(wd, &mainvar->linestyle);
@@ -3468,7 +3621,9 @@ static bool do_history(const char *name, ReportList *reports)
int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportList *reports, const int *thumb)
{
char tempname[FILE_MAX+1];
- int file, err, write_user_block;
+ int err, write_user_block;
+ eWriteWrapType ww_type;
+ WriteWrap ww;
/* path backup/restore */
void *path_list_backup = NULL;
@@ -3477,8 +3632,16 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
/* open temporary file, so we preserve the original in case we crash */
BLI_snprintf(tempname, sizeof(tempname), "%s@", filepath);
- file = BLI_open(tempname, O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
- if (file == -1) {
+ if (write_flags & G_FILE_COMPRESS) {
+ ww_type = WW_WRAP_ZLIB;
+ }
+ else {
+ ww_type = WW_WRAP_NONE;
+ }
+
+ ww_handle_init(ww_type, &ww);
+
+ if (ww.open(&ww, tempname) == false) {
BKE_reportf(reports, RPT_ERROR, "Cannot open file %s for writing: %s", tempname, strerror(errno));
return 0;
}
@@ -3519,8 +3682,9 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
BKE_bpath_relative_convert(mainvar, filepath, NULL); /* note, making relative to something OTHER then G.main->name */
/* actual file writing */
- err= write_file_handle(mainvar, file, NULL, NULL, write_user_block, write_flags, thumb);
- close(file);
+ err = write_file_handle(mainvar, &ww, NULL, NULL, write_user_block, write_flags, thumb);
+
+ ww.close(&ww);
if (UNLIKELY(path_list_backup)) {
BKE_bpath_list_restore(mainvar, path_list_flag, path_list_backup);
@@ -3544,34 +3708,7 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
}
}
- if (write_flags & G_FILE_COMPRESS) {
- /* compressed files have the same ending as regular files... only from 2.4!!! */
- char gzname[FILE_MAX+4];
- int ret;
-
- /* first write compressed to separate @.gz */
- BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", filepath);
- ret = BLI_file_gzip(tempname, gzname);
-
- if (0==ret) {
- /* now rename to real file name, and delete temp @ file too */
- if (BLI_rename(gzname, filepath) != 0) {
- BKE_report(reports, RPT_ERROR, "Cannot change old file (file saved with @)");
- return 0;
- }
-
- BLI_delete(tempname, false, false);
- }
- else if (-1==ret) {
- BKE_report(reports, RPT_ERROR, "Failed opening .gz file");
- return 0;
- }
- else if (-2==ret) {
- BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression");
- return 0;
- }
- }
- else if (BLI_rename(tempname, filepath) != 0) {
+ if (BLI_rename(tempname, filepath) != 0) {
BKE_report(reports, RPT_ERROR, "Cannot change old file (file saved with @)");
return 0;
}
@@ -3584,7 +3721,7 @@ int BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, int wr
{
int err;
- err= write_file_handle(mainvar, 0, compare, current, 0, write_flags, NULL);
+ err = write_file_handle(mainvar, NULL, compare, current, 0, write_flags, NULL);
if (err==0) return 1;
return 0;
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 2cd256e2346..a43e835f022 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -136,6 +136,8 @@ set(SRC
tools/bmesh_edgenet.h
tools/bmesh_edgesplit.c
tools/bmesh_edgesplit.h
+ tools/bmesh_intersect.c
+ tools/bmesh_intersect.h
tools/bmesh_path.c
tools/bmesh_path.h
tools/bmesh_triangulate.c
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 01745396cd1..39359b97a4e 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -285,8 +285,8 @@ extern void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self);
typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data);
/* defines */
-#define BM_ELEM_CD_SET_INT(ele, offset, f) \
- { assert(offset != -1); *((int *)((char *)(ele)->head.data + (offset))) = (f); } (void)0
+#define BM_ELEM_CD_SET_INT(ele, offset, f) { CHECK_TYPE_NONCONST(ele); \
+ assert(offset != -1); *((int *)((char *)(ele)->head.data + (offset))) = (f); } (void)0
#define BM_ELEM_CD_GET_INT(ele, offset) \
(assert(offset != -1), *((int *)((char *)(ele)->head.data + (offset))))
@@ -294,8 +294,8 @@ typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data);
#define BM_ELEM_CD_GET_VOID_P(ele, offset) \
(assert(offset != -1), (void *)((char *)(ele)->head.data + (offset)))
-#define BM_ELEM_CD_SET_FLOAT(ele, offset, f) \
- { assert(offset != -1); *((float *)((char *)(ele)->head.data + (offset))) = (f); } (void)0
+#define BM_ELEM_CD_SET_FLOAT(ele, offset, f) { CHECK_TYPE_NONCONST(ele); \
+ assert(offset != -1); *((float *)((char *)(ele)->head.data + (offset))) = (f); } (void)0
#define BM_ELEM_CD_GET_FLOAT(ele, offset) \
(assert(offset != -1), *((float *)((char *)(ele)->head.data + (offset))))
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 1c93eccf8bd..1f942dad048 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -62,6 +62,8 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3],
{
BMVert *v = BLI_mempool_alloc(bm->vpool);
+ BLI_assert((v_example == NULL) || (v_example->head.htype == BM_VERT));
+ BLI_assert(!(create_flag & 1));
/* --- assign all members --- */
v->head.data = NULL;
@@ -136,6 +138,8 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2,
BLI_assert(v1 != v2);
BLI_assert(v1->head.htype == BM_VERT && v2->head.htype == BM_VERT);
+ BLI_assert((e_example == NULL) || (e_example->head.htype == BM_EDGE));
+ BLI_assert(!(create_flag & 1));
if ((create_flag & BM_CREATE_NO_DOUBLE) && (e = BM_edge_exists(v1, v2)))
return e;
@@ -191,12 +195,15 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2,
}
static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
- const BMLoop *example, const eBMCreateFlag create_flag)
+ const BMLoop *l_example, const eBMCreateFlag create_flag)
{
BMLoop *l = NULL;
l = BLI_mempool_alloc(bm->lpool);
+ BLI_assert((l_example == NULL) || (l_example->head.htype == BM_LOOP));
+ BLI_assert(!(create_flag & 1));
+
/* --- assign all members --- */
l->head.data = NULL;
@@ -226,8 +233,8 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
bm->totloop++;
if (!(create_flag & BM_CREATE_SKIP_CD)) {
- if (example) {
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data);
+ if (l_example) {
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_example->head.data, &l->head.data);
}
else {
CustomData_bmesh_set_default(&bm->ldata, &l->head.data);
@@ -388,7 +395,10 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
BMFace *f = NULL;
BMLoop *l, *startl, *lastl;
int i;
-
+
+ BLI_assert((f_example == NULL) || (f_example->head.htype == BM_FACE));
+ BLI_assert(!(create_flag & 1));
+
if (len == 0) {
/* just return NULL for now */
return NULL;
@@ -956,54 +966,38 @@ bool bmesh_loop_reverse(BMesh *bm, BMFace *f)
#endif
}
-static void bm_elements_systag_enable(void *veles, int tot, int flag)
+static void bm_elements_systag_enable(void *veles, int tot, const char api_flag)
{
BMHeader **eles = veles;
int i;
for (i = 0; i < tot; i++) {
- BM_ELEM_API_FLAG_ENABLE((BMElemF *)eles[i], flag);
+ BM_ELEM_API_FLAG_ENABLE((BMElemF *)eles[i], api_flag);
}
}
-static void bm_elements_systag_disable(void *veles, int tot, int flag)
+static void bm_elements_systag_disable(void *veles, int tot, const char api_flag)
{
BMHeader **eles = veles;
int i;
for (i = 0; i < tot; i++) {
- BM_ELEM_API_FLAG_DISABLE((BMElemF *)eles[i], flag);
+ BM_ELEM_API_FLAG_DISABLE((BMElemF *)eles[i], api_flag);
}
}
-static int count_flagged_radial(BMesh *bm, BMLoop *l, int flag)
+static int bm_loop_systag_count_radial(BMLoop *l, const char api_flag)
{
- BMLoop *l2 = l;
- int i = 0, c = 0;
-
+ BMLoop *l_iter = l;
+ int i = 0;
do {
- if (UNLIKELY(!l2)) {
- BMESH_ASSERT(0);
- goto error;
- }
-
- i += BM_ELEM_API_FLAG_TEST(l2->f, flag) ? 1 : 0;
- l2 = l2->radial_next;
- if (UNLIKELY(c >= BM_LOOP_RADIAL_MAX)) {
- BMESH_ASSERT(0);
- goto error;
- }
- c++;
- } while (l2 != l);
+ i += BM_ELEM_API_FLAG_TEST(l_iter->f, api_flag) ? 1 : 0;
+ } while ((l_iter = l_iter->radial_next) != l);
return i;
-
-error:
- BMO_error_raise(bm, bm->currentop, BMERR_MESH_ERROR, NULL);
- return 0;
}
-static int UNUSED_FUNCTION(count_flagged_disk)(BMVert *v, int flag)
+static int UNUSED_FUNCTION(bm_vert_systag_count_disk)(BMVert *v, const char api_flag)
{
BMEdge *e = v->e;
int i = 0;
@@ -1012,13 +1006,13 @@ static int UNUSED_FUNCTION(count_flagged_disk)(BMVert *v, int flag)
return 0;
do {
- i += BM_ELEM_API_FLAG_TEST(e, flag) ? 1 : 0;
+ i += BM_ELEM_API_FLAG_TEST(e, api_flag) ? 1 : 0;
} while ((e = bmesh_disk_edge_next(e, v)) != v->e);
return i;
}
-static bool disk_is_flagged(BMVert *v, int flag)
+static bool disk_is_flagged(BMVert *v, const char api_flag)
{
BMEdge *e = v->e;
@@ -1036,7 +1030,7 @@ static bool disk_is_flagged(BMVert *v, int flag)
return false;
do {
- if (!BM_ELEM_API_FLAG_TEST(l->f, flag))
+ if (!BM_ELEM_API_FLAG_TEST(l->f, api_flag))
return false;
} while ((l = l->radial_next) != e->l);
} while ((e = bmesh_disk_edge_next(e, v)) != v->e);
@@ -1093,7 +1087,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
f = faces[i];
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
- int rlen = count_flagged_radial(bm, l_iter, _FLAG_JF);
+ int rlen = bm_loop_systag_count_radial(l_iter, _FLAG_JF);
if (rlen > 2) {
err = N_("Input faces do not form a contiguous manifold region");
@@ -1318,7 +1312,7 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2,
#ifdef USE_BMESH_HOLES
ListBase *holes,
#endif
- BMEdge *example,
+ BMEdge *e_example,
const bool no_double
)
{
@@ -1338,7 +1332,7 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2,
BLI_assert(f == l_v1->f && f == l_v2->f);
/* allocate new edge between v1 and v2 */
- e = BM_edge_create(bm, v1, v2, example, no_double ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP);
+ e = BM_edge_create(bm, v1, v2, e_example, no_double ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP);
f2 = bm_face_create__sfme(bm, f);
l_f1 = bm_loop_create(bm, v2, e, f, l_v2, 0);
@@ -1748,8 +1742,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
l_kill = l_kill->radial_next;
}
for (i = 0; i < radlen; i++) {
- bm->totloop--;
- BLI_mempool_free(bm->lpool, loops[i]);
+ bm_kill_only_loop(bm, loops[i]);
}
}
#ifndef NDEBUG
@@ -1957,6 +1950,44 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
}
/**
+ * Check if splicing vertices would create any double edges.
+ *
+ * \note assume caller will handle case where verts share an edge.
+ */
+bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
+{
+ bool is_double = false;
+
+ BLI_assert(BM_edge_exists(v_a, v_b) == false);
+
+ if (v_a->e && v_b->e) {
+ SmallHash visit;
+ BMEdge *e, *e_first;
+
+ BLI_smallhash_init(&visit);
+
+ e = e_first = v_a->e;
+ do {
+ BMVert *v_other = BM_edge_other_vert(e, v_a);
+ BLI_smallhash_insert(&visit, (uintptr_t)v_other, NULL);
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first);
+
+ e = e_first = v_b->e;
+ do {
+ BMVert *v_other = BM_edge_other_vert(e, v_b);
+ if (BLI_smallhash_haskey(&visit, (uintptr_t)v_other)) {
+ is_double = true;
+ break;
+ }
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_b)) != e_first);
+
+ BLI_smallhash_release(&visit);
+ }
+
+ return is_double;
+}
+
+/**
* \brief Splice Vert
*
* Merges two verts into one (\a v into \a vtarget).
@@ -1969,10 +2000,6 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
*/
bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
{
- void *loops_stack[BM_DEFAULT_ITER_STACK_SIZE];
- BMLoop **loops;
- int i, loops_tot;
-
BMEdge *e;
/* verts already spliced */
@@ -1980,21 +2007,25 @@ bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
return false;
}
- /* we can't modify the vert while iterating so first allocate an array of loops */
- loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot,
- loops_stack, BM_DEFAULT_ITER_STACK_SIZE);
-
- if (LIKELY(loops != NULL)) {
- for (i = 0; i < loops_tot; i++) {
- loops[i]->v = v_target;
- }
- if (loops != (BMLoop **)loops_stack) {
- MEM_freeN(loops);
- }
- }
+ BLI_assert(BM_vert_pair_share_face_check(v, v_target) == false);
/* move all the edges from v's disk to vtarget's disk */
while ((e = v->e)) {
+
+ /* loop */
+ BMLoop *l_first;
+ if ((l_first = e->l)) {
+ BMLoop *l_iter = l_first;
+ do {
+ if (l_iter->v == v) {
+ l_iter->v = v_target;
+ }
+ /* else if (l_iter->prev->v == v) {...}
+ * (this case will be handled by a different edge) */
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ /* disk */
bmesh_disk_edge_remove(e, v);
bmesh_edge_swapverts(e, v, v_target);
bmesh_disk_edge_append(e, v_target);
@@ -2048,15 +2079,16 @@ void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len
/* Considering only edges and faces incident on vertex v, walk
* the edges & faces and assign an index to each connected set */
+ BLI_smallhash_insert(&visithash, (uintptr_t)e, SET_INT_IN_POINTER(maxindex));
do {
- BLI_smallhash_insert(&visithash, (uintptr_t)e, SET_INT_IN_POINTER(maxindex));
-
if (e->l) {
BMLoop *l_iter, *l_first;
l_iter = l_first = e->l;
do {
l_new = (l_iter->v == v) ? l_iter->prev : l_iter->next;
+ BLI_assert(BM_vert_in_edge(l_new->e, v));
if (!BLI_smallhash_haskey(&visithash, (uintptr_t)l_new->e)) {
+ BLI_smallhash_insert(&visithash, (uintptr_t)l_new->e, SET_INT_IN_POINTER(maxindex));
STACK_PUSH(stack, l_new->e);
}
} while ((l_iter = l_iter->radial_next) != l_first);
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index 4a2b4b7feca..ab847fc82eb 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -61,6 +61,7 @@ void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep,
const bool copy_select);
bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target);
bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target);
+bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b);
void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
const bool copy_select);
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c
index f01e1197bb7..e83a1d5b00a 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.c
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.c
@@ -682,12 +682,12 @@ void BM_edgeloop_expand(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store, int el_sto
LinkData *node_curr_init = node_curr;
LinkData *node_curr_copy;
int i = 0;
- LISTBASE_CIRCULAR_FORWARD_BEGIN (&el_store->verts, node_curr, node_curr_init) {
+ BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN (&el_store->verts, node_curr, node_curr_init) {
if (i++ < step) {
break;
}
}
- LISTBASE_CIRCULAR_FORWARD_END (&el_store->verts, node_curr, node_curr_init);
+ BLI_LISTBASE_CIRCULAR_FORWARD_END (&el_store->verts, node_curr, node_curr_init);
node_curr_copy = MEM_dupallocN(node_curr);
BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index 2250b8135d7..306b6e74350 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -397,8 +397,8 @@ static float bm_loop_flip_equotion(float mat[2][2], float b[2], const float targ
return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0];
}
-static void bm_loop_flip_disp(float source_axis_x[3], float source_axis_y[3],
- float target_axis_x[3], float target_axis_y[3], float disp[3])
+static void bm_loop_flip_disp(const float source_axis_x[3], const float source_axis_y[3],
+ const float target_axis_x[3], const float target_axis_y[3], float disp[3])
{
float vx[3], vy[3], coord[3];
float n[3], vec[3];
diff --git a/source/blender/bmesh/intern/bmesh_interp.h b/source/blender/bmesh/intern/bmesh_interp.h
index 2a3b5190ece..c605ad31ae7 100644
--- a/source/blender/bmesh/intern/bmesh_interp.h
+++ b/source/blender/bmesh/intern/bmesh_interp.h
@@ -33,9 +33,9 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source);
void BM_data_interp_from_verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, const float fac);
void BM_data_interp_from_edges(BMesh *bm, BMEdge *e1, BMEdge *e2, BMEdge *e, const float fac);
void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, BMEdge *e1, const float fac);
-void BM_data_layer_add(BMesh *em, CustomData *data, int type);
+void BM_data_layer_add(BMesh *bm, CustomData *data, int type);
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name);
-void BM_data_layer_free(BMesh *em, CustomData *data, int type);
+void BM_data_layer_free(BMesh *bm, CustomData *data, int type);
void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n);
void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n);
diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h
index 6a0eb0e0a30..b9733d4702f 100644
--- a/source/blender/bmesh/intern/bmesh_iterators_inline.h
+++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h
@@ -80,60 +80,70 @@ BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *da
break;
case BM_EDGES_OF_VERT:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
iter->begin = (BMIter__begin_cb)bmiter__edge_of_vert_begin;
iter->step = (BMIter__step_cb)bmiter__edge_of_vert_step;
iter->data.edge_of_vert.vdata = (BMVert *)data;
break;
case BM_FACES_OF_VERT:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
iter->begin = (BMIter__begin_cb)bmiter__face_of_vert_begin;
iter->step = (BMIter__step_cb)bmiter__face_of_vert_step;
iter->data.face_of_vert.vdata = (BMVert *)data;
break;
case BM_LOOPS_OF_VERT:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
iter->begin = (BMIter__begin_cb)bmiter__loop_of_vert_begin;
iter->step = (BMIter__step_cb)bmiter__loop_of_vert_step;
iter->data.loop_of_vert.vdata = (BMVert *)data;
break;
case BM_VERTS_OF_EDGE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
iter->begin = (BMIter__begin_cb)bmiter__vert_of_edge_begin;
iter->step = (BMIter__step_cb)bmiter__vert_of_edge_step;
iter->data.vert_of_edge.edata = (BMEdge *)data;
break;
case BM_FACES_OF_EDGE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
iter->begin = (BMIter__begin_cb)bmiter__face_of_edge_begin;
iter->step = (BMIter__step_cb)bmiter__face_of_edge_step;
iter->data.face_of_edge.edata = (BMEdge *)data;
break;
case BM_VERTS_OF_FACE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
iter->begin = (BMIter__begin_cb)bmiter__vert_of_face_begin;
iter->step = (BMIter__step_cb)bmiter__vert_of_face_step;
iter->data.vert_of_face.pdata = (BMFace *)data;
break;
case BM_EDGES_OF_FACE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
iter->begin = (BMIter__begin_cb)bmiter__edge_of_face_begin;
iter->step = (BMIter__step_cb)bmiter__edge_of_face_step;
iter->data.edge_of_face.pdata = (BMFace *)data;
break;
case BM_LOOPS_OF_FACE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
iter->begin = (BMIter__begin_cb)bmiter__loop_of_face_begin;
iter->step = (BMIter__step_cb)bmiter__loop_of_face_step;
iter->data.loop_of_face.pdata = (BMFace *)data;
break;
case BM_LOOPS_OF_LOOP:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_LOOP);
iter->begin = (BMIter__begin_cb)bmiter__loop_of_loop_begin;
iter->step = (BMIter__step_cb)bmiter__loop_of_loop_step;
iter->data.loop_of_loop.ldata = (BMLoop *)data;
break;
case BM_LOOPS_OF_EDGE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
iter->begin = (BMIter__begin_cb)bmiter__loop_of_edge_begin;
iter->step = (BMIter__step_cb)bmiter__loop_of_edge_step;
iter->data.loop_of_edge.edata = (BMEdge *)data;
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index e23a5721234..19e6f646564 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -864,7 +864,9 @@ void BM_select_history_validate(BMesh *bm)
}
}
-/* utility function */
+/**
+ * Get the active mesh element (with active-face fallback).
+ */
bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
{
BMEditSelection *ese_last = bm->selected.last;
@@ -887,7 +889,8 @@ bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
ese->htype = ese_last->htype;
}
}
- else if (efa) { /* no */
+ else if (efa) {
+ /* no edit-selection, fallback to active face */
ese->ele = (BMElem *)efa;
ese->htype = BM_FACE;
}
@@ -899,6 +902,27 @@ bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
return true;
}
+/**
+ * Return a map from BMVert/Edge/Face -> BMEditSelection
+ */
+GHash *BM_select_history_map_create(BMesh *bm)
+{
+ BMEditSelection *ese;
+ GHash *map;
+
+ if (BLI_listbase_is_empty(&bm->selected)) {
+ return NULL;
+ }
+
+ map = BLI_ghash_ptr_new(__func__);
+
+ for (ese = bm->selected.first; ese; ese = ese->next) {
+ BLI_ghash_insert(map, ese->ele, ese);
+ }
+
+ return map;
+}
+
void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag,
const bool respecthide, const bool overwrite, const char hflag_test)
{
diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h
index 99456ea2c98..9e0c0923164 100644
--- a/source/blender/bmesh/intern/bmesh_marking.h
+++ b/source/blender/bmesh/intern/bmesh_marking.h
@@ -98,7 +98,14 @@ void _bm_select_history_store_after(BMesh *bm, BMEditSelection *ese_ref, BMHead
void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele);
void BM_select_history_validate(BMesh *bm);
-void BM_select_history_clear(BMesh *em);
+void BM_select_history_clear(BMesh *bm);
bool BM_select_history_active_get(BMesh *bm, struct BMEditSelection *ese);
+struct GHash *BM_select_history_map_create(BMesh *bm);
+
+#define BM_SELECT_HISTORY_BACKUP(bm) { \
+ ListBase _bm_prev_selected = (bm)->selected; BLI_listbase_clear(&(bm)->selected)
+
+#define BM_SELECT_HISTORY_RESTORE(bm) \
+ (bm)->selected = _bm_prev_selected; } (void)0
#endif /* __BMESH_MARKING_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index e66d1263578..b16ea42304a 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -641,11 +641,13 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, const float (*vcos)[3], const
copy_v3_v3(nor, lnor);
}
}
+ else {
+ /* We still have to clear the stack! */
+ while (BLI_SMALLSTACK_POP(normal));
+ }
}
} while ((l_curr = l_curr->next) != l_first);
}
-
- BLI_SMALLSTACK_FREE(normal);
}
#if 0 /* Unused currently */
@@ -764,6 +766,8 @@ void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag))
*/
void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
{
+ ListBase select_history;
+
/* BMO_OPTYPE_FLAG_UNTAN_MULTIRES disabled for now, see comment above in bmesh_edit_begin. */
#ifdef BMOP_UNTAN_MULTIRES_ENABLED
/* switch multires data into tangent space */
@@ -782,9 +786,19 @@ void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
BM_mesh_normals_update(bm);
}
+
+ if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) {
+ select_history = bm->selected;
+ BLI_listbase_clear(&bm->selected);
+ }
+
if (type_flag & BMO_OPTYPE_FLAG_SELECT_FLUSH) {
BM_mesh_select_mode_flush(bm);
}
+
+ if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) {
+ bm->selected = select_history;
+ }
}
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
@@ -800,7 +814,7 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
}
/* skip if we only need to operate on one element */
-#pragma omp parallel sections if ((!ELEM5(htype_needed, BM_VERT, BM_EDGE, BM_FACE, BM_LOOP, BM_FACE | BM_LOOP)) && \
+#pragma omp parallel sections if ((!ELEM(htype_needed, BM_VERT, BM_EDGE, BM_FACE, BM_LOOP, BM_FACE | BM_LOOP)) && \
(bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT))
{
#pragma omp section
@@ -1054,7 +1068,7 @@ void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
}
/* skip if we only need to operate on one element */
-#pragma omp parallel sections if ((!ELEM3(htype_needed, BM_VERT, BM_EDGE, BM_FACE)) && \
+#pragma omp parallel sections if ((!ELEM(htype_needed, BM_VERT, BM_EDGE, BM_FACE)) && \
(bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT))
{
#pragma omp section
@@ -1179,7 +1193,11 @@ int BM_mesh_elem_count(BMesh *bm, const char htype)
*
* WARNING: Be careful if you keep pointers to affected BM elements, or arrays, when using this func!
*/
-void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, unsigned int *face_idx)
+void BM_mesh_remap(
+ BMesh *bm,
+ const unsigned int *vert_idx,
+ const unsigned int *edge_idx,
+ const unsigned int *face_idx)
{
/* Mapping old to new pointers. */
GHash *vptr_map = NULL, *eptr_map = NULL, *fptr_map = NULL;
@@ -1192,18 +1210,23 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
if (!(vert_idx || edge_idx || face_idx))
return;
+ BM_mesh_elem_table_ensure(
+ bm,
+ (vert_idx ? BM_VERT : 0) |
+ (edge_idx ? BM_EDGE : 0) |
+ (face_idx ? BM_FACE : 0));
+
/* Remap Verts */
if (vert_idx) {
BMVert **verts_pool, *verts_copy, **vep;
int i, totvert = bm->totvert;
- unsigned int *new_idx = NULL;
+ const unsigned int *new_idx;
/* Init the old-to-new vert pointers mapping */
vptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap vert pointers mapping", bm->totvert);
/* Make a copy of all vertices. */
- verts_pool = MEM_callocN(sizeof(BMVert *) * totvert, "BM_mesh_remap verts pool");
- BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)verts_pool, totvert);
+ verts_pool = bm->vtable;
verts_copy = MEM_mallocN(sizeof(BMVert) * totvert, "BM_mesh_remap verts copy");
for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--; ve--, vep--) {
*ve = **vep;
@@ -1221,8 +1244,8 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
BLI_ghash_insert(vptr_map, (void *)*vep, (void *)new_vep);
}
bm->elem_index_dirty |= BM_VERT;
+ bm->elem_table_dirty |= BM_VERT;
- MEM_freeN(verts_pool);
MEM_freeN(verts_copy);
}
@@ -1230,14 +1253,13 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
if (edge_idx) {
BMEdge **edges_pool, *edges_copy, **edp;
int i, totedge = bm->totedge;
- unsigned int *new_idx = NULL;
+ const unsigned int *new_idx;
/* Init the old-to-new vert pointers mapping */
eptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap edge pointers mapping", bm->totedge);
/* Make a copy of all vertices. */
- edges_pool = MEM_callocN(sizeof(BMEdge *) * totedge, "BM_mesh_remap edges pool");
- BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)edges_pool, totedge);
+ edges_pool = bm->etable;
edges_copy = MEM_mallocN(sizeof(BMEdge) * totedge, "BM_mesh_remap edges copy");
for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--; ed--, edp--) {
*ed = **edp;
@@ -1254,8 +1276,8 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
/* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/
}
bm->elem_index_dirty |= BM_EDGE;
+ bm->elem_table_dirty |= BM_EDGE;
- MEM_freeN(edges_pool);
MEM_freeN(edges_copy);
}
@@ -1263,14 +1285,13 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
if (face_idx) {
BMFace **faces_pool, *faces_copy, **fap;
int i, totface = bm->totface;
- unsigned int *new_idx = NULL;
+ const unsigned int *new_idx;
/* Init the old-to-new vert pointers mapping */
fptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap face pointers mapping", bm->totface);
/* Make a copy of all vertices. */
- faces_pool = MEM_callocN(sizeof(BMFace *) * totface, "BM_mesh_remap faces pool");
- BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)faces_pool, totface);
+ faces_pool = bm->ftable;
faces_copy = MEM_mallocN(sizeof(BMFace) * totface, "BM_mesh_remap faces copy");
for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--; fa--, fap--) {
*fa = **fap;
@@ -1287,8 +1308,8 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
}
bm->elem_index_dirty |= BM_FACE | BM_LOOP;
+ bm->elem_table_dirty |= BM_FACE;
- MEM_freeN(faces_pool);
MEM_freeN(faces_copy);
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 3923c2515a3..22e50502aee 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -50,7 +50,7 @@ void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *fu
const char *msg_a, const char *msg_b);
#ifndef NDEBUG
-bool BM_mesh_elem_table_check(BMesh *em);
+bool BM_mesh_elem_table_check(BMesh *bm);
#endif
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype);
@@ -69,7 +69,11 @@ BMFace *BM_face_at_index_find(BMesh *bm, const int index);
int BM_mesh_elem_count(BMesh *bm, const char htype);
-void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, unsigned int *face_idx);
+void BM_mesh_remap(
+ BMesh *bm,
+ const unsigned int *vert_idx,
+ const unsigned int *edge_idx,
+ const unsigned int *face_idx);
typedef struct BMAllocTemplate {
int totvert, totedge, totloop, totface;
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 2d7a2cf93d6..6e8591da0f3 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -32,12 +32,19 @@
#include "BLI_math.h"
#include "BLI_array.h"
+#include "BLI_alloca.h"
+#include "BLI_stackdefines.h"
+#include "BLI_linklist_stack.h"
+#include "BLI_sort_utils.h"
#include "BKE_customdata.h"
#include "bmesh.h"
#include "intern/bmesh_private.h"
+// #define DEBUG_PRINT
+
+
/**
* \brief Dissolve Vert
*
@@ -416,6 +423,547 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f,
return f_new;
}
+
+/* -------------------------------------------------------------------- */
+/* Face Split Edge-Net */
+
+/** \name BM_face_split_edgenet and helper functions.
+ *
+ * \note Don't use #BM_edge_is_wire or #BM_edge_is_boundary
+ * since we need to take flagged faces into account.
+ * Also take care accessing e->l directly.
+ *
+ * \{ */
+
+/* Note: All these flags _must_ be cleared on exit */
+
+/* face is apart of the edge-net (including the original face we're splitting) */
+#define FACE_NET _FLAG_WALK
+/* edge is apart of the edge-net we're filling */
+#define EDGE_NET _FLAG_WALK
+/* tag verts we've visit */
+#define VERT_VISIT _FLAG_WALK
+
+struct VertOrder {
+ float angle;
+ BMVert *v;
+};
+
+static unsigned int bm_edge_flagged_radial_count(BMEdge *e)
+{
+ unsigned int count = 0;
+ BMLoop *l;
+
+ if ((l = e->l)) {
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) {
+ count++;
+ }
+ } while ((l = l->radial_next) != e->l);
+ }
+ return count;
+}
+
+static BMLoop *bm_edge_flagged_radial_first(BMEdge *e)
+{
+ BMLoop *l;
+
+ if ((l = e->l)) {
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) {
+ return l;
+ }
+ } while ((l = l->radial_next) != e->l);
+ }
+ return NULL;
+}
+
+static bool bm_face_split_edgenet_find_loop_pair(
+ BMVert *v_init, const float face_normal[3],
+ BMEdge *e_pair[2])
+{
+ /* Always find one boundary edge (to determine winding)
+ * and one wire (if available), otherwise another boundary.
+ */
+ BMIter iter;
+ BMEdge *e;
+
+ /* detect winding */
+ BMLoop *l_walk;
+ bool swap;
+
+ BLI_SMALLSTACK_DECLARE(edges_boundary, BMEdge *);
+ BLI_SMALLSTACK_DECLARE(edges_wire, BMEdge *);
+ int edges_boundary_len = 0;
+ int edges_wire_len = 0;
+
+ BM_ITER_ELEM (e, &iter, v_init, BM_EDGES_OF_VERT) {
+ if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) {
+ const unsigned int count = bm_edge_flagged_radial_count(e);
+ if (count == 1) {
+ BLI_SMALLSTACK_PUSH(edges_boundary, e);
+ edges_boundary_len++;
+ }
+ else if (count == 0) {
+ BLI_SMALLSTACK_PUSH(edges_wire, e);
+ edges_wire_len++;
+ }
+ }
+ }
+
+ /* first edge should always be boundary */
+ if (edges_boundary_len == 0) {
+ return false;
+ }
+ e_pair[0] = BLI_SMALLSTACK_POP(edges_boundary);
+
+ /* attempt one boundary and one wire, or 2 boundary */
+ if (edges_wire_len == 0) {
+ if (edges_boundary_len >= 2) {
+ e_pair[1] = BLI_SMALLSTACK_POP(edges_boundary);
+ }
+ else {
+ /* one boundary and no wire */
+ return false;
+ }
+ }
+ else {
+ e_pair[1] = BLI_SMALLSTACK_POP(edges_wire);
+
+ if (edges_wire_len > 1) {
+ BMVert *v_prev = BM_edge_other_vert(e_pair[0], v_init);
+ BMVert *v_next;
+ float angle_best;
+
+ v_next = BM_edge_other_vert(e_pair[1], v_init);
+ angle_best = angle_on_axis_v3v3v3_v3(v_prev->co, v_init->co, v_next->co, face_normal);
+
+ while ((e = BLI_SMALLSTACK_POP(edges_wire))) {
+ float angle_test;
+ v_next = BM_edge_other_vert(e, v_init);
+ angle_test = angle_on_axis_v3v3v3_v3(v_prev->co, v_init->co, v_next->co, face_normal);
+ if (angle_test < angle_best) {
+ angle_best = angle_test;
+ e_pair[1] = e;
+ }
+ }
+ }
+ }
+
+
+ /* flip based on winding */
+ l_walk = bm_edge_flagged_radial_first(e_pair[0]);
+ swap = false;
+ if (face_normal == l_walk->f->no) {
+ swap = !swap;
+ }
+ if (l_walk->v != v_init) {
+ swap = !swap;
+ }
+ if (swap) {
+ SWAP(BMEdge *, e_pair[0], e_pair[1]);
+ }
+
+ return true;
+}
+
+static bool bm_face_split_edgenet_find_loop_walk(
+ BMVert *v_init, const float face_normal[3],
+ /* cache to avoid realloc every time */
+ struct VertOrder *edge_order, const unsigned int edge_order_len,
+ BMEdge *e_pair[2])
+{
+ /* fast-path for the common case (avoid push-pop).
+ * Also avoids tagging as visited since we know we
+ * can't reach these verts some other way */
+#define USE_FASTPATH_NOFORK
+
+ BMVert *v;
+ BMVert *v_dst;
+ bool found = false;
+
+ struct VertOrder *eo;
+ STACK_DECLARE(edge_order);
+
+ /* store visited verts so we can clear the visit flag after execution */
+ BLI_SMALLSTACK_DECLARE(vert_visit, BMVert *);
+
+ /* likely this will stay very small
+ * all verts pushed into this stack _must_ have their previous edges set! */
+ BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *);
+ BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *);
+
+ STACK_INIT(edge_order, edge_order_len);
+
+ /* start stepping */
+ v = BM_edge_other_vert(e_pair[0], v_init);
+ v->e = e_pair[0];
+ BLI_SMALLSTACK_PUSH(vert_stack, v);
+
+ v_dst = BM_edge_other_vert(e_pair[1], v_init);
+
+#ifdef DEBUG_PRINT
+ printf("%s: vert (search) %d\n", __func__, BM_elem_index_get(v_init));
+#endif
+
+ /* This loop will keep stepping over the best possible edge,
+ * in most cases it finds the direct route to close the face.
+ *
+ * In cases where paths can't be closed,
+ * alternatives are stored in the 'vert_stack'.
+ */
+ while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) {
+ BMIter eiter;
+ BMEdge *e_next;
+
+#ifdef USE_FASTPATH_NOFORK
+walk_nofork:
+#else
+ BLI_SMALLSTACK_PUSH(vert_visit, v);
+ BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
+#endif
+
+ BLI_assert(STACK_SIZE(edge_order) == 0);
+
+ /* check if we're done! */
+ if (v == v_dst) {
+ found = true;
+ goto finally;
+ }
+
+ BM_ITER_ELEM (e_next, &eiter, v, BM_EDGES_OF_VERT) {
+ if ((v->e != e_next) &&
+ (BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) &&
+ (bm_edge_flagged_radial_count(e_next) < 2))
+ {
+ BMVert *v_next;
+
+ v_next = BM_edge_other_vert(e_next, v);
+
+#ifdef DEBUG_PRINT
+ /* indent and print */
+ {
+ BMVert *_v = v;
+ do {
+ printf(" ");
+ } while ((_v = BM_edge_other_vert(_v->e, _v)) != v_init);
+ printf("vert %d -> %d (add=%d)\n",
+ BM_elem_index_get(v), BM_elem_index_get(v_next),
+ BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT) == 0);
+ }
+#endif
+
+ if (!BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT)) {
+ eo = STACK_PUSH_RET_PTR(edge_order);
+ eo->v = v_next;
+
+ v_next->e = e_next;
+ }
+ }
+ }
+
+#ifdef USE_FASTPATH_NOFORK
+ if (STACK_SIZE(edge_order) == 1) {
+ eo = STACK_POP_PTR(edge_order);
+ v = eo->v;
+
+ goto walk_nofork;
+ }
+#endif
+
+ /* sort by angle if needed */
+ if (STACK_SIZE(edge_order) > 1) {
+ unsigned int j;
+ BMVert *v_prev = BM_edge_other_vert(v->e, v);
+
+ for (j = 0; j < STACK_SIZE(edge_order); j++) {
+ edge_order[j].angle = angle_signed_on_axis_v3v3v3_v3(v_prev->co, v->co, edge_order[j].v->co, face_normal);
+ }
+ qsort(edge_order, STACK_SIZE(edge_order), sizeof(struct VertOrder), BLI_sortutil_cmp_float_reverse);
+
+#ifdef USE_FASTPATH_NOFORK
+ /* only tag forks */
+ BLI_SMALLSTACK_PUSH(vert_visit, v);
+ BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
+#endif
+ }
+
+ while ((eo = STACK_POP_PTR(edge_order))) {
+ BLI_SMALLSTACK_PUSH(vert_stack_next, eo->v);
+ }
+
+ if (!BLI_SMALLSTACK_IS_EMPTY(vert_stack_next)) {
+ BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next);
+ }
+ }
+
+
+finally:
+ /* clear flag for next execution */
+ while ((v = BLI_SMALLSTACK_POP(vert_visit))) {
+ BM_ELEM_API_FLAG_DISABLE(v, VERT_VISIT);
+ }
+
+ return found;
+
+#undef USE_FASTPATH_NOFORK
+}
+
+static bool bm_face_split_edgenet_find_loop(
+ BMVert *v_init, const float face_normal[3],
+ /* cache to avoid realloc every time */
+ struct VertOrder *edge_order, const unsigned int edge_order_len,
+ BMVert **r_face_verts, int *r_face_verts_len)
+{
+ BMEdge *e_pair[2];
+ BMVert *v;
+
+ if (!bm_face_split_edgenet_find_loop_pair(v_init, face_normal, e_pair)) {
+ return false;
+ }
+
+ BLI_assert((bm_edge_flagged_radial_count(e_pair[0]) == 1) ||
+ (bm_edge_flagged_radial_count(e_pair[1]) == 1));
+
+ if (bm_face_split_edgenet_find_loop_walk(v_init, face_normal, edge_order, edge_order_len, e_pair)) {
+ unsigned int i = 0;
+
+ r_face_verts[i++] = v_init;
+ v = BM_edge_other_vert(e_pair[1], v_init);
+ do {
+ r_face_verts[i++] = v;
+ } while ((v = BM_edge_other_vert(v->e, v)) != v_init);
+ *r_face_verts_len = i;
+ return (i > 2) ? true : false;
+ }
+ else {
+ return false;
+ }
+}
+
+/**
+ * Splits a face into many smaller faces defined by an edge-net.
+ * handle customdata and degenerate cases.
+ *
+ * - isolated holes or unsupported face configurations, will be ignored.
+ * - customdata calculations aren't efficient
+ * (need to calculate weights for each vert).
+ */
+bool BM_face_split_edgenet(
+ BMesh *bm,
+ BMFace *f, BMEdge **edge_net, const int edge_net_len,
+ BMFace ***r_face_arr, int *r_face_arr_len)
+{
+ /* re-use for new face verts */
+ BMVert **face_verts;
+ int face_verts_len;
+
+ BMFace **face_arr = NULL;
+ BLI_array_declare(face_arr);
+
+ BMVert **vert_queue;
+ STACK_DECLARE(vert_queue);
+ int i;
+
+ struct VertOrder *edge_order;
+ const unsigned int edge_order_len = edge_net_len + 2;
+
+ BMVert *v;
+
+ BMLoop *l_iter, *l_first;
+
+
+ if (!edge_net_len) {
+ if (r_face_arr) {
+ *r_face_arr = NULL;
+ *r_face_arr_len = 0;
+ }
+ return false;
+ }
+
+ /* over-alloc (probably 2-4 is only used in most cases), for the biggest-fan */
+ edge_order = BLI_array_alloca(edge_order, edge_order_len);
+
+ /* use later */
+ face_verts = BLI_array_alloca(face_verts, edge_net_len + f->len);
+
+ vert_queue = BLI_array_alloca(vert_queue, edge_net_len + f->len);
+ STACK_INIT(vert_queue, f->len + edge_net_len);
+
+ BLI_assert(BM_ELEM_API_FLAG_TEST(f, FACE_NET) == 0);
+ BM_ELEM_API_FLAG_ENABLE(f, FACE_NET);
+
+#ifdef DEBUG
+ for (i = 0; i < edge_net_len; i++) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET) == 0);
+ BLI_assert(BM_edge_in_face(edge_net[i], f) == false);
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter->e, EDGE_NET) == 0);
+ } while ((l_iter = l_iter->next) != l_first);
+#endif
+
+
+ for (i = 0; i < edge_net_len; i++) {
+ BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET);
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET);
+ } while ((l_iter = l_iter->next) != l_first);
+
+
+ /* any vert can be used to begin with */
+ STACK_PUSH(vert_queue, l_first->v);
+
+ while ((v = STACK_POP(vert_queue))) {
+ if (bm_face_split_edgenet_find_loop(v, f->no, edge_order, edge_order_len, face_verts, &face_verts_len)) {
+ BMFace *f_new;
+
+ f_new = BM_face_create_verts(bm, face_verts, face_verts_len, f, BM_CREATE_NOP, false);
+
+ for (i = 0; i < edge_net_len; i++) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET));
+ }
+
+ if (f_new) {
+ bool l_prev_is_boundary;
+ BLI_array_append(face_arr, f_new);
+ copy_v3_v3(f_new->no, f->no);
+
+ BM_ELEM_API_FLAG_ENABLE(f_new, FACE_NET);
+
+ /* add new verts to keep finding loops for
+ * (verts between boundary and manifold edges) */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
+ l_prev_is_boundary = (bm_edge_flagged_radial_count(l_iter->prev->e) == 1);
+ do {
+ bool l_iter_is_boundary = (bm_edge_flagged_radial_count(l_iter->e) == 1);
+ if (l_prev_is_boundary != l_iter_is_boundary) {
+ STACK_PUSH(vert_queue, l_iter->v);
+ }
+ l_prev_is_boundary = l_iter_is_boundary;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ }
+
+
+ if (CustomData_has_math(&bm->ldata)) {
+ /* reuse VERT_VISIT here to tag vert's already interpolated */
+ BMIter iter;
+ BMLoop *l_other;
+
+ /* see: #BM_loop_interp_from_face for similar logic */
+ void **blocks = BLI_array_alloca(blocks, f->len);
+ float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f->len);
+ float *w = BLI_array_alloca(w, f->len);
+ float axis_mat[3][3];
+ float co[2];
+
+ /* interior loops */
+ axis_dominant_v3_to_m3(axis_mat, f->no);
+
+
+ /* first simply copy from existing face */
+ i = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ITER_ELEM (l_other, &iter, l_iter->v, BM_LOOPS_OF_VERT) {
+ if ((l_other->f != f) && BM_ELEM_API_FLAG_TEST(l_other->f, FACE_NET)) {
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata,
+ l_iter->head.data, &l_other->head.data);
+ }
+ }
+ /* tag not to interpolate */
+ BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_VISIT);
+
+
+ mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
+ blocks[i] = l_iter->head.data;
+
+ } while (i++, (l_iter = l_iter->next) != l_first);
+
+
+ for (i = 0; i < edge_net_len; i++) {
+ BM_ITER_ELEM (v, &iter, edge_net[i], BM_VERTS_OF_EDGE) {
+ if (!BM_ELEM_API_FLAG_TEST(v, VERT_VISIT)) {
+ BMIter liter;
+
+ BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
+
+ /* interpolate this loop, then copy to the rest */
+ l_first = NULL;
+
+ BM_ITER_ELEM (l_iter, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->f, FACE_NET)) {
+ if (l_first == NULL) {
+ mul_v2_m3v3(co, axis_mat, v->co);
+ interp_weights_poly_v2(w, cos_2d, f->len, co);
+ CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, f->len, l_iter->head.data);
+ l_first = l_iter;
+ }
+ else {
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata,
+ l_first->head.data, &l_iter->head.data);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+
+ /* cleanup */
+ for (i = 0; i < edge_net_len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i], EDGE_NET);
+ /* from interp only */
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_VISIT);
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ELEM_API_FLAG_DISABLE(l_iter->e, EDGE_NET);
+ /* from interp only */
+ BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_VISIT);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (BLI_array_count(face_arr)) {
+ bmesh_face_swap_data(f, face_arr[0]);
+ BM_face_kill(bm, face_arr[0]);
+ face_arr[0] = f;
+ }
+ else {
+ BM_ELEM_API_FLAG_DISABLE(f, FACE_NET);
+ }
+
+ for (i = 0; i < BLI_array_count(face_arr); i++) {
+ BM_ELEM_API_FLAG_DISABLE(face_arr[i], FACE_NET);
+ }
+
+ if (r_face_arr) {
+ *r_face_arr = face_arr;
+ *r_face_arr_len = BLI_array_count(face_arr);
+ }
+ else {
+ if (face_arr) {
+ MEM_freeN(face_arr);
+ }
+ }
+
+ return true;
+}
+
+#undef FACE_NET
+#undef VERT_VISIT
+#undef EDGE_NET
+
+/** \} */
+
+
/**
* \brief Vert Collapse Faces
*
@@ -589,22 +1137,32 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
/**
* \brief Edge Split
*
- * Splits an edge. \a v should be one of the vertices in \a e and defines
- * the "from" end of the splitting operation: the new vertex will be
- * \a percent of the way from \a v to the other end.
- * The newly created edge is attached to \a v and is returned in \a r_e.
- * The original edge \a e will be the other half of the split.
+ * <pre>
+ * Before: v
+ * +-----------------------------------+
+ * e
+ *
+ * After: v v_new (returned)
+ * +-----------------+-----------------+
+ * r_e e
+ * </pre>
*
- * \return The new vert
+ * \param e The edge to split.
+ * \param v One of the vertices in \a e and defines the the "from" end of the splitting operation,
+ * the new vertex will be \a fac of the way from \a v to the other end.
+ * \param r_e The newly created edge.
+ * \return The new vertex.
*/
-BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent)
+BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
{
- BMVert *v_new, *v2;
+ BMVert *v_new, *v_other;
BMFace **oldfaces = NULL;
BMEdge *e_dummy;
BLI_array_staticdeclare(oldfaces, 32);
const bool do_mdisp = (e->l && CustomData_has_layer(&bm->ldata, CD_MDISPS));
+ BLI_assert(BM_vert_in_edge(e, v) == true);
+
/* we need this for handling multi-res */
if (!r_e) {
r_e = &e_dummy;
@@ -629,22 +1187,22 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce
}
}
- v2 = BM_edge_other_vert(e, v);
+ v_other = BM_edge_other_vert(e, v);
v_new = bmesh_semv(bm, v, e, r_e);
BLI_assert(v_new != NULL);
+ BLI_assert(BM_vert_in_edge(*r_e, v) && BM_vert_in_edge(*r_e, v_new));
+ BLI_assert(BM_vert_in_edge(e, v_new) && BM_vert_in_edge(e, v_other));
- sub_v3_v3v3(v_new->co, v2->co, v->co);
- madd_v3_v3v3fl(v_new->co, v->co, v_new->co, percent);
+ sub_v3_v3v3(v_new->co, v_other->co, v->co);
+ madd_v3_v3v3fl(v_new->co, v->co, v_new->co, fac);
- if (r_e) {
- (*r_e)->head.hflag = e->head.hflag;
- BM_elem_attrs_copy(bm, bm, e, *r_e);
- }
+ (*r_e)->head.hflag = e->head.hflag;
+ BM_elem_attrs_copy(bm, bm, e, *r_e);
/* v->v_new->v2 */
- BM_data_interp_face_vert_edge(bm, v2, v, v_new, e, percent);
- BM_data_interp_from_verts(bm, v, v2, v_new, percent);
+ BM_data_interp_face_vert_edge(bm, v_other, v, v_new, e, fac);
+ BM_data_interp_from_verts(bm, v, v_other, v_new, fac);
if (do_mdisp) {
int i, j;
diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h
index 7c81e6b750e..59aee323bba 100644
--- a/source/blender/bmesh/intern/bmesh_mods.h
+++ b/source/blender/bmesh/intern/bmesh_mods.h
@@ -45,6 +45,10 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f,
float cos[][3], int n,
BMLoop **r_l, BMEdge *example);
+bool BM_face_split_edgenet(BMesh *bm, BMFace *f,
+ BMEdge **edge_net, const int edge_net_len,
+ BMFace ***r_face_arr, int *r_face_arr_len);
+
BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
const bool do_del, const bool join_faces, const bool kill_degenerate_faces);
BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 7c77302c942..74bd9110d8c 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -115,7 +115,7 @@ static BMOpDefine bmo_smooth_vert_def = {
},
{{{'\0'}}}, /* no output */
bmo_smooth_vert_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -138,7 +138,7 @@ static BMOpDefine bmo_smooth_laplacian_vert_def = {
},
{{{'\0'}}}, /* no output */
bmo_smooth_laplacian_vert_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -154,7 +154,8 @@ static BMOpDefine bmo_recalc_face_normals_def = {
},
{{{'\0'}}}, /* no output */
bmo_recalc_face_normals_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -180,7 +181,8 @@ static BMOpDefine bmo_region_extend_def = {
{{'\0'}},
},
bmo_region_extend_exec,
- BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -201,7 +203,10 @@ static BMOpDefine bmo_rotate_edges_def = {
{{'\0'}},
},
bmo_rotate_edges_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -218,7 +223,8 @@ static BMOpDefine bmo_reverse_faces_def = {
},
{{{'\0'}}}, /* no output */
bmo_reverse_faces_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -240,7 +246,10 @@ static BMOpDefine bmo_bisect_edges_def = {
{{'\0'}},
},
bmo_bisect_edges_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -266,7 +275,9 @@ static BMOpDefine bmo_mirror_def = {
{{'\0'}},
},
bmo_mirror_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -291,7 +302,7 @@ static BMOpDefine bmo_find_doubles_def = {
{{'\0'}},
},
bmo_find_doubles_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -309,7 +320,10 @@ static BMOpDefine bmo_remove_doubles_def = {
},
{{{'\0'}}}, /* no output */
bmo_remove_doubles_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -328,7 +342,10 @@ static BMOpDefine bmo_automerge_def = {
},
{{{'\0'}}}, /* no output */
bmo_automerge_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -344,7 +361,10 @@ static BMOpDefine bmo_collapse_def = {
},
{{{'\0'}}}, /* no output */
bmo_collapse_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -361,7 +381,7 @@ static BMOpDefine bmo_pointmerge_facedata_def = {
},
{{{'\0'}}}, /* no output */
bmo_pointmerge_facedata_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -379,7 +399,7 @@ static BMOpDefine bmo_average_vert_facedata_def = {
},
{{{'\0'}}}, /* no output */
bmo_average_vert_facedata_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -396,7 +416,10 @@ static BMOpDefine bmo_pointmerge_def = {
},
{{{'\0'}}}, /* no output */
bmo_pointmerge_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -412,7 +435,7 @@ static BMOpDefine bmo_collapse_uvs_def = {
},
{{{'\0'}}}, /* no output */
bmo_collapse_uvs_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -431,7 +454,10 @@ static BMOpDefine bmo_weld_verts_def = {
},
{{{'\0'}}}, /* no output */
bmo_weld_verts_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -451,7 +477,7 @@ static BMOpDefine bmo_create_vert_def = {
{{'\0'}},
},
bmo_create_vert_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -476,7 +502,10 @@ static BMOpDefine bmo_join_triangles_def = {
{{'\0'}},
},
bmo_join_triangles_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -504,7 +533,10 @@ static BMOpDefine bmo_contextual_create_def = {
{{'\0'}},
},
bmo_contextual_create_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -527,7 +559,9 @@ static BMOpDefine bmo_bridge_loops_def = {
{{'\0'}},
},
bmo_bridge_loops_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -551,7 +585,8 @@ static BMOpDefine bmo_grid_fill_def = {
{{'\0'}},
},
bmo_grid_fill_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -573,7 +608,8 @@ static BMOpDefine bmo_holes_fill_def = {
{{'\0'}},
},
bmo_holes_fill_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -596,7 +632,7 @@ static BMOpDefine bmo_face_attribute_fill_def = {
{{'\0'}},
},
bmo_face_attribute_fill_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -619,7 +655,8 @@ static BMOpDefine bmo_edgeloop_fill_def = {
{{'\0'}},
},
bmo_edgeloop_fill_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -643,7 +680,8 @@ static BMOpDefine bmo_edgenet_fill_def = {
{{'\0'}},
},
bmo_edgenet_fill_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -667,7 +705,7 @@ static BMOpDefine bmo_edgenet_prepare_def = {
{{'\0'}},
},
bmo_edgenet_prepare_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -686,7 +724,7 @@ static BMOpDefine bmo_rotate_def = {
},
{{{'\0'}}}, /* no output */
bmo_rotate_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -704,7 +742,7 @@ static BMOpDefine bmo_translate_def = {
},
{{{'\0'}}}, /* no output */
bmo_translate_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -722,7 +760,7 @@ static BMOpDefine bmo_scale_def = {
},
{{{'\0'}}}, /* no output */
bmo_scale_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
@@ -742,7 +780,7 @@ static BMOpDefine bmo_transform_def = {
},
{{{'\0'}}}, /* no output */
bmo_transform_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -760,7 +798,7 @@ static BMOpDefine bmo_object_load_bmesh_def = {
},
{{{'\0'}}}, /* no output */
bmo_object_load_bmesh_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
@@ -782,7 +820,7 @@ static BMOpDefine bmo_bmesh_to_mesh_def = {
},
{{{'\0'}}}, /* no output */
bmo_bmesh_to_mesh_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -804,7 +842,7 @@ static BMOpDefine bmo_mesh_to_bmesh_def = {
},
{{{'\0'}}}, /* no output */
bmo_mesh_to_bmesh_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -816,6 +854,7 @@ static BMOpDefine bmo_extrude_discrete_faces_def = {
"extrude_discrete_faces",
/* slots_in */
{{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
{{'\0'}},
},
/* slots_out */
@@ -823,7 +862,7 @@ static BMOpDefine bmo_extrude_discrete_faces_def = {
{{'\0'}},
},
bmo_extrude_discrete_faces_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -836,6 +875,7 @@ static BMOpDefine bmo_extrude_edge_only_def = {
"extrude_edge_only",
/* slots_in */
{{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */
+ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
{{'\0'}},
},
/* slots_out */
@@ -843,7 +883,7 @@ static BMOpDefine bmo_extrude_edge_only_def = {
{{'\0'}},
},
bmo_extrude_edge_only_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -855,6 +895,7 @@ static BMOpDefine bmo_extrude_vert_indiv_def = {
"extrude_vert_indiv",
/* slots_in */
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
{{'\0'}},
},
/* slots_out */
@@ -863,7 +904,7 @@ static BMOpDefine bmo_extrude_vert_indiv_def = {
{{'\0'}},
},
bmo_extrude_vert_indiv_exec,
- BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -875,6 +916,7 @@ static BMOpDefine bmo_connect_verts_def = {
"connect_verts",
/* slots_in */
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
+ {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
{"check_degenerate", BMO_OP_SLOT_BOOL}, /* prevent splits with overlaps & intersections */
{{'\0'}},
},
@@ -883,7 +925,9 @@ static BMOpDefine bmo_connect_verts_def = {
{{'\0'}},
},
bmo_connect_verts_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -904,7 +948,9 @@ static BMOpDefine bmo_connect_verts_nonplanar_def = {
{{'\0'}},
},
bmo_connect_verts_nonplanar_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -916,6 +962,8 @@ static BMOpDefine bmo_connect_vert_pair_def = {
"connect_vert_pair",
/* slots_in */
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
+ {"verts_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
+ {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
{{'\0'}},
},
/* slots_out */
@@ -923,7 +971,9 @@ static BMOpDefine bmo_connect_vert_pair_def = {
{{'\0'}},
},
bmo_connect_vert_pair_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -938,6 +988,7 @@ static BMOpDefine bmo_extrude_face_region_def = {
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */
{"edges_exclude", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}},
{"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry */
+ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
{{'\0'}},
},
/* slots_out */
@@ -945,7 +996,7 @@ static BMOpDefine bmo_extrude_face_region_def = {
{{'\0'}},
},
bmo_extrude_face_region_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -956,11 +1007,15 @@ static BMOpDefine bmo_dissolve_verts_def = {
/* slots_in */
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
{"use_face_split", BMO_OP_SLOT_BOOL},
+ {"use_boundary_tear", BMO_OP_SLOT_BOOL},
{{'\0'}},
},
{{{'\0'}}}, /* no output */
bmo_dissolve_verts_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -979,7 +1034,10 @@ static BMOpDefine bmo_dissolve_edges_def = {
{{'\0'}},
},
bmo_dissolve_edges_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -997,7 +1055,10 @@ static BMOpDefine bmo_dissolve_faces_def = {
{{'\0'}},
},
bmo_dissolve_faces_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1019,7 +1080,10 @@ static BMOpDefine bmo_dissolve_limit_def = {
{{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
{{'\0'}}},
bmo_dissolve_limit_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1037,7 +1101,10 @@ static BMOpDefine bmo_dissolve_degenerate_def = {
/* slots_out */
{{{'\0'}}},
bmo_dissolve_degenerate_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1058,7 +1125,9 @@ static BMOpDefine bmo_triangulate_def = {
{{'\0'}},
},
bmo_triangulate_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1075,7 +1144,10 @@ static BMOpDefine bmo_unsubdivide_def = {
},
{{{'\0'}}}, /* no output */
bmo_unsubdivide_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1113,7 +1185,10 @@ static BMOpDefine bmo_subdivide_edges_def = {
{{'\0'}},
},
bmo_subdivide_edges_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1135,7 +1210,10 @@ static BMOpDefine bmo_subdivide_edgering_def = {
{{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
{{'\0'}}},
bmo_subdivide_edgering_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1159,7 +1237,10 @@ static BMOpDefine bmo_bisect_plane_def = {
{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input and output geometry (result of cut) */
{{'\0'}}},
bmo_bisect_plane_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1176,7 +1257,9 @@ static BMOpDefine bmo_delete_def = {
},
{{{'\0'}}}, /* no output */
bmo_delete_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1191,6 +1274,7 @@ static BMOpDefine bmo_duplicate_def = {
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
/* destination bmesh, if NULL will use current on */
{"dest", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
+ {"use_select_history", BMO_OP_SLOT_BOOL},
{{'\0'}},
},
/* slots_out */
@@ -1206,7 +1290,8 @@ static BMOpDefine bmo_duplicate_def = {
{{'\0'}},
},
bmo_duplicate_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1231,7 +1316,8 @@ static BMOpDefine bmo_split_def = {
{{'\0'}},
},
bmo_split_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1258,7 +1344,8 @@ static BMOpDefine bmo_spin_def = {
{{'\0'}},
},
bmo_spin_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -1281,7 +1368,7 @@ static BMOpDefine bmo_similar_faces_def = {
{{'\0'}},
},
bmo_similar_faces_exec,
- BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1303,7 +1390,7 @@ static BMOpDefine bmo_similar_edges_def = {
{{'\0'}},
},
bmo_similar_edges_exec,
- BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1325,7 +1412,7 @@ static BMOpDefine bmo_similar_verts_def = {
{{'\0'}},
},
bmo_similar_verts_exec,
- BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1342,7 +1429,7 @@ static BMOpDefine bmo_rotate_uvs_def = {
},
{{{'\0'}}}, /* no output */
bmo_rotate_uvs_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -1358,7 +1445,7 @@ static BMOpDefine bmo_reverse_uvs_def = {
},
{{{'\0'}}}, /* no output */
bmo_reverse_uvs_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -1375,7 +1462,7 @@ static BMOpDefine bmo_rotate_colors_def = {
},
{{{'\0'}}}, /* no output */
bmo_rotate_colors_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -1391,7 +1478,7 @@ static BMOpDefine bmo_reverse_colors_def = {
},
{{{'\0'}}}, /* no output */
bmo_reverse_colors_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -1413,7 +1500,9 @@ static BMOpDefine bmo_split_edges_def = {
{{'\0'}},
},
bmo_split_edges_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1435,7 +1524,8 @@ static BMOpDefine bmo_create_grid_def = {
{{'\0'}},
},
bmo_create_grid_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1457,7 +1547,8 @@ static BMOpDefine bmo_create_uvsphere_def = {
{{'\0'}},
},
bmo_create_uvsphere_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1478,7 +1569,8 @@ static BMOpDefine bmo_create_icosphere_def = {
{{'\0'}},
},
bmo_create_icosphere_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1497,7 +1589,8 @@ static BMOpDefine bmo_create_monkey_def = {
{{'\0'}},
},
bmo_create_monkey_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1522,7 +1615,8 @@ static BMOpDefine bmo_create_cone_def = {
{{'\0'}},
},
bmo_create_cone_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1543,7 +1637,8 @@ static BMOpDefine bmo_create_circle_def = {
{{'\0'}},
},
bmo_create_circle_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1563,7 +1658,8 @@ static BMOpDefine bmo_create_cube_def = {
{{'\0'}},
},
bmo_create_cube_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1580,6 +1676,7 @@ static BMOpDefine bmo_bevel_def = {
{"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */
{"profile", BMO_OP_SLOT_FLT}, /* profile shape, 0->1 (.5=>round) */
{"vertex_only", BMO_OP_SLOT_BOOL}, /* only bevel vertices, not edges */
+ {"material", BMO_OP_SLOT_INT}, /* material for bevel faces, -1 means get from adjacent faces */
{{'\0'}},
},
/* slots_out */
@@ -1588,7 +1685,10 @@ static BMOpDefine bmo_bevel_def = {
},
bmo_bevel_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1610,7 +1710,10 @@ static BMOpDefine bmo_beautify_fill_def = {
{{'\0'}},
},
bmo_beautify_fill_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1632,7 +1735,9 @@ static BMOpDefine bmo_triangle_fill_def = {
{{'\0'}},
},
bmo_triangle_fill_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1652,7 +1757,8 @@ static BMOpDefine bmo_solidify_def = {
{{'\0'}},
},
bmo_solidify_face_region_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1676,7 +1782,8 @@ static BMOpDefine bmo_inset_individual_def = {
{{'\0'}},
},
bmo_inset_individual_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC, /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */
+ /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -1703,7 +1810,8 @@ static BMOpDefine bmo_inset_region_def = {
{{'\0'}},
},
bmo_inset_region_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1732,7 +1840,9 @@ static BMOpDefine bmo_wireframe_def = {
{{'\0'}},
},
bmo_wireframe_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1755,7 +1865,9 @@ static BMOpDefine bmo_poke_def = {
{{'\0'}},
},
bmo_poke_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
#ifdef WITH_BULLET
@@ -1789,7 +1901,9 @@ static BMOpDefine bmo_convex_hull_def = {
{{'\0'}},
},
bmo_convex_hull_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
#endif
@@ -1816,7 +1930,9 @@ static BMOpDefine bmo_symmetrize_def = {
{{'\0'}},
},
bmo_symmetrize_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
const BMOpDefine *bmo_opdefines[] = {
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 7fad3a8c20e..287aafc8f9f 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -182,8 +182,9 @@ typedef struct BMOpSlot {
typedef enum {
BMO_OPTYPE_FLAG_NOP = 0,
BMO_OPTYPE_FLAG_UNTAN_MULTIRES = (1 << 0), /* switch from multires tangent space to absolute coordinates */
- BMO_OPTYPE_FLAG_NORMALS_CALC = (1 << 1), /*switch from multires tangent space to absolute coordinates*/
- BMO_OPTYPE_FLAG_SELECT_FLUSH = (1 << 2) /*switch from multires tangent space to absolute coordinates*/
+ BMO_OPTYPE_FLAG_NORMALS_CALC = (1 << 1),
+ BMO_OPTYPE_FLAG_SELECT_FLUSH = (1 << 2),
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE = (1 << 3),
} BMOpTypeFlag;
typedef struct BMOperator {
@@ -337,7 +338,8 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, cons
void BMO_mesh_selected_remap(BMesh *bm,
BMOpSlot *slot_vert_map,
BMOpSlot *slot_edge_map,
- BMOpSlot *slot_face_map);
+ BMOpSlot *slot_face_map,
+ const bool check_select);
/* copies the values from another slot to the end of the output slot */
#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 7f872613896..b041c010c22 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -605,7 +605,8 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty
void BMO_mesh_selected_remap(BMesh *bm,
BMOpSlot *slot_vert_map,
BMOpSlot *slot_edge_map,
- BMOpSlot *slot_face_map)
+ BMOpSlot *slot_face_map,
+ const bool check_select)
{
if (bm->selected.first) {
BMEditSelection *ese, *ese_next;
@@ -623,7 +624,7 @@ void BMO_mesh_selected_remap(BMesh *bm,
ese->ele = BMO_slot_map_elem_get(slot_elem_map, ese->ele);
if (UNLIKELY((ese->ele == NULL) ||
- (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false)))
+ (check_select && (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false))))
{
BLI_remlink(&bm->selected, ese);
MEM_freeN(ese);
@@ -764,6 +765,9 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_
BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
int totelement = 0, i = 0;
+ BLI_assert(output->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+
if (htype & BM_VERT) totelement += bm->totvert;
if (htype & BM_EDGE) totelement += bm->totedge;
if (htype & BM_FACE) totelement += bm->totface;
@@ -811,7 +815,11 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_
{
BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
int totelement = 0, i = 0;
- const int respecthide = (op->flag & BMO_FLAG_RESPECT_HIDE) != 0;
+ const bool respecthide = ((op->flag & BMO_FLAG_RESPECT_HIDE) != 0) && ((hflag & BM_ELEM_HIDDEN) == 0);
+
+ BLI_assert(output->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+ BLI_assert((output->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
if (test_for_enabled)
totelement = BM_mesh_elem_hflag_count_enabled(bm, htype, hflag, respecthide);
@@ -951,14 +959,15 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op,
BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+ BLI_assert((slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
+
if (test_for_enabled)
totelement = BMO_mesh_enabled_flag_count(bm, htype, oflag);
else
totelement = BMO_mesh_disabled_flag_count(bm, htype, oflag);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
-
if (totelement) {
BMIter iter;
BMHeader *ele;
@@ -1034,6 +1043,7 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm,
BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+ BLI_assert((slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
for (i = 0; i < slot->len; i++, data++) {
if (!(htype & (*data)->head.htype))
@@ -1654,7 +1664,6 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
char slot_name[64] = {0};
int i, type;
bool noslot, state;
- char htype;
/* basic useful info to help find where bmop formatting strings fail */
@@ -1729,9 +1738,8 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
break;
case 'm':
{
- int size, c;
-
- c = NEXT_CHAR(fmt);
+ int size;
+ const char c = NEXT_CHAR(fmt);
fmt++;
if (c == '3') size = 3;
@@ -1800,22 +1808,23 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double));
}
else {
- bool stop = false;
+ char htype = 0;
- htype = 0;
while (1) {
- switch (NEXT_CHAR(fmt)) {
- case 'f': htype |= BM_FACE; break;
- case 'e': htype |= BM_EDGE; break;
- case 'v': htype |= BM_VERT; break;
- default:
- stop = true;
- break;
- }
- if (stop) {
+ char htype_set;
+ const char c = NEXT_CHAR(fmt);
+ if (c == 'f') htype_set = BM_FACE;
+ else if (c == 'e') htype_set = BM_EDGE;
+ else if (c == 'v') htype_set = BM_VERT;
+ else {
break;
}
+ if (UNLIKELY(htype & htype_set)) {
+ GOTO_ERROR("htype duplicated");
+ }
+
+ htype |= htype_set;
fmt++;
}
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 307c391a406..9a0fce9dba0 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -854,7 +854,7 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
l_tri[1]->v,
l_tri[2]->v};
- f_new = BM_face_create_verts(bm, v_tri, 3, f, false, true);
+ f_new = BM_face_create_verts(bm, v_tri, 3, f, BM_CREATE_NOP, true);
l_new = BM_FACE_FIRST_LOOP(f_new);
BLI_assert(v_tri[0] == l_new->v);
diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h
index 731c36437d5..102a677943b 100644
--- a/source/blender/bmesh/intern/bmesh_private.h
+++ b/source/blender/bmesh/intern/bmesh_private.h
@@ -64,7 +64,8 @@ enum {
_FLAG_JF = (1 << 0), /* join faces */
_FLAG_MF = (1 << 1), /* make face */
_FLAG_MV = (1 << 1), /* make face, vertex */
- _FLAG_OVERLAP = (1 << 2) /* general overlap flag */
+ _FLAG_OVERLAP = (1 << 2), /* general overlap flag */
+ _FLAG_WALK = (1 << 3), /* general walk flag (keep clean) */
};
#define BM_ELEM_API_FLAG_ENABLE(element, f) { ((element)->head.api_flag |= (f)); } (void)0
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 606e93d4a85..685e5443583 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -183,6 +183,26 @@ BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v)
}
/**
+ * Check if verts share a face.
+ */
+bool BM_vert_pair_share_face_check(
+ BMVert *v_a, BMVert *v_b)
+{
+ if (v_a->e && v_b->e) {
+ BMIter iter;
+ BMFace *f;
+
+ BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) {
+ if (BM_vert_in_face(f, v_b)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/**
* Given 2 verts, find the smallest face they share and give back both loops.
*/
BMFace *BM_vert_pair_share_face_by_len(
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 21d20976901..0d47633dc73 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -27,29 +27,31 @@
* \ingroup bmesh
*/
-bool BM_vert_in_face(BMFace *f, BMVert *v);
-int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len);
-bool BM_verts_in_face(BMFace *f, BMVert **varr, int len);
-
-bool BM_edge_in_face(BMEdge *e, BMFace *f);
-BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l);
-
-BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v);
-BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e);
-
-float BM_edge_calc_length(BMEdge *e);
-float BM_edge_calc_length_squared(BMEdge *e);
-bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb);
-bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb);
-BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v);
-BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l);
-BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v);
-BMLoop *BM_loop_other_edge_loop(BMLoop *l, BMVert *v);
-BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v);
-BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v);
-BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step);
-BMLoop *BM_vert_find_first_loop(BMVert *v);
-
+bool BM_vert_in_face(BMFace *f, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_verts_in_face(BMFace *f, BMVert **varr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+bool BM_edge_in_face(BMEdge *e, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+float BM_edge_calc_length(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_edge_calc_length_squared(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) ATTR_NONNULL();
+bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) ATTR_NONNULL();
+BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_loop_other_edge_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_vert_find_first_loop(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+bool BM_vert_pair_share_face_check(
+ BMVert *v_a, BMVert *v_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMFace *BM_vert_pair_share_face_by_len(
BMVert *v_a, BMVert *v_b,
BMLoop **r_l_a, BMLoop **r_l_b,
@@ -59,95 +61,95 @@ BMFace *BM_vert_pair_share_face_by_angle(
BMLoop **r_l_a, BMLoop **r_l_b,
const bool allow_adjacent) ATTR_NONNULL();
-int BM_vert_edge_count_nonwire(BMVert *v);
-int BM_vert_edge_count(BMVert *v);
-int BM_edge_face_count(BMEdge *e);
-int BM_vert_face_count(BMVert *v);
-BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e);
+int BM_vert_edge_count_nonwire(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_vert_edge_count(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_edge_face_count(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_vert_face_count(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_is_edge_pair(BMVert *v);
-bool BM_vert_is_wire(const BMVert *v);
-BLI_INLINE bool BM_edge_is_wire(const BMEdge *e);
+bool BM_vert_is_edge_pair(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_wire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_is_manifold(const BMVert *v);
-BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e);
-bool BM_vert_is_boundary(const BMVert *v);
-BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e);
-BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e);
-bool BM_edge_is_convex(const BMEdge *e);
+bool BM_vert_is_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_boundary(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_is_convex(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_loop_is_convex(const BMLoop *l);
-BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b);
+bool BM_loop_is_convex(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_loop_calc_face_angle(BMLoop *l);
-void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]);
+float BM_loop_calc_face_angle(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]) ATTR_NONNULL();
void BM_loop_calc_face_direction(BMLoop *l, float r_normal[3]);
void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3]);
-float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback);
-float BM_edge_calc_face_angle(const BMEdge *e);
-float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback);
-float BM_edge_calc_face_angle_signed(const BMEdge *e);
-void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]);
+float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]) ATTR_NONNULL();
-float BM_vert_calc_edge_angle(BMVert *v);
-float BM_vert_calc_shell_factor(BMVert *v);
-float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag);
-float BM_vert_calc_mean_tagged_edge_length(BMVert *v);
+float BM_vert_calc_edge_angle(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_shell_factor(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_mean_tagged_edge_length(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMLoop *BM_face_find_shortest_loop(BMFace *f);
-BMLoop *BM_face_find_longest_loop(BMFace *f);
+BMLoop *BM_face_find_shortest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_face_find_longest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2);
-BMEdge *BM_edge_find_double(BMEdge *e);
+BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMEdge *BM_edge_find_double(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface);
+bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface) ATTR_NONNULL(1);
-bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len);
-bool BM_face_exists_multi_edge(BMEdge **earr, int len);
+bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_exists_multi_edge(BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_exists_overlap(BMVert **varr, const int len, BMFace **r_f_overlap);
-bool BM_face_exists_overlap_subset(BMVert **varr, const int len);
+bool BM_face_exists_overlap(BMVert **varr, const int len, BMFace **r_f_overlap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+bool BM_face_exists_overlap_subset(BMVert **varr, const int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_face_share_face_count(BMFace *f_a, BMFace *f_b);
-int BM_face_share_edge_count(BMFace *f1, BMFace *f2);
+int BM_face_share_face_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_face_share_edge_count(BMFace *f1, BMFace *f2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_share_face_check(BMFace *f1, BMFace *f2);
-bool BM_face_share_edge_check(BMFace *f1, BMFace *f2);
-bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2);
-bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2);
-bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2);
+bool BM_face_share_face_check(BMFace *f1, BMFace *f2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_share_edge_check(BMFace *f1, BMFace *f2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2);
-BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v);
-BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v);
-BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e);
+BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2);
+void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) ATTR_NONNULL();
void BM_edge_ordered_verts_ex(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
- const BMLoop *edge_loop);
+ const BMLoop *edge_loop) ATTR_NONNULL();
-bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide);
-bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide);
-bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide);
+bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag);
-bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag);
-bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag);
+bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_is_normal_valid(const BMFace *f);
+bool BM_face_is_normal_valid(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_mesh_calc_volume(BMesh *bm, bool is_signed);
+float BM_mesh_calc_volume(BMesh *bm, bool is_signed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
BMElemFilterFunc filter_fn, void *user_data,
- const char hflag_test, const char htype_step);
+ const char hflag_test, const char htype_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
BMElemFilterFunc filter_fn, void *user_data,
- const char hflag_test);
+ const char hflag_test) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
/* not really any good place to put this */
-float bmesh_subd_falloff_calc(const int falloff, float val);
+float bmesh_subd_falloff_calc(const int falloff, float val) ATTR_WARN_UNUSED_RESULT;
#include "bmesh_queries_inline.h"
diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h
index 8e721ddd229..d2ad655ae75 100644
--- a/source/blender/bmesh/intern/bmesh_structure.h
+++ b/source/blender/bmesh/intern/bmesh_structure.h
@@ -39,39 +39,37 @@
* descriptive comments. but seriously, don't use this stuff.
*/
-struct ListBase;
-
/* LOOP CYCLE MANAGEMENT */
-bool bmesh_loop_validate(BMFace *f);
+bool bmesh_loop_validate(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* DISK CYCLE MANAGMENT */
-void bmesh_disk_edge_append(BMEdge *e, BMVert *v);
-void bmesh_disk_edge_remove(BMEdge *e, BMVert *v);
-BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v);
-BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v);
-BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v);
-BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v);
-int bmesh_disk_facevert_count(const BMVert *v);
-BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v);
-BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v);
+void bmesh_disk_edge_append(BMEdge *e, BMVert *v) ATTR_NONNULL();
+void bmesh_disk_edge_remove(BMEdge *e, BMVert *v) ATTR_NONNULL();
+BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int bmesh_disk_facevert_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* RADIAL CYCLE MANAGMENT */
-void bmesh_radial_append(BMEdge *e, BMLoop *l);
-void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e);
+void bmesh_radial_append(BMEdge *e, BMLoop *l) ATTR_NONNULL();
+void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e) ATTR_NONNULL(1);
/* note:
* bmesh_radial_loop_next(BMLoop *l) / prev.
* just use member access l->radial_next, l->radial_prev now */
-int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v);
-BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v);
-BMLoop *bmesh_radial_faceloop_find_next(const BMLoop *l, const BMVert *v);
-BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v);
-bool bmesh_radial_validate(int radlen, BMLoop *l);
+int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *bmesh_radial_faceloop_find_next(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* EDGE UTILITIES */
-bool bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv); /* relink edge */
-BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2);
-bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v);
+bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new) ATTR_NONNULL();
+BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
#include "intern/bmesh_structure_inline.h"
diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c
index 8f74e98e762..6a5efbe70ac 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.c
+++ b/source/blender/bmesh/intern/bmesh_walkers.c
@@ -47,7 +47,7 @@
*
* basic design pattern: the walker step function goes through it's
* list of possible choices for recursion, and recurses (by pushing a new state)
- * using the first non-visited one. this choise is the flagged as visited using
+ * using the first non-visited one. This choice is the flagged as visited using
* the ghash. each step may push multiple new states onto the worklist at once.
*
* - Walkers use tool flags, not header flags.
diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c
index 07a2e674863..213a0830e63 100644
--- a/source/blender/bmesh/operators/bmo_bevel.c
+++ b/source/blender/bmesh/operators/bmo_bevel.c
@@ -40,6 +40,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
const int seg = BMO_slot_int_get(op->slots_in, "segments");
const bool vonly = BMO_slot_bool_get(op->slots_in, "vertex_only");
const float profile = BMO_slot_float_get(op->slots_in, "profile");
+ const int material = BMO_slot_int_get(op->slots_in, "material");
if (offset > 0) {
BMOIter siter;
@@ -60,7 +61,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
}
}
- BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, false, NULL, -1);
+ BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, false, NULL, -1, material);
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
}
diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c
index 9e9cd0d66e2..e4417477e76 100644
--- a/source/blender/bmesh/operators/bmo_bridge.c
+++ b/source/blender/bmesh/operators/bmo_bridge.c
@@ -119,7 +119,7 @@ static void bm_bridge_best_rotation(struct BMEdgeLoopStore *el_store_a, struct B
}
if (el_b_best) {
- BLI_rotatelist_first(lb_b, el_b_best);
+ BLI_listbase_rotate_first(lb_b, el_b_best);
}
}
@@ -272,7 +272,7 @@ static void bridge_loop_pair(BMesh *bm,
const int len_b = BM_edgeloop_length_get(el_store_b);
ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
LinkData *el_b = BLI_rfindlink(lb_b, mod_i(twist_offset, len_b));
- BLI_rotatelist_first(lb_b, el_b);
+ BLI_listbase_rotate_first(lb_b, el_b);
}
}
diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index 4cf6e82fc8e..0213329118c 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -36,54 +36,68 @@
#include "intern/bmesh_operators_private.h" /* own include */
#define VERT_INPUT 1
+
#define EDGE_OUT 1
-#define FACE_TAG 2
+/* Edge spans 2 VERT_INPUT's, its a nop,
+ * but include in "edges.out" */
+#define EDGE_OUT_ADJ 2
+
+#define FACE_TAG 2
+#define FACE_EXCLUDE 4
static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenerate)
{
- BMLoop *(*loops_split)[2] = BLI_array_alloca(loops_split, f->len);
+ const unsigned pair_split_max = f->len / 2;
+ BMLoop *(*loops_split)[2] = BLI_array_alloca(loops_split, pair_split_max);
STACK_DECLARE(loops_split);
- BMVert *(*verts_pair)[2] = BLI_array_alloca(verts_pair, f->len);
+ BMVert *(*verts_pair)[2] = BLI_array_alloca(verts_pair, pair_split_max);
STACK_DECLARE(verts_pair);
- BMIter liter;
- BMFace *f_new;
- BMLoop *l;
- BMLoop *l_last;
+ BMLoop *l_tag_prev = NULL, *l_tag_first = NULL;
+ BMLoop *l_iter, *l_first;
unsigned int i;
- STACK_INIT(loops_split, f->len);
- STACK_INIT(verts_pair, f->len);
+ STACK_INIT(loops_split, pair_split_max);
+ STACK_INIT(verts_pair, pair_split_max);
- l_last = NULL;
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (BMO_elem_flag_test(bm, l->v, VERT_INPUT)) {
- if (!l_last) {
- l_last = l;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BMO_elem_flag_test(bm, l_iter->v, VERT_INPUT) &&
+ /* ensure this vertex isnt part of a contiguous group */
+ ((BMO_elem_flag_test(bm, l_iter->prev->v, VERT_INPUT) == 0) ||
+ (BMO_elem_flag_test(bm, l_iter->next->v, VERT_INPUT) == 0)))
+ {
+ if (!l_tag_prev) {
+ l_tag_prev = l_tag_first = l_iter;
continue;
}
- if (!BM_loop_is_adjacent(l_last, l)) {
+ if (!BM_loop_is_adjacent(l_tag_prev, l_iter)) {
BMEdge *e;
- e = BM_edge_exists(l_last->v, l->v);
+ e = BM_edge_exists(l_tag_prev->v, l_iter->v);
if (e == NULL || !BMO_elem_flag_test(bm, e, EDGE_OUT)) {
BMLoop **l_pair = STACK_PUSH_RET(loops_split);
- l_pair[0] = l_last;
- l_pair[1] = l;
+ l_pair[0] = l_tag_prev;
+ l_pair[1] = l_iter;
}
}
- l_last = l;
+
+ l_tag_prev = l_iter;
}
- }
+ } while ((l_iter = l_iter->next) != l_first);
if (STACK_SIZE(loops_split) == 0) {
return 0;
}
- if (STACK_SIZE(loops_split) > 1) {
+ if (!BM_loop_is_adjacent(l_tag_first, l_tag_prev) &&
+ /* ensure we don't add the same pair twice */
+ (((loops_split[0][0] == l_tag_first) &&
+ (loops_split[0][1] == l_tag_prev)) == 0))
+ {
BMLoop **l_pair = STACK_PUSH_RET(loops_split);
- l_pair[0] = loops_split[STACK_SIZE(loops_split) - 2][1];
- l_pair[1] = loops_split[0][0];
+ l_pair[0] = l_tag_first;
+ l_pair[1] = l_tag_prev;
}
if (check_degenerate) {
@@ -105,6 +119,7 @@ static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenera
}
for (i = 0; i < STACK_SIZE(verts_pair); i++) {
+ BMFace *f_new;
BMLoop *l_new;
BMLoop *l_a, *l_b;
@@ -134,7 +149,6 @@ static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenera
void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
{
BMOIter siter;
- BMIter iter;
BMVert *v;
BMFace *f;
const bool check_degenerate = BMO_slot_bool_get(op->slots_in, "check_degenerate");
@@ -142,16 +156,35 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
BLI_LINKSTACK_INIT(faces);
+ /* tag so we won't touch ever (typically hidden faces) */
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces_exclude", BM_FACE, FACE_EXCLUDE);
+
/* add all faces connected to verts */
BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
+ BMIter iter;
+ BMLoop *l_iter;
+
BMO_elem_flag_enable(bm, v, VERT_INPUT);
- BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
- if (!BMO_elem_flag_test(bm, f, FACE_TAG)) {
- BMO_elem_flag_enable(bm, f, FACE_TAG);
- if (f->len > 3) {
- BLI_LINKSTACK_PUSH(faces, f);
+ BM_ITER_ELEM (l_iter, &iter, v, BM_LOOPS_OF_VERT) {
+ f = l_iter->f;
+ if (!BMO_elem_flag_test(bm, f, FACE_EXCLUDE)) {
+ if (!BMO_elem_flag_test(bm, f, FACE_TAG)) {
+ BMO_elem_flag_enable(bm, f, FACE_TAG);
+ if (f->len > 3) {
+ BLI_LINKSTACK_PUSH(faces, f);
+ }
}
}
+
+ /* flag edges even if these are not newly created
+ * this way cut-pairs that include co-linear edges will get
+ * predictable output. */
+ if (BMO_elem_flag_test(bm, l_iter->prev->v, VERT_INPUT)) {
+ BMO_elem_flag_enable(bm, l_iter->prev->e, EDGE_OUT_ADJ);
+ }
+ if (BMO_elem_flag_test(bm, l_iter->next->v, VERT_INPUT)) {
+ BMO_elem_flag_enable(bm, l_iter->e, EDGE_OUT_ADJ);
+ }
}
}
@@ -164,5 +197,5 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
BLI_LINKSTACK_FREE(faces);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT | EDGE_OUT_ADJ);
}
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index b497ab2f693..a0acf6ed2c5 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -51,6 +51,15 @@
#define CONNECT_EPS 0.0001f
#define VERT_OUT 1
+#define VERT_EXCLUDE 2
+
+/* typically hidden faces */
+#define FACE_EXCLUDE 2
+
+#define FACE_WALK_TEST(f) (CHECK_TYPE_INLINE(f, BMFace *), \
+ BMO_elem_flag_test(pc->bm_bmoflag, f, FACE_EXCLUDE) == 0)
+#define VERT_WALK_TEST(v) (CHECK_TYPE_INLINE(v, BMVert *), \
+ BMO_elem_flag_test(pc->bm_bmoflag, v, VERT_EXCLUDE) == 0)
// #define DEBUG_PRINT
@@ -59,6 +68,9 @@ typedef struct PathContext {
float matrix[3][3];
float axis_sep;
+ /* only to access BMO flags */
+ BMesh *bm_bmoflag;
+
BMVert *v_a, *v_b;
BLI_mempool *link_pool;
@@ -134,7 +146,7 @@ static void state_calc_co_pair(const PathContext *pc,
static bool state_link_find(PathLinkState *state, BMElem *ele)
{
PathLink *link = state->link_last;
- BLI_assert(ELEM3(ele->head.htype, BM_VERT, BM_EDGE, BM_FACE));
+ BLI_assert(ELEM(ele->head.htype, BM_VERT, BM_EDGE, BM_FACE));
if (link) {
do {
if (link->ele == ele) {
@@ -204,8 +216,9 @@ static void state_link_add(PathContext *pc, PathLinkState *state,
state->link_last = step_new;
}
-static PathLinkState *state_dupe_add(PathContext *pc,
- PathLinkState *state, const PathLinkState *state_orig)
+static PathLinkState *state_dupe_add(
+ PathContext *pc,
+ PathLinkState *state, const PathLinkState *state_orig)
{
state = MEM_mallocN(sizeof(*state), __func__);
*state = *state_orig;
@@ -214,16 +227,19 @@ static PathLinkState *state_dupe_add(PathContext *pc,
}
/* walk around the face edges */
-static PathLinkState *state_step__face_edges(PathContext *pc,
- PathLinkState *state, const PathLinkState *state_orig,
- BMLoop *l_iter, BMLoop *l_last)
+static PathLinkState *state_step__face_edges(
+ PathContext *pc,
+ PathLinkState *state, const PathLinkState *state_orig,
+ BMLoop *l_iter, BMLoop *l_last)
{
do {
if (state_isect_co_pair(pc, l_iter->v->co, l_iter->next->v->co)) {
BMElem *ele_next = (BMElem *)l_iter->e;
BMElem *ele_next_from = (BMElem *)l_iter->f;
- if (state_link_find(state, ele_next) == false) {
+ if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
+ (state_link_find(state, ele_next) == false))
+ {
if (state_orig->link_last != state->link_last) {
state = state_dupe_add(pc, state, state_orig);
}
@@ -235,16 +251,19 @@ static PathLinkState *state_step__face_edges(PathContext *pc,
}
/* walk around the face verts */
-static PathLinkState *state_step__face_verts(PathContext *pc,
- PathLinkState *state, const PathLinkState *state_orig,
- BMLoop *l_iter, BMLoop *l_last)
+static PathLinkState *state_step__face_verts(
+ PathContext *pc,
+ PathLinkState *state, const PathLinkState *state_orig,
+ BMLoop *l_iter, BMLoop *l_last)
{
do {
if (state_isect_co_exact(pc, l_iter->v->co)) {
BMElem *ele_next = (BMElem *)l_iter->v;
BMElem *ele_next_from = (BMElem *)l_iter->f;
- if (state_link_find(state, ele_next) == false) {
+ if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
+ state_link_find(state, ele_next) == false)
+ {
if (state_orig->link_last != state->link_last) {
state = state_dupe_add(pc, state, state_orig);
}
@@ -268,7 +287,9 @@ static bool state_step(PathContext *pc, PathLinkState *state)
BMLoop *l_start;
BM_ITER_ELEM (l_start, &liter, e, BM_LOOPS_OF_EDGE) {
- if (l_start->f != ele_from) {
+ if ((l_start->f != ele_from) &&
+ FACE_WALK_TEST(l_start->f))
+ {
/* very similar to block below */
if (BM_vert_in_face(l_start->f, pc->v_b)) {
if (state_orig.link_last != state->link_last) {
@@ -295,7 +316,9 @@ static bool state_step(PathContext *pc, PathLinkState *state)
BMLoop *l_start;
BM_ITER_ELEM (l_start, &liter, v, BM_LOOPS_OF_VERT) {
- if (l_start->f != ele_from) {
+ if ((l_start->f != ele_from) &&
+ FACE_WALK_TEST(l_start->f))
+ {
/* very similar to block above */
if (BM_vert_in_face(l_start->f, pc->v_b)) {
BMElem *ele_next = (BMElem *)pc->v_b;
@@ -324,8 +347,10 @@ static bool state_step(PathContext *pc, PathLinkState *state)
BMIter eiter;
BMEdge *e;
BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if ((BMElem *)e != ele_from) {
- BMVert *v_other = BM_edge_other_vert(e, v);
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (((BMElem *)e != ele_from) &&
+ VERT_WALK_TEST(v_other))
+ {
if (v_other == pc->v_b) {
BMElem *ele_next = (BMElem *)pc->v_b;
BMElem *ele_next_from = (BMElem *)e;
@@ -371,6 +396,7 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
return;
}
+ pc.bm_bmoflag = bm;
pc.v_a = ((BMVert **)op_verts_slot->data.p)[0];
pc.v_b = ((BMVert **)op_verts_slot->data.p)[1];
@@ -384,6 +410,10 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
printf("%s: v_b: %d\n", __func__, BM_elem_index_get(pc.v_b));
#endif
+ /* tag so we won't touch ever (typically hidden faces) */
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces_exclude", BM_FACE, FACE_EXCLUDE);
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts_exclude", BM_VERT, VERT_EXCLUDE);
+
/* setup context */
{
BLI_listbase_clear(&pc.state_lb);
@@ -468,9 +498,7 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
BLI_remlink(&pc.state_lb, state);
MEM_freeN(state);
}
- else {
- found_all = false;
- }
+ found_all = false;
}
else {
/* didn't reach the end, remove it,
@@ -481,6 +509,11 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
}
if (found_all) {
+#ifdef DEBUG
+ for (state = pc.state_lb.first; state; state = state->next) {
+ BLI_assert(state->link_last->ele == (BMElem *)pc.v_b);
+ }
+#endif
break;
}
}
@@ -533,7 +566,8 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
* always connect even when resulting faces are degenerate [#39418] */
BMOperator op_sub;
BMO_op_initf(bm, &op_sub, 0,
- "connect_verts verts=%fv", VERT_OUT);
+ "connect_verts verts=%fv faces_exclude=%s",
+ VERT_OUT, op, "faces_exclude");
BMO_op_exec(bm, &op_sub);
BMO_slot_copy(&op_sub, slots_out, "edges.out",
op, slots_out, "edges.out");
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index 209ca30ddc3..8cd9ee14bcb 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -29,6 +29,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_array.h"
+#include "BLI_stack.h"
#include "BLI_math.h"
#include "bmesh.h"
@@ -51,6 +52,7 @@
#define VERT_MARK_PAIR 4
#define VERT_TAG 2
#define VERT_ISGC 8
+#define VERT_MARK_TEAR 16
@@ -85,15 +87,20 @@ static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f)
return true;
}
-static void bm_face_split(BMesh *bm, const short oflag)
+static void bm_face_split(BMesh *bm, const short oflag, bool use_edge_delete)
{
+ BLI_Stack *edge_delete_verts;
BMIter iter;
BMVert *v;
- BMIter liter;
+ if (use_edge_delete) {
+ edge_delete_verts = BLI_stack_new(sizeof(BMVert *), __func__);
+ }
+
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, oflag)) {
if (BM_vert_is_edge_pair(v) == false) {
+ BMIter liter;
BMLoop *l;
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
if (l->f->len > 3) {
@@ -104,8 +111,23 @@ static void bm_face_split(BMesh *bm, const short oflag)
}
}
}
+
+ if (use_edge_delete) {
+ BLI_stack_push(edge_delete_verts, &v);
+ }
+ }
+ }
+ }
+
+ if (use_edge_delete) {
+ while (!BLI_stack_is_empty(edge_delete_verts)) {
+ /* remove surrounding edges & faces */
+ BLI_stack_pop(edge_delete_verts, &v);
+ while (v->e) {
+ BM_edge_kill(bm, v->e);
}
}
+ BLI_stack_free(edge_delete_verts);
}
}
@@ -268,7 +290,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
}
}
- bm_face_split(bm, VERT_TAG);
+ bm_face_split(bm, VERT_TAG, false);
}
if (use_verts) {
@@ -345,13 +367,29 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
BMFace *act_face = bm->act_face;
const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
+ const bool use_boundary_tear = BMO_slot_bool_get(op->slots_in, "use_boundary_tear");
BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
BMO_elem_flag_enable(bm, v, VERT_MARK | VERT_ISGC);
}
if (use_face_split) {
- bm_face_split(bm, VERT_MARK);
+ bm_face_split(bm, VERT_MARK, false);
+ }
+
+ if (use_boundary_tear) {
+ BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
+ if (!BM_vert_is_edge_pair(v)) {
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_boundary(e)) {
+ BMO_elem_flag_enable(bm, v, VERT_MARK_TEAR);
+ break;
+ }
+ }
+ }
+ }
+
+ bm_face_split(bm, VERT_MARK_TEAR, true);
}
BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index 794c688b26b..cd5592f08c9 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -183,6 +183,7 @@ static BMFace *bmo_face_copy(BMOperator *op,
*/
static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
{
+ const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
BMVert *v = NULL, *v2;
BMEdge *e = NULL;
@@ -285,6 +286,16 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
/* free pointer hashes */
BLI_ghash_free(vhash, NULL, NULL);
BLI_ghash_free(ehash, NULL, NULL);
+
+ if (use_select_history) {
+ BLI_assert(bm_src == bm_dst);
+ BMO_mesh_selected_remap(
+ bm_dst,
+ slot_vert_map_out,
+ slot_edge_map_out,
+ slot_face_map_out,
+ false);
+ }
}
/**
diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c
index 0c5de590ccf..4423123f65e 100644
--- a/source/blender/bmesh/operators/bmo_edgenet.c
+++ b/source/blender/bmesh/operators/bmo_edgenet.c
@@ -179,11 +179,11 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op)
if (!count) {
edges1 = edges;
- BLI_array_length_set(edges1, BLI_array_count(edges));
+ BLI_array_count_set(edges1, BLI_array_count(edges));
}
else {
edges2 = edges;
- BLI_array_length_set(edges2, BLI_array_count(edges));
+ BLI_array_count_set(edges2, BLI_array_count(edges));
}
BLI_array_empty(edges);
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index 510c3ae0078..88b53b63abb 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -53,9 +53,16 @@ enum {
void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
{
+ const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
+ GHash *select_history_map = NULL;
+
BMOIter siter;
BMFace *f_org;
+ if (use_select_history) {
+ select_history_map = BM_select_history_map_create(bm);
+ }
+
BMO_ITER (f_org, &siter, op->slots_in, "faces", BM_FACE) {
BMFace *f_new;
BMLoop *l_org, *l_org_first;
@@ -66,6 +73,14 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
f_new = BM_face_copy(bm, bm, f_org, true, true);
BMO_elem_flag_enable(bm, f_new, EXT_KEEP);
+ if (select_history_map) {
+ BMEditSelection *ese;
+ ese = BLI_ghash_lookup(select_history_map, f_org);
+ if (ese) {
+ ese->ele = (BMElem *)f_new;
+ }
+ }
+
l_org = l_org_first = BM_FACE_FIRST_LOOP(f_org);
l_new = BM_FACE_FIRST_LOOP(f_new);
@@ -85,10 +100,28 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
BM_elem_attrs_copy(bm, bm, l_org->next, l_side_iter); l_side_iter = l_side_iter->next;
BM_elem_attrs_copy(bm, bm, l_org, l_side_iter); l_side_iter = l_side_iter->next;
BM_elem_attrs_copy(bm, bm, l_org, l_side_iter);
+
+ if (select_history_map) {
+ BMEditSelection *ese;
+
+ ese = BLI_ghash_lookup(select_history_map, l_org->v);
+ if (ese) {
+ ese->ele = (BMElem *)l_new->v;
+ }
+ ese = BLI_ghash_lookup(select_history_map, l_org->e);
+ if (ese) {
+ ese->ele = (BMElem *)l_new->e;
+ }
+ }
+
} while (((l_new = l_new->next),
(l_org = l_org->next)) != l_org_first);
}
+ if (select_history_map) {
+ BLI_ghash_free(select_history_map, NULL, NULL);
+ }
+
BMO_op_callf(bm, op->flag,
"delete geom=%ff context=%i",
EXT_DEL, DEL_ONLYFACES);
@@ -157,7 +190,11 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_enable(bm, e->v2, EXT_INPUT);
}
- BMO_op_initf(bm, &dupeop, op->flag, "duplicate geom=%fve", EXT_INPUT);
+ BMO_op_initf(
+ bm, &dupeop, op->flag,
+ "duplicate geom=%fve use_select_history=%b",
+ EXT_INPUT, BMO_slot_bool_get(op->slots_in, "use_select_history"));
+
BMO_op_exec(bm, &dupeop);
/* disable root flag on all new skin nodes */
@@ -205,10 +242,16 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op)
void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
{
+ const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
BMOIter siter;
BMVert *v, *dupev;
BMEdge *e;
const bool has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN);
+ GHash *select_history_map = NULL;
+
+ if (use_select_history) {
+ select_history_map = BM_select_history_map_create(bm);
+ }
for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) {
dupev = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
@@ -217,6 +260,14 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
if (has_vskin)
bm_extrude_disable_skin_root(bm, v);
+ if (select_history_map) {
+ BMEditSelection *ese;
+ ese = BLI_ghash_lookup(select_history_map, v);
+ if (ese) {
+ ese->ele = (BMElem *)dupev;
+ }
+ }
+
/* not essential, but ensures face normals from extruded edges are contiguous */
if (BM_vert_is_wire_endpoint(v)) {
if (v->e->v1 == v) {
@@ -228,6 +279,10 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_enable(bm, e, EXT_KEEP);
}
+ if (select_history_map) {
+ BLI_ghash_free(select_history_map, NULL, NULL);
+ }
+
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, EXT_KEEP);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EXT_KEEP);
}
@@ -245,8 +300,11 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
BMOpSlot *slot_edges_exclude;
/* initialize our sub-operators */
- BMO_op_init(bm, &dupeop, op->flag, "duplicate");
-
+ BMO_op_initf(
+ bm, &dupeop, op->flag,
+ "duplicate use_select_history=%b",
+ BMO_slot_bool_get(op->slots_in, "use_select_history"));
+
BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, EXT_INPUT);
/* if one flagged face is bordered by an un-flagged face, then we delete
diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c
index fa77e6b509c..d9f50ac891c 100644
--- a/source/blender/bmesh/operators/bmo_fill_attribute.c
+++ b/source/blender/bmesh/operators/bmo_fill_attribute.c
@@ -154,7 +154,7 @@ static unsigned int bmesh_face_attribute_fill(BMesh *bm,
return face_tot;
}
-void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op)
+void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op)
{
const bool use_normals = BMO_slot_bool_get(op->slots_in, "use_normals");
const bool use_data = BMO_slot_bool_get(op->slots_in, "use_data");
diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c
index 6a0fca425f8..40f6937245b 100644
--- a/source/blender/bmesh/operators/bmo_fill_grid.c
+++ b/source/blender/bmesh/operators/bmo_fill_grid.c
@@ -313,12 +313,12 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const unsigned int xt
if (use_interp_simple == false) {
float co_a[3], co_b[3];
- barycentric_transform(
+ transform_point_by_tri_v3(
co_a,
v_grid[x]->co,
tri_t[0], tri_t[1], tri_t[2],
tri_a[0], tri_a[1], tri_a[2]);
- barycentric_transform(
+ transform_point_by_tri_v3(
co_b,
v_grid[(xtot * ytot) + (x - xtot)]->co,
tri_t[0], tri_t[1], tri_t[2],
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index 0ca4ddf8d55..f2e5ebad9c8 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -389,7 +389,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
const bool use_outset = BMO_slot_bool_get(op->slots_in, "use_outset");
const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary") && (use_outset == false);
const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
- const bool use_even_boundry = use_even_offset; /* could make own option */
+ const bool use_even_boundary = use_even_offset; /* could make own option */
const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
const bool use_edge_rail = BMO_slot_bool_get(op->slots_in, "use_edge_rail");
const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate");
@@ -716,7 +716,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
else if (vert_edge_tag_tot == 1) { /* 1 edge user - boundary vert, not so common */
const float *e_no_a = edge_info[vecpair[0]].no;
- if (use_even_boundry) {
+ if (use_even_boundary) {
/* This case where only one edge attached to v_split
* is used - ei - the face to inset is on a boundary.
@@ -984,7 +984,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
const float fac = (depth *
(use_relative_offset ? bm_edge_info_average_length(v, edge_info) : 1.0f) *
- (use_even_boundry ? BM_vert_calc_shell_factor(v) : 1.0f));
+ (use_even_boundary ? BM_vert_calc_shell_factor(v) : 1.0f));
madd_v3_v3v3fl(varr_co[i], v->co, v->no, fac);
}
}
diff --git a/source/blender/bmesh/operators/bmo_poke.c b/source/blender/bmesh/operators/bmo_poke.c
index 26f20656478..363e395e082 100644
--- a/source/blender/bmesh/operators/bmo_poke.c
+++ b/source/blender/bmesh/operators/bmo_poke.c
@@ -101,7 +101,7 @@ void bmo_poke_exec(BMesh *bm, BMOperator *op)
do {
BMLoop *l_new;
- f_new = BM_face_create_quad_tri(bm, l_iter->v, l_iter->next->v, v_center, NULL, f, false);
+ f_new = BM_face_create_quad_tri(bm, l_iter->v, l_iter->next->v, v_center, NULL, f, BM_CREATE_NOP);
l_new = BM_FACE_FIRST_LOOP(f_new);
if (i == 0) {
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index f0e31b78ca0..e69dcca6342 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -405,7 +405,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
v2 = eva[icoface[a][1]];
v3 = eva[icoface[a][2]];
- eftemp = BM_face_create_quad_tri(bm, v1, v2, v3, NULL, NULL, false);
+ eftemp = BM_face_create_quad_tri(bm, v1, v2, v3, NULL, NULL, BM_CREATE_NOP);
BM_ITER_ELEM (l, &liter, eftemp, BM_LOOPS_OF_FACE) {
BMO_elem_flag_enable(bm, l->e, EDGE_MARK);
@@ -476,14 +476,14 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op)
tv[monkeyf[i][1] + i - monkeyo],
tv[monkeyf[i][2] + i - monkeyo],
(monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeyf[i][3] + i - monkeyo] : NULL,
- NULL, false);
+ NULL, BM_CREATE_NOP);
BM_face_create_quad_tri(bm,
tv[monkeynv + monkeyf[i][2] + i - monkeyo],
tv[monkeynv + monkeyf[i][1] + i - monkeyo],
tv[monkeynv + monkeyf[i][0] + i - monkeyo],
(monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeynv + monkeyf[i][3] + i - monkeyo] : NULL,
- NULL, false);
+ NULL, BM_CREATE_NOP);
}
MEM_freeN(tv);
@@ -535,7 +535,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
if (a && cap_ends) {
BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, false);
+ f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
@@ -553,7 +553,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
if (cap_ends) {
BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, false);
+ f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
@@ -622,12 +622,12 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
if (cap_ends) {
BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, false);
+ f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
- f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, false);
+ f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
- BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, false);
+ BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, BM_CREATE_NOP);
}
else {
firstv1 = v1;
@@ -644,9 +644,9 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
if (cap_ends) {
BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, false);
+ f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
- f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, false);
+ f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
@@ -654,7 +654,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW);
}
- BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, false);
+ BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, BM_CREATE_NOP);
BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.000001);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
@@ -726,14 +726,14 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_enable(bm, v8, VERT_MARK);
/* the four sides */
- BM_face_create_quad_tri(bm, v5, v6, v2, v1, NULL, false);
- BM_face_create_quad_tri(bm, v6, v7, v3, v2, NULL, false);
- BM_face_create_quad_tri(bm, v7, v8, v4, v3, NULL, false);
- BM_face_create_quad_tri(bm, v8, v5, v1, v4, NULL, false);
+ BM_face_create_quad_tri(bm, v5, v6, v2, v1, NULL, BM_CREATE_NOP);
+ BM_face_create_quad_tri(bm, v6, v7, v3, v2, NULL, BM_CREATE_NOP);
+ BM_face_create_quad_tri(bm, v7, v8, v4, v3, NULL, BM_CREATE_NOP);
+ BM_face_create_quad_tri(bm, v8, v5, v1, v4, NULL, BM_CREATE_NOP);
/* top/bottom */
- BM_face_create_quad_tri(bm, v1, v2, v3, v4, NULL, false);
- BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, false);
+ BM_face_create_quad_tri(bm, v1, v2, v3, v4, NULL, BM_CREATE_NOP);
+ BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, BM_CREATE_NOP);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index 814649c7dbf..75f9feef413 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -528,7 +528,8 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op,
int i, j, keepvert = 0;
const float dist = BMO_slot_float_get(op->slots_in, "dist");
- const float dist3 = dist * 3.0f;
+ const float dist_sq = dist * dist;
+ const float dist3 = (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")) {
@@ -576,7 +577,7 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op,
continue;
}
- if (compare_len_v3v3(v_check->co, v_other->co, dist)) {
+ 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_elem_flag_test(bm, v_other, VERT_KEEP)) {
diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
index af5f35f2a75..a250c716c16 100644
--- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c
+++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
@@ -156,7 +156,7 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in
return sys;
}
-/* Compute weigth between vertice v_i and all your neighbors
+/* Compute weight between vertice v_i and all your neighbors
* weight between v_i and v_neighbor
* Wij = cot(alpha) + cot(beta) / (4.0 * total area of all faces * sum all weight)
* v_i *
diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
index e13a9df4474..c01ad10d716 100644
--- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c
+++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
@@ -727,8 +727,8 @@ static void bm_edgering_pair_interpolate(BMesh *bm, LoopPairStore *lpair,
tri_tmp = tri_array[i];
- barycentric_transform(co_a, v_a->co, UNPACK3(tri_tmp), UNPACK3(tri_sta));
- barycentric_transform(co_b, v_b->co, UNPACK3(tri_tmp), UNPACK3(tri_end));
+ transform_point_by_tri_v3(co_a, v_a->co, UNPACK3(tri_tmp), UNPACK3(tri_sta));
+ transform_point_by_tri_v3(co_b, v_b->co, UNPACK3(tri_tmp), UNPACK3(tri_end));
interp_v3_v3v3(((BMVert *)v_iter->data)->co, co_a, co_b, (float)i / (float)(resolu - 1));
}
@@ -920,13 +920,13 @@ static void bm_edgering_pair_order(BMesh *bm,
}
BLI_assert(node != NULL);
- BLI_rotatelist_first(lb_b, node);
+ BLI_listbase_rotate_first(lb_b, node);
/* now check we are winding the same way */
if (bm_edgering_pair_order_is_flipped(bm, el_store_a, el_store_b)) {
BM_edgeloop_flip(bm, el_store_b);
/* re-ensure the first node */
- BLI_rotatelist_first(lb_b, node);
+ BLI_listbase_rotate_first(lb_b, node);
}
/* sanity checks that we are aligned & winding now */
diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c
index 8e254b2e499..986583cc21b 100644
--- a/source/blender/bmesh/operators/bmo_triangulate.c
+++ b/source/blender/bmesh/operators/bmo_triangulate.c
@@ -26,10 +26,12 @@
* Triangulate faces, also defines triangle fill.
*/
+#include "MEM_guardedalloc.h"
+
#include "DNA_listBase.h"
#include "BLI_math.h"
-#include "BLI_smallhash.h"
+#include "BLI_sort_utils.h"
#include "BLI_scanfill.h"
#include "bmesh.h"
@@ -56,6 +58,10 @@ void bmo_triangulate_exec(BMesh *bm, BMOperator *op)
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
}
+struct SortNormal {
+ float value; /* keep first */
+ float no[3];
+};
void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
{
@@ -65,54 +71,153 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
BMEdge *e;
ScanFillContext sf_ctx;
/* ScanFillEdge *sf_edge; */ /* UNUSED */
- ScanFillVert *sf_vert_1, *sf_vert_2;
ScanFillFace *sf_tri;
- SmallHash hash;
- float normal[3], *normal_pt;
+ GHash *sf_vert_map;
+ float normal[3];
const int scanfill_flag = BLI_SCANFILL_CALC_HOLES | BLI_SCANFILL_CALC_POLYS | BLI_SCANFILL_CALC_LOOSE;
+ bool calc_winding = false;
- BLI_smallhash_init_ex(&hash, BMO_slot_buffer_count(op->slots_in, "edges"));
+ sf_vert_map = BLI_ghash_ptr_new_ex(__func__, BMO_slot_buffer_count(op->slots_in, "edges"));
BMO_slot_vec_get(op->slots_in, "normal", normal);
BLI_scanfill_begin(&sf_ctx);
BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ ScanFillVert *sf_verts[2];
+ BMVert **e_verts = &e->v1;
+ unsigned int i;
+
BMO_elem_flag_enable(bm, e, EDGE_MARK);
-
- if ((sf_vert_1 = BLI_smallhash_lookup(&hash, (uintptr_t)e->v1)) == NULL) {
- sf_vert_1 = BLI_scanfill_vert_add(&sf_ctx, e->v1->co);
- sf_vert_1->tmp.p = e->v1;
- BLI_smallhash_insert(&hash, (uintptr_t)e->v1, sf_vert_1);
- }
-
- if ((sf_vert_2 = BLI_smallhash_lookup(&hash, (uintptr_t)e->v2)) == NULL) {
- sf_vert_2 = BLI_scanfill_vert_add(&sf_ctx, e->v2->co);
- sf_vert_2->tmp.p = e->v2;
- BLI_smallhash_insert(&hash, (uintptr_t)e->v2, sf_vert_2);
+
+ calc_winding = (calc_winding || BM_edge_is_boundary(e));
+
+ for (i = 0; i < 2; i++) {
+ if ((sf_verts[i] = BLI_ghash_lookup(sf_vert_map, e_verts[i])) == NULL) {
+ sf_verts[i] = BLI_scanfill_vert_add(&sf_ctx, e_verts[i]->co);
+ sf_verts[i]->tmp.p = e_verts[i];
+ BLI_ghash_insert(sf_vert_map, e_verts[i], sf_verts[i]);
+ }
}
-
- /* sf_edge = */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_1, sf_vert_2);
+ /* sf_edge = */ BLI_scanfill_edge_add(&sf_ctx, UNPACK2(sf_verts));
/* sf_edge->tmp.p = e; */ /* UNUSED */
}
+ BLI_ghash_free(sf_vert_map, NULL, NULL);
+
if (is_zero_v3(normal)) {
- normal_pt = NULL;
+ /* calculate the normal from the cross product of vert-edge pairs.
+ * Since we don't know winding, just accumulate */
+ ScanFillVert *sf_vert;
+ struct SortNormal *nors;
+ const unsigned int nors_tot = BLI_ghash_size(sf_vert_map);
+ unsigned int i;
+ bool is_degenerate = true;
+
+ nors = MEM_mallocN(sizeof(*nors) * nors_tot, __func__);
+
+ for (sf_vert = sf_ctx.fillvertbase.first, i = 0; sf_vert; sf_vert = sf_vert->next, i++) {
+ BMVert *v = sf_vert->tmp.p;
+ BMIter eiter;
+ BMEdge *e, *e_pair[2];
+ unsigned int e_index = 0;
+
+ nors[i].value = -1.0f;
+
+ /* only use if 'is_degenerate' stays true */
+ add_v3_v3(normal, v->no);
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
+ if (e_index == 2) {
+ e_index = 0;
+ break;
+ }
+ e_pair[e_index++] = e;
+ }
+ }
+
+ if (e_index == 2) {
+ float dir_a[3], dir_b[3];
+
+ is_degenerate = false;
+
+ sub_v3_v3v3(dir_a, v->co, BM_edge_other_vert(e_pair[0], v)->co);
+ sub_v3_v3v3(dir_b, v->co, BM_edge_other_vert(e_pair[1], v)->co);
+
+ cross_v3_v3v3(nors[i].no, dir_a, dir_b);
+ nors[i].value = len_squared_v3(nors[i].no);
+
+ /* only to get deterministic behavior (for initial normal) */
+ if (len_squared_v3(dir_a) > len_squared_v3(dir_b)) {
+ negate_v3(nors[i].no);
+ }
+ }
+ }
+
+ if (UNLIKELY(is_degenerate)) {
+ /* no vertices have 2 edges?
+ * in this case fall back to the average vertex normals */
+ }
+ else {
+ qsort(nors, nors_tot, sizeof(*nors), BLI_sortutil_cmp_float_reverse);
+
+ copy_v3_v3(normal, nors[0].no);
+ for (i = 0; i < nors_tot; i++) {
+ if (UNLIKELY(nors[i].value == -1.0f)) {
+ break;
+ }
+ if (dot_v3v3(normal, nors[i].no) < 0.0f) {
+ negate_v3(nors[i].no);
+ }
+ add_v3_v3(normal, nors[i].no);
+ }
+ normalize_v3(normal);
+ }
+
+ MEM_freeN(nors);
}
else {
- normalize_v3(normal);
- normal_pt = normal;
+ calc_winding = false;
}
- BLI_scanfill_calc_ex(&sf_ctx, scanfill_flag, normal_pt);
-
+ normalize_v3(normal);
+
+ BLI_scanfill_calc_ex(&sf_ctx, scanfill_flag, normal);
+
+
+ /* if we have existing faces, base winding on those */
+ if (calc_winding) {
+ int winding_votes = 0;
+ for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ BMVert *v_tri[3] = {sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p};
+ unsigned int i, i_prev;
+
+ for (i = 0, i_prev = 2; i < 3; i_prev = i++) {
+ e = BM_edge_exists(v_tri[i], v_tri[i_prev]);
+ if (e && BM_edge_is_boundary(e) && BMO_elem_flag_test(bm, e, EDGE_MARK)) {
+ winding_votes += (e->l->v == v_tri[i]) ? 1 : -1;
+ }
+ }
+ }
+
+ if (winding_votes < 0) {
+ for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ SWAP(struct ScanFillVert *, sf_tri->v2, sf_tri->v3);
+ }
+ }
+ }
+
+
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
- BMFace *f = BM_face_create_quad_tri(bm,
- sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p, NULL,
- NULL, true);
+ BMFace *f;
BMLoop *l;
BMIter liter;
+
+ f = BM_face_create_quad_tri(bm,
+ sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p, NULL,
+ NULL, BM_CREATE_NO_DOUBLE);
BMO_elem_flag_enable(bm, f, ELE_NEW);
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
@@ -123,7 +228,6 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
}
BLI_scanfill_end(&sf_ctx);
- BLI_smallhash_release(&hash);
if (use_beauty) {
BMOperator bmop;
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index 600386893dd..d2d1c0854de 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -63,7 +63,7 @@ void bmo_transform_exec(BMesh *UNUSED(bm), BMOperator *op)
if (!is_zero_m4(mat_space)) {
invert_m4_m4(imat_space, mat_space);
- mul_serie_m4(mat, imat_space, mat, mat_space, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, imat_space, mat, mat_space);
}
BMO_ITER (v, &iter, op->slots_in, "verts", BM_VERT) {
diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c
index 90d26a775d3..6639e767e77 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.c
+++ b/source/blender/bmesh/tools/bmesh_beautify.c
@@ -67,6 +67,7 @@ static unsigned int erot_gsetutil_hash(const void *ptr)
return BLI_ghashutil_inthash_v4(&e_state->v1);
}
#endif
+#if 0
static int erot_gsetutil_cmp(const void *a, const void *b)
{
const EdRotState *e_state_a = (const EdRotState *)a;
@@ -81,10 +82,10 @@ static int erot_gsetutil_cmp(const void *a, const void *b)
else if (e_state_a->f2 > e_state_b->f2) return 1;
else return 0;
}
-
+#endif
static GSet *erot_gset_new(void)
{
- return BLI_gset_new(BLI_ghashutil_inthash_v4_p, erot_gsetutil_cmp, __func__);
+ return BLI_gset_new(BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, __func__);
}
/* ensure v0 is smaller */
@@ -142,10 +143,10 @@ static float bm_edge_calc_rotate_beauty__area(
float axis_mat[3][3];
// printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
- BLI_assert((ELEM3(v1, v2, v3, v4) == false) &&
- (ELEM3(v2, v1, v3, v4) == false) &&
- (ELEM3(v3, v1, v2, v4) == false) &&
- (ELEM3(v4, v1, v2, v3) == false));
+ BLI_assert((ELEM(v1, v2, v3, v4) == false) &&
+ (ELEM(v2, v1, v3, v4) == false) &&
+ (ELEM(v3, v1, v2, v4) == false) &&
+ (ELEM(v4, v1, v2, v3) == false));
is_zero_a = (normal_tri_v3(no_a, v2, v3, v4) <= FLT_EPSILON);
is_zero_b = (normal_tri_v3(no_b, v2, v4, v1) <= FLT_EPSILON);
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index c583464ab6d..4a9fb677257 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -187,6 +187,7 @@ typedef struct BevelParams {
bool limit_offset; /* should offsets be limited by collisions? */
const struct MDeformVert *dvert; /* vertex group array, maybe set if vertex_only */
int vertex_group; /* vertex group index, maybe set if vertex_only */
+ int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */
} BevelParams;
// #pragma GCC diagnostic ignored "-Wpadded"
@@ -356,11 +357,12 @@ static BMFace *boundvert_rep_face(BoundVert *v)
* Make ngon from verts alone.
* Make sure to properly copy face attributes and do custom data interpolation from
* corresponding elements of face_arr, if that is non-NULL, else from facerep.
+ * If mat_nr >= 0 then the material of the face is set to that.
*
* \note ALL face creation goes through this function, this is important to keep!
*/
static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv,
- BMFace **face_arr, BMFace *facerep, bool do_interp)
+ BMFace **face_arr, BMFace *facerep, int mat_nr, bool do_interp)
{
BMIter iter;
BMLoop *l;
@@ -395,22 +397,24 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv,
BM_elem_flag_enable(f, BM_ELEM_TAG);
}
+ if (mat_nr >= 0)
+ f->mat_nr = mat_nr;
return f;
}
static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- BMFace *facerep, bool do_interp)
+ BMFace *facerep, int mat_nr, bool do_interp)
{
BMVert *varr[4] = {v1, v2, v3, v4};
- return bev_create_ngon(bm, varr, v4 ? 4 : 3, NULL, facerep, do_interp);
+ return bev_create_ngon(bm, varr, v4 ? 4 : 3, NULL, facerep, mat_nr, do_interp);
}
static BMFace *bev_create_quad_tri_ex(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4)
+ BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4, int mat_nr)
{
BMVert *varr[4] = {v1, v2, v3, v4};
BMFace *farr[4] = {f1, f2, f3, f4};
- return bev_create_ngon(bm, varr, v4 ? 4 : 3, farr, f1, true);
+ return bev_create_ngon(bm, varr, v4 ? 4 : 3, farr, f1, mat_nr, true);
}
@@ -490,13 +494,13 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f
* one side (f1, arbitrarily), and interpolate them all on that side.
* For face data, use f1 (arbitrarily) as face representative. */
static BMFace *bev_create_quad_straddle(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- BMFace *f1, BMFace *f2, bool is_seam)
+ BMFace *f1, BMFace *f2, int mat_nr, bool is_seam)
{
BMFace *f, *facerep;
BMLoop *l;
BMIter iter;
- f = bev_create_quad_tri(bm, v1, v2, v3, v4, f1, false);
+ f = bev_create_quad_tri(bm, v1, v2, v3, v4, f1, mat_nr, false);
if (!f)
return NULL;
@@ -1627,7 +1631,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
* corresponding ones that changed on the other end.
* The graph is dynamic in the sense that having an offset that
* doesn't meet the user spec can be added as the search proceeds.
- * We want this search to be deterministic (not dependendent
+ * We want this search to be deterministic (not dependent
* on order of processing through hash table), so as to avoid
* flicker to to different decisions made if search is different
* while dragging the offset number in the UI. So look for the
@@ -1719,7 +1723,7 @@ static BoundVert *pipe_test(BevVert *bv)
sub_v3_v3v3(dir3, BM_edge_other_vert(v3->ebev->e, bv->v)->co, bv->v->co);
normalize_v3(dir1);
normalize_v3(dir3);
- if (angle_v3v3(dir1, dir3) < BEVEL_EPSILON_BIG) {
+ if (angle_normalized_v3v3(dir1, dir3) < BEVEL_EPSILON_BIG) {
epipe = v1->ebev;
break;
}
@@ -1865,7 +1869,7 @@ static float sabin_gamma(int n)
k2 = k * k;
k4 = k2 * k2;
k6 = k4 * k2;
- y = pow(1.73205080756888 * sqrt(64.0 * k6 - 144.0 * k4 + 135.0 * k2 - 27.0) + 9.0 * k,
+ y = pow(M_SQRT3 * sqrt(64.0 * k6 - 144.0 * k4 + 135.0 * k2 - 27.0) + 9.0 * k,
1.0 / 3.0);
x = 0.480749856769136 * y - (0.231120424783545 * (12.0 * k2 - 9.0)) / y;
ans = (k * x + 2.0 * k2 - 1.0) / (x * x * (k * x + 1.0));
@@ -2258,7 +2262,7 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
bndv = bndv->next;
}
/* center vertex */
- w = 0.57735027f; /* 1/sqrt(3) */
+ w = (float)(1.0 / M_SQRT3);
co[0] = w;
co[1] = w;
co[2] = w;
@@ -2500,6 +2504,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
BMVert *bmv1, *bmv2, *bmv3, *bmv4;
BMFace *f, *f2, *f23;
BoundVert *vpipe;
+ int mat_nr = bp->mat_nr;
n = bv->vmesh->count;
ns = bv->vmesh->seg;
@@ -2552,7 +2557,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
if (odd && k == ns2 && f2 && !v->any_seam)
f23 = f2;
bev_create_quad_tri_ex(bm, bmv1, bmv2, bmv3, bmv4,
- f, f23, f23, f);
+ f, f23, f23, f, mat_nr);
}
}
} while ((v = v->next) != vm->boundstart);
@@ -2589,13 +2594,13 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
BLI_array_append(vf, v->any_seam ? f : boundvert_rep_face(v));
} while ((v = v->next) != vm->boundstart);
f = boundvert_rep_face(vm->boundstart);
- bev_create_ngon(bm, vv, BLI_array_count(vv), vf, f, true);
+ bev_create_ngon(bm, vv, BLI_array_count(vv), vf, f, mat_nr, true);
BLI_array_free(vv);
}
}
-static BMFace *bevel_build_poly(BMesh *bm, BevVert *bv)
+static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
{
BMFace *f;
int n, k;
@@ -2625,7 +2630,7 @@ static BMFace *bevel_build_poly(BMesh *bm, BevVert *bv)
}
} while ((v = v->next) != vm->boundstart);
if (n > 2) {
- f = bev_create_ngon(bm, vv, n, vf, boundvert_rep_face(v), true);
+ f = bev_create_ngon(bm, vv, n, vf, boundvert_rep_face(v), bp->mat_nr, true);
}
else {
f = NULL;
@@ -2634,12 +2639,12 @@ static BMFace *bevel_build_poly(BMesh *bm, BevVert *bv)
return f;
}
-static void bevel_build_trifan(BMesh *bm, BevVert *bv)
+static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
{
BMFace *f;
BLI_assert(next_bev(bv, NULL)->seg == 1 || bv->selcount == 1);
- f = bevel_build_poly(bm, bv);
+ f = bevel_build_poly(bp, bm, bv);
if (f) {
/* we have a polygon which we know starts at the previous vertex, make it into a fan */
@@ -2669,12 +2674,12 @@ static void bevel_build_trifan(BMesh *bm, BevVert *bv)
}
}
-static void bevel_build_quadstrip(BMesh *bm, BevVert *bv)
+static void bevel_build_quadstrip(BevelParams *bp, BMesh *bm, BevVert *bv)
{
BMFace *f;
BLI_assert(bv->selcount == 2);
- f = bevel_build_poly(bm, bv);
+ f = bevel_build_poly(bp, bm, bv);
if (f) {
/* we have a polygon which we know starts at this vertex, make it into strips */
@@ -2813,16 +2818,16 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
bevel_build_one_wire(bm, bv);
break;
case M_POLY:
- bevel_build_poly(bm, bv);
+ bevel_build_poly(bp, bm, bv);
break;
case M_ADJ:
bevel_build_rings(bp, bm, bv);
break;
case M_TRI_FAN:
- bevel_build_trifan(bm, bv);
+ bevel_build_trifan(bp, bm, bv);
break;
case M_QUAD_STRIP:
- bevel_build_quadstrip(bm, bv);
+ bevel_build_quadstrip(bp, bm, bv);
break;
}
}
@@ -3173,7 +3178,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
}
if (do_rebuild) {
n = BLI_array_count(vv);
- f_new = bev_create_ngon(bm, vv, n, NULL, f, true);
+ f_new = bev_create_ngon(bm, vv, n, NULL, f, -1, true);
for (k = 0; k < BLI_array_count(vv_fix); k++) {
bev_merge_uvs(bm, vv_fix[k]);
@@ -3384,6 +3389,7 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
BMEdge *bme1, *bme2;
BMFace *f1, *f2, *f;
int k, nseg, i1, i2, odd, mid;
+ int mat_nr = bp->mat_nr;
if (!BM_edge_is_manifold(bme))
return;
@@ -3422,7 +3428,7 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
vm2 = bv2->vmesh;
if (nseg == 1) {
- bev_create_quad_straddle(bm, bmv1, bmv2, bmv3, bmv4, f1, f2, e1->is_seam);
+ bev_create_quad_straddle(bm, bmv1, bmv2, bmv3, bmv4, f1, f2, mat_nr, e1->is_seam);
}
else {
bmv1i = bmv1;
@@ -3433,11 +3439,11 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
bmv4i = mesh_vert(vm1, i1, 0, k)->v;
bmv3i = mesh_vert(vm2, i2, 0, nseg - k)->v;
if (odd && k == mid + 1) {
- bev_create_quad_straddle(bm, bmv1i, bmv2i, bmv3i, bmv4i, f1, f2, e1->is_seam);
+ bev_create_quad_straddle(bm, bmv1i, bmv2i, bmv3i, bmv4i, f1, f2, mat_nr, e1->is_seam);
}
else {
f = (k <= mid) ? f1 : f2;
- bev_create_quad_tri(bm, bmv1i, bmv2i, bmv3i, bmv4i, f, true);
+ bev_create_quad_tri(bm, bmv1i, bmv2i, bmv3i, bmv4i, f, mat_nr, true);
}
bmv1i = bmv4i;
bmv2i = bmv3i;
@@ -3676,7 +3682,7 @@ static float bevel_limit_offset(BMesh *bm, BevelParams *bp)
void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type,
const float segments, const float profile,
const bool vertex_only, const bool use_weights, const bool limit_offset,
- const struct MDeformVert *dvert, const int vertex_group)
+ const struct MDeformVert *dvert, const int vertex_group, const int mat)
{
BMIter iter;
BMVert *v, *v_next;
@@ -3694,6 +3700,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type,
bp.limit_offset = limit_offset;
bp.dvert = dvert;
bp.vertex_group = vertex_group;
+ bp.mat_nr = mat;
if (bp.pro_super_r < 0.60f)
bp.pro_super_r = 0.60f; /* TODO: implement 0 case properly */
diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h
index 0c088ce0238..52d8faa5401 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.h
+++ b/source/blender/bmesh/tools/bmesh_bevel.h
@@ -31,6 +31,7 @@ struct MDeformVert;
void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, const float segments,
const float profile, const bool vertex_only, const bool use_weights,
- const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group);
+ const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group,
+ const int mat);
#endif /* __BMESH_BEVEL_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c
index 0ecb8066ac1..ae9b882cea0 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.c
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c
@@ -124,7 +124,7 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con
/* add plane-aligned verts to the stack
* and check we have verts from both sides in this face,
- * ... that the face doesn't only have boundry verts on the plane for eg. */
+ * ... that the face doesn't only have boundary verts on the plane for eg. */
l_iter = l_first;
do {
if (vert_is_center_test(l_iter->v)) {
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index 4b6209fc4eb..ef1783cc693 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -414,10 +414,10 @@ static void bm_decim_triangulate_end(BMesh *bm)
BM_vert_in_edge(e, l_b->next->v) ? l_b->prev->v : l_b->next->v,
};
- BLI_assert(ELEM3(vquad[0], vquad[1], vquad[2], vquad[3]) == false);
- BLI_assert(ELEM3(vquad[1], vquad[0], vquad[2], vquad[3]) == false);
- BLI_assert(ELEM3(vquad[2], vquad[1], vquad[0], vquad[3]) == false);
- BLI_assert(ELEM3(vquad[3], vquad[1], vquad[2], vquad[0]) == false);
+ BLI_assert(ELEM(vquad[0], vquad[1], vquad[2], vquad[3]) == false);
+ BLI_assert(ELEM(vquad[1], vquad[0], vquad[2], vquad[3]) == false);
+ BLI_assert(ELEM(vquad[2], vquad[1], vquad[0], vquad[3]) == false);
+ BLI_assert(ELEM(vquad[3], vquad[1], vquad[2], vquad[0]) == false);
if (is_quad_convex_v3(vquad[0]->co, vquad[1]->co, vquad[2]->co, vquad[3]->co)) {
/* highly unlikely to fail, but prevents possible double-ups */
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c
index a08aa6184b5..1328b81b746 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.c
+++ b/source/blender/bmesh/tools/bmesh_edgenet.c
@@ -393,8 +393,8 @@ static LinkNode *bm_edgenet_path_calc_best(
if (path == NULL) {
return NULL;
}
- else if (path_cost <= 1) {
- /* any face that takes 1-2 iterations to find we consider valid */
+ else if (path_cost < 1) {
+ /* any face that takes 1 iteration to find we consider valid */
return path;
}
else {
@@ -465,7 +465,6 @@ void BM_mesh_edgenet(BMesh *bm,
if (use_edge_tag == false) {
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
BM_elem_flag_set(e, BM_ELEM_TAG, bm_edge_step_ok(e));
}
}
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
new file mode 100644
index 00000000000..4d87c3e3551
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -0,0 +1,1302 @@
+/*
+ * ***** 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 *****
+ */
+
+/** \file blender/bmesh/tools/bmesh_intersect.c
+ * \ingroup bmesh
+ *
+ * Cut meshes along intersections.
+ *
+ * Boolean-like modeling operation (without calculating inside/outside).
+ *
+ * Supported:
+ * - Concave faces.
+ * - Non-planar faces.
+ * - Custom-data (UV's etc).
+ *
+ * Unsupported:
+ * - Intersecting between different meshes.
+ * - No support for holes (cutting a hole into a single face).
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+#include "BLI_memarena.h"
+#include "BLI_alloca.h"
+#include "BLI_sort_utils.h"
+
+#include "BLI_linklist_stack.h"
+#include "BLI_stackdefines.h"
+#include "BLI_array.h"
+
+#include "BLI_kdopbvh.h"
+
+#include "bmesh.h"
+#include "bmesh_intersect.h" /* own include */
+
+#include "tools/bmesh_edgesplit.h"
+
+#include "BLI_strict_flags.h"
+
+/*
+ * Some of these depend on each other:
+ */
+
+/* splice verts into existing edges */
+#define USE_SPLICE
+/* split faces by intersecting edges */
+#define USE_NET
+/* split resulting edges */
+#define USE_SEPARATE
+/* remove verts created by intersecting triangles */
+#define USE_DISSOLVE
+
+/* strict asserts that may fail in practice (handy for debugging cases which should succeed) */
+// #define USE_PARANOID
+/* use accelerated overlap check */
+#define USE_BVH
+
+
+static void tri_v3_scale(
+ float v1[3], float v2[3], float v3[3],
+ const float t)
+{
+ float p[3];
+
+ mid_v3_v3v3v3(p, v1, v2, v3);
+
+ interp_v3_v3v3(v1, p, v1, t);
+ interp_v3_v3v3(v2, p, v2, t);
+ interp_v3_v3v3(v3, p, v3, t);
+}
+
+#ifdef USE_DISSOLVE
+/* other edge when a vert only has 2 edges */
+static BMEdge *bm_vert_other_edge(BMVert *v, BMEdge *e)
+{
+ BLI_assert(BM_vert_is_edge_pair(v));
+ BLI_assert(BM_vert_in_edge(e, v));
+
+ if (v->e != e) {
+ return v->e;
+ }
+ else {
+ return BM_DISK_EDGE_NEXT(v->e, v);
+ }
+}
+#endif
+
+enum ISectType {
+ IX_NONE = -1,
+ IX_EDGE_TRI_EDGE0,
+ IX_EDGE_TRI_EDGE1,
+ IX_EDGE_TRI_EDGE2,
+ IX_EDGE_TRI,
+ IX_TOT,
+};
+
+struct ISectEpsilon {
+ float eps, eps_sq;
+ float eps2x, eps2x_sq;
+ float eps_margin, eps_margin_sq;
+};
+
+struct ISectState {
+ BMesh *bm;
+ GHash *edgetri_cache; /* int[4]: BMVert */
+ GHash *edge_verts; /* BMEdge: LinkList(of verts), new and original edges */
+ GHash *face_edges; /* BMFace-index: LinkList(of edges), only original faces */
+ GSet *wire_edges; /* BMEdge (could use tags instead) */
+ LinkNode *vert_dissolve; /* BMVert's */
+
+ MemArena *mem_arena;
+
+ struct ISectEpsilon epsilon;
+};
+
+/**
+ * Store as value in GHash so we can get list-length without counting every time.
+ * Also means we don't need to update the GHash value each time.
+ */
+struct LinkBase {
+ LinkNode *list;
+ unsigned int list_len;
+};
+
+static bool ghash_insert_link(
+ GHash *gh, void *key, void *val, bool use_test,
+ MemArena *mem_arena)
+{
+ struct LinkBase *ls_base;
+ LinkNode *ls;
+
+ ls_base = BLI_ghash_lookup(gh, key);
+
+ if (ls_base) {
+ if (use_test && (BLI_linklist_index(ls_base->list, key) != -1)) {
+ return false;
+ }
+ }
+ else {
+ ls_base = BLI_memarena_alloc(mem_arena, sizeof(*ls_base));
+ ls_base->list = NULL;
+ ls_base->list_len = 0;
+ BLI_ghash_insert(gh, key, ls_base);
+ }
+
+ ls = BLI_memarena_alloc(mem_arena, sizeof(*ls));
+ ls->next = ls_base->list;
+ ls->link = val;
+ ls_base->list = ls;
+ ls_base->list_len += 1;
+
+ return true;
+}
+
+struct vert_sort_t {
+ float val;
+ BMVert *v;
+};
+
+#ifdef USE_SPLICE
+static void edge_verts_sort(const float co[3], struct LinkBase *v_ls_base)
+{
+ /* not optimal but list will be typically < 5 */
+ unsigned int i;
+ struct vert_sort_t *vert_sort = BLI_array_alloca(vert_sort, v_ls_base->list_len);
+ LinkNode *node;
+
+ BLI_assert(v_ls_base->list_len > 1);
+
+ for (i = 0, node = v_ls_base->list; i < v_ls_base->list_len; i++, node = node->next) {
+ BMVert *v = node->link;
+ BLI_assert(v->head.htype == BM_VERT);
+ vert_sort[i].val = len_squared_v3v3(co, v->co);
+ vert_sort[i].v = v;
+ }
+
+ qsort(vert_sort, v_ls_base->list_len, sizeof(*vert_sort), BLI_sortutil_cmp_float);
+
+ for (i = 0, node = v_ls_base->list; i < v_ls_base->list_len; i++, node = node->next) {
+ node->link = vert_sort[i].v;
+ }
+}
+#endif
+
+static void edge_verts_add(
+ struct ISectState *s,
+ BMEdge *e,
+ BMVert *v,
+ const bool use_test
+ )
+{
+ BLI_assert(e->head.htype == BM_EDGE);
+ BLI_assert(v->head.htype == BM_VERT);
+ ghash_insert_link(s->edge_verts, (void *)e, v, use_test, s->mem_arena);
+}
+
+static void face_edges_add(
+ struct ISectState *s,
+ const int f_index,
+ BMEdge *e,
+ const bool use_test)
+{
+ void *f_index_key = SET_INT_IN_POINTER(f_index);
+ BLI_assert(e->head.htype == BM_EDGE);
+ BLI_assert(BM_edge_in_face(e, s->bm->ftable[f_index]) == false);
+ BLI_assert(BM_elem_index_get(s->bm->ftable[f_index]) == f_index);
+
+ ghash_insert_link(s->face_edges, f_index_key, e, use_test, s->mem_arena);
+}
+
+#ifdef USE_NET
+static void face_edges_split(
+ BMesh *bm,
+ BMFace *f,
+ struct LinkBase *e_ls_base)
+{
+ unsigned int i;
+ BMEdge **edge_arr = BLI_array_alloca(edge_arr, e_ls_base->list_len);
+ LinkNode *node;
+ BLI_assert(f->head.htype == BM_FACE);
+
+ for (i = 0, node = e_ls_base->list; i < e_ls_base->list_len; i++, node = node->next) {
+ edge_arr[i] = node->link;
+ }
+ BLI_assert(node == NULL);
+
+#ifdef USE_DUMP
+ printf("# %s: %d %u\n", __func__, BM_elem_index_get(f), e_ls_base->list_len);
+#endif
+
+ BM_face_split_edgenet(bm, f, edge_arr, (int)e_ls_base->list_len, NULL, NULL);
+}
+#endif
+
+#ifdef USE_DISSOLVE
+static void vert_dissolve_add(
+ struct ISectState *s,
+ BMVert *v)
+{
+ BLI_assert(v->head.htype == BM_VERT);
+ BLI_assert(!BM_elem_flag_test(v, BM_ELEM_TAG));
+ BLI_assert(BLI_linklist_index(s->vert_dissolve, v) == -1);
+
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ BLI_linklist_prepend_arena(&s->vert_dissolve, v, s->mem_arena);
+}
+#endif
+
+static enum ISectType intersect_line_tri(
+ const float p0[3], const float p1[3],
+ const float *t_cos[3], const float t_nor[3],
+ float r_ix[3],
+ const struct ISectEpsilon *e)
+{
+ float p_dir[3];
+ unsigned int i_t0;
+ float fac;
+
+ sub_v3_v3v3(p_dir, p0, p1);
+ normalize_v3(p_dir);
+
+ for (i_t0 = 0; i_t0 < 3; i_t0++) {
+ const unsigned int i_t1 = (i_t0 + 1) % 3;
+ float te_dir[3];
+
+ sub_v3_v3v3(te_dir, t_cos[i_t0], t_cos[i_t1]);
+ normalize_v3(te_dir);
+ if (fabsf(dot_v3v3(p_dir, te_dir)) >= 1.0f - e->eps) {
+ /* co-linear */
+ }
+ else {
+ float ix_pair[2][3];
+ int ix_pair_type;
+
+ ix_pair_type = isect_line_line_epsilon_v3(p0, p1, t_cos[i_t0], t_cos[i_t1], ix_pair[0], ix_pair[1], 0.0f);
+
+ if (ix_pair_type != 0) {
+ if (ix_pair_type == 1) {
+ copy_v3_v3(ix_pair[1], ix_pair[0]);
+ }
+
+ if ((ix_pair_type == 1) ||
+ (len_squared_v3v3(ix_pair[0], ix_pair[1]) <= e->eps_margin_sq))
+ {
+ fac = line_point_factor_v3(ix_pair[1], t_cos[i_t0], t_cos[i_t1]);
+ if ((fac >= e->eps_margin) && (fac <= 1.0f - e->eps_margin)) {
+ fac = line_point_factor_v3(ix_pair[0], p0, p1);
+ if ((fac >= e->eps_margin) && (fac <= 1.0f - e->eps_margin)) {
+ copy_v3_v3(r_ix, ix_pair[0]);
+ return (IX_EDGE_TRI_EDGE0 + (enum ISectType)i_t0);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* check ray isn't planar with tri */
+ if (fabsf(dot_v3v3(p_dir, t_nor)) >= e->eps) {
+ if (isect_line_tri_epsilon_v3(p0, p1, t_cos[0], t_cos[1], t_cos[2], &fac, NULL, 0.0f)) {
+ if ((fac >= e->eps_margin) && (fac <= 1.0f - e->eps_margin)) {
+ interp_v3_v3v3(r_ix, p0, p1, fac);
+ if (min_fff(len_squared_v3v3(t_cos[0], r_ix),
+ len_squared_v3v3(t_cos[1], r_ix),
+ len_squared_v3v3(t_cos[2], r_ix)) >= e->eps_margin_sq)
+ {
+ return IX_EDGE_TRI;
+ }
+ }
+ }
+ }
+
+ /* r_ix may be unset */
+ return IX_NONE;
+}
+
+static BMVert *bm_isect_edge_tri(
+ struct ISectState *s,
+ BMVert *e_v0, BMVert *e_v1,
+ BMVert *t[3], const int t_index,
+ const float *t_cos[3], const float t_nor[3],
+ enum ISectType *r_side)
+{
+ BMesh *bm = s->bm;
+ int k_arr[IX_TOT][4];
+ unsigned int i;
+ const int ti[3] = {UNPACK3_EX(BM_elem_index_get, t, )};
+ float ix[3];
+
+ if (BM_elem_index_get(e_v0) > BM_elem_index_get(e_v1)) {
+ SWAP(BMVert *, e_v0, e_v1);
+ }
+
+#ifdef USE_PARANOID
+ BLI_assert(len_squared_v3v3(e_v0->co, t[0]->co) >= s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(e_v0->co, t[1]->co) >= s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(e_v0->co, t[2]->co) >= s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(e_v1->co, t[0]->co) >= s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(e_v1->co, t[1]->co) >= s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(e_v1->co, t[2]->co) >= s->epsilon.eps_sq);
+#endif
+
+#define KEY_SET(k, i0, i1, i2, i3) { \
+ (k)[0] = i0; \
+ (k)[1] = i1; \
+ (k)[2] = i2; \
+ (k)[3] = i3; \
+} (void)0
+
+ /* order tri, then order (1-2, 2-3)*/
+#define KEY_EDGE_TRI_ORDER(k) { \
+ if (k[2] > k[3]) { \
+ SWAP(int, k[2], k[3]); \
+ } \
+ if (k[0] > k[2]) { \
+ SWAP(int, k[0], k[2]); \
+ SWAP(int, k[1], k[3]); \
+ } \
+} (void)0
+
+ KEY_SET(k_arr[IX_EDGE_TRI], BM_elem_index_get(e_v0), BM_elem_index_get(e_v1), t_index, -1);
+ /* need to order here */
+ KEY_SET(k_arr[IX_EDGE_TRI_EDGE0], BM_elem_index_get(e_v0), BM_elem_index_get(e_v1), ti[0], ti[1]);
+ KEY_SET(k_arr[IX_EDGE_TRI_EDGE1], BM_elem_index_get(e_v0), BM_elem_index_get(e_v1), ti[1], ti[2]);
+ KEY_SET(k_arr[IX_EDGE_TRI_EDGE2], BM_elem_index_get(e_v0), BM_elem_index_get(e_v1), ti[2], ti[0]);
+
+ KEY_EDGE_TRI_ORDER(k_arr[IX_EDGE_TRI_EDGE0]);
+ KEY_EDGE_TRI_ORDER(k_arr[IX_EDGE_TRI_EDGE1]);
+ KEY_EDGE_TRI_ORDER(k_arr[IX_EDGE_TRI_EDGE2]);
+
+#undef KEY_SET
+#undef KEY_EDGE_TRI_ORDER
+
+
+
+ for (i = 0; i < ARRAY_SIZE(k_arr); i++) {
+ BMVert *iv;
+
+ iv = BLI_ghash_lookup(s->edgetri_cache, k_arr[i]);
+
+ if (iv) {
+#ifdef USE_DUMP
+ printf("# cache hit (%d, %d, %d, %d)\n", UNPACK4(k_arr[i]));
+#endif
+ *r_side = (enum ISectType)i;
+ return iv;
+ }
+ }
+
+ *r_side = intersect_line_tri(e_v0->co, e_v1->co, t_cos, t_nor, ix, &s->epsilon);
+ if (*r_side != IX_NONE) {
+ BMVert *iv;
+ BMEdge *e;
+#ifdef USE_DUMP
+ printf("# new vertex (%.6f, %.6f, %.6f) %d\n", UNPACK3(ix), *r_side);
+#endif
+
+#ifdef USE_PARANOID
+ BLI_assert(len_squared_v3v3(ix, e_v0->co) > s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(ix, e_v1->co) > s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(ix, t[0]->co) > s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(ix, t[1]->co) > s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(ix, t[2]->co) > s->epsilon.eps_sq);
+#endif
+ iv = BM_vert_create(bm, ix, NULL, 0);
+
+ e = BM_edge_exists(e_v0, e_v1);
+ if (e) {
+#ifdef USE_DUMP
+ printf("# adding to edge %d\n", BM_elem_index_get(e));
+#endif
+ edge_verts_add(s, e, iv, false);
+ }
+ else {
+#ifdef USE_DISSOLVE
+ vert_dissolve_add(s, iv);
+#endif
+ }
+
+ if ((*r_side >= IX_EDGE_TRI_EDGE0) && (*r_side <= IX_EDGE_TRI_EDGE2)) {
+ i = (unsigned int)(*r_side - IX_EDGE_TRI_EDGE0);
+ e = BM_edge_exists(t[i], t[(i + 1) % 3]);
+ if (e) {
+ edge_verts_add(s, e, iv, false);
+ }
+ }
+
+ {
+ int *k = BLI_memarena_alloc(s->mem_arena, sizeof(int[4]));
+ memcpy(k, k_arr[*r_side], sizeof(int[4]));
+ BLI_ghash_insert(s->edgetri_cache, k, iv);
+ }
+
+ return iv;
+
+ }
+
+ *r_side = IX_NONE;
+
+ return NULL;
+}
+
+/**
+ * Return true if we have any intersections.
+ */
+static void bm_isect_tri_tri(
+ struct ISectState *s,
+ int a_index, int b_index,
+ BMLoop **a, BMLoop **b)
+{
+ BMFace *f_a = (*a)->f;
+ BMFace *f_b = (*b)->f;
+ BMVert *fv_a[3] = {UNPACK3_EX(, a, ->v)};
+ BMVert *fv_b[3] = {UNPACK3_EX(, b, ->v)};
+ const float *f_a_cos[3] = {UNPACK3_EX(, fv_a, ->co)};
+ const float *f_b_cos[3] = {UNPACK3_EX(, fv_b, ->co)};
+ float f_a_nor[3];
+ float f_b_nor[3];
+ int a_mask = 0;
+ int b_mask = 0;
+ unsigned int i;
+
+
+ /* should be enough but may need to bump */
+ BMVert *iv_ls_a[8];
+ BMVert *iv_ls_b[8];
+ STACK_DECLARE(iv_ls_a);
+ STACK_DECLARE(iv_ls_b);
+
+ if (UNLIKELY(ELEM(fv_a[0], UNPACK3(fv_b)) ||
+ ELEM(fv_a[1], UNPACK3(fv_b)) ||
+ ELEM(fv_a[2], UNPACK3(fv_b))))
+ {
+ return;
+ }
+
+ STACK_INIT(iv_ls_a, ARRAY_SIZE(iv_ls_a));
+ STACK_INIT(iv_ls_b, ARRAY_SIZE(iv_ls_b));
+
+ /* vert-vert
+ * --------- */
+ {
+ /* first check in any verts are touching
+ * (any case where we wont create new verts)
+ */
+ unsigned int i_a;
+ for (i_a = 0; i_a < 3; i_a++) {
+ unsigned int i_b;
+ for (i_b = 0; i_b < 3; i_b++) {
+ if (len_squared_v3v3(fv_a[i_a]->co, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
+ if (!((1 << i_a) & a_mask)) {
+ STACK_PUSH(iv_ls_a, fv_a[i_a]);
+ a_mask |= (1 << i_a);
+#ifdef USE_DUMP
+ printf(" ('VERT-VERT-A') %d, %d),\n",
+ i_a, BM_elem_index_get(fv_a[i_a]));
+#endif
+ }
+ if (!((1 << i_b) & b_mask)) {
+ STACK_PUSH(iv_ls_b, fv_b[i_b]);
+ b_mask |= (1 << i_b);
+#ifdef USE_DUMP
+ printf(" ('VERT-VERT-B') %d, %d),\n",
+ i_b, BM_elem_index_get(fv_b[i_b]));
+#endif
+ }
+ }
+ }
+ }
+ }
+
+ /* vert-edge
+ * --------- */
+ {
+ unsigned int i_a;
+ for (i_a = 0; i_a < 3; i_a++) {
+ if (!((1 << i_a) & a_mask)) {
+ unsigned int i_b_e0;
+ for (i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) {
+ unsigned int i_b_e1 = (i_b_e0 + 1) % 3;
+ float fac;
+ if (((1 << i_b_e0) | (1 << i_b_e1)) & b_mask)
+ continue;
+ fac = line_point_factor_v3(fv_a[i_a]->co, fv_b[i_b_e0]->co, fv_b[i_b_e1]->co);
+ if ((fac > 0.0f - s->epsilon.eps) && (fac < 1.0 + s->epsilon.eps)) {
+ float ix[3];
+ interp_v3_v3v3(ix, fv_b[i_b_e0]->co, fv_b[i_b_e1]->co, fac);
+ if (len_squared_v3v3(ix, fv_a[i_a]->co) <= s->epsilon.eps2x_sq) {
+ BMEdge *e;
+ STACK_PUSH(iv_ls_b, fv_a[i_a]);
+ // STACK_PUSH(iv_ls_a, fv_a[i_a]);
+ a_mask |= (1 << i_a);
+ e = BM_edge_exists(fv_b[i_b_e0], fv_b[i_b_e1]);
+#ifdef USE_DUMP
+ printf(" ('VERT-EDGE-A', %d, %d),\n",
+ BM_elem_index_get(fv_b[i_b_e0]), BM_elem_index_get(fv_b[i_b_e1]));
+#endif
+ if (e) {
+#ifdef USE_DUMP
+ printf("# adding to edge %d\n", BM_elem_index_get(e));
+#endif
+ edge_verts_add(s, e, fv_a[i_a], true);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ {
+ unsigned int i_b;
+ for (i_b = 0; i_b < 3; i_b++) {
+ if (!((1 << i_b) & b_mask)) {
+ unsigned int i_a_e0;
+ for (i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) {
+ unsigned int i_a_e1 = (i_a_e0 + 1) % 3;
+ float fac;
+ if (((1 << i_a_e0) | (1 << i_a_e1)) & a_mask)
+ continue;
+ fac = line_point_factor_v3(fv_b[i_b]->co, fv_a[i_a_e0]->co, fv_a[i_a_e1]->co);
+ if ((fac > 0.0 - s->epsilon.eps) && (fac < 1.0 + s->epsilon.eps)) {
+ float ix[3];
+ interp_v3_v3v3(ix, fv_a[i_a_e0]->co, fv_a[i_a_e1]->co, fac);
+ if (len_squared_v3v3(ix, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
+ BMEdge *e;
+ STACK_PUSH(iv_ls_a, fv_b[i_b]);
+ // STACK_PUSH(iv_ls_b, fv_b[i_b]);
+ b_mask |= (1 << i_b);
+ e = BM_edge_exists(fv_a[i_a_e0], fv_a[i_a_e1]);
+#ifdef USE_DUMP
+ printf(" ('VERT-EDGE-B', %d, %d),\n",
+ BM_elem_index_get(fv_a[i_a_e0]), BM_elem_index_get(fv_a[i_a_e1]));
+#endif
+ if (e) {
+#ifdef USE_DUMP
+ printf(" adding to edge %d\n", BM_elem_index_get(e));
+#endif
+ edge_verts_add(s, e, fv_b[i_b], true);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* vert-tri
+ * -------- */
+ {
+
+ float t_scale[3][3];
+ unsigned int i_a;
+
+ copy_v3_v3(t_scale[0], fv_b[0]->co);
+ copy_v3_v3(t_scale[1], fv_b[1]->co);
+ copy_v3_v3(t_scale[2], fv_b[2]->co);
+ tri_v3_scale(UNPACK3(t_scale), 1.0f - s->epsilon.eps2x);
+
+ // second check for verts intersecting the triangle
+ for (i_a = 0; i_a < 3; i_a++) {
+ float ix[3];
+ if ((1 << i_a) & a_mask)
+ continue;
+ if (isect_point_tri_v3(fv_a[i_a]->co, UNPACK3(t_scale), ix)) {
+ if (len_squared_v3v3(ix, fv_a[i_a]->co) <= s->epsilon.eps2x_sq) {
+ BLI_assert(BLI_array_findindex(iv_ls_a, STACK_SIZE(iv_ls_a), fv_a[i_a]) == -1);
+ BLI_assert(BLI_array_findindex(iv_ls_b, STACK_SIZE(iv_ls_b), fv_a[i_a]) == -1);
+
+ STACK_PUSH(iv_ls_a, fv_a[i_a]);
+ STACK_PUSH(iv_ls_b, fv_a[i_a]);
+ a_mask |= (1 << i_a);
+#ifdef USE_DUMP
+ printf(" 'VERT TRI-A',\n");
+#endif
+ }
+ }
+ }
+ }
+
+ {
+ float t_scale[3][3];
+ unsigned int i_b;
+
+ copy_v3_v3(t_scale[0], fv_a[0]->co);
+ copy_v3_v3(t_scale[1], fv_a[1]->co);
+ copy_v3_v3(t_scale[2], fv_a[2]->co);
+ tri_v3_scale(UNPACK3(t_scale), 1.0f - s->epsilon.eps2x);
+
+ for (i_b = 0; i_b < 3; i_b++) {
+ float ix[3];
+ if ((1 << i_b) & b_mask)
+ continue;
+
+ if (isect_point_tri_v3(fv_b[i_b]->co, UNPACK3(t_scale), ix)) {
+ if (len_squared_v3v3(ix, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
+ BLI_assert(BLI_array_findindex((void **)iv_ls_a, STACK_SIZE(iv_ls_a), fv_b[i_b]) == -1);
+ BLI_assert(BLI_array_findindex((void **)iv_ls_b, STACK_SIZE(iv_ls_b), fv_b[i_b]) == -1);
+
+ STACK_PUSH(iv_ls_a, fv_b[i_b]);
+ STACK_PUSH(iv_ls_b, fv_b[i_b]);
+ b_mask |= (1 << i_b);
+#ifdef USE_DUMP
+ printf(" 'VERT TRI-B',\n");
+#endif
+ }
+ }
+ }
+ }
+
+ if ((STACK_SIZE(iv_ls_a) >= 3) &&
+ (STACK_SIZE(iv_ls_b) >= 3))
+ {
+#ifdef USE_DUMP
+ printf("# OVERLAP\n");
+#endif
+ return;
+ }
+
+ normal_tri_v3(f_a_nor, UNPACK3(f_a_cos));
+ normal_tri_v3(f_b_nor, UNPACK3(f_b_cos));
+
+ /* edge-tri & edge-edge
+ * -------------------- */
+ {
+ unsigned int i_e0;
+ for (i_e0 = 0; i_e0 < 3; i_e0++) {
+ unsigned int i_e1 = (i_e0 + 1) % 3;
+ enum ISectType side;
+ BMVert *iv;
+ if (((1 << i_e0) | (1 << i_e1)) & a_mask)
+ continue;
+ iv = bm_isect_edge_tri(s, fv_a[i_e0], fv_a[i_e1], fv_b, b_index, f_b_cos, f_b_nor, &side);
+ if (iv) {
+ BLI_assert(BLI_array_findindex((void **)iv_ls_a, STACK_SIZE(iv_ls_a), iv) == -1);
+ BLI_assert(BLI_array_findindex((void **)iv_ls_b, STACK_SIZE(iv_ls_b), iv) == -1);
+ STACK_PUSH(iv_ls_a, iv);
+ STACK_PUSH(iv_ls_b, iv);
+#ifdef USE_DUMP
+ printf(" ('EDGE-TRI-A', %d),\n", side);
+#endif
+ }
+ }
+
+ for (i_e0 = 0; i_e0 < 3; i_e0++) {
+ unsigned int i_e1 = (i_e0 + 1) % 3;
+ enum ISectType side;
+ BMVert *iv;
+ if (((1 << i_e0) | (1 << i_e1)) & b_mask)
+ continue;
+ iv = bm_isect_edge_tri(s, fv_b[i_e0], fv_b[i_e1], fv_a, a_index, f_a_cos, f_a_nor, &side);
+ if (iv) {
+ /* check this wasn't handled above */
+ if (!(side >= IX_EDGE_TRI_EDGE0 && side <= IX_EDGE_TRI_EDGE2)) {
+ BLI_assert(BLI_array_findindex((void **)iv_ls_a, STACK_SIZE(iv_ls_a), iv) == -1);
+ BLI_assert(BLI_array_findindex((void **)iv_ls_b, STACK_SIZE(iv_ls_b), iv) == -1);
+ STACK_PUSH(iv_ls_a, iv);
+ STACK_PUSH(iv_ls_b, iv);
+#ifdef USE_DUMP
+ printf(" ('EDGE-RAY-B', %d),\n", side);
+#endif
+ }
+ }
+ }
+ }
+
+ {
+ for (i = 0; i < 2; i++) {
+ BMVert **ie_vs;
+ BMFace *f;
+ bool ie_exists;
+ BMEdge *ie;
+
+ if (i == 0) {
+ if (STACK_SIZE(iv_ls_a) != 2)
+ continue;
+ ie_vs = iv_ls_a;
+ f = f_a;
+ }
+ else {
+ if (STACK_SIZE(iv_ls_b) != 2)
+ continue;
+ ie_vs = iv_ls_b;
+ f = f_b;
+ }
+
+ /* possible but unlikely we get this - for edge-edge intersection */
+ ie = BM_edge_exists(UNPACK2(ie_vs));
+ if (ie == NULL) {
+ ie_exists = false;
+ /* one of the verts must be new if we are making an edge
+ * ...no, we need this in case 2x quads intersect at either ends.
+ * if not (ie_vs[0].index == -1 or ie_vs[1].index == -1):
+ * continue */
+ ie = BM_edge_create(s->bm, UNPACK2(ie_vs), NULL, 0);
+ BLI_gset_insert(s->wire_edges, ie);
+ }
+ else {
+ ie_exists = true;
+ /* may already exist */
+ BLI_gset_add(s->wire_edges, ie);
+
+ if (BM_edge_in_face(ie, f)) {
+ continue;
+ }
+ }
+
+ face_edges_add(s, BM_elem_index_get(f), ie, ie_exists);
+ // BLI_assert(len(ie_vs) <= 2)
+ }
+ }
+}
+
+/**
+ * Intersect tessellated faces
+ * leaving the resulting edges tagged.
+ *
+ * \param test_fn Return value: -1: skip, 0: tree_a, 1: tree_b (use_self == false)
+ */
+bool BM_mesh_intersect(
+ BMesh *bm,
+ struct BMLoop *(*looptris)[3], const int looptris_tot,
+ int (*test_fn)(BMFace *f, void *user_data), void *user_data,
+ const bool use_self, const bool use_separate,
+ const float eps)
+{
+ struct ISectState s;
+ bool has_isect;
+ const int totface_orig = bm->totface;
+
+#ifdef USE_BVH
+ BVHTree *tree_a, *tree_b;
+ unsigned int tree_overlap_tot;
+ BVHTreeOverlap *overlap;
+#else
+ int i_a, i_b;
+#endif
+
+ s.bm = bm;
+
+ s.edgetri_cache = BLI_ghash_new(BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, __func__);
+
+ s.edge_verts = BLI_ghash_ptr_new(__func__);
+ s.face_edges = BLI_ghash_ptr_new(__func__);
+ s.wire_edges = BLI_gset_ptr_new(__func__);
+ s.vert_dissolve = NULL;
+
+ s.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ /* setup epsilon from base */
+ s.epsilon.eps = eps;
+ s.epsilon.eps2x = eps * 2.0f;
+ s.epsilon.eps_margin = s.epsilon.eps2x * 10.0f;
+
+ s.epsilon.eps_sq = s.epsilon.eps * s.epsilon.eps;
+ s.epsilon.eps2x_sq = s.epsilon.eps2x * s.epsilon.eps2x;
+ s.epsilon.eps_margin_sq = s.epsilon.eps_margin * s.epsilon.eps_margin;
+
+ BM_mesh_elem_index_ensure(
+ bm,
+ BM_VERT |
+ BM_EDGE |
+#ifdef USE_NET
+ BM_FACE |
+#endif
+ 0);
+
+
+ BM_mesh_elem_table_ensure(
+ bm,
+#ifdef USE_SPLICE
+ BM_EDGE |
+#endif
+#ifdef USE_NET
+ BM_FACE |
+#endif
+ 0);
+
+#ifdef USE_DISSOLVE
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_VERT, BM_ELEM_TAG, false);
+#endif
+
+#ifdef USE_DUMP
+ printf("data = [\n");
+#endif
+
+#ifdef USE_BVH
+ {
+ int i;
+ tree_a = BLI_bvhtree_new(looptris_tot, s.epsilon.eps_margin, 8, 8);
+ for (i = 0; i < looptris_tot; i++) {
+ if (test_fn(looptris[i][0]->f, user_data) == 0) {
+ const float t_cos[3][3] = {
+ {UNPACK3(looptris[i][0]->v->co)},
+ {UNPACK3(looptris[i][1]->v->co)},
+ {UNPACK3(looptris[i][2]->v->co)},
+ };
+
+ BLI_bvhtree_insert(tree_a, i, (float *)t_cos, 3);
+ }
+ }
+ BLI_bvhtree_balance(tree_a);
+ }
+
+ if (use_self == false) {
+ int i;
+ tree_b = BLI_bvhtree_new(looptris_tot, s.epsilon.eps_margin, 8, 8);
+ for (i = 0; i < looptris_tot; i++) {
+ if (test_fn(looptris[i][0]->f, user_data) == 1) {
+ const float t_cos[3][3] = {
+ {UNPACK3(looptris[i][0]->v->co)},
+ {UNPACK3(looptris[i][1]->v->co)},
+ {UNPACK3(looptris[i][2]->v->co)},
+ };
+
+ BLI_bvhtree_insert(tree_b, i, (float *)t_cos, 3);
+ }
+ }
+ BLI_bvhtree_balance(tree_b);
+ }
+ else {
+ tree_b = tree_a;
+ }
+
+ overlap = BLI_bvhtree_overlap(tree_b, tree_a, &tree_overlap_tot);
+
+ if (overlap) {
+ unsigned int i;
+
+ for (i = 0; i < tree_overlap_tot; i++) {
+#ifdef USE_DUMP
+ printf(" ((%d, %d), (\n",
+ overlap[i].indexA,
+ overlap[i].indexB);
+#endif
+ bm_isect_tri_tri(
+ &s,
+ overlap[i].indexA,
+ overlap[i].indexB,
+ looptris[overlap[i].indexA],
+ looptris[overlap[i].indexB]);
+#ifdef USE_DUMP
+ printf(")),\n");
+#endif
+ }
+ MEM_freeN(overlap);
+ }
+ BLI_bvhtree_free(tree_a);
+ if (tree_a != tree_b) {
+ BLI_bvhtree_free(tree_b);
+ }
+
+#else
+ {
+ for (i_a = 0; i_a < looptris_tot; i_a++) {
+ const int t_a = test_fn(looptris[i_a][0]->f, user_data);
+ for (i_b = i_a + 1; i_b < looptris_tot; i_b++) {
+ const int t_b = test_fn(looptris[i_b][0]->f, user_data);
+
+ if (use_self) {
+ if ((t_a != 0) || (t_b != 0)) {
+ continue;
+ }
+ }
+ else {
+ if ((t_a != t_b) && !ELEM(-1, t_a, t_b)) {
+ continue;
+ }
+ }
+
+#ifdef USE_DUMP
+ printf(" ((%d, %d), (",
+ i_a, i_b);
+#endif
+ bm_isect_tri_tri(
+ &s,
+ i_a,
+ i_b,
+ looptris[i_a],
+ looptris[i_b]);
+#ifdef USE_DUMP
+ printf(")),\n");
+#endif
+ }
+ }
+ }
+#endif /* USE_BVH */
+
+#ifdef USE_DUMP
+ printf("]\n");
+#endif
+
+ /* --------- */
+
+#ifdef USE_SPLICE
+ {
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, s.edge_verts) {
+ BMEdge *e = BLI_ghashIterator_getKey(&gh_iter);
+ struct LinkBase *v_ls_base = BLI_ghashIterator_getValue(&gh_iter);
+
+ BMVert *v_start;
+ BMVert *v_end;
+ BMVert *v_prev;
+ bool is_wire;
+
+ LinkNode *node;
+
+ /* direction is arbitrary, could be swapped */
+ v_start = e->v1;
+ v_end = e->v2;
+
+ if (v_ls_base->list_len > 1) {
+ edge_verts_sort(v_start->co, v_ls_base);
+ }
+
+#ifdef USE_DUMP
+ printf("# SPLITTING EDGE: %d, %d\n", e_index, v_ls_base->list_len);
+#endif
+ /* intersect */
+ is_wire = BLI_gset_haskey(s.wire_edges, e);
+
+#ifdef USE_PARANOID
+ for (node = v_ls_base->list; node; node = node->next) {
+ BMVert *_v = node->link;
+ BLI_assert(len_squared_v3v3(_v->co, e->v1->co) > s.epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(_v->co, e->v2->co) > s.epsilon.eps_sq);
+ }
+#endif
+
+ v_prev = v_start;
+
+ for (node = v_ls_base->list; node; node = node->next) {
+ BMVert *vi = node->link;
+ const float fac = line_point_factor_v3(vi->co, e->v1->co, e->v2->co);
+
+ if (BM_vert_in_edge(e, v_prev)) {
+ v_prev = BM_edge_split(bm, e, v_prev, NULL, CLAMPIS(fac, 0.0f, 1.0f));
+ BLI_assert( BM_vert_in_edge(e, v_end));
+
+ if (!BM_edge_exists(v_prev, vi) &&
+ !BM_vert_splice_check_double(v_prev, vi) &&
+ !BM_vert_pair_share_face_check(v_prev, vi))
+ {
+ BM_vert_splice(bm, v_prev, vi);
+ }
+ else {
+ copy_v3_v3(v_prev->co, vi->co);
+ }
+ v_prev = vi;
+ if (is_wire) {
+ BLI_gset_insert(s.wire_edges, e);
+ }
+ }
+ }
+ }
+ }
+#endif
+
+
+ /* important to handle before edgenet */
+#ifdef USE_DISSOLVE
+ {
+ /* first pass */
+ BMVert *(*splice_ls)[2];
+ STACK_DECLARE(splice_ls);
+ LinkNode *node;
+
+
+ for (node = s.vert_dissolve; node; node = node->next) {
+ BMVert *v = node->link;
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ if (!BM_vert_is_edge_pair(v)) {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+ }
+ }
+
+ splice_ls = MEM_mallocN((unsigned int)BLI_gset_size(s.wire_edges) * sizeof(*splice_ls), __func__);
+ STACK_INIT(splice_ls, (unsigned int)BLI_gset_size(s.wire_edges));
+
+ for (node = s.vert_dissolve; node; node = node->next) {
+ BMEdge *e_pair[2];
+ BMVert *v = node->link;
+ BMVert *v_a, *v_b;
+
+ if (!BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ continue;
+ }
+
+ /* get chain */
+ e_pair[0] = v->e;
+ e_pair[1] = BM_DISK_EDGE_NEXT(v->e, v);
+
+ if (BM_elem_flag_test(e_pair[0], BM_ELEM_TAG) ||
+ BM_elem_flag_test(e_pair[1], BM_ELEM_TAG))
+ {
+ continue;
+ }
+
+ v_a = BM_edge_other_vert(e_pair[0], v);
+ v_b = BM_edge_other_vert(e_pair[1], v);
+
+ /* simple case */
+ if (BM_elem_flag_test(v_a, BM_ELEM_TAG) &&
+ BM_elem_flag_test(v_b, BM_ELEM_TAG))
+ {
+ /* only start on an edge-case */
+ /* pass */
+ }
+ else if ((!BM_elem_flag_test(v_a, BM_ELEM_TAG)) &&
+ (!BM_elem_flag_test(v_b, BM_ELEM_TAG)))
+ {
+ /* simple case, single edge spans face */
+ BMVert **splice_pair;
+ BM_elem_flag_enable(e_pair[1], BM_ELEM_TAG);
+ splice_pair = STACK_PUSH_RET(splice_ls);
+ splice_pair[0] = v;
+ splice_pair[1] = v_b;
+#ifdef USE_DUMP
+ printf("# Simple Case!\n");
+#endif
+ }
+ else {
+#ifdef USE_PARANOID
+ BMEdge *e_keep;
+#endif
+ BMEdge *e;
+ BMEdge *e_step;
+ BMVert *v_step;
+
+ /* walk the chain! */
+ if (BM_elem_flag_test(v_a, BM_ELEM_TAG)) {
+ e = e_pair[0];
+#ifdef USE_PARANOID
+ e_keep = e_pair[1];
+#endif
+ }
+ else {
+ SWAP(BMVert *, v_a, v_b);
+ e = e_pair[1];
+#ifdef USE_PARANOID
+ e_keep = e_pair[0];
+#endif
+ }
+
+ /* WALK */
+ v_step = v;
+ e_step = e;
+
+ while (true) {
+ BMEdge *e_next;
+ BMVert *v_next;
+
+ v_next = BM_edge_other_vert(e_step, v_step);
+ BM_elem_flag_enable(e_step, BM_ELEM_TAG);
+ if (!BM_elem_flag_test(v_next, BM_ELEM_TAG)) {
+ BMVert **splice_pair;
+#ifdef USE_PARANOID
+ BLI_assert(e_step != e_keep);
+#endif
+ splice_pair = STACK_PUSH_RET(splice_ls);
+ splice_pair[0] = v;
+ splice_pair[1] = v_next;
+ break;
+ }
+ else {
+ e_next = bm_vert_other_edge(v_next, e_step);
+ }
+
+ e_step = e_next;
+ v_step = v_next;
+ BM_elem_flag_enable(e_step, BM_ELEM_TAG);
+#ifdef USE_PARANOID
+ BLI_assert(e_step != e_keep);
+#endif
+#ifdef USE_DUMP
+ printf("# walk step %p %p\n", e_next, v_next);
+#endif
+ }
+#ifdef USE_PARANOID
+ BLI_assert(BM_elem_flag_test(e_keep, BM_ELEM_TAG) == 0);
+#endif
+ }
+ }
+
+ /* Remove edges! */
+ {
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, s.face_edges) {
+ struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
+ LinkNode **node_prev_p;
+ unsigned int i;
+
+ node_prev_p = &e_ls_base->list;
+ for (i = 0, node = e_ls_base->list; node; i++, node = node->next) {
+ BMEdge *e = node->link;
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ /* allocated by arena, don't free */
+ *node_prev_p = node->next;
+ e_ls_base->list_len--;
+ }
+ else {
+ node_prev_p = &node->next;
+ }
+ }
+ }
+ }
+
+ {
+ BMIter eiter;
+ BMEdge *e, *e_next;
+
+ BM_ITER_MESH_MUTABLE (e, e_next, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+
+ /* in rare and annoying cases,
+ * there can be faces from 's.face_edges' removed by the edges.
+ * These are degenerate cases, so just make sure we don't reference the faces again. */
+ if (e->l) {
+ BMLoop *l_iter = e->l;
+ BMFace **faces;
+
+ faces = bm->ftable;
+
+ do {
+ const int f_index = BM_elem_index_get(l_iter->f);
+ if (f_index >= 0) {
+ BLI_assert(f_index < totface_orig);
+ /* we could check if these are in: 's.face_edges', but easier just to remove */
+ faces[f_index] = NULL;
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ }
+
+ BLI_gset_remove(s.wire_edges, e, NULL);
+ BM_edge_kill(bm, e);
+ }
+ }
+ }
+
+ /* Remove verts! */
+ {
+ GSet *verts_invalid = BLI_gset_ptr_new(__func__);
+
+ for (node = s.vert_dissolve; node; node = node->next) {
+ /* arena allocated, don't free */
+ BMVert *v = node->link;
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ if (!v->e) {
+ BLI_gset_add(verts_invalid, v);
+ BM_vert_kill(bm, v);
+ }
+ }
+ }
+
+ {
+ unsigned int i;
+ for (i = 0; i < STACK_SIZE(splice_ls); i++) {
+ if (!BLI_gset_haskey(verts_invalid, splice_ls[i][0]) &&
+ !BLI_gset_haskey(verts_invalid, splice_ls[i][1]))
+ {
+ if (!BM_edge_exists(UNPACK2(splice_ls[i])) &&
+ !BM_vert_splice_check_double(UNPACK2(splice_ls[i])))
+ {
+ BM_vert_splice(bm, UNPACK2(splice_ls[i]));
+ }
+ }
+ }
+ }
+
+ BLI_gset_free(verts_invalid, NULL);
+ }
+
+ MEM_freeN(splice_ls);
+ }
+#endif /* USE_DISSOLVE */
+
+
+ /* now split faces */
+#ifdef USE_NET
+ {
+ GHashIterator gh_iter;
+ BMFace **faces;
+
+ faces = bm->ftable;
+
+ GHASH_ITER (gh_iter, s.face_edges) {
+ const int f_index = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
+ BMFace *f;
+ struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
+
+ BLI_assert(f_index >= 0 && f_index < totface_orig);
+
+ f = faces[f_index];
+ if (UNLIKELY(f == NULL)) {
+ continue;
+ }
+
+ BLI_assert(BM_elem_index_get(f) == f_index);
+
+ face_edges_split(bm, f, e_ls_base);
+ }
+ }
+#else
+ (void)totface_orig;
+#endif /* USE_NET */
+
+
+#ifdef USE_SEPARATE
+ if (use_separate) {
+ GSetIterator gs_iter;
+
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE, BM_ELEM_TAG, false);
+
+ GSET_ITER (gs_iter, s.wire_edges) {
+ BMEdge *e = BLI_gsetIterator_getKey(&gs_iter);
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+
+ BM_mesh_edgesplit(bm, false, true, false);
+ }
+#else
+ (void)use_separate;
+#endif /* USE_SEPARATE */
+
+ has_isect = (BLI_ghash_size(s.face_edges) != 0);
+
+ /* cleanup */
+ BLI_ghash_free(s.edgetri_cache, NULL, NULL);
+
+ BLI_ghash_free(s.edge_verts, NULL, NULL);
+ BLI_ghash_free(s.face_edges, NULL, NULL);
+ BLI_gset_free(s.wire_edges, NULL);
+
+ BLI_memarena_free(s.mem_arena);
+
+ return has_isect;
+}
diff --git a/intern/opencl/intern/OCL_opencl.c b/source/blender/bmesh/tools/bmesh_intersect.h
index 33a936896fd..af6e510a8f6 100644
--- a/intern/opencl/intern/OCL_opencl.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011, Blender Foundation.
+ * ***** 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
@@ -15,23 +15,21 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
+ * ***** END GPL LICENSE BLOCK *****
*/
-#include "OCL_opencl.h"
+#ifndef __BMESH_INTERSECT_H__
+#define __BMESH_INTERSECT_H__
-int OCL_init(void)
-{
-#ifdef _WIN32
- const char *path = "OpenCL.dll";
-#elif defined(__APPLE__)
- const char *path = "/Library/Frameworks/OpenCL.framework/OpenCL";
-#else
- const char *path = "libOpenCL.so";
-#endif
+/** \file blender/bmesh/tools/bmesh_intersect.h
+ * \ingroup bmesh
+ */
- return (clewInit(path) == CLEW_SUCCESS);
-}
+bool BM_mesh_intersect(
+ BMesh *bm,
+ struct BMLoop *(*looptris)[3], const int looptris_tot,
+ int (*test_fn)(BMFace *f, void *user_data), void *user_data,
+ const bool use_self, const bool use_separate,
+ const float eps);
+#endif /* __BMESH_INTERSECT_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_wireframe.c b/source/blender/bmesh/tools/bmesh_wireframe.c
index e2ce31d15b9..79fea3e5da1 100644
--- a/source/blender/bmesh/tools/bmesh_wireframe.c
+++ b/source/blender/bmesh/tools/bmesh_wireframe.c
@@ -441,7 +441,7 @@ void BM_mesh_wireframe(
BMVert *v_pos1 = verts_pos[i_1];
BMVert *v_pos2 = verts_pos[i_2];
- f_new = BM_face_create_quad_tri(bm, v_l1, v_l2, v_neg2, v_neg1, f_src, false);
+ f_new = BM_face_create_quad_tri(bm, v_l1, v_l2, v_neg2, v_neg1, f_src, BM_CREATE_NOP);
if (mat_offset) f_new->mat_nr = CLAMPIS(f_new->mat_nr + mat_offset, 0, mat_max);
BM_elem_flag_enable(f_new, BM_ELEM_TAG);
l_new = BM_FACE_FIRST_LOOP(f_new);
@@ -451,7 +451,7 @@ void BM_mesh_wireframe(
BM_elem_attrs_copy(bm, bm, l_next, l_new->next);
BM_elem_attrs_copy(bm, bm, l_next, l_new->next->next);
- f_new = BM_face_create_quad_tri(bm, v_l2, v_l1, v_pos1, v_pos2, f_src, false);
+ f_new = BM_face_create_quad_tri(bm, v_l2, v_l1, v_pos1, v_pos2, f_src, BM_CREATE_NOP);
if (mat_offset) f_new->mat_nr = CLAMPIS(f_new->mat_nr + mat_offset, 0, mat_max);
BM_elem_flag_enable(f_new, BM_ELEM_TAG);
@@ -469,7 +469,7 @@ void BM_mesh_wireframe(
BMVert *v_b1 = verts_boundary[i_1];
BMVert *v_b2 = verts_boundary[i_2];
- f_new = BM_face_create_quad_tri(bm, v_b2, v_b1, v_neg1, v_neg2, f_src, false);
+ f_new = BM_face_create_quad_tri(bm, v_b2, v_b1, v_neg1, v_neg2, f_src, BM_CREATE_NOP);
if (mat_offset) f_new->mat_nr = CLAMPIS(f_new->mat_nr + mat_offset, 0, mat_max);
BM_elem_flag_enable(f_new, BM_ELEM_TAG);
l_new = BM_FACE_FIRST_LOOP(f_new);
@@ -479,7 +479,7 @@ void BM_mesh_wireframe(
BM_elem_attrs_copy(bm, bm, l, l_new->next);
BM_elem_attrs_copy(bm, bm, l, l_new->next->next);
- f_new = BM_face_create_quad_tri(bm, v_b1, v_b2, v_pos2, v_pos1, f_src, false);
+ f_new = BM_face_create_quad_tri(bm, v_b1, v_b2, v_pos2, v_pos1, f_src, BM_CREATE_NOP);
if (mat_offset) f_new->mat_nr = CLAMPIS(f_new->mat_nr + mat_offset, 0, mat_max);
BM_elem_flag_enable(f_new, BM_ELEM_TAG);
l_new = BM_FACE_FIRST_LOOP(f_new);
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index d27795b0ab2..6e2d337a32e 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -804,7 +804,7 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& a
// evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
// calc special matrix
- mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, irest, temp, irest_dae, rest);
}
else {
copy_m4_m4(mat, matfra);
@@ -1210,7 +1210,7 @@ void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector<FCurv
// evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
// calc special matrix
- mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, irest, temp, irest_dae, rest);
float rot[4], loc[3], scale[3];
@@ -1545,7 +1545,7 @@ Object *AnimationImporter::translate_animation_OLD(COLLADAFW::Node *node,
// evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
// calc special matrix
- mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, irest, temp, irest_dae, rest);
}
else {
copy_m4_m4(mat, matfra);
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index e34161f4aaa..bc1c4172f46 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -284,7 +284,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
}
if (oob_counter > 0) {
- fprintf(stderr, "Ignored %d Vertex weigths which use index to non existing VGroup %ld.\n", oob_counter, joint_index_by_def_index.size());
+ fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %ld.\n", oob_counter, joint_index_by_def_index.size());
}
}
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index bbbbbf211c6..8101e579098 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -483,6 +483,17 @@ void DocumentImporter::create_constraints(ExtraTags *et, Object *ob)
}
}
+void DocumentImporter::report_unknown_reference(const COLLADAFW::Node &node, const std::string object_type)
+{
+ std::string id = node.getOriginalId();
+ std::string name = node.getName();
+ fprintf(stderr,
+ "error: node id=\"%s\", name=\"%s\" refers to an undefined %s.\n",
+ id.c_str(),
+ name.c_str(),
+ object_type.c_str());
+}
+
std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
{
Object *ob = NULL;
@@ -538,10 +549,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
material_texture_mapping_map);
if (ob == NULL) {
- fprintf(stderr,
- "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_mesh.\n",
- id.c_str(),
- name.c_str());
+ report_unknown_reference(*node, "instance_mesh");
}
else {
objects_done->push_back(ob);
@@ -554,9 +562,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
while (camera_done < camera.getCount()) {
ob = create_camera_object(camera[camera_done], sce);
if (ob == NULL) {
- std::string id = node->getOriginalId();
- std::string name = node->getName();
- fprintf(stderr, "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_camera.\n", id.c_str(), name.c_str());
+ report_unknown_reference(*node, "instance_camera");
}
else {
objects_done->push_back(ob);
@@ -568,18 +574,28 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
}
while (lamp_done < lamp.getCount()) {
ob = create_lamp_object(lamp[lamp_done], sce);
- objects_done->push_back(ob);
- if (parent_node == NULL) {
- root_objects->push_back(ob);
+ if (ob == NULL) {
+ report_unknown_reference(*node, "instance_lamp");
+ }
+ else {
+ objects_done->push_back(ob);
+ if (parent_node == NULL) {
+ root_objects->push_back(ob);
+ }
}
++lamp_done;
}
while (controller_done < controller.getCount()) {
COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry *)controller[controller_done];
ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map);
- objects_done->push_back(ob);
- if (parent_node == NULL) {
- root_objects->push_back(ob);
+ if (ob == NULL) {
+ report_unknown_reference(*node, "instance_controller");
+ }
+ else {
+ objects_done->push_back(ob);
+ if (parent_node == NULL) {
+ root_objects->push_back(ob);
+ }
}
++controller_done;
}
@@ -805,10 +821,14 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia
// DIFFUSE
// color
if (ef->getDiffuse().isColor()) {
+ /* too high intensity can create artefacts (fireflies)
+ So here we take care that intensity is set to 0.8 wherever possible
+ */
col = ef->getDiffuse().getColor();
- ma->r = col.getRed();
- ma->g = col.getGreen();
- ma->b = col.getBlue();
+ ma->ref = max_ffff(col.getRed(), col.getGreen(), col.getBlue(), 0.8);
+ ma->r = col.getRed() / ma->ref;
+ ma->g = col.getGreen() / ma->ref;
+ ma->b = col.getBlue() / ma->ref;
}
// texture
else if (ef->getDiffuse().isTexture()) {
diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h
index 96aa7eb4578..5a7df9a41cf 100644
--- a/source/blender/collada/DocumentImporter.h
+++ b/source/blender/collada/DocumentImporter.h
@@ -171,6 +171,8 @@ private:
std::map<COLLADAFW::UniqueId, const COLLADAFW::Object*> FW_object_map;
std::string import_from_version;
+
+ void report_unknown_reference(const COLLADAFW::Node &node, const std::string object_type);
};
#endif
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index 211c34ed325..a4bf1d28366 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -84,7 +84,7 @@ static const char *bc_primTypeToStr(COLLADAFW::MeshPrimitive::PrimitiveType type
case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
return "TRIANGLE_FANS";
case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
- return "TRIANGLE_FANS";
+ return "TRIANGLE_STRIPS";
case COLLADAFW::MeshPrimitive::POINTS:
return "POINTS";
case COLLADAFW::MeshPrimitive::UNDEFINED_PRIMITIVE_TYPE:
diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp
index 7ae1750d2ca..75928f9d189 100644
--- a/source/blender/collada/SkinInfo.cpp
+++ b/source/blender/collada/SkinInfo.cpp
@@ -34,6 +34,10 @@
/* COLLADABU_ASSERT, may be able to remove later */
#include "COLLADABUPlatform.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_compiler_attrs.h"
+
#include "BKE_object.h"
#include "DNA_armature_types.h"
#include "DNA_modifier_types.h"
@@ -41,8 +45,6 @@
#include "ED_mesh.h"
#include "ED_object.h"
#include "BKE_action.h"
-#include "BLI_listbase.h"
-#include "BLI_math.h"
#include "SkinInfo.h"
#include "collada_utils.h"
diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp
index c3665a33ca4..595787b44ac 100644
--- a/source/blender/collada/TransformWriter.cpp
+++ b/source/blender/collada/TransformWriter.cpp
@@ -77,7 +77,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, B
BKE_object_to_mat4(ob, C);
copy_v3_v3(ob->size, scale);
- mul_serie_m4(tmat, ob->parent->obmat, ob->parentinv, C, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(tmat, ob->parent->obmat, ob->parentinv, C);
// calculate local mat
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index a19433436f1..4bcdd4d9e34 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -39,7 +39,7 @@ set(INC
../nodes/intern
../render/extern/include
../render/intern/include
- ../../../intern/opencl
+ ../../../extern/clew/include
../../../intern/guardedalloc
)
@@ -175,6 +175,11 @@ set(SRC
nodes/COM_GlareNode.cpp
nodes/COM_GlareNode.h
+ nodes/COM_SunBeamsNode.cpp
+ nodes/COM_SunBeamsNode.h
+ operations/COM_SunBeamsOperation.cpp
+ operations/COM_SunBeamsOperation.h
+
nodes/COM_CornerPinNode.cpp
nodes/COM_CornerPinNode.h
nodes/COM_PlaneTrackDeformNode.cpp
@@ -535,4 +540,6 @@ list(APPEND INC
data_to_c(${CMAKE_CURRENT_SOURCE_DIR}/operations/COM_OpenCLKernels.cl
${CMAKE_CURRENT_BINARY_DIR}/operations/COM_OpenCLKernels.cl.h SRC)
+add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_1_APIS)
+
blender_add_lib(bf_compositor "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h
index 2cf2c690d3e..9b22444cf7f 100644
--- a/source/blender/compositor/COM_compositor.h
+++ b/source/blender/compositor/COM_compositor.h
@@ -208,7 +208,7 @@ extern "C" {
*
* @see ExecutionGroup.execute Execute a complete ExecutionGroup. Halts until finished or breaked by user
* @see ExecutionGroup.scheduleChunkWhenPossible Tries to schedule a single chunk,
- * checks if all input data is available. Can trigger dependant chunks to be calculated
+ * checks if all input data is available. Can trigger dependent chunks to be calculated
* @see ExecutionGroup.scheduleAreaWhenPossible Tries to schedule an area. This can be multiple chunks
* (is called from [@ref ExecutionGroup.scheduleChunkWhenPossible])
* @see ExecutionGroup.scheduleChunk Schedule a chunk on the WorkScheduler
diff --git a/source/blender/compositor/SConscript b/source/blender/compositor/SConscript
index 073b100e156..eab40873f64 100644
--- a/source/blender/compositor/SConscript
+++ b/source/blender/compositor/SConscript
@@ -26,7 +26,7 @@
# ***** END GPL LICENSE BLOCK *****
Import ('env')
-defs = ['GLEW_STATIC']
+defs = ['GLEW_STATIC', 'CL_USE_DEPRECATED_OPENCL_1_1_APIS']
sources_intern = env.Glob('intern/*.cpp')
sources_nodes = env.Glob('nodes/*.cpp')
@@ -37,7 +37,7 @@ incs = [
'intern',
'nodes',
'operations',
- '#/intern/opencl',
+ '#/extern/clew/include',
'../blenkernel',
'../blenlib',
'../imbuf',
diff --git a/source/blender/compositor/intern/COM_ChunkOrder.cpp b/source/blender/compositor/intern/COM_ChunkOrder.cpp
index 1b7c435ecea..3b094609a26 100644
--- a/source/blender/compositor/intern/COM_ChunkOrder.cpp
+++ b/source/blender/compositor/intern/COM_ChunkOrder.cpp
@@ -34,7 +34,7 @@ ChunkOrder::ChunkOrder()
void ChunkOrder::determineDistance(ChunkOrderHotspot **hotspots, unsigned int numberOfHotspots)
{
unsigned int index;
- double distance = MAXFLOAT;
+ double distance = FLT_MAX;
for (index = 0; index < numberOfHotspots; index++) {
ChunkOrderHotspot *hotspot = hotspots[index];
double ndistance = hotspot->determineDistance(this->m_x, this->m_y);
diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp
index 9251e161839..99f66bcb5b4 100644
--- a/source/blender/compositor/intern/COM_Converter.cpp
+++ b/source/blender/compositor/intern/COM_Converter.cpp
@@ -99,6 +99,7 @@ extern "C" {
#include "COM_SetValueOperation.h"
#include "COM_SplitViewerNode.h"
#include "COM_Stabilize2dNode.h"
+#include "COM_SunBeamsNode.h"
#include "COM_SwitchNode.h"
#include "COM_TextureNode.h"
#include "COM_TimeNode.h"
@@ -394,6 +395,9 @@ Node *Converter::convert(bNode *b_node)
case CMP_NODE_CORNERPIN:
node = new CornerPinNode(b_node);
break;
+ case CMP_NODE_SUNBEAMS:
+ node = new SunBeamsNode(b_node);
+ break;
}
return node;
}
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
index c1916f4a68f..c59ecced93c 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
@@ -178,162 +178,58 @@ void MemoryBuffer::addPixel(int x, int y, const float color[4])
}
}
-
-// table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2
-// used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible
-#define EWA_MAXIDX 255
-static const float EWA_WTS[EWA_MAXIDX + 1] = {
- 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f,
- 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f,
- 0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f,
- 0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f,
- 0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f,
- 0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f,
- 0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f,
- 0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f,
- 0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f,
- 0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f,
- 0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f,
- 0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f,
- 0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f,
- 0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f,
- 0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f,
- 0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f,
- 0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f,
- 0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f,
- 0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f,
- 0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f,
- 0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f,
- 0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f,
- 0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f,
- 0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f,
- 0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f,
- 0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f,
- 0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f,
- 0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f,
- 0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f,
- 0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f,
- 0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f,
- 0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f
-};
-
-static void ellipse_bounds(float A, float B, float C, float F, float &xmax, float &ymax)
-{
- float denom = 4.0f * A * C - B * B;
- if (denom > 0.0f && A != 0.0f && C != 0.0f) {
- xmax = sqrtf(F) / (2.0f * A) * (sqrtf(F * (4.0f * A - B * B / C)) + B * B * sqrtf(F / (C * denom)));
- ymax = sqrtf(F) / (2.0f * C) * (sqrtf(F * (4.0f * C - B * B / A)) + B * B * sqrtf(F / (A * denom)));
+typedef struct ReadEWAData {
+ MemoryBuffer *buffer;
+ PixelSampler sampler;
+ float ufac, vfac;
+} ReadEWAData;
+
+static void read_ewa_pixel_sampled(void *userdata, int x, int y, float result[4])
+{
+ ReadEWAData *data = (ReadEWAData *) userdata;
+ switch (data->sampler) {
+ case COM_PS_NEAREST:
+ data->buffer->read(result, x, y);
+ break;
+ case COM_PS_BILINEAR:
+ data->buffer->readBilinear(result,
+ (float)x + data->ufac,
+ (float)y + data->vfac);
+ break;
+ case COM_PS_BICUBIC:
+ /* TOOD(sergey): no readBicubic method yet */
+ data->buffer->readBilinear(result,
+ (float)x + data->ufac,
+ (float)y + data->vfac);
+ break;
+ default:
+ zero_v4(result);
+ break;
}
- else {
- xmax = 0.0f;
- ymax = 0.0f;
- }
-}
-
-static void ellipse_params(float Ux, float Uy, float Vx, float Vy,
- float &A, float &B, float &C, float &F, float &umax, float &vmax)
-{
- A = Vx * Vx + Vy * Vy;
- B = -2.0f * (Ux * Vx + Uy * Vy);
- C = Ux * Ux + Uy * Uy;
- F = A * C - B * B * 0.25f;
-
- float factor = (F != 0.0f ? (float)(EWA_MAXIDX + 1) / F : 0.0f);
- A *= factor;
- B *= factor;
- C *= factor;
- F = (float)(EWA_MAXIDX + 1);
-
- ellipse_bounds(A, B, C, sqrtf(F), umax, vmax);
}
-/**
- * Filtering method based on
- * "Creating raster omnimax images from multiple perspective views using the elliptical weighted average filter"
- * by Ned Greene and Paul S. Heckbert (1986)
- */
void MemoryBuffer::readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler)
{
- zero_v4(result);
- int width = this->getWidth(), height = this->getHeight();
- if (width == 0 || height == 0)
- return;
-
- float u = uv[0], v = uv[1];
- float Ux = derivatives[0][0], Vx = derivatives[1][0], Uy = derivatives[0][1], Vy = derivatives[1][1];
- float A, B, C, F, ue, ve;
- ellipse_params(Ux, Uy, Vx, Vy, A, B, C, F, ue, ve);
+ ReadEWAData data;
+ data.buffer = this;
+ data.sampler = sampler;
+ data.ufac = uv[0] - floorf(uv[0]);
+ data.vfac = uv[1] - floorf(uv[1]);
- /* Note: highly eccentric ellipses can lead to large texture space areas to filter!
- * This is limited somewhat by the EWA_WTS size in the loop, but a nicer approach
- * could be the one found in
- * "High Quality Elliptical Texture Filtering on GPU"
- * by Pavlos Mavridis and Georgios Papaioannou
- * in which the eccentricity of the ellipse is clamped.
- */
-
- int U0 = (int)u;
- int V0 = (int)v;
- /* pixel offset for interpolation */
- float ufac = u - floorf(u), vfac = v - floorf(v);
- /* filter size */
- int u1 = (int)(u - ue);
- int u2 = (int)(u + ue);
- int v1 = (int)(v - ve);
- int v2 = (int)(v + ve);
-
- /* sane clamping to avoid unnecessarily huge loops */
- /* note: if eccentricity gets clamped (see above),
- * the ue/ve limits can also be lowered accordingly
+ int width = this->getWidth(), height = this->getHeight();
+ /* TODO(sergey): Render pipeline uses normalized coordinates and derivatives,
+ * but compositor uses pixel space. For now let's just divide the values and
+ * switch compositor to normalized space for EWA later.
*/
- if (U0 - u1 > EWA_MAXIDX) u1 = U0 - EWA_MAXIDX;
- if (u2 - U0 > EWA_MAXIDX) u2 = U0 + EWA_MAXIDX;
- if (V0 - v1 > EWA_MAXIDX) v1 = V0 - EWA_MAXIDX;
- if (v2 - V0 > EWA_MAXIDX) v2 = V0 + EWA_MAXIDX;
-
- /* Early output check for cases the whole region is outside of the buffer. */
- if ((u2 < m_rect.xmin || u1 >= m_rect.xmax) ||
- (v2 < m_rect.ymin || v1 >= m_rect.ymax))
- {
- zero_v4(result);
- return;
- }
-
- /* Clamp sampling rectagle to the buffer dimensions. */
- u1 = max_ii(u1, m_rect.xmin);
- u2 = min_ii(u2, m_rect.xmax);
- v1 = max_ii(v1, m_rect.ymin);
- v2 = min_ii(v2, m_rect.ymax);
-
- float DDQ = 2.0f * A;
- float U = u1 - U0;
- float ac1 = A * (2.0f * U + 1.0f);
- float ac2 = A * U * U;
- float BU = B * U;
-
- float sum = 0.0f;
- for (int v = v1; v <= v2; ++v) {
- float V = v - V0;
-
- float DQ = ac1 + B * V;
- float Q = (C * V + BU) * V + ac2;
- for (int u = u1; u <= u2; ++u) {
- if (Q < F) {
- float tc[4];
- const float wt = EWA_WTS[CLAMPIS((int)Q, 0, EWA_MAXIDX)];
- switch (sampler) {
- case COM_PS_NEAREST: read(tc, u, v); break;
- case COM_PS_BILINEAR: readBilinear(tc, (float)u + ufac, (float)v + vfac); break;
- case COM_PS_BICUBIC: readBilinear(tc, (float)u + ufac, (float)v + vfac); break; /* XXX no readBicubic method yet */
- default: zero_v4(tc); break;
- }
- madd_v4_v4fl(result, tc, wt);
- sum += wt;
- }
- Q += DQ;
- DQ += DDQ;
- }
- }
-
- mul_v4_fl(result, (sum != 0.0f ? 1.0f / sum : 0.0f));
+ float uv_normal[2] = {uv[0] / width, uv[1] / height};
+ float du_normal[2] = {derivatives[0][0] / width, derivatives[0][1] / height};
+ float dv_normal[2] = {derivatives[1][0] / width, derivatives[1][1] / height};
+
+ BLI_ewa_filter(this->getWidth(), this->getHeight(),
+ false,
+ true,
+ uv_normal, du_normal, dv_normal,
+ read_ewa_pixel_sampled,
+ &data,
+ result);
}
diff --git a/source/blender/compositor/intern/COM_NodeConverter.cpp b/source/blender/compositor/intern/COM_NodeConverter.cpp
index 81a10a58cc5..208a3db812f 100644
--- a/source/blender/compositor/intern/COM_NodeConverter.cpp
+++ b/source/blender/compositor/intern/COM_NodeConverter.cpp
@@ -83,9 +83,9 @@ NodeOperation *NodeConverter::setInvalidOutput(NodeOutput *output)
return operation;
}
-NodeOperationOutput *NodeConverter::addInputProxy(NodeInput *input)
+NodeOperationOutput *NodeConverter::addInputProxy(NodeInput *input, bool use_conversion)
{
- SocketProxyOperation *proxy = new SocketProxyOperation(input->getDataType());
+ SocketProxyOperation *proxy = new SocketProxyOperation(input->getDataType(), use_conversion);
m_builder->addOperation(proxy);
m_builder->mapInputSocket(input, proxy->getInputSocket(0));
@@ -93,9 +93,9 @@ NodeOperationOutput *NodeConverter::addInputProxy(NodeInput *input)
return proxy->getOutputSocket();
}
-NodeOperationInput *NodeConverter::addOutputProxy(NodeOutput *output)
+NodeOperationInput *NodeConverter::addOutputProxy(NodeOutput *output, bool use_conversion)
{
- SocketProxyOperation *proxy = new SocketProxyOperation(output->getDataType());
+ SocketProxyOperation *proxy = new SocketProxyOperation(output->getDataType(), use_conversion);
m_builder->addOperation(proxy);
m_builder->mapOutputSocket(output, proxy->getOutputSocket());
diff --git a/source/blender/compositor/intern/COM_NodeConverter.h b/source/blender/compositor/intern/COM_NodeConverter.h
index e5e7629f39a..414b4f1ee95 100644
--- a/source/blender/compositor/intern/COM_NodeConverter.h
+++ b/source/blender/compositor/intern/COM_NodeConverter.h
@@ -70,12 +70,12 @@ public:
* This operation will be removed later and replaced
* by direct links between the connected operations.
*/
- NodeOperationOutput *addInputProxy(NodeInput *input);
+ NodeOperationOutput *addInputProxy(NodeInput *input, bool use_conversion);
/** Create a proxy operation for a node output.
* This operation will be removed later and replaced
* by direct links between the connected operations.
*/
- NodeOperationInput *addOutputProxy(NodeOutput *output);
+ NodeOperationInput *addOutputProxy(NodeOutput *output, bool use_conversion);
/** Define a constant input value. */
void addInputValue(NodeOperationInput *input, float value);
diff --git a/source/blender/compositor/intern/COM_NodeGraph.cpp b/source/blender/compositor/intern/COM_NodeGraph.cpp
index cbe47238249..2dcf419d81b 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.cpp
+++ b/source/blender/compositor/intern/COM_NodeGraph.cpp
@@ -202,7 +202,7 @@ void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink
void NodeGraph::add_proxies_mute(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
{
for (bNodeLink *b_link = (bNodeLink *)b_node->internal_links.first; b_link; b_link = b_link->next) {
- SocketProxyNode *proxy = new SocketProxyNode(b_node, b_link->fromsock, b_link->tosock);
+ SocketProxyNode *proxy = new SocketProxyNode(b_node, b_link->fromsock, b_link->tosock, false);
add_node(proxy, b_ntree, key, is_active_group);
}
}
@@ -219,7 +219,7 @@ void NodeGraph::add_proxies_skip(bNodeTree *b_ntree, bNode *b_node, bNodeInstanc
}
if (input) {
- SocketProxyNode *proxy = new SocketProxyNode(b_node, input, output);
+ SocketProxyNode *proxy = new SocketProxyNode(b_node, input, output, true);
add_node(proxy, b_ntree, key, is_active_group);
}
}
@@ -237,7 +237,7 @@ void NodeGraph::add_proxies_group_inputs(bNode *b_node, bNode *b_node_io)
for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->outputs.first; b_sock_io; b_sock_io = b_sock_io->next) {
bNodeSocket *b_sock_group = find_b_node_input(b_node, b_sock_io->identifier);
if (b_sock_group) {
- SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_group, b_sock_io);
+ SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_group, b_sock_io, true);
add_node(proxy, b_group_tree, key, is_active_group);
}
}
@@ -260,7 +260,7 @@ void NodeGraph::add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool
add_node(buffer, b_group_tree, key, is_active_group);
}
else {
- SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_io, b_sock_group);
+ SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_io, b_sock_group, true);
add_node(proxy, b_group_tree, key, is_active_group);
}
}
@@ -294,6 +294,6 @@ void NodeGraph::add_proxies_group(const CompositorContext &context, bNode *b_nod
void NodeGraph::add_proxies_reroute(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
{
- SocketProxyNode *proxy = new SocketProxyNode(b_node, (bNodeSocket *)b_node->inputs.first, (bNodeSocket *)b_node->outputs.first);
+ SocketProxyNode *proxy = new SocketProxyNode(b_node, (bNodeSocket *)b_node->inputs.first, (bNodeSocket *)b_node->outputs.first, false);
add_node(proxy, b_ntree, key, is_active_group);
}
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index 3f636dff63c..d9c16615fb6 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -38,7 +38,7 @@ extern "C" {
#include "COM_MemoryProxy.h"
#include "COM_SocketReader.h"
-#include "OCL_opencl.h"
+#include "clew.h"
using std::list;
using std::min;
@@ -288,6 +288,8 @@ public:
virtual bool isFileOutputOperation() const { return false; }
virtual bool isProxyOperation() const { return false; }
+ virtual bool useDatatypeConversion() const { return true; }
+
inline bool isBreaked() const {
return this->m_btree->test_break(this->m_btree->tbh);
}
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
index 6554926991c..fb5bc8fcd9b 100644
--- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
@@ -269,6 +269,13 @@ void NodeOperationBuilder::add_datatype_conversions()
Links convert_links;
for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
const Link &link = *it;
+
+ /* proxy operations can skip data type conversion */
+ NodeOperation *from_op = &link.from()->getOperation();
+ NodeOperation *to_op = &link.to()->getOperation();
+ if (!(from_op->useDatatypeConversion() || to_op->useDatatypeConversion()))
+ continue;
+
if (link.from()->getDataType() != link.to()->getDataType())
convert_links.push_back(link);
}
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
index 2cfc10cff29..c5b663d2aef 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
@@ -103,7 +103,7 @@ void OpenCLDevice::COM_clAttachMemoryBufferOffsetToKernelParameter(cl_kernel ker
if (offsetIndex != -1) {
cl_int error;
rcti *rect = memoryBuffer->getRect();
- cl_int2 offset = {rect->xmin, rect->ymin};
+ cl_int2 offset = {{rect->xmin, rect->ymin}};
error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
@@ -114,7 +114,7 @@ void OpenCLDevice::COM_clAttachSizeToKernelParameter(cl_kernel kernel, int offse
{
if (offsetIndex != -1) {
cl_int error;
- cl_int2 offset = {(cl_int)operation->getWidth(), (cl_int)operation->getHeight()};
+ cl_int2 offset = {{(cl_int)operation->getWidth(), (cl_int)operation->getHeight()}};
error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
@@ -154,7 +154,7 @@ void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemo
bool breaked = false;
for (offsety = 0; offsety < height && (!breaked); offsety += localSize) {
- offset[1] = offsety;
+ offset.y = offsety;
if (offsety + localSize < height) {
size[1] = localSize;
}
@@ -169,7 +169,7 @@ void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemo
else {
size[0] = width - offsetx;
}
- offset[0] = offsetx;
+ offset.x = offsetx;
error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.h b/source/blender/compositor/intern/COM_OpenCLDevice.h
index 50cc6f25f70..94df2f2b44c 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.h
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.h
@@ -26,7 +26,7 @@ class OpenCLDevice;
#define _COM_OpenCLDevice_h
#include "COM_Device.h"
-#include "OCL_opencl.h"
+#include "clew.h"
#include "COM_WorkScheduler.h"
#include "COM_ReadBufferOperation.h"
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp
index d60f9cb7f10..e1016731c7f 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cpp
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp
@@ -28,7 +28,7 @@
#include "COM_CPUDevice.h"
#include "COM_OpenCLDevice.h"
#include "COM_OpenCLKernels.cl.h"
-#include "OCL_opencl.h"
+#include "clew.h"
#include "COM_WriteBufferOperation.h"
#include "MEM_guardedalloc.h"
@@ -274,7 +274,7 @@ bool WorkScheduler::hasGPUDevices()
#endif
}
-static void clContextError(const char *errinfo, const void *private_info, size_t cb, void *user_data)
+static void CL_CALLBACK clContextError(const char *errinfo, const void *private_info, size_t cb, void *user_data)
{
printf("OPENCL error: %s\n", errinfo);
}
@@ -326,7 +326,7 @@ void WorkScheduler::initialize(bool use_opencl, int num_cpu_threads)
g_context = NULL;
g_program = NULL;
- if (!OCL_init()) /* this will check for errors and skip if already initialized */
+ if (clewInit() != CLEW_SUCCESS) /* this will check for errors and skip if already initialized */
return;
if (clCreateContextFromType) {
diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp
index 99655c67a3f..ec9ef6c7e68 100644
--- a/source/blender/compositor/intern/COM_compositor.cpp
+++ b/source/blender/compositor/intern/COM_compositor.cpp
@@ -32,7 +32,7 @@ extern "C" {
#include "COM_compositor.h"
#include "COM_ExecutionSystem.h"
#include "COM_WorkScheduler.h"
-#include "OCL_opencl.h"
+#include "clew.h"
#include "COM_MovieDistortionOperation.h"
static ThreadMutex s_compositorMutex;
diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp
index f750a44a788..48c8acfc6a1 100644
--- a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp
+++ b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp
@@ -29,7 +29,9 @@
#include "COM_WriteBufferOperation.h"
#include "COM_ReadBufferOperation.h"
-SocketProxyNode::SocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bNodeSocket *editorOutput) : Node(editorNode, false)
+SocketProxyNode::SocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bNodeSocket *editorOutput, bool use_conversion) :
+ Node(editorNode, false),
+ m_use_conversion(use_conversion)
{
DataType dt;
@@ -46,7 +48,7 @@ SocketProxyNode::SocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bN
void SocketProxyNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
- NodeOperationOutput *proxy_output = converter.addInputProxy(getInputSocket(0));
+ NodeOperationOutput *proxy_output = converter.addInputProxy(getInputSocket(0), m_use_conversion);
converter.mapOutputSocket(getOutputSocket(), proxy_output);
}
diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.h b/source/blender/compositor/nodes/COM_SocketProxyNode.h
index 2fbaa71421c..5dbf39382cc 100644
--- a/source/blender/compositor/nodes/COM_SocketProxyNode.h
+++ b/source/blender/compositor/nodes/COM_SocketProxyNode.h
@@ -31,8 +31,15 @@
*/
class SocketProxyNode : public Node {
public:
- SocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bNodeSocket *editorOutput);
+ SocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bNodeSocket *editorOutput, bool use_conversion);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+
+ bool getUseConversion() const { return m_use_conversion; }
+ void setUseConversion(bool use_conversion) { m_use_conversion = use_conversion; }
+
+private:
+ /** If true, the proxy will convert input and output data to/from the proxy socket types. */
+ bool m_use_conversion;
};
diff --git a/source/blender/compositor/nodes/COM_SunBeamsNode.cpp b/source/blender/compositor/nodes/COM_SunBeamsNode.cpp
new file mode 100644
index 00000000000..ed14acabf36
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_SunBeamsNode.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#include "COM_SunBeamsNode.h"
+#include "COM_SunBeamsOperation.h"
+
+SunBeamsNode::SunBeamsNode(bNode *editorNode) : Node(editorNode)
+{
+ /* pass */
+}
+
+void SunBeamsNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+{
+ NodeInput *inputSocket = this->getInputSocket(0);
+ NodeOutput *outputSocket = this->getOutputSocket(0);
+ NodeSunBeams *data = (NodeSunBeams *)getbNode()->storage;
+
+ SunBeamsOperation *operation = new SunBeamsOperation();
+ operation->setData(*data);
+ converter.addOperation(operation);
+
+ converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
+ converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
+}
diff --git a/intern/opencl/OCL_opencl.h b/source/blender/compositor/nodes/COM_SunBeamsNode.h
index 733e3527197..4024eb276bc 100644
--- a/intern/opencl/OCL_opencl.h
+++ b/source/blender/compositor/nodes/COM_SunBeamsNode.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011, Blender Foundation.
+ * Copyright 2014, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -15,23 +15,23 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
+ * Contributor:
+ * Lukas Toenne
*/
-#ifndef OCL_OPENCL_H
-#define OCL_OPENCL_H
+#ifndef _COM_SunBeamsNode_h_
+#define _COM_SunBeamsNode_h_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "intern/clew.h"
-int OCL_init(void);
+#include "COM_Node.h"
-#ifdef __cplusplus
-}
-#endif
+/**
+ * @brief SunBeamsNode
+ * @ingroup Node
+ */
+class SunBeamsNode : public Node {
+public:
+ SunBeamsNode(bNode *editorNode);
+ void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+};
#endif
diff --git a/source/blender/compositor/nodes/COM_SwitchNode.cpp b/source/blender/compositor/nodes/COM_SwitchNode.cpp
index 692b8d743f6..10f0ee3821d 100644
--- a/source/blender/compositor/nodes/COM_SwitchNode.cpp
+++ b/source/blender/compositor/nodes/COM_SwitchNode.cpp
@@ -33,9 +33,9 @@ void SwitchNode::convertToOperations(NodeConverter &converter, const CompositorC
NodeOperationOutput *result;
if (!condition)
- result = converter.addInputProxy(getInputSocket(0));
+ result = converter.addInputProxy(getInputSocket(0), false);
else
- result = converter.addInputProxy(getInputSocket(1));
+ result = converter.addInputProxy(getInputSocket(1), false);
converter.mapOutputSocket(getOutputSocket(0), result);
}
diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.h b/source/blender/compositor/operations/COM_BokehImageOperation.h
index f1f0f1ed11c..3cf9afda32a 100644
--- a/source/blender/compositor/operations/COM_BokehImageOperation.h
+++ b/source/blender/compositor/operations/COM_BokehImageOperation.h
@@ -88,7 +88,7 @@ private:
bool m_deleteData;
/**
- * @brief detemine the coordinate of a flap cornder
+ * @brief determine the coordinate of a flap cornder
*
* @param r result in bokehimage space are stored [x,y]
* @param flapNumber the flap number to calculate
diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
index b54e47c136d..cbf4ce693d9 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
@@ -371,7 +371,7 @@ void *DilateStepOperation::initializeTileData(rcti *rect)
float *rectf = result->buffer;
// temp holds maxima for every step in the algorithm, buf holds a
- // single row or column of input values, padded with MAXFLOATs to
+ // single row or column of input values, padded with FLT_MAX's to
// simplify the logic.
float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp");
float *buf = (float *)MEM_mallocN(sizeof(float) * (max(bwidth, bheight) + 5 * half_window), "dilate erode buf");
@@ -380,7 +380,7 @@ void *DilateStepOperation::initializeTileData(rcti *rect)
// first pass, horizontal dilate/erode
for (y = ymin; y < ymax; y++) {
for (x = 0; x < bwidth + 5 * half_window; x++) {
- buf[x] = -MAXFLOAT;
+ buf[x] = -FLT_MAX;
}
for (x = xmin; x < xmax; ++x) {
buf[x - rect->xmin + window - 1] = buffer[4 * (y * width + x)];
@@ -405,7 +405,7 @@ void *DilateStepOperation::initializeTileData(rcti *rect)
// second pass, vertical dilate/erode
for (x = 0; x < bwidth; x++) {
for (y = 0; y < bheight + 5 * half_window; y++) {
- buf[y] = -MAXFLOAT;
+ buf[y] = -FLT_MAX;
}
for (y = ymin; y < ymax; y++) {
buf[y - rect->ymin + window - 1] = rectf[(y - ymin) * bwidth + x];
@@ -498,7 +498,7 @@ void *ErodeStepOperation::initializeTileData(rcti *rect)
float *rectf = result->buffer;
// temp holds maxima for every step in the algorithm, buf holds a
- // single row or column of input values, padded with MAXFLOATs to
+ // single row or column of input values, padded with FLT_MAX's to
// simplify the logic.
float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp");
float *buf = (float *)MEM_mallocN(sizeof(float) * (max(bwidth, bheight) + 5 * half_window), "dilate erode buf");
@@ -507,7 +507,7 @@ void *ErodeStepOperation::initializeTileData(rcti *rect)
// first pass, horizontal dilate/erode
for (y = ymin; y < ymax; y++) {
for (x = 0; x < bwidth + 5 * half_window; x++) {
- buf[x] = MAXFLOAT;
+ buf[x] = FLT_MAX;
}
for (x = xmin; x < xmax; ++x) {
buf[x - rect->xmin + window - 1] = buffer[4 * (y * width + x)];
@@ -532,7 +532,7 @@ void *ErodeStepOperation::initializeTileData(rcti *rect)
// second pass, vertical dilate/erode
for (x = 0; x < bwidth; x++) {
for (y = 0; y < bheight + 5 * half_window; y++) {
- buf[y] = MAXFLOAT;
+ buf[y] = FLT_MAX;
}
for (y = ymin; y < ymax; y++) {
buf[y - rect->ymin + window - 1] = rectf[(y - ymin) * bwidth + x];
diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp
index 0cea2a7183f..67f52934b13 100644
--- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp
@@ -109,8 +109,8 @@ void DirectionalBlurOperation::executeOpenCL(OpenCLDevice *device,
cl_kernel directionalBlurKernel = device->COM_clCreateKernel("directionalBlurKernel", NULL);
cl_int iterations = pow(2.0f, this->m_data->iter);
- cl_float2 ltxy = {this->m_tx, this->m_ty};
- cl_float2 centerpix = {this->m_center_x_pix, this->m_center_y_pix};
+ cl_float2 ltxy = {{this->m_tx, this->m_ty}};
+ cl_float2 centerpix = {{this->m_center_x_pix, this->m_center_y_pix}};
cl_float lsc = this->m_sc;
cl_float lrot = this->m_rot;
diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cpp b/source/blender/compositor/operations/COM_MathBaseOperation.cpp
index cbc60b5091d..32a1e77b9a7 100644
--- a/source/blender/compositor/operations/COM_MathBaseOperation.cpp
+++ b/source/blender/compositor/operations/COM_MathBaseOperation.cpp
@@ -335,12 +335,11 @@ void MathModuloOperation::executePixelSampled(float output[4], float x, float y,
void MathAbsoluteOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- float inputValue1[4];
+ float inputValue1[4];
- this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler);
+ this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler);
- output[0] = fabs(inputValue1[0]);
+ output[0] = fabs(inputValue1[0]);
- clampIfNeeded(output);
+ clampIfNeeded(output);
}
-
diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.h b/source/blender/compositor/operations/COM_MathBaseOperation.h
index 05d2bb054d3..32cd19f1fb9 100644
--- a/source/blender/compositor/operations/COM_MathBaseOperation.h
+++ b/source/blender/compositor/operations/COM_MathBaseOperation.h
@@ -165,8 +165,8 @@ public:
class MathAbsoluteOperation : public MathBaseOperation {
public:
- MathAbsoluteOperation() : MathBaseOperation() {}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ MathAbsoluteOperation() : MathBaseOperation() {}
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
};
#endif
diff --git a/source/blender/compositor/operations/COM_SocketProxyOperation.cpp b/source/blender/compositor/operations/COM_SocketProxyOperation.cpp
index da345b282fd..21d2f28332e 100644
--- a/source/blender/compositor/operations/COM_SocketProxyOperation.cpp
+++ b/source/blender/compositor/operations/COM_SocketProxyOperation.cpp
@@ -22,7 +22,9 @@
#include "COM_SocketProxyOperation.h"
-SocketProxyOperation::SocketProxyOperation(DataType type) : NodeOperation()
+SocketProxyOperation::SocketProxyOperation(DataType type, bool use_conversion) :
+ NodeOperation(),
+ m_use_conversion(use_conversion)
{
this->addInputSocket(type);
this->addOutputSocket(type);
diff --git a/source/blender/compositor/operations/COM_SocketProxyOperation.h b/source/blender/compositor/operations/COM_SocketProxyOperation.h
index 9733a1fbeec..c9d6cb6ef9e 100644
--- a/source/blender/compositor/operations/COM_SocketProxyOperation.h
+++ b/source/blender/compositor/operations/COM_SocketProxyOperation.h
@@ -27,9 +27,16 @@
class SocketProxyOperation : public NodeOperation {
public:
- SocketProxyOperation(DataType type);
+ SocketProxyOperation(DataType type, bool use_conversion);
bool isProxyOperation() const { return true; }
+ bool useDatatypeConversion() const { return m_use_conversion; }
+
+ bool getUseConversion() const { return m_use_conversion; }
+ void setUseConversion(bool use_conversion) { m_use_conversion = use_conversion; }
+
+private:
+ bool m_use_conversion;
};
#endif
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
new file mode 100644
index 00000000000..9a34dccacb1
--- /dev/null
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2014, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "COM_SunBeamsOperation.h"
+
+SunBeamsOperation::SunBeamsOperation() : NodeOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_COLOR);
+ this->setResolutionInputSocketIndex(0);
+
+ this->setComplex(true);
+}
+
+void SunBeamsOperation::initExecution()
+{
+ /* convert to pixels */
+ this->m_source_px[0] = this->m_data.source[0] * this->getWidth();
+ this->m_source_px[1] = this->m_data.source[1] * this->getHeight();
+ this->m_ray_length_px = this->m_data.ray_length * max(this->getWidth(), this->getHeight());
+}
+
+/**
+ * Defines a line accumulator for a specific sector,
+ * given by the four matrix entries that rotate from buffer space into the sector
+ *
+ * (x,y) is used to designate buffer space coordinates
+ * (u,v) is used to designate sector space coordinates
+ *
+ * For a target point (x,y) the sector should be chosen such that
+ * ``u >= v >= 0``
+ * This removes the need to handle all sorts of special cases.
+ */
+template <int fxx, int fxy, int fyx, int fyy>
+struct BufferLineAccumulator {
+
+ /* utility functions implementing the matrix transform to/from sector space */
+
+ static inline void buffer_to_sector(int x, int y, int &u, int &v)
+ {
+ u = x * fxx + y * fyx;
+ v = x * fxy + y * fyy;
+ }
+
+ static inline void buffer_to_sector(float x, float y, float &u, float &v)
+ {
+ u = x * fxx + y * fyx;
+ v = x * fxy + y * fyy;
+ }
+
+ static inline void sector_to_buffer(int u, int v, int &x, int &y)
+ {
+ x = u * fxx + v * fxy;
+ y = u * fyx + v * fyy;
+ }
+
+ static inline void sector_to_buffer(float u, float v, float &x, float &y)
+ {
+ x = u * fxx + v * fxy;
+ y = u * fyx + v * fyy;
+ }
+
+ /**
+ * Set up the initial buffer pointer and calculate necessary variables for looping.
+ *
+ * Note that sector space is centered around the "source" point while the loop starts
+ * at dist_min from the target pt. This way the loop can be canceled as soon as it runs
+ * out of the buffer rect, because no pixels further along the line can contribute.
+ *
+ * \param x, y Start location in the buffer
+ * \param num Total steps in the loop
+ * \param v, dv Vertical offset in sector space, for line offset perpendicular to the loop axis
+ */
+ static float *init_buffer_iterator(MemoryBuffer *input, const float source[2], const float pt_ofs[2],
+ float dist_min, float dist_max,
+ int &x, int &y, int &num, float &v, float &dv, float &falloff_factor)
+ {
+ float pu, pv;
+ buffer_to_sector(pt_ofs[0], pt_ofs[1], pu, pv);
+
+ /* line angle */
+ float tan_phi = pv / pu;
+ float dr = sqrtf(tan_phi * tan_phi + 1.0f);
+ float cos_phi = 1.0f / dr;
+
+ /* clamp u range to avoid influence of pixels "behind" the source */
+ float umin = max_ff(pu - cos_phi * dist_min, 0.0f);
+ float umax = max_ff(pu - cos_phi * dist_max, 0.0f);
+ v = umin * tan_phi;
+ dv = tan_phi;
+
+ int start = (int)floorf(umax);
+ int end = (int)ceilf(umin);
+ num = end - start;
+
+ sector_to_buffer(end, (int)ceilf(v), x, y);
+ x += (int)source[0];
+ y += (int)source[1];
+
+ falloff_factor = dist_max > dist_min ? dr / (float)(dist_max - dist_min) : 0.0f;
+
+ float *iter = input->getBuffer() + COM_NUMBER_OF_CHANNELS * (x + input->getWidth() * y);
+ return iter;
+ }
+
+ /**
+ * Perform the actual accumulation along a ray segment from source to pt.
+ * Only pixels withing dist_min..dist_max contribute.
+ *
+ * The loop runs backwards(!) over the primary sector space axis u, i.e. increasing distance to pt.
+ * After each step it decrements v by dv < 1, adding a buffer shift when necessary.
+ */
+ static void eval(MemoryBuffer *input, float output[4], const float pt_ofs[2], const float source[2],
+ float dist_min, float dist_max)
+ {
+ rcti rect = *input->getRect();
+ int buffer_width = input->getWidth();
+ int x, y, num;
+ float v, dv;
+ float falloff_factor;
+
+ /* initialise the iteration variables */
+ float *buffer = init_buffer_iterator(input, source, pt_ofs, dist_min, dist_max, x, y, num, v, dv, falloff_factor);
+
+ int tot = 0;
+
+ /* v_local keeps track of when to decrement v (see below) */
+ float v_local = v - floorf(v);
+
+ for (int i = 0; i < num; i++) {
+ /* range check, abort when running beyond the image border */
+ if (x < rect.xmin || x >= rect.xmax || y < rect.ymin || y >= rect.ymax)
+ break;
+
+ float f = 1.0f - (float)i * falloff_factor;
+ madd_v4_v4fl(output, buffer, buffer[3] * f * f);
+ /* TODO implement proper filtering here, see
+ * http://en.wikipedia.org/wiki/Lanczos_resampling
+ * http://en.wikipedia.org/wiki/Sinc_function
+ *
+ * using lanczos with x = distance from the line segment,
+ * normalized to a == 0.5f, could give a good result
+ *
+ * for now just count samples and divide equally at the end ...
+ */
+ tot++;
+
+ /* decrement u */
+ x -= fxx;
+ y -= fyx;
+ buffer -= (fxx + fyx * buffer_width) * COM_NUMBER_OF_CHANNELS;
+
+ /* decrement v (in steps of dv < 1) */
+ v_local -= dv;
+ if (v_local < 0.0f) {
+ v_local += 1.0f;
+
+ x -= fxy;
+ y -= fyy;
+ buffer -= (fxy + fyy * buffer_width) * COM_NUMBER_OF_CHANNELS;
+ }
+ }
+
+ /* normalize */
+ if (num > 0) {
+ mul_v4_fl(output, 1.0f / (float)num);
+ }
+ }
+};
+
+/**
+ * Dispatch function which selects an appropriate accumulator based on the sector of the target point,
+ * relative to the source.
+ *
+ * The BufferLineAccumulator defines the actual loop over the buffer, with an efficient inner loop
+ * due to using compile time constants instead of a local matrix variable defining the sector space.
+ */
+static void accumulate_line(MemoryBuffer *input, float output[4], const float co[2], const float source[2],
+ float dist_min, float dist_max)
+{
+ /* coordinates relative to source */
+ float pt_ofs[2] = {co[0] - source[0], co[1] - source[1]};
+
+ /* The source sectors are defined like so:
+ *
+ * \ 3 | 2 /
+ * \ | /
+ * 4 \ | / 1
+ * \|/
+ * -----------
+ * /|\
+ * 5 / | \ 8
+ * / | \
+ * / 6 | 7 \
+ *
+ * The template arguments encode the transformation into "sector space",
+ * by means of rotation/mirroring matrix elements.
+ */
+
+ if (fabsf(pt_ofs[1]) > fabsf(pt_ofs[0])) {
+ if (pt_ofs[0] > 0.0f) {
+ if (pt_ofs[1] > 0.0f) {
+ /* 2 */
+ BufferLineAccumulator<0, 1, 1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ else {
+ /* 7 */
+ BufferLineAccumulator<0, 1, -1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ }
+ else {
+ if (pt_ofs[1] > 0.0f) {
+ /* 3 */
+ BufferLineAccumulator<0, -1, 1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ else {
+ /* 6 */
+ BufferLineAccumulator<0, -1, -1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ }
+ }
+ else {
+ if (pt_ofs[0] > 0.0f) {
+ if (pt_ofs[1] > 0.0f) {
+ /* 1 */
+ BufferLineAccumulator< 1, 0, 0, 1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ else {
+ /* 8 */
+ BufferLineAccumulator< 1, 0, 0, -1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ }
+ else {
+ if (pt_ofs[1] > 0.0f) {
+ /* 4 */
+ BufferLineAccumulator<-1, 0, 0, 1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ else {
+ /* 5 */
+ BufferLineAccumulator<-1, 0, 0, -1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ }
+ }
+}
+
+void *SunBeamsOperation::initializeTileData(rcti *rect)
+{
+ void *buffer = getInputOperation(0)->initializeTileData(NULL);
+ return buffer;
+}
+
+void SunBeamsOperation::executePixel(float output[4], int x, int y, void *data)
+{
+ const float co[2] = {(float)x, (float)y};
+
+ accumulate_line((MemoryBuffer *)data, output, co, this->m_source_px, 0.0f, this->m_ray_length_px);
+}
+
+static void calc_ray_shift(rcti *rect, float x, float y, const float source[2], float ray_length)
+{
+ float co[2] = {(float)x, (float)y};
+ float dir[2], dist;
+
+ /* move (x,y) vector toward the source by ray_length distance */
+ sub_v2_v2v2(dir, co, source);
+ dist = normalize_v2(dir);
+ mul_v2_fl(dir, min_ff(dist, ray_length));
+ sub_v2_v2(co, dir);
+
+ int ico[2] = {(int)co[0], (int)co[1]};
+ BLI_rcti_do_minmax_v(rect, ico);
+}
+
+bool SunBeamsOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+{
+ /* Enlarges the rect by moving each corner toward the source.
+ * This is the maximum distance that pixels can influence each other
+ * and gives a rect that contains all possible accumulated pixels.
+ */
+ rcti rect = *input;
+ calc_ray_shift(&rect, input->xmin, input->ymin, this->m_source_px, this->m_ray_length_px);
+ calc_ray_shift(&rect, input->xmin, input->ymax, this->m_source_px, this->m_ray_length_px);
+ calc_ray_shift(&rect, input->xmax, input->ymin, this->m_source_px, this->m_ray_length_px);
+ calc_ray_shift(&rect, input->xmax, input->ymax, this->m_source_px, this->m_ray_length_px);
+
+ return NodeOperation::determineDependingAreaOfInterest(&rect, readOperation, output);
+}
+
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.h b/source/blender/compositor/operations/COM_SunBeamsOperation.h
new file mode 100644
index 00000000000..ef80a31fe40
--- /dev/null
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#ifndef _COM_SunBeamsOperation_h
+#define _COM_SunBeamsOperation_h
+
+#include "COM_NodeOperation.h"
+
+class SunBeamsOperation : public NodeOperation {
+public:
+ SunBeamsOperation();
+
+ void executePixel(float output[4], int x, int y, void *data);
+
+ void initExecution();
+
+ void *initializeTileData(rcti *rect);
+
+ bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
+
+ void setData(const NodeSunBeams &data) { m_data = data; }
+
+private:
+ NodeSunBeams m_data;
+
+ float m_source_px[2];
+ float m_ray_length_px;
+};
+
+#endif
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index b47e096dbff..c00fe6f103e 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -3845,7 +3845,7 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
short offset;
/* sanity checks - don't draw anything */
- if (ELEM3(NULL, acf, ale, block))
+ if (ELEM(NULL, acf, ale, block))
return;
/* get initial offset */
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 9997cc07c19..b6ab0407711 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -605,7 +605,7 @@ static int animedit_poll_channels_active(bContext *C)
if (ELEM(NULL, sa, CTX_wm_region(C)))
return 0;
/* animation editor test */
- if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
+ if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
return 0;
return 1;
@@ -622,7 +622,7 @@ static int animedit_poll_channels_nla_tweakmode_off(bContext *C)
if (ELEM(NULL, sa, CTX_wm_region(C)))
return 0;
/* animation editor test */
- if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
+ if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
return 0;
/* NLA TweakMode test */
@@ -901,10 +901,10 @@ static void rearrange_animchannels_filter_visible(ListBase *anim_data_visible, b
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale, *ale_next;
- int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
/* get all visible channels */
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* now, only keep the ones that are of the types we are interested in */
for (ale = anim_data.first; ale; ale = ale_next) {
@@ -2257,7 +2257,7 @@ static int animchannels_find_poll(bContext *C)
return 0;
/* animation editor with dopesheet */
- return ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA);
+ return ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA);
}
/* find_invoke() - Get initial channels */
@@ -2802,7 +2802,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
/* deselect all other channels */
ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
- if (pchan) ED_pose_deselectall(ob, 0);
+ if (pchan) ED_pose_de_selectall(ob, SEL_DESELECT, false);
/* only select channels in group and group itself */
for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next)
@@ -2812,7 +2812,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
else {
/* select group by itself */
ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
- if (pchan) ED_pose_deselectall(ob, 0);
+ if (pchan) ED_pose_de_selectall(ob, SEL_DESELECT, false);
agrp->flag |= AGRP_SELECTED;
}
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index 640349199be..f3b47b168e9 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -193,7 +193,7 @@ static void animchan_sync_fcurve(bAnimContext *ac, bAnimListElem *ale, FCurve **
/* major priority is selection status, so refer to the checks done in anim_filter.c
* skip_fcurve_selected_data() for reference about what's going on here...
*/
- if (ELEM3(NULL, fcu, fcu->rna_path, owner_id))
+ if (ELEM(NULL, fcu, fcu->rna_path, owner_id))
return;
if (GS(owner_id->name) == ID_OB) {
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index d3e6d8f474f..57df6d32f03 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -63,7 +63,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
/* sanity checks */
if (name == NULL)
return icon;
- else if (ELEM3(NULL, id, fcu, fcu->rna_path)) {
+ else if (ELEM(NULL, id, fcu, fcu->rna_path)) {
if (fcu == NULL)
strcpy(name, IFACE_("<invalid>"));
else if (fcu->rna_path == NULL)
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index da3d17b3190..0789aa6c148 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -204,7 +204,7 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la
/* sanity check */
//printf("markers = %p - %p, %p\n", markers, markers->first, markers->last);
- if (ELEM3(NULL, markers, markers->first, markers->last)) {
+ if (ELEM(NULL, markers, markers->first, markers->last)) {
*first = 0.0f;
*last = 0.0f;
return;
@@ -603,24 +603,88 @@ typedef struct MarkerMove {
NumInput num;
} MarkerMove;
+static bool ed_marker_move_use_time(MarkerMove *mm)
+{
+ if (((mm->slink->spacetype == SPACE_TIME) && !(((SpaceTime *)mm->slink)->flag & TIME_DRAWFRAMES)) ||
+ ((mm->slink->spacetype == SPACE_SEQ) && !(((SpaceSeq *)mm->slink)->flag & SEQ_DRAWFRAMES)) ||
+ ((mm->slink->spacetype == SPACE_ACTION) && (((SpaceAction *)mm->slink)->flag & SACTION_DRAWTIME)) ||
+ ((mm->slink->spacetype == SPACE_IPO) && !(((SpaceIpo *)mm->slink)->flag & SIPO_DRAWTIME)) ||
+ ((mm->slink->spacetype == SPACE_NLA) && !(((SpaceNla *)mm->slink)->flag & SNLA_DRAWTIME)))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+static void ed_marker_move_update_header(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ MarkerMove *mm = op->customdata;
+ TimeMarker *marker, *selmarker = NULL;
+ const int offs = RNA_int_get(op->ptr, "frames");
+ char str[256];
+ char str_offs[NUM_STR_REP_LEN];
+ int totmark;
+ const bool use_time = ed_marker_move_use_time(mm);
+
+ for (totmark = 0, marker = mm->markers->first; marker; marker = marker->next) {
+ if (marker->flag & SELECT) {
+ selmarker = marker;
+ totmark++;
+ }
+ }
+
+ if (hasNumInput(&mm->num)) {
+ outputNumInput(&mm->num, str_offs, &scene->unit);
+ }
+ else if (use_time) {
+ BLI_snprintf(str_offs, sizeof(str_offs), "%.2f", FRA2TIME(offs));
+ }
+ else {
+ BLI_snprintf(str_offs, sizeof(str_offs), "%d", offs);
+ }
+
+ if (totmark == 1 && selmarker) {
+ /* we print current marker value */
+ if (use_time) {
+ BLI_snprintf(str, sizeof(str), "Marker %.2f offset %s", FRA2TIME(selmarker->frame), str_offs);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), "Marker %d offset %s", selmarker->frame, str_offs);
+ }
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), "Marker offset %s", str_offs);
+ }
+
+ ED_area_headerprint(CTX_wm_area(C), str);
+}
+
/* copy selection to temp buffer */
/* return 0 if not OK */
-static int ed_marker_move_init(bContext *C, wmOperator *op)
+static bool ed_marker_move_init(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
ListBase *markers = ED_context_get_markers(C);
MarkerMove *mm;
TimeMarker *marker;
- int totmark = 0;
- int a;
+ int a, totmark;
+
+ if (markers == NULL) {
+ return false;
+ }
+
+ for (totmark = 0, marker = markers->first; marker; marker = marker->next) {
+ if (marker->flag & SELECT) {
+ totmark++;
+ }
+ }
+
+ if (totmark == 0) {
+ return false;
+ }
- if (markers == NULL) return 0;
-
- for (marker = markers->first; marker; marker = marker->next)
- if (marker->flag & SELECT) totmark++;
-
- if (totmark == 0) return 0;
-
op->customdata = mm = MEM_callocN(sizeof(MarkerMove), "Markermove");
mm->slink = CTX_wm_space_data(C);
mm->markers = markers;
@@ -631,16 +695,16 @@ static int ed_marker_move_init(bContext *C, wmOperator *op)
mm->num.val_flag[0] |= NUM_NO_FRACTION;
mm->num.unit_sys = scene->unit.system;
/* No time unit supporting frames currently... */
- mm->num.unit_type[0] = B_UNIT_NONE;
-
+ mm->num.unit_type[0] = ed_marker_move_use_time(mm) ? B_UNIT_TIME : B_UNIT_NONE;
+
for (a = 0, marker = markers->first; marker; marker = marker->next) {
if (marker->flag & SELECT) {
mm->oldframe[a] = marker->frame;
a++;
}
}
-
- return 1;
+
+ return true;
}
/* free stuff */
@@ -671,7 +735,9 @@ static int ed_marker_move_invoke(bContext *C, wmOperator *op, const wmEvent *eve
/* reset frs delta */
RNA_int_set(op->ptr, "frames", 0);
-
+
+ ed_marker_move_update_header(C, op);
+
return OPERATOR_RUNNING_MODAL;
}
@@ -725,138 +791,88 @@ static void ed_marker_move_cancel(bContext *C, wmOperator *op)
ed_marker_move_exit(C, op);
}
-
-
static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
MarkerMove *mm = op->customdata;
View2D *v2d = UI_view2d_fromcontext(C);
- TimeMarker *marker, *selmarker = NULL;
- char str[256];
-
- switch (event->type) {
- case ESCKEY:
- ed_marker_move_cancel(C, op);
- return OPERATOR_CANCELLED;
- case RIGHTMOUSE:
- /* press = user manually demands transform to be canceled */
- if (event->val == KM_PRESS) {
+ const bool has_numinput = hasNumInput(&mm->num);
+ const bool use_time = ed_marker_move_use_time(mm);
+
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &mm->num, event)) {
+ float value = (float)RNA_int_get(op->ptr, "frames");
+
+ applyNumInput(&mm->num, &value);
+ if (use_time) {
+ value = TIME2FRA(value);
+ }
+
+ RNA_int_set(op->ptr, "frames", (int)value);
+ ed_marker_move_apply(C, op);
+ ed_marker_move_update_header(C, op);
+ }
+ else {
+ bool handled = false;
+ switch (event->type) {
+ case ESCKEY:
ed_marker_move_cancel(C, op);
return OPERATOR_CANCELLED;
- }
- /* else continue; <--- see if release event should be caught for tweak-end */
-
- case RETKEY:
- case PADENTER:
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- if (WM_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);
- return OPERATOR_FINISHED;
- }
- break;
- case MOUSEMOVE:
- {
- float dx, fac;
-
- if (hasNumInput(&mm->num))
- break;
-
- dx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
-
- if (event->x != mm->evtx) { /* XXX maybe init for first time */
- int a, offs, totmark = 0;
-
- mm->evtx = event->x;
-
- fac = ((float)(event->x - mm->firstx) * dx);
-
- if (mm->slink->spacetype == SPACE_TIME)
- apply_keyb_grid(event->shift, event->ctrl, &fac, 0.0, FPS, 0.1 * FPS, 0);
- else
- apply_keyb_grid(event->shift, event->ctrl, &fac, 0.0, 1.0, 0.1, 0 /*was: U.flag & USER_AUTOGRABGRID*/);
-
- offs = (int)fac;
- RNA_int_set(op->ptr, "frames", offs);
- ed_marker_move_apply(C, op);
-
- /* cruft below is for header print */
- for (a = 0, marker = mm->markers->first; marker; marker = marker->next) {
- if (marker->flag & SELECT) {
- selmarker = marker;
- a++; totmark++;
- }
+ case RIGHTMOUSE:
+ /* press = user manually demands transform to be canceled */
+ if (event->val == KM_PRESS) {
+ ed_marker_move_cancel(C, op);
+ return OPERATOR_CANCELLED;
}
-
- if (totmark == 1) {
- /* we print current marker value */
- if (mm->slink->spacetype == SPACE_TIME) {
- SpaceTime *stime = (SpaceTime *)mm->slink;
- if (stime->flag & TIME_DRAWFRAMES)
- BLI_snprintf(str, sizeof(str), "Marker %d offset %d", selmarker->frame, offs);
- else
- BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
- }
- else if (mm->slink->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)mm->slink;
- if (saction->flag & SACTION_DRAWTIME)
- BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
- else
- BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
- }
- else {
- BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
- }
+ /* else continue; <--- see if release event should be caught for tweak-end */
+
+ case RETKEY:
+ case PADENTER:
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ if (WM_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);
+ return OPERATOR_FINISHED;
}
- else {
- /* we only print the offset */
- if (mm->slink->spacetype == SPACE_TIME) {
- SpaceTime *stime = (SpaceTime *)mm->slink;
- if (stime->flag & TIME_DRAWFRAMES)
- BLI_snprintf(str, sizeof(str), "Marker offset %d ", offs);
- else
- BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", FRA2TIME(offs));
- }
- else if (mm->slink->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)mm->slink;
- if (saction->flag & SACTION_DRAWTIME)
- BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", FRA2TIME(offs));
+ break;
+ case MOUSEMOVE:
+ if (!has_numinput) {
+ float dx;
+
+ dx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
+
+ if (event->x != mm->evtx) { /* XXX maybe init for first time */
+ float fac;
+
+ mm->evtx = event->x;
+ fac = ((float)(event->x - mm->firstx) * dx);
+
+ if (mm->slink->spacetype == SPACE_TIME)
+ apply_keyb_grid(event->shift, event->ctrl, &fac, 0.0, FPS, 0.1 * FPS, 0);
else
- BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", (double)(offs));
- }
- else {
- BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", (double)(offs));
+ apply_keyb_grid(event->shift, event->ctrl, &fac, 0.0, 1.0, 0.1, 0 /*was: U.flag & USER_AUTOGRABGRID*/);
+
+ RNA_int_set(op->ptr, "frames", (int)fac);
+ ed_marker_move_apply(C, op);
+ ed_marker_move_update_header(C, op);
}
}
-
- ED_area_headerprint(CTX_wm_area(C), str);
- }
- break;
+ break;
}
- }
- if (event->val == KM_PRESS) {
- if (handleNumInput(C, &mm->num, event)) {
- char str_tx[NUM_STR_REP_LEN];
- float value = RNA_int_get(op->ptr, "frames");
- applyNumInput(&mm->num, &value);
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &mm->num, event)) {
+ float value = (float)RNA_int_get(op->ptr, "frames");
- if (hasNumInput(&mm->num)) {
- outputNumInput(&mm->num, str_tx, scene->unit.scale_length);
- }
- else {
- BLI_snprintf(str_tx, sizeof(str_tx), "%d", (int)value);
+ applyNumInput(&mm->num, &value);
+ if (use_time) {
+ value = TIME2FRA(value);
}
- RNA_int_set(op->ptr, "frames", value);
+ RNA_int_set(op->ptr, "frames", (int)value);
ed_marker_move_apply(C, op);
- // ed_marker_header_update(C, op, str, (int)value);
- // strcat(str, str_tx);
- BLI_snprintf(str, sizeof(str), "Marker offset %s", str_tx);
- ED_area_headerprint(CTX_wm_area(C), str);
+ ed_marker_move_update_header(C, op);
}
}
@@ -1011,14 +1027,14 @@ static void select_timeline_marker_frame(ListBase *markers, int frame, bool exte
}
}
- LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_first) {
+ BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_first) {
/* this way a not-extend select will allways give 1 selected marker */
if (marker->frame == frame) {
marker->flag ^= SELECT;
break;
}
}
- LISTBASE_CIRCULAR_FORWARD_END (markers, marker, marker_first);
+ BLI_LISTBASE_CIRCULAR_FORWARD_END (markers, marker, marker_first);
}
static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool camera)
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 88429aa3867..0f202003dd8 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -72,7 +72,7 @@ static int change_frame_poll(bContext *C)
* this shouldn't show up in 3D editor (or others without 2D timeline view) via search
*/
if (sa) {
- if (ELEM5(sa->spacetype, SPACE_TIME, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
+ if (ELEM(sa->spacetype, SPACE_TIME, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
return true;
}
else if (sa->spacetype == SPACE_IPO) {
@@ -168,6 +168,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
case LEFTMOUSE:
case RIGHTMOUSE:
+ case MIDDLEMOUSE:
/* we check for either mouse-button to end, as checking for ACTIONMOUSE (which is used to init
* the modal op) doesn't work for some reason
*/
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index ee5039488bd..83593faff22 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -670,8 +670,8 @@ static short snap_bezier_horizontal(KeyframeEditData *UNUSED(ked), BezTriple *be
if (bezt->f2 & SELECT) {
bezt->vec[0][1] = bezt->vec[2][1] = bezt->vec[1][1];
- if (ELEM3(bezt->h1, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h1 = HD_ALIGN;
- if (ELEM3(bezt->h2, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h2 = HD_ALIGN;
+ if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h1 = HD_ALIGN;
+ if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h2 = HD_ALIGN;
}
return 0;
}
@@ -810,9 +810,9 @@ KeyframeEditFunc ANIM_editkeyframes_mirror(short type)
*/
#define ENSURE_HANDLES_MATCH(bezt) \
if (bezt->h1 != bezt->h2) { \
- if (ELEM3(bezt->h1, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM)) \
+ if (ELEM(bezt->h1, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM)) \
bezt->h1 = HD_FREE; \
- if (ELEM3(bezt->h2, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM)) \
+ if (ELEM(bezt->h2, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM)) \
bezt->h2 = HD_FREE; \
} (void)0
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index 640568a99e4..56165c36efa 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -408,8 +408,8 @@ void sample_fcurve(FCurve *fcu)
* keyframes while sampling will affect the outcome...
* - only start sampling+adding from index=1, so that we don't overwrite original keyframe
*/
- range = (int)(ceil(end->vec[1][0] - start->vec[1][0]) );
- sfra = (int)(floor(start->vec[1][0]) );
+ range = (int)(ceil(end->vec[1][0] - start->vec[1][0]));
+ sfra = (int)(floor(start->vec[1][0]));
if (range) {
value_cache = MEM_callocN(sizeof(TempFrameValCache) * range, "IcuFrameValCache");
@@ -732,9 +732,9 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float
bezt->vec[2][0] += offset;
/* insert the keyframe
- * NOTE: no special flags here for now
+ * NOTE: we do not want to inherit handles from existing keyframes in this case!
*/
- insert_bezt_fcurve(fcu, bezt, 0);
+ insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL);
/* un-apply offset from src beztriple after copying */
bezt->vec[0][0] -= offset;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 878c9193b23..4c2d90179a7 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -310,20 +310,25 @@ int insert_bezt_fcurve(FCurve *fcu, BezTriple *bezt, short flag)
if (replace) {
/* sanity check: 'i' may in rare cases exceed arraylen */
if ((i >= 0) && (i < fcu->totvert)) {
- /* just change the values when replacing, so as to not overwrite handles */
- BezTriple *dst = (fcu->bezt + i);
- float dy = bezt->vec[1][1] - dst->vec[1][1];
-
- /* just apply delta value change to the handle values */
- dst->vec[0][1] += dy;
- dst->vec[1][1] += dy;
- dst->vec[2][1] += dy;
-
- dst->f1 = bezt->f1;
- dst->f2 = bezt->f2;
- dst->f3 = bezt->f3;
-
- /* TODO: perform some other operations? */
+ if (flag & INSERTKEY_OVERWRITE_FULL) {
+ fcu->bezt[i] = *bezt;
+ }
+ else {
+ /* just change the values when replacing, so as to not overwrite handles */
+ BezTriple *dst = (fcu->bezt + i);
+ float dy = bezt->vec[1][1] - dst->vec[1][1];
+
+ /* just apply delta value change to the handle values */
+ dst->vec[0][1] += dy;
+ dst->vec[1][1] += dy;
+ dst->vec[2][1] += dy;
+
+ dst->f1 = bezt->f1;
+ dst->f2 = bezt->f2;
+ dst->f3 = bezt->f3;
+
+ /* TODO: perform some other operations? */
+ }
}
}
/* keyframing modes allow to not replace keyframe */
@@ -652,7 +657,7 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
const char *identifier = NULL;
/* validate data */
- if (ELEM3(NULL, ptr, ptr->data, prop))
+ if (ELEM(NULL, ptr, ptr->data, prop))
return 0;
/* get first constraint and determine type of keyframe constraints to check for
@@ -1042,7 +1047,7 @@ 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 (ELEM5(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
+ if (ELEM(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
fcu->color_mode = FCURVE_COLOR_AUTO_RGB;
}
}
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index fc211f0e60b..d82da1c827f 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -23,10 +23,10 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
- ../../gpu
../../makesdna
../../makesrna
../../windowmanager
+ ../../gpu
../../../../intern/guardedalloc
../../../../intern/glew-mx
)
diff --git a/source/blender/editors/armature/SConscript b/source/blender/editors/armature/SConscript
index b3c1ea2dbe9..c68045c9398 100644
--- a/source/blender/editors/armature/SConscript
+++ b/source/blender/editors/armature/SConscript
@@ -39,6 +39,7 @@ incs = [
'../../blenlib',
'../../makesdna',
'../../makesrna',
+ '../../gpu',
'../../windowmanager',
]
incs = ' '.join(incs)
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index 16975eed75e..eba1bc4d78d 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -84,7 +84,7 @@ EditBone *ED_armature_edit_bone_add(bArmature *arm, const char *name)
return bone;
}
-void add_primitive_bone(Object *obedit_arm, bool view_aligned)
+EditBone *ED_armature_edit_bone_add_primitive(Object *obedit_arm, float length, bool view_aligned)
{
bArmature *arm = obedit_arm->data;
EditBone *bone;
@@ -99,10 +99,9 @@ void add_primitive_bone(Object *obedit_arm, bool view_aligned)
zero_v3(bone->head);
zero_v3(bone->tail);
- if (view_aligned)
- bone->tail[1] = 1.0f;
- else
- bone->tail[2] = 1.0f;
+ bone->tail[view_aligned ? 1 : 2] = length;
+
+ return bone;
}
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index f71cfd52175..1e4d9bac246 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -1343,7 +1343,9 @@ static int armature_reveal_exec(bContext *C, wmOperator *UNUSED(op))
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
if (arm->layer & ebone->layer) {
if (ebone->flag & BONE_HIDDEN_A) {
- ebone->flag |= (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ if (!(ebone->flag & BONE_UNSELECTABLE)) {
+ ebone->flag |= (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ }
ebone->flag &= ~BONE_HIDDEN_A;
}
}
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 9c3c93e4850..12d13b05ee1 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -160,7 +160,7 @@ void *get_nearest_bone(bContext *C, short findunsel, int x, int y)
rect.ymin = rect.ymax = y;
glInitNames();
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+ hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
if (hits > 0)
return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel);
@@ -295,13 +295,13 @@ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
rect.ymin = mval[1] - 5;
rect.ymax = mval[1] + 5;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
+ hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, true);
if (hits == 0) {
rect.xmin = mval[0] - 12;
rect.xmax = mval[0] + 12;
rect.ymin = mval[1] - 12;
rect.ymax = mval[1] + 12;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
+ hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, true);
}
/* See if there are any selected bones in this group */
if (hits > 0) {
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index e898e600e9b..fbc18e977ce 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -180,15 +180,6 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
return 0;
}
-static void add_vgroups__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
-{
- /* DerivedMesh mapFunc for getting final coords in weight paint mode */
-
- float (*verts)[3] = userData;
- copy_v3_v3(verts[index], co);
-}
-
static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist,
bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
float (*root)[3], float (*tip)[3], const int *selected, float scale)
@@ -200,10 +191,22 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
float distance;
int i, iflip, j;
bool use_topology = (mesh->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ bool use_mask = false;
+
+ if ((ob->mode & OB_MODE_WEIGHT_PAINT) &&
+ (mesh->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)))
+ {
+ use_mask = true;
+ }
/* for each vertex in the mesh */
for (i = 0; i < mesh->totvert; i++) {
- iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, i, use_topology) : 0;
+
+ if (use_mask && !(mesh->mvert[i].flag & SELECT)) {
+ continue;
+ }
+
+ iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, i, use_topology) : -1;
/* for each skinnable bone */
for (j = 0; j < numbones; ++j) {
@@ -224,7 +227,7 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
ED_vgroup_vert_remove(ob, dgroup, i);
/* do same for mirror */
- if (dgroupflip && dgroupflip[j] && iflip >= 0) {
+ if (dgroupflip && dgroupflip[j] && iflip != -1) {
if (distance != 0.0f)
ED_vgroup_vert_add(ob, dgroupflip[j], iflip, distance,
WEIGHT_REPLACE);
@@ -362,7 +365,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
if (dm->foreachMappedVert) {
- dm->foreachMappedVert(dm, add_vgroups__mapFunc, (void *)verts, DM_FOREACH_NOP);
+ mesh_get_mapped_verts_coords(dm, verts, mesh->totvert);
vertsfilled = 1;
}
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index ec139b9b2a1..85dcb2ed4da 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -53,6 +53,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "GPU_select.h"
+
typedef int (*GestureDetectFct)(bContext *, SK_Gesture *, SK_Sketch *);
typedef void (*GestureApplyFct)(bContext *, SK_Gesture *, SK_Sketch *);
@@ -493,7 +495,7 @@ static void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int
gluQuadricNormals(quad, GLU_SMOOTH);
if (id != -1) {
- glLoadName(id);
+ GPU_select_load_id(id);
for (i = 0; i < stk->nb_points; i++) {
glPushMatrix();
@@ -1969,7 +1971,7 @@ static int sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], in
rect.ymin = mval[1] - 5;
rect.ymax = mval[1] + 5;
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+ hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
if (hits > 0) {
int besthitresult = -1;
@@ -2032,7 +2034,7 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch,
sk_drawStroke(stk, id, NULL, -1, -1);
}
- glLoadName(-1);
+ GPU_select_load_id(-1);
}
else {
float selected_rgb[3] = {1, 0, 0};
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 56e7bde0081..49650fcadbf 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -635,8 +635,8 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
MVert *mvert = me->mvert;
- bool use_vert_sel = false;
- bool use_face_sel = false;
+ bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
*err_str = NULL;
@@ -652,9 +652,8 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
return;
/* count triangles and create mask */
- if (ob->mode == OB_MODE_WEIGHT_PAINT &&
- ((use_face_sel = ((me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0)) ||
- (use_vert_sel = ((me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0))))
+ if (ob->mode & OB_MODE_WEIGHT_PAINT &&
+ (use_face_sel || use_vert_sel))
{
mask = MEM_callocN(sizeof(int) * me->totvert, "heat_bone_weighting mask");
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 890bf6649b9..da68108285f 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -1074,7 +1074,9 @@ static int show_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
if (arm->layer & bone->layer) {
if (bone->flag & BONE_HIDDEN_P) {
bone->flag &= ~BONE_HIDDEN_P;
- bone->flag |= BONE_SELECTED;
+ if (!(bone->flag & BONE_UNSELECTABLE)) {
+ bone->flag |= BONE_SELECTED;
+ }
}
}
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 0b115da5ff0..0609fcc29e8 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -307,7 +307,7 @@ static int poselib_sanitize_exec(bContext *C, wmOperator *op)
/* check if any pose matches this */
/* TODO: don't go looking through the list like this every time... */
for (marker = act->markers.first; marker; marker = marker->next) {
- if (IS_EQ(marker->frame, (double)ak->cfra)) {
+ if (IS_EQ((double)marker->frame, (double)ak->cfra)) {
marker->flag = -1;
break;
}
@@ -1417,7 +1417,7 @@ static void poselib_preview_init_data(bContext *C, wmOperator *op)
pld->marker = (pld->act) ? BLI_findlink(&pld->act->markers, pose_index) : NULL;
/* check if valid poselib */
- if (ELEM3(NULL, pld->ob, pld->pose, pld->arm)) {
+ if (ELEM(NULL, pld->ob, pld->pose, pld->arm)) {
BKE_report(op->reports, RPT_ERROR, "Pose lib is only for armatures in pose mode");
pld->state = PL_PREVIEW_ERROR;
return;
@@ -1490,7 +1490,6 @@ static void poselib_preview_cleanup(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
else
BKE_pose_where_is(scene, ob);
-
}
else if (pld->state == PL_PREVIEW_CONFIRM) {
/* tag poses as appropriate */
@@ -1511,6 +1510,9 @@ static void poselib_preview_cleanup(bContext *C, wmOperator *op)
BKE_pose_where_is(scene, ob);
}
+ /* Request final redraw of the view. */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pld->ob);
+
/* free memory used for backups and searching */
poselib_backup_free_data(pld);
BLI_freelistN(&pld->searchp);
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index aa741ef9aaf..76284ba44de 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -69,6 +69,29 @@
/* ***************** Pose Select Utilities ********************* */
+/* Note: SEL_TOGGLE is assumed to have already been handled! */
+static void pose_do_bone_select(bPoseChannel *pchan, const int select_mode)
+{
+ /* select pchan only if selectable, but deselect works always */
+ switch (select_mode) {
+ case SEL_SELECT:
+ if (!(pchan->bone->flag & BONE_UNSELECTABLE))
+ pchan->bone->flag |= BONE_SELECTED;
+ break;
+ case SEL_DESELECT:
+ pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ break;
+ case SEL_INVERT:
+ if (pchan->bone->flag & BONE_SELECTED) {
+ pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else if (!(pchan->bone->flag & BONE_UNSELECTABLE)) {
+ pchan->bone->flag |= BONE_SELECTED;
+ }
+ break;
+ }
+}
+
/* Utility method for changing the selection status of a bone */
void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
{
@@ -76,7 +99,7 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
/* sanity checks */
// XXX: actually, we can probably still get away with no object - at most we have no updates
- if (ELEM4(NULL, ob, ob->pose, pchan, pchan->bone))
+ if (ELEM(NULL, ob, ob->pose, pchan, pchan->bone))
return;
arm = ob->data;
@@ -139,7 +162,7 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
}
if (!extend && !deselect && !toggle) {
- ED_pose_deselectall(ob, 0);
+ ED_pose_de_selectall(ob, SEL_DESELECT, true);
nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
arm->act_bone = nearBone;
}
@@ -191,16 +214,12 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
return nearBone != NULL;
}
-/* test==0: deselect all
- * test==1: swap select (apply to all the opposite of current situation)
- * test==2: only clear active tag
- * test==3: swap select (no test / inverse selection status of all independently)
- */
-void ED_pose_deselectall(Object *ob, int test)
+/* 'select_mode' is usual SEL_SELECT/SEL_DESELECT/SEL_TOGGLE/SEL_INVERT.
+ * When true, 'ignore_visibility' makes this func also affect invisible bones (hidden or on hidden layers). */
+void ED_pose_de_selectall(Object *ob, int select_mode, const bool ignore_visibility)
{
bArmature *arm = ob->data;
bPoseChannel *pchan;
- int selectmode = 0;
/* we call this from outliner too */
if (ob->pose == NULL) {
@@ -208,31 +227,23 @@ void ED_pose_deselectall(Object *ob, int test)
}
/* Determine if we're selecting or deselecting */
- if (test == 1) {
+ if (select_mode == SEL_TOGGLE) {
+ select_mode = SEL_SELECT;
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (PBONE_VISIBLE(arm, pchan->bone)) {
- if (pchan->bone->flag & BONE_SELECTED)
+ if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ select_mode = SEL_DESELECT;
break;
+ }
}
}
-
- if (pchan == NULL)
- selectmode = 1;
}
- else if (test == 2)
- selectmode = 2;
- /* Set the flags accordingly */
+ /* Set the flags accordingly */
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
/* ignore the pchan if it isn't visible or if its selection cannot be changed */
- if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & (BONE_HIDDEN_P | BONE_UNSELECTABLE))) {
- if (test == 3) {
- pchan->bone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- if (selectmode == 0) pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- else if (selectmode == 1) pchan->bone->flag |= BONE_SELECTED;
- }
+ if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
+ pose_do_bone_select(pchan, select_mode);
}
}
}
@@ -353,24 +364,7 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
/* Set the flags */
CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones)
{
- /* select pchan only if selectable, but deselect works always */
- switch (action) {
- case SEL_SELECT:
- if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)
- pchan->bone->flag |= BONE_SELECTED;
- break;
- case SEL_DESELECT:
- pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- break;
- case SEL_INVERT:
- if (pchan->bone->flag & BONE_SELECTED) {
- pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
- pchan->bone->flag |= BONE_SELECTED;
- }
- break;
- }
+ pose_do_bone_select(pchan, action);
}
CTX_DATA_END;
@@ -644,7 +638,7 @@ static bool pose_select_same_group(bContext *C, Object *ob, bool extend)
bool changed = false, tagged = false;
/* sanity checks */
- if (ELEM3(NULL, ob, pose, arm))
+ if (ELEM(NULL, ob, pose, arm))
return 0;
/* count the number of groups */
@@ -701,7 +695,7 @@ static bool pose_select_same_layer(bContext *C, Object *ob, bool extend)
bool changed = false;
int layers = 0;
- if (ELEM3(NULL, ob, pose, arm))
+ if (ELEM(NULL, ob, pose, arm))
return 0;
/* figure out what bones are selected */
@@ -761,7 +755,7 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, Object
return false;
}
- if (ELEM3(NULL, ob, pose, arm))
+ if (ELEM(NULL, ob, pose, arm))
return false;
/* if not extending selection, deselect all selected first */
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 375cbb0fe2b..5f9f24d23a4 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -134,7 +134,7 @@ static int pose_slide_init(bContext *C, wmOperator *op, short mode)
pso->nextFrame = RNA_int_get(op->ptr, "next_frame");
/* check the settings from the context */
- if (ELEM4(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action))
+ if (ELEM(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action))
return 0;
else
act = pso->ob->adt->action;
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 7b78b255a55..a52b2a619dc 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -1191,7 +1191,7 @@ static int *initialize_index_map(Object *obedit, int *r_old_totvert)
for (nu = editnurb->nurbs.first, vertex_index = 0;
nu != NULL;
- nu = nu->next, vertex_index++)
+ nu = nu->next)
{
if (nu->bezt) {
BezTriple *bezt = nu->bezt;
@@ -1238,9 +1238,18 @@ static void remap_hooks_and_vertex_parents(Object *obedit)
{
Object *object;
Curve *curve = (Curve *) obedit->data;
+ EditNurb *editnurb = curve->editnurb;
int *old_to_new_map = NULL;
int old_totvert;
+ if (editnurb->keyindex == NULL) {
+ /* TODO(sergey): Happens when separating curves, this would lead to
+ * the wrong indices in the hook modifier, address this together with
+ * other indices issues.
+ */
+ return;
+ }
+
for (object = G.main->object.first; object; object = object->id.next) {
ModifierData *md;
int index;
@@ -1467,37 +1476,6 @@ void ED_curve_select_swap(EditNurb *editnurb, bool hide_handles)
}
}
-/******************** transform operator **********************/
-
-void ED_curve_transform(Curve *cu, float mat[4][4])
-{
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
-
- float scale = mat4_to_scale(mat);
-
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- for (bezt = nu->bezt; a--; bezt++) {
- mul_m4_v3(mat, bezt->vec[0]);
- mul_m4_v3(mat, bezt->vec[1]);
- mul_m4_v3(mat, bezt->vec[2]);
- bezt->radius *= scale;
- }
- BKE_nurb_handles_calc(nu);
- }
- else {
- a = nu->pntsu * nu->pntsv;
- for (bp = nu->bp; a--; bp++)
- mul_m4_v3(mat, bp->vec);
- }
- }
- DAG_id_tag_update(&cu->id, 0);
-}
-
/******************** separate operator ***********************/
static int separate_exec(bContext *C, wmOperator *op)
@@ -1975,17 +1953,15 @@ static void ed_curve_delete_selected(Object *obedit)
next = nu->next;
type = 0;
if (nu->type == CU_BEZIER) {
- int delta = 0;
bezt = nu->bezt;
for (a = 0; a < nu->pntsu; a++) {
if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple));
- keyIndex_delBezt(editnurb, bezt + delta);
+ keyIndex_delBezt(editnurb, bezt);
keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1);
nu->pntsu--;
a--;
type = 1;
- delta++;
}
else {
bezt++;
@@ -2001,18 +1977,16 @@ static void ed_curve_delete_selected(Object *obedit)
}
}
else if (nu->pntsv == 1) {
- int delta = 0;
bp = nu->bp;
for (a = 0; a < nu->pntsu; a++) {
if (bp->f1 & SELECT) {
memmove(bp, bp + 1, (nu->pntsu - a - 1) * sizeof(BPoint));
- keyIndex_delBP(editnurb, bp + delta);
+ keyIndex_delBP(editnurb, bp);
keyIndex_updateBP(editnurb, bp + 1, bp, nu->pntsu - a - 1);
nu->pntsu--;
a--;
type = 1;
- delta++;
}
else {
bp++;
@@ -7023,7 +6997,7 @@ static int match_texture_space_poll(bContext *C)
{
Object *object = CTX_data_active_object(C);
- return object && ELEM3(object->type, OB_CURVE, OB_SURF, OB_FONT);
+ return object && ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT);
}
static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 3fc6e2e6f0d..2a84ca7f297 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -93,6 +93,8 @@ if(WITH_BLENDER)
data_to_c_simple(../../../../release/datafiles/brushicons/soften.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/subtract.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/texdraw.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/texfill.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/texmask.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/thumb.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/vertexdraw.png SRC)
diff --git a/source/blender/editors/datafiles/SConscript b/source/blender/editors/datafiles/SConscript
index 47819d0e33c..6bc8f21e384 100644
--- a/source/blender/editors/datafiles/SConscript
+++ b/source/blender/editors/datafiles/SConscript
@@ -77,6 +77,8 @@ sources.extend((
os.path.join(env['DATA_SOURCES'], "soften.png.c"),
os.path.join(env['DATA_SOURCES'], "subtract.png.c"),
os.path.join(env['DATA_SOURCES'], "texdraw.png.c"),
+ os.path.join(env['DATA_SOURCES'], "texfill.png.c"),
+ os.path.join(env['DATA_SOURCES'], "texmask.png.c"),
os.path.join(env['DATA_SOURCES'], "thumb.png.c"),
os.path.join(env['DATA_SOURCES'], "twist.png.c"),
os.path.join(env['DATA_SOURCES'], "vertexdraw.png.c"),
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 6c73cc19d04..35982c63357 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -771,7 +771,7 @@ void ED_gpencil_draw_view3d(Scene *scene, View3D *v3d, ARegion *ar, bool only3d)
int offsx, offsy, winx, winy;
/* check that we have grease-pencil stuff to draw */
- gpd = ED_gpencil_data_get_active_v3d(scene); // XXX
+ gpd = ED_gpencil_data_get_active_v3d(scene, v3d);
if (gpd == NULL) return;
/* when rendering to the offscreen buffer we don't want to
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index b725f5c773a..13334448941 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -62,6 +62,7 @@
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "BKE_tracking.h"
#include "UI_interface.h"
@@ -186,15 +187,15 @@ bGPdata *ED_gpencil_data_get_active(const bContext *C)
return (gpd_ptr) ? *(gpd_ptr) : NULL;
}
-/* needed for offscreen rendering */
-bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene)
+bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d)
{
Base *base = scene->basact;
bGPdata *gpd = NULL;
/* We have to make sure active object is actually visible and selected, else we must use default scene gpd,
* to be consistent with ED_gpencil_data_get_active's behavior.
*/
- if (base && (scene->lay & base->lay) && (base->object->flag & SELECT)) {
+
+ if (base && TESTBASE(v3d, base)) {
gpd = base->object->gpd;
}
return gpd ? gpd : scene->gpd;
@@ -1399,6 +1400,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
const bool norm_weights, const float rad_fac, const bool link_strokes, tGpTimingData *gtd)
{
struct Main *bmain = CTX_data_main(C);
+ View3D *v3d = CTX_wm_view3d(C); /* may be NULL */
Scene *scene = CTX_data_scene(C);
bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0);
bGPDstroke *gps, *prev_gps = NULL;
@@ -1412,7 +1414,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
rctf subrect, *subrect_ptr = NULL;
/* error checking */
- if (ELEM3(NULL, gpd, gpl, gpf))
+ if (ELEM(NULL, gpd, gpl, gpf))
return;
/* only convert if there are any strokes on this layer's frame to convert */
@@ -1493,7 +1495,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
}
/* set the layer and select */
- base_new->lay = ob->lay = base_orig ? base_orig->lay : scene->lay;
+ base_new->lay = ob->lay = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene);
base_new->flag = ob->flag = base_new->flag | SELECT;
}
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 4910396ac6f..afecdd91599 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1861,7 +1861,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */
if (ISKEYBOARD(event->type)) {
- if (ELEM4(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY)) {
+ if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY)) {
/* allow some keys - for frame changing: [#33412] */
}
else {
@@ -1874,7 +1874,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* exit painting mode (and/or end current stroke)
* NOTE: cannot do RIGHTMOUSE (as is standard for canceling) as that would break polyline [#32647]
*/
- if (ELEM4(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) {
+ if (ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) {
/* exit() ends the current stroke before cleaning up */
/* printf("\t\tGP - end of paint op + end of stroke\n"); */
p->status = GP_STATUS_DONE;
@@ -1949,7 +1949,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* eraser size */
else if ((p->paintmode == GP_PAINTMODE_ERASER) &&
- ELEM4(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, PADPLUSKEY, PADMINUS))
+ ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, PADPLUSKEY, PADMINUS))
{
/* just resize the brush (local version)
* TODO: fix the hardcoded size jumps (set to make a visible difference) and hardcoded keys
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index 5f6c924f469..cd26bb22ada 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -58,8 +58,24 @@
* */
void cpack(unsigned int x);
-#define glMultMatrixf(x) glMultMatrixf( (float *)(x))
-#define glLoadMatrixf(x) glLoadMatrixf( (float *)(x))
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+# define glMultMatrixf(x) \
+ glMultMatrixf(_Generic((x), \
+ float *: (float *)(x), \
+ float (*)[4]: (float *)(x), \
+ const float *: (float *)(x), \
+ const float (*)[4]: (float *)(x)) \
+)
+# define glLoadMatrixf(x) \
+ glLoadMatrixf(_Generic((x), \
+ float *: (float *)(x), \
+ float (*)[4]: (float *)(x)) \
+)
+#else
+# define glMultMatrixf(x) glMultMatrixf((float *)(x))
+# define glLoadMatrixf(x) glLoadMatrixf((float *)(x))
+#endif
#define GLA_PIXEL_OFS 0.375f
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 7579f6cba65..6eac9f14bf6 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -133,8 +133,8 @@ EditBone *ED_armature_bone_get_mirrored(const struct ListBase *edbo, EditBone *e
void ED_armature_sync_selection(struct ListBase *edbo);
void ED_armature_validate_active(struct bArmature *arm);
-void add_primitive_bone(struct Object *obedit_arm, bool view_aligned);
-struct EditBone *ED_armature_edit_bone_add(struct bArmature *arm, const char *name);
+EditBone *ED_armature_edit_bone_add_primitive(struct Object *obedit_arm, float length, bool view_aligned);
+EditBone *ED_armature_edit_bone_add(struct bArmature *arm, const char *name);
void ED_armature_edit_bone_remove(struct bArmature *arm, EditBone *exBone);
bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child);
@@ -174,7 +174,7 @@ void ED_armature_ebone_selectflag_disable(EditBone *ebone, int flag);
/* poseobject.c */
void ED_armature_exit_posemode(struct bContext *C, struct Base *base);
void ED_armature_enter_posemode(struct bContext *C, struct Base *base);
-void ED_pose_deselectall(struct Object *ob, int test);
+void ED_pose_de_selectall(struct Object *ob, int select_mode, const bool ignore_visibility);
void ED_pose_bone_select(struct Object *ob, struct bPoseChannel *pchan, bool select);
void ED_pose_recalculate_paths(struct Scene *scene, struct Object *ob);
struct Object *ED_pose_object_from_context(struct bContext *C);
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index 330147db077..58e64f30b05 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -51,7 +51,6 @@ void ED_operatormacros_curve(void);
void ED_keymap_curve(struct wmKeyConfig *keyconf);
/* editcurve.c */
-void ED_curve_transform(struct Curve *cu, float mat[4][4]);
void ED_curve_deselect_all(struct EditNurb *editnurb);
void ED_curve_select_all(struct EditNurb *editnurb);
void ED_curve_select_swap(struct EditNurb *editnurb, bool hide_handles);
diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h
index 9022a1481aa..661ab58b98c 100644
--- a/source/blender/editors/include/ED_datafiles.h
+++ b/source/blender/editors/include/ED_datafiles.h
@@ -150,6 +150,12 @@ extern char datatoc_subtract_png[];
extern int datatoc_texdraw_png_size;
extern char datatoc_texdraw_png[];
+extern int datatoc_texfill_png_size;
+extern char datatoc_texfill_png[];
+
+extern int datatoc_texmask_png_size;
+extern char datatoc_texmask_png[];
+
extern int datatoc_thumb_png_size;
extern char datatoc_thumb_png[];
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 63ffa1bef0c..05fb76b7aea 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -67,7 +67,7 @@ typedef struct tGPspoint {
struct bGPdata **ED_gpencil_data_get_pointers(const struct bContext *C, struct PointerRNA *ptr);
struct bGPdata *ED_gpencil_data_get_active(const struct bContext *C);
-struct bGPdata *ED_gpencil_data_get_active_v3d(struct Scene *scene); /* for offscreen rendering */
+struct bGPdata *ED_gpencil_data_get_active_v3d(struct Scene *scene, struct View3D *v3d);
/* ----------- Grease Pencil Operators ----------------- */
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index b15a83809f5..db13c628ade 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -69,8 +69,11 @@ void ED_image_point_pos__reverse(struct SpaceImage *sima, struct ARegion *ar, co
bool ED_space_image_show_render(struct SpaceImage *sima);
bool ED_space_image_show_paint(struct SpaceImage *sima);
bool ED_space_image_show_uvedit(struct SpaceImage *sima, struct Object *obedit);
+bool ED_space_image_show_texpaint(struct SpaceImage *sima, struct Object *ob);
bool ED_space_image_show_uvshadow(struct SpaceImage *sima, struct Object *obedit);
+bool ED_space_image_paint_curve(const struct bContext *C);
+
bool ED_space_image_check_show_maskedit(struct Scene *scene, struct SpaceImage *sima);
int ED_space_image_maskedit_poll(struct bContext *C);
int ED_space_image_maskedit_mask_poll(struct bContext *C);
diff --git a/source/blender/editors/include/ED_lattice.h b/source/blender/editors/include/ED_lattice.h
index 4d19b6d5548..6636319dc9b 100644
--- a/source/blender/editors/include/ED_lattice.h
+++ b/source/blender/editors/include/ED_lattice.h
@@ -37,6 +37,5 @@ struct Lattice;
void free_editLatt(struct Object *ob);
void make_editLatt(struct Object *obedit);
void load_editLatt(struct Object *obedit);
-void ED_lattice_transform(struct Lattice *lt, float mat[4][4]);
#endif /* __ED_LATTICE_H__ */
diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h
index 680e9d79109..5e774c63841 100644
--- a/source/blender/editors/include/ED_mball.h
+++ b/source/blender/editors/include/ED_mball.h
@@ -50,6 +50,4 @@ void load_editMball(struct Object *obedit);
void undo_push_mball(struct bContext *C, const char *name);
-void ED_mball_transform(struct MetaBall *mb, float mat[4][4]);
-
#endif /* __ED_MBALL_H__ */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index ebc97c58e24..6a562da0a0e 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -119,7 +119,7 @@ void EDBM_mesh_reveal(struct BMEditMesh *em);
void EDBM_update_generic(struct BMEditMesh *em, const bool do_tessface, const bool is_destructive);
-struct UvElementMap *BM_uv_element_map_create(struct BMesh *em, const bool selected, const bool do_islands);
+struct UvElementMap *BM_uv_element_map_create(struct BMesh *bm, const bool selected, const bool do_islands);
void BM_uv_element_map_free(struct UvElementMap *vmap);
struct UvElement *BM_uv_element_get(struct UvElementMap *map, struct BMFace *efa, struct BMLoop *l);
@@ -264,7 +264,6 @@ void ED_mesh_faces_remove(struct Mesh *mesh, struct ReportList *reports, int cou
void ED_mesh_edges_remove(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_vertices_remove(struct Mesh *mesh, struct ReportList *reports, int count);
-void ED_mesh_transform(struct Mesh *me, float mat[4][4]);
void ED_mesh_calc_tessface(struct Mesh *mesh);
void ED_mesh_update(struct Mesh *mesh, struct bContext *C, int calc_edges, int calc_tessface);
diff --git a/source/blender/editors/include/ED_numinput.h b/source/blender/editors/include/ED_numinput.h
index 4e96ed0c7e7..f9a22429fc2 100644
--- a/source/blender/editors/include/ED_numinput.h
+++ b/source/blender/editors/include/ED_numinput.h
@@ -64,6 +64,8 @@ enum {
/* (1 << 9) and above are reserved for internal flags! */
};
+struct UnitSettings;
+
/*********************** NumInput ********************************/
/* There are important things to note here for code using numinput:
@@ -76,7 +78,7 @@ enum {
*/
void initNumInput(NumInput *n);
-void outputNumInput(NumInput *n, char *str, const float scale_length);
+void outputNumInput(NumInput *n, char *str, struct UnitSettings *unit_settings);
bool hasNumInput(const NumInput *n);
bool applyNumInput(NumInput *n, float *vec);
bool handleNumInput(struct bContext *C, NumInput *n, const struct wmEvent *event);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 5504b7e0352..2328f7d5135 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -150,8 +150,9 @@ bool ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, c
float loc[3], float rot[3],
bool *enter_editmode, unsigned int *layer, bool *is_view_aligned);
-struct Object *ED_object_add_type(struct bContext *C, int type, const float loc[3], const float rot[3],
- bool enter_editmode, unsigned int layer);
+struct Object *ED_object_add_type(
+ struct bContext *C, int type, const float loc[3], const float rot[3],
+ bool enter_editmode, unsigned int layer) ATTR_RETURNS_NONNULL;
void ED_object_single_users(struct Main *bmain, struct Scene *scene, bool full, bool copy_groups);
void ED_object_single_user(struct Main *bmain, struct Scene *scene, struct Object *ob);
diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h
index d7e84d8f50d..decd79fcc7b 100644
--- a/source/blender/editors/include/ED_paint.h
+++ b/source/blender/editors/include/ED_paint.h
@@ -28,9 +28,11 @@
struct bContext;
struct RegionView3D;
struct wmKeyConfig;
+struct wmOperator;
/* paint_ops.c */
void ED_operatortypes_paint(void);
+void ED_operatormacros_paint(void);
void ED_keymap_paint(struct wmKeyConfig *keyconf);
/* paint_undo.c */
@@ -41,6 +43,7 @@ enum {
typedef void (*UndoRestoreCb)(struct bContext *C, struct ListBase *lb);
typedef void (*UndoFreeCb)(struct ListBase *lb);
+typedef bool (*UndoCleanupCb)(struct bContext *C, struct ListBase *lb);
int ED_undo_paint_step(struct bContext *C, int type, int step, const char *name);
void ED_undo_paint_step_num(struct bContext *C, int type, int num);
@@ -48,7 +51,7 @@ const char *ED_undo_paint_get_name(struct bContext *C, int type, int nr, int *ac
void ED_undo_paint_free(void);
int ED_undo_paint_valid(int type, const char *name);
bool ED_undo_paint_empty(int type);
-void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free);
+void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup);
void ED_undo_paint_push_end(int type);
/* paint_image.c */
@@ -57,5 +60,6 @@ void ED_image_undo_restore(struct bContext *C, struct ListBase *lb);
void ED_image_undo_free(struct ListBase *lb);
void ED_imapaint_clear_partial_redraw(void);
void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h);
+void ED_imapaint_bucket_fill(struct bContext *C, float color[3], struct wmOperator *op);
#endif /* __ED_PAINT_H__ */
diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h
index 4fbe01a5fc7..d268c578cf2 100644
--- a/source/blender/editors/include/ED_space_api.h
+++ b/source/blender/editors/include/ED_space_api.h
@@ -35,6 +35,7 @@ struct ARegionType;
struct bContext;
void ED_spacetypes_init(void);
+void ED_spacemacros_init(void);
/* the pluginnable API for export to editors */
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 41ff9b88da9..daa6864b5aa 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -98,6 +98,7 @@ enum TfmMode {
#define CTX_NDOF (1 << 5)
#define CTX_MOVIECLIP (1 << 6)
#define CTX_MASK (1 << 7)
+#define CTX_PAINT_CURVE (1 << 8)
/* Standalone call to get the transformation center corresponding to the current situation
* returns 1 if successful, 0 otherwise (usually means there's no selection)
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 04eb829979f..4b82fa40c6a 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -54,7 +54,7 @@ void ED_uvedit_assign_image(struct Main *bmain, struct Scene *scene, struct Obje
bool ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obedit, float min[2], float max[2]);
bool ED_object_get_active_image(struct Object *ob, int mat_nr,
- struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node);
+ struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node, struct bNodeTree **r_ntree);
void ED_object_assign_active_image(struct Main *bmain, struct Object *ob, int mat_nr, struct Image *ima);
bool ED_uvedit_test(struct Object *obedit);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 76839747076..bd4f37cfb1e 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -56,6 +56,7 @@ struct bContext;
struct bPoseChannel;
struct bScreen;
struct bglMats;
+struct rctf;
struct rcti;
struct wmOperator;
struct wmOperatorType;
@@ -84,6 +85,7 @@ typedef struct ViewDepths {
float *ED_view3d_cursor3d_get(struct Scene *scene, struct View3D *v3d);
void ED_view3d_cursor3d_position(struct bContext *C, float fp[3], const int mval[2]);
+void ED_view3d_cursor3d_update(struct bContext *C, const int mval[2]);
struct Camera *ED_view3d_camera_data_get(struct View3D *v3d, struct RegionView3D *rv3d);
@@ -217,7 +219,8 @@ void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, cons
/* end */
-
+void ED_view3d_dist_range_get(struct View3D *v3d,
+ float r_dist_range[2]);
bool ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d,
float *r_clipsta, float *r_clipend, const bool use_ortho_factor);
bool ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi,
@@ -269,7 +272,7 @@ bool ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], con
/* select */
#define MAXPICKBUF 10000
-short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input);
+short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input, bool do_nearest);
/* view3d_select.c */
float ED_view3d_select_dist_px(void);
@@ -347,6 +350,7 @@ void ED_view3D_background_image_clear(struct View3D *v3d);
#define VIEW3D_MARGIN 1.4f
#define VIEW3D_DIST_FALLBACK 1.0f
+
float ED_view3d_offset_distance(float mat[4][4], const float ofs[3], const float dist_fallback);
void ED_view3d_distance_set(struct RegionView3D *rv3d, const float dist);
@@ -364,6 +368,6 @@ void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx,
#endif
/* render */
-void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa);
+void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa);
#endif /* __ED_VIEW3D_H__ */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index c776026a811..1d79cf749f9 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -668,8 +668,8 @@ DEF_ICON(IPO_EASE_IN_OUT)
DEF_ICON(VERTEXSEL)
DEF_ICON(EDGESEL)
DEF_ICON(FACESEL)
+DEF_ICON(LOOPSEL)
#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK209)
DEF_ICON(BLANK210)
#endif
DEF_ICON(ROTATE)
@@ -976,6 +976,8 @@ DEF_ICON(BRUSH_SNAKE_HOOK)
DEF_ICON(BRUSH_SOFTEN)
DEF_ICON(BRUSH_SUBTRACT)
DEF_ICON(BRUSH_TEXDRAW)
+DEF_ICON(BRUSH_TEXFILL)
+DEF_ICON(BRUSH_TEXMASK)
DEF_ICON(BRUSH_THUMB)
DEF_ICON(BRUSH_ROTATE)
DEF_ICON(BRUSH_VERTEXDRAW)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 1565583b574..1e9756ff771 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -75,6 +75,9 @@ struct ImBuf;
struct bNodeTree;
struct bNode;
struct bNodeSocket;
+struct wmDropBox;
+struct wmDrag;
+struct wmEvent;
typedef struct uiBut uiBut;
typedef struct uiBlock uiBlock;
@@ -99,6 +102,7 @@ typedef struct uiLayout uiLayout;
#define UI_EMBOSSN 1 /* Nothing, only icon and/or text */
#define UI_EMBOSSP 2 /* Pulldown menu style */
#define UI_EMBOSST 3 /* Table */
+#define UI_EMBOSSR 4 /* Pie Menu */
/* uiBlock->direction */
#define UI_DIRECTION (UI_TOP | UI_DOWN | UI_LEFT | UI_RIGHT)
@@ -134,6 +138,7 @@ typedef struct uiLayout uiLayout;
/* block->flag bits 14-17 are identical to but->drawflag bits */
#define UI_BLOCK_LIST_ITEM (1 << 19)
+#define UI_BLOCK_RADIAL (1 << 20)
/* uiPopupBlockHandle->menuretval */
#define UI_RETURN_CANCEL (1 << 0) /* cancel all menus cascading */
@@ -175,6 +180,7 @@ enum {
UI_BUT_DRAG_MULTI = (1 << 25), /* edit this button as well as the active button (not just dragging) */
UI_BUT_SCA_LINK_GREY = (1 << 26), /* used to flag if sca links shoud be grey out */
UI_BUT_HAS_SEP_CHAR = (1 << 27), /* but->str contains UI_SEP_CHAR, used for key shortcuts */
+ UI_BUT_TIP_FORCE = (1 << 28), /* force show tooltips when holding option/alt if U's USER_TOOLTIPS is off */
};
#define UI_PANEL_WIDTH 340
@@ -288,6 +294,9 @@ typedef enum {
#define UI_GRAD_V_ALT 9
#define UI_GRAD_L_ALT 10
+#define UI_PALETTE_COLOR 20
+#define UI_PALETTE_COLOR_ACTIVE 1
+
/* Drawing
*
* Functions to draw various shapes, taking theme settings into account.
@@ -353,6 +362,17 @@ struct uiLayout *uiPupMenuLayout(uiPopupMenu *head);
void uiPupMenuReports(struct bContext *C, struct ReportList *reports) ATTR_NONNULL();
bool uiPupMenuInvoke(struct bContext *C, const char *idname, struct ReportList *reports) ATTR_NONNULL(1, 2);
+/* Pie menus */
+typedef struct uiPieMenu uiPieMenu;
+
+void uiPieMenuInvoke(struct bContext *C, const char *idname, const struct wmEvent *event);
+void uiPieOperatorEnumInvoke(struct bContext *C, const char *title, const char *opname,
+ const char *propname, const struct wmEvent *event);
+void uiPieEnumInvoke(struct bContext *C, const char *title, const char *path, const struct wmEvent *event);
+
+struct uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const struct wmEvent *event) ATTR_NONNULL();
+void uiPieMenuEnd(struct bContext *C, uiPieMenu *pie);
+struct uiLayout *uiPieMenuLayout(struct uiPieMenu *pie);
/* Popup Blocks
*
* Functions used to create popup blocks. These are like popup menus
@@ -410,7 +430,8 @@ typedef enum {
UI_BLOCK_BOUNDS_TEXT,
UI_BLOCK_BOUNDS_POPUP_MOUSE,
UI_BLOCK_BOUNDS_POPUP_MENU,
- UI_BLOCK_BOUNDS_POPUP_CENTER
+ UI_BLOCK_BOUNDS_POPUP_CENTER,
+ UI_BLOCK_BOUNDS_PIE_CENTER,
} eBlockBoundsCalc;
void uiBoundsBlock(struct uiBlock *block, int addval);
@@ -437,6 +458,7 @@ void uiButSetDragValue(uiBut *but);
void uiButSetDragImage(uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale);
bool UI_but_active_drop_name(struct bContext *C);
+bool UI_but_active_drop_color(struct bContext *C);
void uiButSetFlag(uiBut *but, int flag);
void uiButClearFlag(uiBut *but, int flag);
@@ -697,7 +719,7 @@ void UI_panel_category_draw_all(struct ARegion *ar, const
* as screen/ if ED_KEYMAP_UI is set, or internally in popup functions. */
void UI_add_region_handlers(struct ListBase *handlers);
-void UI_add_popup_handlers(struct bContext *C, struct ListBase *handlers, uiPopupBlockHandle *popup);
+void UI_add_popup_handlers(struct bContext *C, struct ListBase *handlers, uiPopupBlockHandle *popup, const bool accept_dbl_click);
void UI_remove_popup_handlers(struct ListBase *handlers, uiPopupBlockHandle *popup);
void UI_remove_popup_handlers_all(struct bContext *C, struct ListBase *handlers);
@@ -708,7 +730,6 @@ void UI_remove_popup_handlers_all(struct bContext *C, struct ListBase *handlers)
void UI_init(void);
void UI_init_userdef(void);
-void UI_init_userdef_factory(void);
void UI_reinit_font(void);
void UI_exit(void);
@@ -730,6 +751,7 @@ void UI_exit(void);
#define UI_LAYOUT_HEADER 1
#define UI_LAYOUT_MENU 2
#define UI_LAYOUT_TOOLBAR 3
+#define UI_LAYOUT_PIEMENU 4
#define UI_UNIT_X ((void)0, U.widget_unit)
#define UI_UNIT_Y ((void)0, U.widget_unit)
@@ -820,8 +842,8 @@ uiLayout *uiLayoutListBox(uiLayout *layout, struct uiList *ui_list, struct Point
uiLayout *uiLayoutAbsolute(uiLayout *layout, int align);
uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align);
uiLayout *uiLayoutOverlap(uiLayout *layout);
-
uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout);
+uiLayout *uiLayoutRadial(uiLayout *layout);
/* templates */
void uiTemplateHeader(uiLayout *layout, struct bContext *C);
@@ -847,6 +869,7 @@ void uiTemplateVectorscope(uiLayout *layout, struct PointerRNA *ptr, const char
void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int type,
int levels, int brush, int neg_slope);
void uiTemplateColorPicker(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic);
+void uiTemplatePalette(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int color);
void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
PointerRNA *used_ptr, const char *used_propname, int active_layer);
void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
@@ -916,7 +939,14 @@ void uiItemMenuEnumO(uiLayout *layout, struct bContext *C, const char *opname, c
void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon);
/* UI Operators */
+typedef struct uiDragColorHandle {
+ float color[3];
+ bool gamma_corrected;
+} uiDragColorHandle;
+
void UI_buttons_operatortypes(void);
+void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop);
+int UI_drop_color_poll(struct bContext *C, struct wmDrag *drag, const struct wmEvent *event);
/* Helpers for Operators */
uiBut *uiContextActiveButton(const struct bContext *C);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 2e78940a813..872bd32b75b 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -106,6 +106,7 @@ enum {
TH_FACE_SELECT,
TH_NORMAL,
TH_VNORMAL,
+ TH_LNORMAL,
TH_FACE_DOT,
TH_FACEDOT_SIZE,
TH_CFRAME,
@@ -237,6 +238,9 @@ enum {
TH_STITCH_PREVIEW_UNSTITCHABLE,
TH_STITCH_PREVIEW_ACTIVE,
+ TH_PAINT_CURVE_HANDLE,
+ TH_PAINT_CURVE_PIVOT,
+
TH_UV_SHADOW,
TH_UV_OTHERS,
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index c059b16f1a0..c3f63f8a7fe 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -51,6 +51,7 @@
#include "BKE_context.h"
#include "BKE_unit.h"
+#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_idprop.h"
@@ -97,6 +98,11 @@ bool ui_block_is_menu(const uiBlock *block)
((block->flag & UI_BLOCK_KEEP_OPEN) == 0));
}
+bool ui_block_is_pie_menu(const uiBlock *block)
+{
+ return ((block->flag & UI_BLOCK_RADIAL) != 0);
+}
+
static bool ui_is_but_unit_radians_ex(UnitSettings *unit, const int unit_type)
{
return (unit->system_rotation == USER_UNIT_ROT_RADIANS && unit_type == PROP_UNIT_ROTATION);
@@ -321,6 +327,20 @@ static void ui_centered_bounds_block(wmWindow *window, uiBlock *block)
ui_bounds_block(block);
}
+
+static void ui_centered_pie_bounds_block(uiBlock *block)
+{
+ const int xy[2] = {
+ block->pie_data.pie_center_spawned[0],
+ block->pie_data.pie_center_spawned[1]
+ };
+
+ ui_block_translate(block, xy[0], xy[1]);
+
+ /* now recompute bounds and safety */
+ ui_bounds_block(block);
+}
+
static void ui_popup_bounds_block(wmWindow *window, uiBlock *block,
eBlockBoundsCalc bounds_calc, const int xy[2])
{
@@ -830,7 +850,7 @@ static void ui_menu_block_set_keyaccels(uiBlock *block)
* fun first pass on all buttons so first word chars always get first priority */
for (but = block->buttons.first; but; but = but->next) {
- if (!ELEM5(but->type, BUT, BUTM, MENU, BLOCK, PULLDOWN) || (but->flag & UI_HIDDEN)) {
+ if (!ELEM(but->type, BUT, BUTM, MENU, BLOCK, PULLDOWN) || (but->flag & UI_HIDDEN)) {
/* pass */
}
else if (but->menu_key == '\0') {
@@ -1062,6 +1082,41 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but,
return found;
}
+/* this goes in a seemingly weird pattern:
+ *
+ * 4
+ * 5 6
+ * 1 2
+ * 7 8
+ * 3
+ *
+ * but it's actually quite logical. It's designed to be 'upwards compatible'
+ * for muscle memory so that the menu item locations are fixed and don't move
+ * as new items are added to the menu later on. It also optimises efficiency -
+ * a radial menu is best kept symmetrical, with as large an angle between
+ * items as possible, so that the gestural mouse movements can be fast and inexact.
+
+ * It starts off with two opposite sides for the first two items
+ * then joined by the one below for the third (this way, even with three items,
+ * the menu seems to still be 'in order' reading left to right). Then the fourth is
+ * added to complete the compass directions. From here, it's just a matter of
+ * subdividing the rest of the angles for the last 4 items.
+ *
+ * --Matt 07/2006
+ */
+const char ui_radial_dir_order[8] = {
+ UI_RADIAL_W, UI_RADIAL_E, UI_RADIAL_S, UI_RADIAL_N,
+ UI_RADIAL_NW, UI_RADIAL_NE, UI_RADIAL_SW, UI_RADIAL_SE};
+
+const char ui_radial_dir_to_numpad[8] = {8, 9, 6, 3, 2, 1, 4, 7};
+const short ui_radial_dir_to_angle[8] = {90, 45, 0, 315, 270, 225, 180, 135};
+
+static void ui_but_pie_direction_string(uiBut *but, char *buf, int size)
+{
+ BLI_assert(but->pie_dir < ARRAY_SIZE(ui_radial_dir_to_numpad));
+ BLI_snprintf(buf, size, "%d", ui_radial_dir_to_numpad[but->pie_dir]);
+}
+
static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
{
uiBut *but;
@@ -1071,13 +1126,23 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
if (block->rect.xmin != block->rect.xmax)
return;
- for (but = block->buttons.first; but; but = but->next) {
-
- if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) {
- ui_but_add_shortcut(but, buf, false);
+ if (block->flag & UI_BLOCK_RADIAL) {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->pie_dir != UI_RADIAL_NONE) {
+ ui_but_pie_direction_string(but, buf, sizeof(buf));
+ ui_but_add_shortcut(but, buf, false);
+ }
}
- else if (ui_but_event_property_operator_string(C, but, buf, sizeof(buf))) {
- ui_but_add_shortcut(but, buf, false);
+ }
+ else {
+ for (but = block->buttons.first; but; but = but->next) {
+
+ if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) {
+ ui_but_add_shortcut(but, buf, false);
+ }
+ else if (ui_but_event_property_operator_string(C, but, buf, sizeof(buf))) {
+ ui_but_add_shortcut(but, buf, false);
+ }
}
}
}
@@ -1173,6 +1238,9 @@ void uiEndBlock_ex(const bContext *C, uiBlock *block, const int xy[2])
case UI_BLOCK_BOUNDS_POPUP_CENTER:
ui_centered_bounds_block(window, block);
break;
+ case UI_BLOCK_BOUNDS_PIE_CENTER:
+ ui_centered_pie_bounds_block(block);
+ break;
/* fallback */
case UI_BLOCK_BOUNDS_POPUP_MOUSE:
@@ -1244,6 +1312,10 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
rcti rect;
int multisample_enabled;
+ /* early exit if cancelled */
+ if ((block->flag & UI_BLOCK_RADIAL) && (block->pie_data.flags & UI_PIE_FINISHED))
+ return;
+
/* get menu region or area region */
ar = CTX_wm_menu(C);
if (!ar)
@@ -1276,7 +1348,9 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f);
/* back */
- if (block->flag & UI_BLOCK_LOOP)
+ if (block->flag & UI_BLOCK_RADIAL)
+ ui_draw_pie_center(block);
+ else if (block->flag & UI_BLOCK_LOOP)
ui_draw_menu_back(&style, block, &rect);
else if (block->panel)
ui_draw_aligned_panel(&style, block, &rect, UI_panel_category_is_visible(ar));
@@ -1317,7 +1391,7 @@ int ui_is_but_push_ex(uiBut *but, double *value)
int is_push = 0;
if (but->bit) {
- const bool state = ELEM3(but->type, TOGN, ICONTOGN, OPTIONN) ? false : true;
+ const bool state = ELEM(but->type, TOGN, ICONTOGN, OPTIONN) ? false : true;
int lvalue;
UI_GET_BUT_VALUE_INIT(but, *value);
lvalue = (int)*value;
@@ -1446,7 +1520,7 @@ void uiComposeLinks(uiBlock *block)
}
}
else if (link->poin) {
- bt = ui_find_inlink(block, *(link->poin) );
+ bt = ui_find_inlink(block, *link->poin);
if (bt) {
if ((but->flag & UI_BUT_SCA_LINK_GREY) || (bt->flag & UI_BUT_SCA_LINK_GREY)) {
ui_add_link_line(&link->lines, but, bt, true);
@@ -1627,7 +1701,7 @@ bool ui_is_but_float(const uiBut *but)
bool ui_is_but_bool(const uiBut *but)
{
- if (ELEM4(but->type, TOG, TOGN, ICONTOG, ICONTOGN))
+ if (ELEM(but->type, TOG, TOGN, ICONTOG, ICONTOGN))
return true;
if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_BOOLEAN)
@@ -1840,7 +1914,7 @@ void ui_set_but_val(uiBut *but, double value)
int ui_get_but_string_max_length(uiBut *but)
{
- if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK))
+ if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK))
return but->hardmax;
else
return UI_MAX_DRAW_STR;
@@ -1866,27 +1940,13 @@ static double ui_get_but_scale_unit(uiBut *but, double value)
UnitSettings *unit = but->block->unit;
int unit_type = uiButGetUnitType(but);
- if (unit_type == PROP_UNIT_LENGTH) {
- return value * (double)unit->scale_length;
- }
- else if (unit_type == PROP_UNIT_CAMERA) {
- return value * (double)unit->scale_length;
- }
- else if (unit_type == PROP_UNIT_AREA) {
- return value * pow(unit->scale_length, 2);
- }
- else if (unit_type == PROP_UNIT_VOLUME) {
- return value * pow(unit->scale_length, 3);
- }
- else if (unit_type == PROP_UNIT_MASS) {
- return value * pow(unit->scale_length, 3);
- }
- else if (unit_type == PROP_UNIT_TIME) { /* WARNING - using evil_C :| */
+ /* Time unit is a bit special, not handled by BKE_scene_unit_scale() for now. */
+ if (unit_type == PROP_UNIT_TIME) { /* WARNING - using evil_C :| */
Scene *scene = CTX_data_scene(but->block->evil_C);
return FRA2TIME(value);
}
else {
- return value;
+ return BKE_scene_unit_scale(unit, RNA_SUBTYPE_UNIT_VALUE(unit_type), value);
}
}
@@ -1955,7 +2015,7 @@ static float ui_get_but_step_unit(uiBut *but, float step_default)
*/
void ui_get_but_string_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision)
{
- if (but->rnaprop && ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (but->rnaprop && ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
PropertyType type;
const char *buf = NULL;
int buf_len;
@@ -2092,7 +2152,7 @@ bool ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double
bool ui_set_but_string(bContext *C, uiBut *but, const char *str)
{
- if (but->rnaprop && ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (but->rnaprop && ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (RNA_property_editable(&but->rnapoin, but->rnaprop)) {
PropertyType type;
@@ -2744,7 +2804,7 @@ void uiBlockEndAlign(uiBlock *block)
bool ui_but_can_align(uiBut *but)
{
- return !ELEM5(but->type, LABEL, OPTION, OPTIONN, SEPR, SEPRLINE);
+ return !ELEM(but->type, LABEL, OPTION, OPTIONN, SEPR, SEPRLINE);
}
static void ui_block_do_align_but(uiBut *first, short nr)
@@ -2999,6 +3059,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
but->lock = block->lock;
but->lockstr = block->lockstr;
but->dt = block->dt;
+ but->pie_dir = UI_RADIAL_NONE;
but->block = block; /* pointer back, used for frontbuffer status, and picker */
@@ -3025,8 +3086,11 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
}
}
- if ((block->flag & UI_BLOCK_LOOP) ||
- ELEM8(but->type, MENU, TEX, LABEL, BLOCK, BUTM, SEARCH_MENU, PROGRESSBAR, SEARCH_MENU_UNLINK))
+ if (block->flag & UI_BLOCK_RADIAL) {
+ but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
+ }
+ else if ((block->flag & UI_BLOCK_LOOP) ||
+ ELEM(but->type, MENU, TEX, LABEL, BLOCK, BUTM, SEARCH_MENU, PROGRESSBAR, SEARCH_MENU_UNLINK))
{
but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
}
@@ -3045,7 +3109,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
}
/* keep track of UI_interface.h */
- if (ELEM11(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, LISTBOX, BUTM, SCROLL, SEPR, SEPRLINE, GRIP)) {}
+ if (ELEM(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, LISTBOX, BUTM, SCROLL, SEPR, SEPRLINE, GRIP)) {}
else if (but->type >= SEARCH_MENU) {}
else but->flag |= UI_BUT_UNDO;
@@ -3210,12 +3274,12 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
int icon = 0;
uiMenuCreateFunc func = NULL;
- if (ELEM3(type, COLOR, HSVCIRCLE, HSVCUBE)) {
+ if (ELEM(type, COLOR, HSVCIRCLE, HSVCUBE)) {
BLI_assert(index == -1);
}
/* use rna values if parameters are not specified */
- if ((proptype == PROP_ENUM) && ELEM3(type, MENU, ROW, LISTROW)) {
+ if ((proptype == PROP_ENUM) && ELEM(type, MENU, ROW, LISTROW)) {
/* MENU is handled a little differently here */
EnumPropertyItem *item;
int value;
@@ -3808,9 +3872,6 @@ void uiBlockFlipOrder(uiBlock *block)
but->rect.ymax = centy - (but->rect.ymax - centy);
SWAP(float, but->rect.ymin, but->rect.ymax);
}
-
- /* also flip order in block itself, for example for arrowkey */
- BLI_listbase_reverse(&block->buttons);
}
@@ -4336,7 +4397,7 @@ void uiButGetStrInfo(bContext *C, uiBut *but, ...)
}
tmp = BLI_strdup(_tmp);
}
- else if (ELEM3(type, BUT_GET_RNAENUM_IDENTIFIER, BUT_GET_RNAENUM_LABEL, BUT_GET_RNAENUM_TIP)) {
+ else if (ELEM(type, BUT_GET_RNAENUM_IDENTIFIER, BUT_GET_RNAENUM_LABEL, BUT_GET_RNAENUM_TIP)) {
PointerRNA *ptr = NULL;
PropertyRNA *prop = NULL;
int value = 0;
@@ -4426,11 +4487,6 @@ void UI_init_userdef(void)
uiStyleInit();
}
-void UI_init_userdef_factory(void)
-{
- init_userdef_factory();
-}
-
void UI_reinit_font(void)
{
uiStyleInit();
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 29da19acf83..53827a9a7bf 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -695,11 +695,11 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
}
/* RGB / YCC (3 channels) */
- else if (ELEM4(scopes->wavefrm_mode,
- SCOPES_WAVEFRM_RGB,
- SCOPES_WAVEFRM_YCC_601,
- SCOPES_WAVEFRM_YCC_709,
- SCOPES_WAVEFRM_YCC_JPEG))
+ else if (ELEM(scopes->wavefrm_mode,
+ SCOPES_WAVEFRM_RGB,
+ SCOPES_WAVEFRM_YCC_601,
+ SCOPES_WAVEFRM_YCC_709,
+ SCOPES_WAVEFRM_YCC_JPEG))
{
int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB);
@@ -1152,9 +1152,11 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
}
/* layer: active handle */
- cbd = &coba->data[coba->cur];
- pos = x1 + cbd->pos * (sizex - 1) + 1;
- ui_draw_colorband_handle(rect, pos, &cbd->r, display, true);
+ if (coba->tot != 0) {
+ cbd = &coba->data[coba->cur];
+ pos = x1 + cbd->pos * (sizex - 1) + 1;
+ ui_draw_colorband_handle(rect, pos, &cbd->r, display, true);
+ }
}
void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index e04fef329b1..9818a593174 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -38,6 +38,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_brush_types.h"
#include "DNA_sensor_types.h"
#include "DNA_controller_types.h"
#include "DNA_actuator_types.h"
@@ -60,6 +61,7 @@
#include "PIL_time.h"
#include "BKE_blender.h"
+#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
@@ -99,6 +101,8 @@
/* drag popups by their header */
#define USE_DRAG_POPUP
+#define UI_MAX_PASSWORD_STR 128
+
/* proto */
static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to);
static void ui_add_link(bContext *C, uiBut *from, uiBut *to);
@@ -114,6 +118,7 @@ static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEve
#define BUTTON_TOOLTIP_DELAY 0.500
#define BUTTON_FLASH_DELAY 0.020
#define MENU_SCROLL_INTERVAL 0.1
+#define PIE_MENU_INTERVAL 0.01
#define BUTTON_AUTO_OPEN_THRESH 0.3
#define BUTTON_MOUSE_TOWARDS_THRESH 1.0
/* pixels to move the cursor to get out of keyboard navigation */
@@ -151,7 +156,7 @@ typedef enum uiHandleButtonState {
* note: half the height of a button is about right... */
#define DRAG_MULTINUM_THRESHOLD_DRAG_X (UI_UNIT_Y / 4)
-/* how far to drag horizontally before we stop checkign which buttons the gesture spans (in pixels),
+/* how far to drag horizontally before we stop checking which buttons the gesture spans (in pixels),
* locking down the buttons so we can drag freely without worrying about vertical movement. */
#define DRAG_MULTINUM_THRESHOLD_DRAG_Y (UI_UNIT_Y / 4)
@@ -383,16 +388,16 @@ void ui_pan_to_scroll(const wmEvent *event, int *type, int *val)
}
}
-static bool ui_but_editable(uiBut *but)
+bool ui_but_is_editable(const uiBut *but)
{
- return ELEM6(but->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX, PROGRESSBAR);
+ return !ELEM(but->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX, PROGRESSBAR);
}
static uiBut *ui_but_prev(uiBut *but)
{
while (but->prev) {
but = but->prev;
- if (!ui_but_editable(but)) return but;
+ if (ui_but_is_editable(but)) return but;
}
return NULL;
}
@@ -401,7 +406,7 @@ static uiBut *ui_but_next(uiBut *but)
{
while (but->next) {
but = but->next;
- if (!ui_but_editable(but)) return but;
+ if (ui_but_is_editable(but)) return but;
}
return NULL;
}
@@ -412,7 +417,7 @@ static uiBut *ui_but_first(uiBlock *block)
but = block->buttons.first;
while (but) {
- if (!ui_but_editable(but)) return but;
+ if (ui_but_is_editable(but)) return but;
but = but->next;
}
return NULL;
@@ -424,7 +429,7 @@ static uiBut *ui_but_last(uiBlock *block)
but = block->buttons.last;
while (but) {
- if (!ui_but_editable(but)) return but;
+ if (ui_but_is_editable(but)) return but;
but = but->prev;
}
return NULL;
@@ -433,7 +438,7 @@ static uiBut *ui_but_last(uiBlock *block)
static bool ui_is_a_warp_but(uiBut *but)
{
if (U.uiflag & USER_CONTINUOUS_MOUSE) {
- if (ELEM6(but->type, NUM, NUMSLI, HSVCIRCLE, TRACKPREVIEW, HSVCUBE, BUT_CURVE)) {
+ if (ELEM(but->type, NUM, NUMSLI, HSVCIRCLE, TRACKPREVIEW, HSVCUBE, BUT_CURVE)) {
return true;
}
}
@@ -463,7 +468,7 @@ bool ui_is_but_utf8(const uiBut *but)
{
if (but->rnaprop) {
const int subtype = RNA_property_subtype(but->rnaprop);
- return !(ELEM4(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING));
+ return !(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING));
}
else {
return !(but->flag & UI_BUT_NO_UTF8);
@@ -599,7 +604,13 @@ static void ui_apply_autokey(bContext *C, uiBut *but)
/* make a little report about what we've done! */
if (but->rnaprop) {
- char *buf = WM_prop_pystring_assign(C, &but->rnapoin, but->rnaprop, but->rnaindex);
+ char *buf;
+
+ if (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD) {
+ return;
+ }
+
+ buf = WM_prop_pystring_assign(C, &but->rnapoin, but->rnaprop, but->rnaindex);
if (buf) {
BKE_report(CTX_wm_reports(C), RPT_PROPERTY, buf);
MEM_freeN(buf);
@@ -633,7 +644,7 @@ static void ui_apply_but_funcs_after(bContext *C)
}
if (after.optype)
- WM_operator_name_call(C, after.optype->idname, after.opcontext, (after.opptr) ? &opptr : NULL);
+ WM_operator_name_call_ptr(C, after.optype, after.opcontext, (after.opptr) ? &opptr : NULL);
if (after.opptr)
WM_operator_properties_free(&opptr);
@@ -717,7 +728,7 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data)
if (value == 0.0) push = 1;
else push = 0;
- if (ELEM3(but->type, TOGN, ICONTOGN, OPTIONN)) push = !push;
+ if (ELEM(but->type, TOGN, ICONTOGN, OPTIONN)) push = !push;
ui_set_but_val(but, (double)push);
if (but->type == ICONTOG || but->type == ICONTOGN) ui_check_but(but);
}
@@ -1189,7 +1200,7 @@ static bool ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, const wmEvent *eve
BLI_rcti_rctf_copy(&rect, &but->rect);
- if (but->imb) {
+ if (but->imb || but->type == COLOR) {
/* use button size itself */
}
else if (but->drawflag & UI_BUT_ICON_LEFT) {
@@ -1236,16 +1247,48 @@ static bool ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data,
WM_event_add_ui_handler(C, &data->window->modalhandlers,
ui_handler_region_drag_toggle,
ui_handler_region_drag_toggle_remove,
- drag_info);
+ drag_info, false);
CTX_wm_region_set(C, ar_prev);
}
else
#endif
- {
+ if (but->type == COLOR) {
+ bool valid = false;
+ uiDragColorHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
+
+ /* TODO support more button pointer types */
+ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, drag_info->color);
+ drag_info->gamma_corrected = true;
+ valid = true;
+ }
+ else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, drag_info->color);
+ drag_info->gamma_corrected = false;
+ valid = true;
+ }
+ else if (but->pointype == UI_BUT_POIN_FLOAT) {
+ copy_v3_v3(drag_info->color, (float *)but->poin);
+ valid = true;
+ }
+ else if (but->pointype == UI_BUT_POIN_CHAR) {
+ rgb_uchar_to_float(drag_info->color, (unsigned char *)but->poin);
+ valid = true;
+ }
+
+ if (valid) {
+ WM_event_start_drag(C, ICON_COLOR, WM_DRAG_COLOR, drag_info, 0.0, WM_DRAG_FREE_DATA);
+ }
+ else {
+ MEM_freeN(drag_info);
+ return false;
+ }
+ }
+ else {
wmDrag *drag;
- drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but));
+ drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but), WM_DRAG_NOP);
if (but->imb)
WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect));
}
@@ -1655,7 +1698,7 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
for (wmd = drags->first; wmd; wmd = wmd->next) {
if (wmd->type == WM_DRAG_ID) {
/* align these types with UI_but_active_drop_name */
- if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
ID *id = (ID *)wmd->poin;
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
@@ -1802,7 +1845,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
}
/* text/string and ID data */
- else if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ else if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
uiHandleButtonData *active_data = but->active;
if (but->poin == NULL && but->rnapoin.data == NULL) {
@@ -1911,28 +1954,35 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
static int ui_text_position_from_hidden(uiBut *but, int pos)
{
- const char *strpos;
+ const char *strpos, *butstr;
int i;
- for (i = 0, strpos = but->drawstr; i < pos; i++)
+ butstr = (but->editstr) ? but->editstr : but->drawstr;
+
+ for (i = 0, strpos = butstr; i < pos; i++)
strpos = BLI_str_find_next_char_utf8(strpos, NULL);
- return (strpos - but->drawstr);
+ return (strpos - butstr);
}
static int ui_text_position_to_hidden(uiBut *but, int pos)
{
- return BLI_strnlen_utf8(but->drawstr, pos);
+ const char *butstr = butstr = (but->editstr) ? but->editstr : but->drawstr;
+ return BLI_strnlen_utf8(butstr, pos);
}
-void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, const bool restore)
+void ui_button_text_password_hide(char password_str[UI_MAX_PASSWORD_STR], uiBut *but, const bool restore)
{
+ char *butstr;
+
if (!(but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_PASSWORD))
return;
+ butstr = (but->editstr) ? but->editstr : but->drawstr;
+
if (restore) {
/* restore original string */
- BLI_strncpy(but->drawstr, password_str, UI_MAX_DRAW_STR);
+ BLI_strncpy(butstr, password_str, UI_MAX_PASSWORD_STR);
/* remap cursor positions */
if (but->pos >= 0) {
@@ -1942,8 +1992,8 @@ void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but
}
}
else {
- /* convert text to hidden test using asterisks (e.g. pass -> ****) */
- const size_t len = BLI_strlen_utf8(but->drawstr);
+ /* convert text to hidden text using asterisks (e.g. pass -> ****) */
+ const size_t len = BLI_strlen_utf8(butstr);
/* remap cursor positions */
if (but->pos >= 0) {
@@ -1953,10 +2003,9 @@ void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but
}
/* save original string */
- BLI_strncpy(password_str, but->drawstr, UI_MAX_DRAW_STR);
-
- memset(but->drawstr, '*', len);
- but->drawstr[len] = '\0';
+ BLI_strncpy(password_str, butstr, UI_MAX_PASSWORD_STR);
+ memset(butstr, '*', len);
+ butstr[len] = '\0';
}
}
@@ -1992,7 +2041,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
float startx = but->rect.xmin;
float starty_dummy = 0.0f;
- char *origstr, password_str[UI_MAX_DRAW_STR];
+ char *origstr, password_str[UI_MAX_PASSWORD_STR];
ui_block_to_window_fl(data->region, but->block, &startx, &starty_dummy);
@@ -2009,7 +2058,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
BLI_strncpy(origstr, but->editstr, data->maxlen);
- if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (but->flag & UI_HAS_ICON) {
startx += UI_DPI_ICON_SIZE / aspect;
}
@@ -2461,11 +2510,11 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
uiBut *but;
/* label and roundbox can overlap real buttons (backdrops...) */
- if (ELEM5(actbut->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX))
+ if (ELEM(actbut->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX))
return;
for (but = actbut->next; but; but = but->next) {
- if (ELEM5(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -2474,7 +2523,7 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
}
for (but = block->buttons.first; but != actbut; but = but->next) {
- if (ELEM5(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -2489,11 +2538,11 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
uiBut *but;
/* label and roundbox can overlap real buttons (backdrops...) */
- if (ELEM5(actbut->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX))
+ if (ELEM(actbut->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX))
return;
for (but = actbut->prev; but; but = but->prev) {
- if (ELEM5(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -2502,7 +2551,7 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
}
for (but = block->buttons.last; but != actbut; but = but->prev) {
- if (ELEM5(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -2803,7 +2852,7 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
data->coba = (ColorBand *)but->poin;
but->editcoba = data->coba;
}
- else if (ELEM4(but->type, BUT_NORMAL, HSVCUBE, HSVCIRCLE, COLOR)) {
+ else if (ELEM(but->type, BUT_NORMAL, HSVCUBE, HSVCIRCLE, COLOR)) {
ui_get_but_vectorf(but, data->origvec);
copy_v3_v3(data->vec, data->origvec);
but->editvec = data->vec;
@@ -2990,7 +3039,7 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, cons
static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
but->drawstr[0] = 0;
but->modifier_key = 0;
button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
@@ -3053,7 +3102,7 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
return WM_UI_HANDLER_BREAK;
}
@@ -3078,7 +3127,7 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, c
static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM4(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) {
if (ELEM(event->type, PADENTER, RETKEY) && (!ui_is_but_utf8(but))) {
/* pass - allow filesel, enter to execute */
}
@@ -3106,7 +3155,7 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
/* unlink icon is on right */
- if (ELEM4(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS &&
+ if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS &&
ui_is_but_search_unlink_visible(but))
{
ARegion *ar = data->region;
@@ -3156,7 +3205,7 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
}
#endif
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
#if 0 /* UNUSED */
data->togdual = event->ctrl;
data->togonly = !event->shift;
@@ -3194,7 +3243,7 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
}
#endif
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
int ret = WM_UI_HANDLER_BREAK;
/* XXX (a bit ugly) Special case handling for filebrowser drag button */
if (but->dragpoin && but->imb && ui_but_mouse_inside_icon(but, data->region, event)) {
@@ -3243,7 +3292,7 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa
if (bUnit_IsValid(unit->system, unit_type)) {
fac = (float)bUnit_BaseScalar(unit->system, unit_type);
- if (ELEM3(unit_type, B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME)) {
+ if (ELEM(unit_type, B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME)) {
fac /= unit->scale_length;
}
}
@@ -3478,7 +3527,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
click = 1;
}
else if (event->val == KM_PRESS) {
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
@@ -3767,7 +3816,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
click = 2;
}
else if (event->val == KM_PRESS) {
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
@@ -4024,7 +4073,7 @@ static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data,
/* hack to pass on ctrl+click and double click to overlapping text
* editing field for editing list item names
*/
- if ((ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS && event->ctrl) ||
+ if ((ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS && event->ctrl) ||
(event->type == LEFTMOUSE && event->val == KM_DBL_CLICK))
{
uiBut *labelbut = ui_but_list_row_text_activate(C, but, data, event, BUTTON_ACTIVATE_TEXT_EDITING);
@@ -4053,7 +4102,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
}
#ifdef USE_DRAG_TOGGLE
- if (event->type == LEFTMOUSE && ui_is_but_drag_toggle(but)) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS && (ui_is_but_drag_toggle(but))) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
data->dragstarty = event->y;
@@ -4061,7 +4110,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
#endif
/* regular open menu */
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
return WM_UI_HANDLER_BREAK;
}
@@ -4206,11 +4255,29 @@ static bool ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data,
static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ /* first handle click on icondrag type button */
+ if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
+ if (ui_but_mouse_inside_icon(but, data->region, event)) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+#ifdef USE_DRAG_TOGGLE
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_BREAK;
+ }
+#endif
+ /* regular open menu */
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
return WM_UI_HANDLER_BREAK;
}
- else if (ELEM3(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
+ else if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
float *hsv = ui_block_hsv_get(but->block);
float col[3];
@@ -4233,6 +4300,84 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
ui_apply_button(C, but->block, but, data, true);
return WM_UI_HANDLER_BREAK;
}
+ else if ((int)(but->a1) == UI_PALETTE_COLOR &&
+ event->type == DELKEY && event->val == KM_PRESS)
+ {
+ Scene *scene = CTX_data_scene(C);
+ Paint *paint = BKE_paint_get_active(scene);
+ Palette *palette = BKE_paint_palette(paint);
+ PaletteColor *color = but->rnapoin.data;
+
+ BKE_palette_color_remove(palette, color);
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_WAIT_DRAG) {
+
+ /* this function also ends state */
+ if (ui_but_start_drag(C, but, data, event)) {
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ /* outside icon quit, not needed if drag activated */
+ if (0 == ui_but_mouse_inside_icon(but, data->region, event)) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ data->cancel = true;
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ if ((int)(but->a1) == UI_PALETTE_COLOR) {
+ Palette *palette = but->rnapoin.id.data;
+ PaletteColor *color = but->rnapoin.data;
+ palette->active_color = BLI_findindex(&palette->colors, color);
+
+ /* enforce redraw, sometimes state here can already be exit */
+ ED_region_tag_redraw(data->region);
+
+ if (!event->ctrl) {
+ float color[3];
+ Scene *scene = CTX_data_scene(C);
+ Paint *paint = BKE_paint_get_active(scene);
+ Brush *brush = BKE_paint_brush(paint);
+
+ if (brush->flag & BRUSH_USE_GRADIENT) {
+ float *target = &brush->gradient->data[brush->gradient->cur].r;
+
+ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target);
+ ui_block_to_scene_linear_v3(but->block, target);
+ }
+ else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target);
+ }
+ }
+ else {
+ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, color);
+ BKE_brush_color_set(scene, brush, color);
+ }
+ else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, color);
+ ui_block_to_display_space_v3(but->block, color);
+ BKE_brush_color_set(scene, brush, color);
+ }
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ }
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+
}
return WM_UI_HANDLER_CONTINUE;
@@ -4412,7 +4557,7 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
}
if (snap != SNAP_OFF) {
- if (ELEM3((int)but->a1, UI_GRAD_HV, UI_GRAD_HS, UI_GRAD_H)) {
+ if (ELEM((int)but->a1, UI_GRAD_HV, UI_GRAD_HS, UI_GRAD_H)) {
ui_color_snap_hue(snap, &hsv[0]);
}
}
@@ -4489,7 +4634,7 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
}
if (snap != SNAP_OFF) {
- if (ELEM3((int)but->a1, UI_GRAD_HV, UI_GRAD_HS, UI_GRAD_H)) {
+ if (ELEM((int)but->a1, UI_GRAD_HV, UI_GRAD_HS, UI_GRAD_H)) {
ui_color_snap_hue(snap, &hsv[0]);
}
}
@@ -4878,6 +5023,9 @@ static bool ui_numedit_but_COLORBAND(uiBut *but, uiHandleButtonData *data, int m
if (data->draglastx == mx)
return changed;
+ if (data->coba->tot == 0)
+ return changed;
+
dx = ((float)(mx - data->draglastx)) / BLI_rctf_size_x(&but->rect);
data->dragcbd->pos += dx;
CLAMP(data->dragcbd->pos, 0.0f, 1.0f);
@@ -6012,7 +6160,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
/* handle drivers */
else if ((event->type == DKEY) &&
- !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
+ !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
(event->val == KM_PRESS))
{
if (event->alt)
@@ -6026,7 +6174,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
/* handle keyingsets */
else if ((event->type == KKEY) &&
- !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
+ !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
(event->val == KM_PRESS))
{
if (event->alt)
@@ -6250,7 +6398,34 @@ static bool ui_but_contains_pt(uiBut *but, float mx, float my)
return BLI_rctf_isect_pt(&but->rect, mx, my);
}
-static uiBut *ui_but_find_activated(ARegion *ar)
+void ui_but_pie_dir(RadialDirection dir, float vec[2])
+{
+ float angle;
+
+ BLI_assert(dir != UI_RADIAL_NONE);
+
+ angle = DEG2RADF((float)ui_radial_dir_to_angle[dir]);
+ vec[0] = cosf(angle);
+ vec[1] = sinf(angle);
+}
+
+static bool ui_but_isect_pie_seg(uiBlock *block, uiBut *but)
+{
+ const float angle_range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_4 : M_PI_4 / 2.0;
+ float vec[2];
+
+ if (block->pie_data.flags & UI_PIE_INVALID_DIR)
+ return false;
+
+ ui_but_pie_dir(but->pie_dir, vec);
+
+ if (saacos(dot_v2v2(vec, block->pie_data.pie_dir)) < angle_range)
+ return true;
+
+ return false;
+}
+
+uiBut *ui_but_find_activated(ARegion *ar)
{
uiBlock *block;
uiBut *but;
@@ -6298,13 +6473,27 @@ bool UI_but_active_drop_name(bContext *C)
uiBut *but = ui_but_find_activated(ar);
if (but) {
- if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK))
+ if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK))
return 1;
}
return 0;
}
+bool UI_but_active_drop_color(bContext *C)
+{
+ ARegion *ar = CTX_wm_region(C);
+
+ if (ar) {
+ uiBut *but = ui_but_find_activated(ar);
+
+ if (but && but->type == COLOR)
+ return true;
+ }
+
+ return false;
+}
+
static void ui_blocks_set_tooltips(ARegion *ar, const bool enable)
{
uiBlock *block;
@@ -6354,6 +6543,7 @@ static bool ui_mouse_inside_region(ARegion *ar, int x, int y)
static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
{
+ uiBlock *block = but->block;
float mx, my;
if (!ui_mouse_inside_region(ar, x, y))
return false;
@@ -6361,10 +6551,16 @@ static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
mx = x;
my = y;
- ui_window_to_block_fl(ar, but->block, &mx, &my);
+ ui_window_to_block_fl(ar, block, &mx, &my);
- if (!ui_but_contains_pt(but, mx, my))
+ if (but->dt == UI_EMBOSSR) {
+ if (!ui_but_isect_pie_seg(block, but)) {
+ return false;
+ }
+ }
+ else if (!ui_but_contains_pt(but, mx, my)) {
return false;
+ }
return true;
}
@@ -6378,7 +6574,7 @@ static bool ui_is_but_interactive(const uiBut *but, const bool labeledit)
/* note, LABEL is included for highlights, this allows drags */
if ((but->type == LABEL) && but->dragpoin == NULL)
return false;
- if (ELEM4(but->type, ROUNDBOX, SEPR, SEPRLINE, LISTBOX))
+ if (ELEM(but->type, ROUNDBOX, SEPR, SEPRLINE, LISTBOX))
return false;
if (but->flag & UI_HIDDEN)
return false;
@@ -6418,7 +6614,13 @@ static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, c
for (but = block->buttons.last; but; but = but->prev) {
if (ui_is_but_interactive(but, labeledit)) {
- if (ui_but_contains_pt(but, mx, my)) {
+ if (but->pie_dir != UI_RADIAL_NONE) {
+ if (ui_but_isect_pie_seg(block, but)) {
+ butover = but;
+ break;
+ }
+ }
+ else if (ui_but_contains_pt(but, mx, my)) {
butover = but;
break;
}
@@ -6471,9 +6673,13 @@ static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
static bool button_modal_state(uiHandleButtonState state)
{
- return ELEM6(state, BUTTON_STATE_WAIT_RELEASE, BUTTON_STATE_WAIT_KEY_EVENT,
- BUTTON_STATE_NUM_EDITING, BUTTON_STATE_TEXT_EDITING,
- BUTTON_STATE_TEXT_SELECTING, BUTTON_STATE_MENU_OPEN);
+ return ELEM(state,
+ BUTTON_STATE_WAIT_RELEASE,
+ BUTTON_STATE_WAIT_KEY_EVENT,
+ BUTTON_STATE_NUM_EDITING,
+ BUTTON_STATE_TEXT_EDITING,
+ BUTTON_STATE_TEXT_SELECTING,
+ BUTTON_STATE_MENU_OPEN);
}
static void button_timers_tooltip_remove(bContext *C, uiBut *but)
@@ -6511,10 +6717,13 @@ static void button_tooltip_timer_reset(bContext *C, uiBut *but)
data->tooltiptimer = NULL;
}
- if (U.flag & USER_TOOLTIPS)
- if (!but->block->tooltipdisabled)
- if (!wm->drags.first)
+ if ((U.flag & USER_TOOLTIPS) || (but->flag & UI_BUT_TIP_FORCE)) {
+ if (!but->block->tooltipdisabled) {
+ if (!wm->drags.first) {
data->tooltiptimer = WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY);
+ }
+ }
+ }
}
static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state)
@@ -6619,7 +6828,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
if (!(but->block->handle && but->block->handle->popup)) {
if (button_modal_state(state)) {
if (!button_modal_state(data->state))
- WM_event_add_ui_handler(C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data);
+ WM_event_add_ui_handler(C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data, false);
}
else {
if (button_modal_state(data->state)) {
@@ -6664,7 +6873,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
copy_v2_fl(data->ungrab_mval, FLT_MAX);
#endif
- if (ELEM3(but->type, BUT_CURVE, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, BUT_CURVE, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
/* XXX curve is temp */
}
else {
@@ -7023,6 +7232,13 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar)
if (event->type == MOUSEMOVE) {
but = ui_but_find_mouse_over(ar, event);
if (but) {
+ if (event->alt) {
+ /* display tooltips if holding alt on mouseover when tooltips are off in prefs */
+ but->flag |= UI_BUT_TIP_FORCE;
+ }
+ else {
+ but->flag &= ~UI_BUT_TIP_FORCE;
+ }
button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
}
}
@@ -7054,6 +7270,17 @@ void ui_button_activate_do(bContext *C, ARegion *ar, uiBut *but)
ui_do_button(C, but->block, but, &event);
}
+/**
+ * Simulate moving the mouse over a button (or navigating to it with arrow keys).
+ *
+ * exported so menus can start with a highlighted button,
+ * even if the mouse isnt over it
+ */
+void ui_button_activate_over(bContext *C, ARegion *ar, uiBut *but)
+{
+ button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+}
+
void ui_button_execute_begin(struct bContext *UNUSED(C), struct ARegion *ar, uiBut *but, void **active_back)
{
/* note: ideally we would not have to change 'but->active' however
@@ -7116,12 +7343,20 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
retval = WM_UI_HANDLER_CONTINUE;
break;
case MOUSEMOVE:
- /* verify if we are still over the button, if not exit */
- if (!ui_mouse_inside_button(ar, but, event->x, event->y)) {
- data->cancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ {
+ uiBut *but_other = ui_but_find_mouse_over(ar, event);
+ bool exit = false;
+
+ if ((!ui_block_is_menu(block) || ui_block_is_pie_menu(but->block)) &&
+ !ui_mouse_inside_button(ar, but, event->x, event->y))
+ {
+ exit = true;
+ }
+ else if (but_other && ui_but_is_editable(but_other) && (but_other != but)) {
+ exit = true;
}
- else if (ui_but_find_mouse_over(ar, event) != but) {
+
+ if (exit) {
data->cancel = true;
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
@@ -7132,6 +7367,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
}
break;
+ }
case TIMER:
{
/* handle tooltip timer */
@@ -7715,6 +7951,25 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock
int retval;
if (but) {
+ /* Its possible there is an active menu item NOT under the mouse,
+ * in this case ignore mouse clicks outside the button (but Enter etc is accepted) */
+ if (event->val == KM_RELEASE) {
+ /* pass, needed so we can exit active menu-items when click-dragging out of them */
+ }
+ else if (!ui_block_is_menu(but->block) || ui_block_is_pie_menu(but->block)) {
+ /* pass, skip for dialogs */
+ }
+ else if (!ui_mouse_inside_region(but->active->region, event->x, event->y)) {
+ /* pass, needed to click-exit outside of non-flaoting menus */
+ }
+ else if ((!ELEM(event->type, MOUSEMOVE, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN)) && ISMOUSE(event->type)) {
+ if (!ui_mouse_inside_button(but->active->region, but, event->x, event->y)) {
+ but = NULL;
+ }
+ }
+ }
+
+ if (but) {
ScrArea *ctx_area = CTX_wm_area(C);
ARegion *ctx_region = CTX_wm_region(C);
@@ -7733,6 +7988,30 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock
return retval;
}
+void ui_block_calculate_pie_segment(uiBlock *block, const float event_xy[2])
+{
+ float seg1[2];
+ float seg2[2];
+ float len;
+
+ if (block->pie_data.flags & UI_PIE_INITIAL_DIRECTION) {
+ copy_v2_v2(seg1, block->pie_data.pie_center_init);
+ }
+ else {
+ copy_v2_v2(seg1, block->pie_data.pie_center_spawned);
+ }
+
+ sub_v2_v2v2(seg2, event_xy, seg1);
+
+ len = normalize_v2_v2(block->pie_data.pie_dir, seg2);
+
+ /* ten pixels for now, a bit arbitrary */
+ if (len < U.pie_menu_threshold * U.pixelsize)
+ block->pie_data.flags |= UI_PIE_INVALID_DIR;
+ else
+ block->pie_data.flags &= ~UI_PIE_INVALID_DIR;
+}
+
static int ui_handle_menu_event(
bContext *C, const wmEvent *event, uiPopupBlockHandle *menu,
int level, const bool is_parent_inside, const bool is_parent_menu, const bool is_floating)
@@ -7764,6 +8043,7 @@ static int ui_handle_menu_event(
if (menu->is_grab) {
if (event->type == LEFTMOUSE) {
menu->is_grab = false;
+ retval = WM_UI_HANDLER_BREAK;
}
else {
if (event->type == MOUSEMOVE) {
@@ -7968,7 +8248,7 @@ static int ui_handle_menu_event(
for (but = block->buttons.first; but; but = but->next) {
bool doit = false;
- if (!ELEM3(but->type, LABEL, SEPR, SEPRLINE))
+ if (!ELEM(but->type, LABEL, SEPR, SEPRLINE))
count++;
/* exception for rna layer buts */
@@ -8079,7 +8359,7 @@ static int ui_handle_menu_event(
if (inside == 0) {
uiSafetyRct *saferct = block->saferct.first;
- if (ELEM3(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) &&
+ if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) &&
ELEM(event->val, KM_PRESS, KM_DBL_CLICK))
{
if ((is_parent_menu == false) && (U.uiflag & USER_MENUOPENAUTO) == 0) {
@@ -8121,9 +8401,14 @@ static int ui_handle_menu_event(
else if ((event->type == LEFTMOUSE) && (event->val == KM_PRESS) &&
(inside && is_floating && inside_title))
{
- if (!ui_but_find_activated(ar)) {
+ if (!but || !ui_mouse_inside_button(ar, but, event->x, event->y)) {
+ if (but) {
+ button_timers_tooltip_remove(C, but);
+ }
+
menu->is_grab = true;
copy_v2_v2_int(menu->grab_xy_prev, &event->x);
+ retval = WM_UI_HANDLER_BREAK;
}
}
#endif
@@ -8228,10 +8513,326 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo
ui_mouse_motion_towards_reinit(menu, &event->x);
}
- if (menu->menuretval)
+ if (menu->menuretval) {
+ /* pie menus should not close but wait for release instead */
+ if ((block->flag & UI_BLOCK_RADIAL) &&
+ !(block->pie_data.flags & UI_PIE_CLICK_STYLE))
+ {
+ menu->menuretval = 0;
+ block->pie_data.flags |= UI_PIE_FINISHED;
+ }
+
return WM_UI_HANDLER_CONTINUE;
- else
+ }
+ else {
+ return WM_UI_HANDLER_BREAK;
+ }
+}
+
+static bool ui_but_pie_menu_supported_apply(uiBut *but)
+{
+ return (but->type != NUMSLI);
+}
+
+static int ui_but_pie_menu_apply(bContext *C, uiPopupBlockHandle *menu, uiBut *but, bool force_close, bool click_style)
+{
+ int retval = WM_UI_HANDLER_BREAK;
+
+ if (but && ui_but_pie_menu_supported_apply(but)) {
+ if (but->type == MENU) {
+ /* forcing the pie menu to close will not handle menus */
+ if (!force_close) {
+ uiBut *active_but = ui_but_find_activated(menu->region);
+
+ if (active_but) {
+ button_activate_exit(C, active_but, active_but->active, false, false);
+ }
+
+ button_activate_init(C, menu->region, but, BUTTON_ACTIVATE_OPEN);
+ return retval;
+ }
+ else {
+ menu->menuretval = UI_RETURN_CANCEL;
+ }
+ }
+ else {
+ ui_apply_button(C, but->block, but, but->active, false);
+ button_activate_exit((bContext *)C, but, but->active, false, true);
+
+ if (!(click_style || force_close)) {
+ but->block->pie_data.flags |= UI_PIE_FINISHED;
+ menu->menuretval = 0;
+ }
+ else {
+ menu->menuretval = UI_RETURN_OK;
+ }
+ }
+ }
+ else {
+ uiBlock *block = menu->region->uiblocks.first;
+
+ if (!(click_style || force_close)) {
+ block->pie_data.flags |= UI_PIE_FINISHED;
+ }
+ else {
+ menu->menuretval = UI_RETURN_CANCEL;
+ }
+
+ ED_region_tag_redraw(menu->region);
+ }
+
+ return retval;
+}
+
+static uiBut *ui_block_pie_dir_activate(uiBlock *block, const wmEvent *event, RadialDirection dir)
+{
+ uiBut *but;
+
+ if ((block->flag & UI_BLOCK_NUMSELECT) && event->val == KM_PRESS) {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->pie_dir == dir && !ELEM(but->type, SEPR, SEPRLINE)) {
+ return but;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static int ui_but_pie_button_activate(bContext *C, uiBut *but, uiPopupBlockHandle *menu, bool is_click_style)
+{
+ uiBut *active_but;
+
+ if (but == NULL)
+ return WM_UI_HANDLER_BREAK;
+
+ active_but = ui_but_find_activated(menu->region);
+
+ if (active_but)
+ button_activate_exit(C, active_but, active_but->active, false, false);
+
+ button_activate_init(C, menu->region, but, BUTTON_ACTIVATE_OVER);
+ return ui_but_pie_menu_apply(C, menu, but, false, is_click_style);
+}
+
+static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu)
+{
+ ARegion *ar;
+ uiBlock *block;
+ uiBut *but;
+ float event_xy[2];
+ double duration;
+ bool is_click_style;
+
+ /* we block all events, this is modal interaction, except for drop events which is described below */
+ int retval = WM_UI_HANDLER_BREAK;
+
+ if (event->type == EVT_DROP) {
+ /* may want to leave this here for later if we support pie ovens */
+
+ retval = WM_UI_HANDLER_CONTINUE;
+ }
+
+ ar = menu->region;
+ block = ar->uiblocks.first;
+
+ is_click_style = (block->pie_data.flags & UI_PIE_CLICK_STYLE);
+
+ if (menu->scrolltimer == NULL) {
+ menu->scrolltimer =
+ WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, PIE_MENU_INTERVAL);
+ menu->scrolltimer->duration = 0.0;
+ }
+
+ duration = menu->scrolltimer->duration;
+
+ if (event->type == TIMER) {
+ if (event->customdata == menu->scrolltimer) {
+ /* deactivate initial direction after a while */
+ if (duration > 0.01 * U.pie_initial_timeout) {
+ block->pie_data.flags &= ~UI_PIE_INITIAL_DIRECTION;
+ }
+
+ /* handle animation */
+ if (!(block->pie_data.flags & UI_PIE_ANIMATION_FINISHED)) {
+ uiBut *but;
+ double final_time = 0.01 * U.pie_animation_timeout;
+ float fac = duration / final_time;
+ float pie_radius = U.pie_menu_radius * UI_DPI_FAC;
+
+ if (fac > 1.0f) {
+ fac = 1.0f;
+ block->pie_data.flags |= UI_PIE_ANIMATION_FINISHED;
+ }
+
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->pie_dir != UI_RADIAL_NONE) {
+ float vec[2];
+ float center[2];
+
+ ui_but_pie_dir(but->pie_dir, vec);
+
+ center[0] = (vec[0] > 0.01f) ? 0.5f : ((vec[0] < -0.01f) ? -0.5f : 0.0f);
+ center[1] = (vec[1] > 0.99f) ? 0.5f : ((vec[1] < -0.99f) ? -0.5f : 0.0f);
+
+ center[0] *= BLI_rctf_size_x(&but->rect);
+ center[1] *= BLI_rctf_size_y(&but->rect);
+
+ mul_v2_fl(vec, pie_radius);
+ add_v2_v2(vec, center);
+ mul_v2_fl(vec, fac);
+ add_v2_v2(vec, block->pie_data.pie_center_spawned);
+
+ BLI_rctf_recenter(&but->rect, vec[0], vec[1]);
+ }
+ }
+ block->pie_data.alphafac = fac;
+
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+
+ event_xy[0] = event->x;
+ event_xy[1] = event->y;
+
+ ui_window_to_block_fl(ar, block, &event_xy[0], &event_xy[1]);
+
+ ui_block_calculate_pie_segment(block, event_xy);
+
+ if (block->pie_data.flags & UI_PIE_FINISHED) {
+ if ((event->type == block->pie_data.event && event->val == KM_RELEASE) ||
+ ((event->type == RIGHTMOUSE || event->type == ESCKEY) && (event->val == KM_PRESS)))
+ {
+ menu->menuretval = UI_RETURN_OK;
+ }
+
+ ED_region_tag_redraw(ar);
return WM_UI_HANDLER_BREAK;
+ }
+
+ if (event->type == block->pie_data.event) {
+ if (event->val != KM_RELEASE) {
+ ui_handle_menu_button(C, event, menu);
+
+ if (len_squared_v2v2(event_xy, block->pie_data.pie_center_init) > PIE_CLICK_THRESHOLD_SQ) {
+ block->pie_data.flags |= UI_PIE_DRAG_STYLE;
+ }
+ /* why redraw here? It's simple, we are getting many double click events here.
+ * Those operate like mouse move events almost */
+ ED_region_tag_redraw(ar);
+ }
+ else {
+ /* distance from initial point */
+ if (!(block->pie_data.flags & UI_PIE_DRAG_STYLE)) {
+ block->pie_data.flags |= UI_PIE_CLICK_STYLE;
+ }
+ else if (!is_click_style) {
+ uiBut *but = ui_but_find_activated(menu->region);
+
+ retval = ui_but_pie_menu_apply(C, menu, but, true, is_click_style);
+ }
+ }
+ }
+ else {
+ /* direction from numpad */
+ RadialDirection num_dir = UI_RADIAL_NONE;
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ if (len_squared_v2v2(event_xy, block->pie_data.pie_center_init) > PIE_CLICK_THRESHOLD_SQ) {
+ block->pie_data.flags |= UI_PIE_DRAG_STYLE;
+ }
+ ui_handle_menu_button(C, event, menu);
+
+ /* mouse move should always refresh the area for pie menus */
+ ED_region_tag_redraw(ar);
+ break;
+
+ case LEFTMOUSE:
+ if (event->val == KM_PRESS) {
+ uiBut *but = ui_but_find_activated(menu->region);
+ retval = ui_but_pie_menu_apply(C, menu, but, false, is_click_style);
+ }
+ break;
+
+ case ESCKEY:
+ case RIGHTMOUSE:
+ if (!is_click_style) {
+ block->pie_data.flags |= UI_PIE_FINISHED;
+ menu->menuretval = 0;
+ ED_region_tag_redraw(ar);
+ }
+ else
+ menu->menuretval = UI_RETURN_CANCEL;
+ break;
+
+ case AKEY:
+ case BKEY:
+ case CKEY:
+ case DKEY:
+ case EKEY:
+ case FKEY:
+ case GKEY:
+ case HKEY:
+ case IKEY:
+ case JKEY:
+ case KKEY:
+ case LKEY:
+ case MKEY:
+ case NKEY:
+ case OKEY:
+ case PKEY:
+ case QKEY:
+ case RKEY:
+ case SKEY:
+ case TKEY:
+ case UKEY:
+ case VKEY:
+ case WKEY:
+ case XKEY:
+ case YKEY:
+ case ZKEY:
+ {
+ if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) &&
+ (event->shift == 0) &&
+ (event->ctrl == 0) &&
+ (event->oskey == 0))
+ {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->menu_key == event->type) {
+ ui_but_pie_button_activate(C, but, menu, is_click_style);
+ }
+ }
+ }
+ break;
+ }
+
+#define CASE_NUM_TO_DIR(n, d) \
+ case (ZEROKEY + n): case (PAD0 + n): \
+ { if (num_dir == UI_RADIAL_NONE) num_dir = d; } (void)0
+
+ CASE_NUM_TO_DIR(1, UI_RADIAL_SW);
+ CASE_NUM_TO_DIR(2, UI_RADIAL_S);
+ CASE_NUM_TO_DIR(3, UI_RADIAL_SE);
+ CASE_NUM_TO_DIR(4, UI_RADIAL_W);
+ CASE_NUM_TO_DIR(6, UI_RADIAL_E);
+ CASE_NUM_TO_DIR(7, UI_RADIAL_NW);
+ CASE_NUM_TO_DIR(8, UI_RADIAL_N);
+ CASE_NUM_TO_DIR(9, UI_RADIAL_NE);
+ {
+ but = ui_block_pie_dir_activate(block, event, num_dir);
+ retval = ui_but_pie_button_activate(C, but, menu, is_click_style);
+ break;
+ }
+#undef CASE_NUM_TO_DIR
+ default:
+ retval = ui_handle_menu_button(C, event, menu);
+ break;
+ }
+ }
+
+ return retval;
}
static int ui_handle_menus_recursive(
@@ -8253,17 +8854,21 @@ static int ui_handle_menus_recursive(
uiBlock *block = menu->region->uiblocks.first;
const bool is_menu = ui_block_is_menu(block);
bool inside = false;
+ /* root pie menus accept the key that spawned them as double click to improve responsiveness */
+ bool do_recursion = (!(block->flag & UI_BLOCK_RADIAL) || event->type != block->pie_data.event);
- if (is_parent_inside == false) {
- int mx, my;
+ if (do_recursion) {
+ if (is_parent_inside == false) {
+ int mx, my;
- mx = event->x;
- my = event->y;
- ui_window_to_block(menu->region, block, &mx, &my);
- inside = BLI_rctf_isect_pt(&block->rect, mx, my);
- }
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(menu->region, block, &mx, &my);
+ inside = BLI_rctf_isect_pt(&block->rect, mx, my);
+ }
- retval = ui_handle_menus_recursive(C, event, submenu, level + 1, is_parent_inside || inside, is_menu, false);
+ retval = ui_handle_menus_recursive(C, event, submenu, level + 1, is_parent_inside || inside, is_menu, false);
+ }
}
/* now handle events for our own menu */
@@ -8296,7 +8901,12 @@ static int ui_handle_menus_recursive(
}
}
else {
- retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside, is_parent_menu, is_floating);
+ uiBlock *block = menu->region->uiblocks.first;
+
+ if (block->flag & UI_BLOCK_RADIAL)
+ retval = ui_handler_pie(C, event, menu);
+ else if (event->type == LEFTMOUSE || event->val != KM_DBL_CLICK)
+ retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside, is_parent_menu, is_floating);
}
}
@@ -8458,15 +9068,15 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata)
/* free if done, does not free handle itself */
if (menu->menuretval) {
+ wmWindow *win = CTX_wm_window(C);
/* copy values, we have to free first (closes region) */
uiPopupBlockHandle temp = *menu;
ui_popup_block_free(C, menu);
- UI_remove_popup_handlers(&CTX_wm_window(C)->modalhandlers, menu);
+ UI_remove_popup_handlers(&win->modalhandlers, menu);
#ifdef USE_DRAG_TOGGLE
{
- wmWindow *win = CTX_wm_window(C);
WM_event_free_ui_handler_all(C, &win->modalhandlers,
ui_handler_region_drag_toggle, ui_handler_region_drag_toggle_remove);
}
@@ -8476,7 +9086,7 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata)
if (temp.popup_func)
temp.popup_func(C, temp.popup_arg, temp.retvalue);
if (temp.optype)
- WM_operator_name_call(C, temp.optype->idname, temp.opcontext, NULL);
+ WM_operator_name_call_ptr(C, temp.optype, temp.opcontext, NULL);
}
else if (temp.cancel_func)
temp.cancel_func(C, temp.popup_arg);
@@ -8511,12 +9121,12 @@ static void ui_handler_remove_popup(bContext *C, void *userdata)
void UI_add_region_handlers(ListBase *handlers)
{
WM_event_remove_ui_handler(handlers, ui_handler_region, ui_handler_remove_region, NULL, false);
- WM_event_add_ui_handler(NULL, handlers, ui_handler_region, ui_handler_remove_region, NULL);
+ WM_event_add_ui_handler(NULL, handlers, ui_handler_region, ui_handler_remove_region, NULL, false);
}
-void UI_add_popup_handlers(bContext *C, ListBase *handlers, uiPopupBlockHandle *popup)
+void UI_add_popup_handlers(bContext *C, ListBase *handlers, uiPopupBlockHandle *popup, const bool accept_dbl_click)
{
- WM_event_add_ui_handler(C, handlers, ui_handler_popup, ui_handler_remove_popup, popup);
+ WM_event_add_ui_handler(C, handlers, ui_handler_popup, ui_handler_remove_popup, popup, accept_dbl_click);
}
void UI_remove_popup_handlers(ListBase *handlers, uiPopupBlockHandle *popup)
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index be6752953d1..cc8fc941ae7 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -508,6 +508,8 @@ static void init_brush_icons(void)
INIT_BRUSH_ICON(ICON_BRUSH_SOFTEN, soften);
INIT_BRUSH_ICON(ICON_BRUSH_SUBTRACT, subtract);
INIT_BRUSH_ICON(ICON_BRUSH_TEXDRAW, texdraw);
+ INIT_BRUSH_ICON(ICON_BRUSH_TEXFILL, texfill);
+ INIT_BRUSH_ICON(ICON_BRUSH_TEXMASK, texmask);
INIT_BRUSH_ICON(ICON_BRUSH_THUMB, thumb);
INIT_BRUSH_ICON(ICON_BRUSH_ROTATE, twist);
INIT_BRUSH_ICON(ICON_BRUSH_VERTEXDRAW, vertexdraw);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index cd3b6390184..cdc611a60f4 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -88,6 +88,7 @@ typedef enum {
UI_WTYPE_PULLDOWN,
UI_WTYPE_MENU_ITEM,
+ UI_WTYPE_MENU_ITEM_RADIAL,
UI_WTYPE_MENU_BACK,
/* specials */
@@ -121,6 +122,23 @@ enum {
/* warn: rest of uiBut->flag in UI_interface.h */
};
+/* but->pie_dir */
+typedef enum RadialDirection {
+ UI_RADIAL_NONE = -1,
+ UI_RADIAL_N = 0,
+ UI_RADIAL_NE = 1,
+ UI_RADIAL_E = 2,
+ UI_RADIAL_SE = 3,
+ UI_RADIAL_S = 4,
+ UI_RADIAL_SW = 5,
+ UI_RADIAL_W = 6,
+ UI_RADIAL_NW = 7,
+} RadialDirection;
+
+extern const char ui_radial_dir_order[8];
+extern const char ui_radial_dir_to_numpad[8];
+extern const short ui_radial_dir_to_angle[8];
+
/* internal panel drawing defines */
#define PNL_GRID (UI_UNIT_Y / 5) /* 4 default */
#define PNL_HEADER (UI_UNIT_Y + 4) /* 24 default */
@@ -144,6 +162,19 @@ enum {
/* split numbuts by ':' and align l/r */
#define USE_NUMBUTS_LR_ALIGN
+/* PieMenuData->flags */
+enum {
+ UI_PIE_DEGREES_RANGE_LARGE = (1 << 0), /* pie menu item collision is detected at 90 degrees */
+ UI_PIE_INITIAL_DIRECTION = (1 << 1), /* use initial center of pie menu to calculate direction */
+ UI_PIE_DRAG_STYLE = (1 << 2), /* pie menu is drag style */
+ UI_PIE_INVALID_DIR = (1 << 3), /* mouse not far enough from center position */
+ UI_PIE_FINISHED = (1 << 4), /* pie menu finished but we still wait for a release event */
+ UI_PIE_CLICK_STYLE = (1 << 5), /* pie menu changed to click style, click to confirm */
+ UI_PIE_ANIMATION_FINISHED = (1 << 6), /* pie animation finished, do not calculate any more motio */
+};
+
+#define PIE_CLICK_THRESHOLD_SQ 50.0f
+
typedef struct uiLinkLine { /* only for draw/edit */
struct uiLinkLine *next, *prev;
struct uiBut *from, *to;
@@ -186,6 +217,7 @@ struct uiBut {
* (type == LABEL), Use (a1 == 1.0f) to use a2 as a blending factor (wow, this is imaginative!).
* (type == SCROLL) Use as scroll size.
* (type == SEARCH_MENU) Use as number or rows.
+ * (type == COLOR) Use as indication of color palette
*/
float a1;
@@ -193,6 +225,7 @@ struct uiBut {
* (type == NUM), Use to store RNA 'precision' value, for dragging and click-step.
* (type == LABEL), If (a1 == 1.0f) use a2 as a blending factor.
* (type == SEARCH_MENU) Use as number or columns.
+ * (type == COLOR) Use as indication of active palette color
*/
float a2;
@@ -225,6 +258,7 @@ struct uiBut {
BIFIconID icon;
bool lock;
char dt; /* drawtype: UI_EMBOSS, UI_EMBOSSN ... etc, copied from the block */
+ signed char pie_dir; /* direction in a pie menu, used for collision detection (RadialDirection) */
char changed; /* could be made into a single flag */
unsigned char unit_type; /* so buttons can support unit systems which are not RNA */
short modifier_key;
@@ -272,6 +306,15 @@ struct uiBut {
uiBlock *block;
};
+struct PieMenuData {
+ float pie_dir[2];
+ float pie_center_init[2];
+ float pie_center_spawned[2];
+ int flags;
+ int event; /* initial event used to fire the pie menu, store here so we can query for release */
+ float alphafac;
+};
+
struct uiBlock {
uiBlock *next, *prev;
@@ -354,6 +397,7 @@ struct uiBlock {
char display_device[64]; /* display device name used to display this block,
* used by color widgets to transform colors from/to scene linear
*/
+ struct PieMenuData pie_data;
};
typedef struct uiSafetyRct {
@@ -369,6 +413,7 @@ extern void ui_delete_linkline(uiLinkLine *line, uiBut *but);
void ui_fontscale(short *points, float aspect);
extern bool ui_block_is_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
+extern bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
extern void ui_block_to_window_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y);
extern void ui_block_to_window(const struct ARegion *ar, uiBlock *block, int *x, int *y);
extern void ui_block_to_window_rctf(const struct ARegion *ar, uiBlock *block, rctf *rct_dst, const rctf *rct_src);
@@ -550,12 +595,19 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol
PointerRNA *ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, int opcontext, bool create_props);
extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but);
+extern void ui_button_activate_over(struct bContext *C, struct ARegion *ar, uiBut *but);
extern void ui_button_execute_begin(struct bContext *C, struct ARegion *ar, uiBut *but, void **active_back);
extern void ui_button_execute_end(struct bContext *C, struct ARegion *ar, uiBut *but, void *active_back);
extern void ui_button_active_free(const struct bContext *C, uiBut *but);
extern bool ui_button_is_active(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT;
extern int ui_button_open_menu_direction(uiBut *but);
extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, const bool restore);
+extern uiBut *ui_but_find_activated(struct ARegion *ar);
+bool ui_but_is_editable(const uiBut *but);
+void ui_but_pie_dir_visual(RadialDirection dir, float vec[2]);
+void ui_but_pie_dir(RadialDirection dir, float vec[2]);
+void ui_block_calculate_pie_segment(struct uiBlock *block, const float event_xy[2]);
+
void ui_button_clipboard_free(void);
void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa);
uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new);
@@ -565,6 +617,7 @@ uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new);
void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3);
void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha);
void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
+void ui_draw_pie_center(uiBlock *block);
uiWidgetColors *ui_tooltip_get_theme(void);
void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *block, rcti *rect);
void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect);
@@ -589,7 +642,6 @@ int ui_id_icon_get(struct bContext *C, struct ID *id, const bool big);
/* resources.c */
void init_userdef_do_versions(void);
-void init_userdef_factory(void);
void ui_theme_init_default(void);
void ui_style_init_default(void);
void ui_resources_init(void);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 789c10d6693..27af550b173 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -106,6 +106,7 @@ typedef enum uiItemType {
ITEM_LAYOUT_ABSOLUTE,
ITEM_LAYOUT_SPLIT,
ITEM_LAYOUT_OVERLAP,
+ ITEM_LAYOUT_RADIAL,
ITEM_LAYOUT_ROOT
#if 0
@@ -218,7 +219,9 @@ static int ui_item_fit(int item, int pos, int all, int available, int last, int
static int ui_layout_vary_direction(uiLayout *layout)
{
- return (layout->root->type == UI_LAYOUT_HEADER || layout->alignment != UI_LAYOUT_ALIGN_EXPAND) ? UI_ITEM_VARY_X : UI_ITEM_VARY_Y;
+ return ((ELEM(layout->root->type, UI_LAYOUT_HEADER, UI_LAYOUT_PIEMENU) ||
+ (layout->alignment != UI_LAYOUT_ALIGN_EXPAND)) ?
+ UI_ITEM_VARY_X : UI_ITEM_VARY_Y);
}
/* estimated size of text + icon */
@@ -553,15 +556,24 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt
*/
uiBut *but;
+ uiLayout *layout_radial = NULL;
EnumPropertyItem *item, *item_array;
const char *name;
int itemw, icon, value;
bool free;
+ bool radial = (layout->root->type == UI_LAYOUT_PIEMENU);
- RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item_array, NULL, &free);
+ if (radial)
+ RNA_property_enum_items_gettexted_all(block->evil_C, ptr, prop, &item_array, NULL, &free);
+ else
+ RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item_array, NULL, &free);
/* we dont want nested rows, cols in menus */
- if (layout->root->type != UI_LAYOUT_MENU) {
+ if (radial) {
+ layout_radial = uiLayoutRadial(layout);
+ uiBlockSetCurLayout(block, layout_radial);
+ }
+ else if (layout->root->type != UI_LAYOUT_MENU) {
uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1));
}
else {
@@ -569,8 +581,11 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt
}
for (item = item_array; item->identifier; item++) {
- if (!item->identifier[0])
+ if (!item->identifier[0]) {
+ if (radial)
+ uiItemS(layout_radial);
continue;
+ }
name = (!uiname || uiname[0]) ? item->name : "";
icon = item->icon;
@@ -869,6 +884,8 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
PointerRNA ptr;
PropertyRNA *prop;
uiBlock *block = layout->root->block;
+ const bool radial = (layout->item.type == ITEM_LAYOUT_RADIAL) ||
+ ((layout->item.type == ITEM_LAYOUT_ROOT) && (layout->root->type == UI_LAYOUT_PIEMENU));
if (!ot || !ot->srna) {
ui_item_disabled(layout, opname);
@@ -887,10 +904,24 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
if (prop && RNA_property_type(prop) == PROP_ENUM) {
EnumPropertyItem *item, *item_array = NULL;
bool free;
- uiLayout *split = uiLayoutSplit(layout, 0.0f, false);
- uiLayout *column = uiLayoutColumn(split, layout->align);
+ uiLayout *split;
+ uiLayout *target;
+
+ if (radial) {
+ target = uiLayoutRadial(layout);
+ }
+ else {
+ split = uiLayoutSplit(layout, 0.0f, false);
+ target = uiLayoutColumn(split, layout->align);
+ }
+
+ if (radial) {
+ RNA_property_enum_items_gettexted_all(block->evil_C, &ptr, prop, &item_array, NULL, &free);
+ }
+ else {
+ RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, NULL, &free);
+ }
- RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, NULL, &free);
for (item = item_array; item->identifier; item++) {
if (item->identifier[0]) {
PointerRNA tptr;
@@ -905,20 +936,24 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
}
RNA_property_enum_set(&tptr, prop, item->value);
- uiItemFullO_ptr(column, ot, item->name, item->icon, tptr.data, context, flag);
+ uiItemFullO_ptr(target, ot, item->name, item->icon, tptr.data, context, flag);
+
ui_but_tip_from_enum_item(block->buttons.last, item);
}
else {
if (item->name) {
uiBut *but;
- if (item != item_array) {
- column = uiLayoutColumn(split, layout->align);
+
+ if (item != item_array && !radial) {
+ target = uiLayoutColumn(split, layout->align);
+
/* inconsistent, but menus with labels do not look good flipped */
block->flag |= UI_BLOCK_NO_FLIP;
}
- if (item->icon) {
- uiItemL(column, item->name, item->icon);
+ if (item->icon || radial) {
+ uiItemL(target, item->name, item->icon);
+
but = block->buttons.last;
}
else {
@@ -928,8 +963,14 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
}
ui_but_tip_from_enum_item(but, item);
}
- else { /* XXX bug here, colums draw bottom item badly */
- uiItemS(column);
+ else {
+ if (radial) {
+ uiItemS(target);
+ }
+ else {
+ /* XXX bug here, colums draw bottom item badly */
+ uiItemS(target);
+ }
}
}
}
@@ -1181,7 +1222,7 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
if (flag & UI_ITEM_R_ICON_ONLY) {
/* pass */
}
- else if (ELEM4(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER)) {
+ else if (ELEM(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER)) {
name = ui_item_name_add_colon(name, namestr);
}
else if (type == PROP_BOOLEAN && is_array && index == RNA_NO_INDEX) {
@@ -1323,9 +1364,9 @@ void uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *pr
for (a = 0; item[a].identifier; a++) {
if (item[a].value == ivalue) {
- const char *item_name = CTX_IFACE_(RNA_property_translation_context(prop), item[a].name);
+ const char *item_name = name ? name : CTX_IFACE_(RNA_property_translation_context(prop), item[a].name);
- uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, ivalue, 0, item_name ? item_name : name, icon ? icon : item[a].icon);
+ uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, ivalue, 0, item_name, icon ? icon : item[a].icon);
break;
}
}
@@ -1559,7 +1600,7 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
}
type = RNA_property_type(prop);
- if (!ELEM3(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) {
+ if (!ELEM(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) {
RNA_warning("Property %s must be a pointer, string or enum", propname);
return;
}
@@ -2072,16 +2113,135 @@ static void ui_litem_layout_column(uiLayout *litem)
litem->y = y;
}
+/* calculates the angle of a specified button in a radial menu,
+ * stores a float vector in unit circle */
+static RadialDirection ui_get_radialbut_vec(float vec[2], short itemnum)
+{
+ RadialDirection dir;
+ BLI_assert(itemnum < 8);
+
+ dir = ui_radial_dir_order[itemnum];
+ ui_but_pie_dir(dir, vec);
+
+ return dir;
+}
+
+static bool ui_item_is_radial_displayable(uiItem *item)
+{
+
+ if ((item->type == ITEM_BUTTON) && (((uiButtonItem *)item)->but->type == LABEL))
+ return false;
+
+ return true;
+}
+
+static bool ui_item_is_radial_drawable(uiButtonItem *bitem)
+{
+
+ if (ELEM(bitem->but->type, SEPR, SEPRLINE))
+ return false;
+
+ return true;
+}
+
+static void ui_litem_layout_radial(uiLayout *litem)
+{
+ uiItem *item;
+ int itemh, itemw, x, y;
+ int itemnum = 0;
+ int totitems = 0;
+
+ int minx, miny, maxx, maxy;
+ /* For the radial layout we will use Matt Ebb's design
+ * for radiation, see http://mattebb.com/weblog/radiation/
+ * also the old code at http://developer.blender.org/T5103
+ */
+
+ int pie_radius = U.pie_menu_radius * UI_DPI_FAC;
+
+ x = litem->x;
+ y = litem->y;
+
+ minx = x, miny = y, maxx = x, maxy = y;
+
+ /* first count total items */
+ for (item = litem->items.first; item; item = item->next)
+ totitems++;
+
+ if (totitems < 5)
+ litem->root->block->pie_data.flags |= UI_PIE_DEGREES_RANGE_LARGE;
+
+ for (item = litem->items.first; item; item = item->next) {
+ /* not all button types are drawn in a radial menu, do filtering here */
+ if (ui_item_is_radial_displayable(item)) {
+ RadialDirection dir;
+ float vec[2];
+ float factor[2];
+
+ dir = ui_get_radialbut_vec(vec, itemnum);
+ factor[0] = (vec[0] > 0.01f) ? 0.0f : ((vec[0] < -0.01f) ? -1.0f : -0.5f);
+ factor[1] = (vec[1] > 0.99f) ? 0.0f : ((vec[1] < -0.99f) ? -1.0f : -0.5f);
+
+ itemnum++;
+
+ if (item->type == ITEM_BUTTON) {
+ uiButtonItem *bitem = (uiButtonItem *) item;
+
+ bitem->but->pie_dir = dir;
+ /* scale the buttons */
+ bitem->but->rect.ymax *= 1.5f;
+ /* 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))
+ bitem->but->dt = UI_EMBOSSR;
+ }
+
+ ui_item_size(item, &itemw, &itemh);
+
+ ui_item_position(item, x + vec[0] * pie_radius + factor[0] * itemw, y + vec[1] * pie_radius + factor[1] * itemh, itemw, itemh);
+
+ minx = min_ii(minx, x + vec[0] * pie_radius - itemw / 2);
+ maxx = max_ii(maxx, x + vec[0] * pie_radius + itemw / 2);
+ miny = min_ii(miny, y + vec[1] * pie_radius - itemh / 2);
+ maxy = max_ii(maxy, y + vec[1] * pie_radius + itemh / 2);
+ }
+ }
+
+ litem->x = minx;
+ litem->y = miny;
+ litem->w = maxx - minx;
+ litem->h = maxy - miny;
+}
+
/* root layout */
static void ui_litem_estimate_root(uiLayout *UNUSED(litem))
{
/* nothing to do */
}
+static void ui_litem_layout_root_radial(uiLayout *litem)
+{
+ /* first item is pie menu title, align on center of menu */
+ uiItem *item = litem->items.first;
+
+ if (item->type == ITEM_BUTTON) {
+ int itemh, itemw, x, y;
+ x = litem->x;
+ y = litem->y;
+
+ ui_item_size(item, &itemw, &itemh);
+
+ ui_item_position(item, x - itemw / 2, y + U.pixelsize * (U.pie_menu_threshold + 9.0f), itemw, itemh);
+ }
+}
+
static void ui_litem_layout_root(uiLayout *litem)
{
if (litem->root->type == UI_LAYOUT_HEADER)
ui_litem_layout_row(litem);
+ else if (litem->root->type == UI_LAYOUT_PIEMENU)
+ ui_litem_layout_root_radial(litem);
else
ui_litem_layout_column(litem);
}
@@ -2497,6 +2657,40 @@ static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type)
return box;
}
+uiLayout *uiLayoutRadial(uiLayout *layout)
+{
+ uiLayout *litem;
+ uiItem *item;
+
+ /* radial layouts are only valid for radial menus */
+ if (layout->root->type != UI_LAYOUT_PIEMENU)
+ return ui_item_local_sublayout(layout, layout, 0);
+
+ /* only one radial wheel per root layout is allowed, so check and return that, if it exists */
+ for (item = layout->root->layout->items.first; item; item = item->next) {
+ litem = (uiLayout *)item;
+ if (litem->item.type == ITEM_LAYOUT_RADIAL) {
+ uiBlockSetCurLayout(layout->root->block, litem);
+ return litem;
+ }
+ }
+
+ litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRadial");
+ litem->item.type = ITEM_LAYOUT_RADIAL;
+ litem->root = layout->root;
+ litem->active = true;
+ litem->enabled = true;
+ litem->context = layout->context;
+ litem->redalert = layout->redalert;
+ litem->w = layout->w;
+ BLI_addtail(&layout->root->layout->items, litem);
+
+ uiBlockSetCurLayout(layout->root->block, litem);
+
+ return litem;
+}
+
+
uiLayout *uiLayoutBox(uiLayout *layout)
{
return (uiLayout *)ui_layout_box(layout, ROUNDBOX);
@@ -2843,6 +3037,9 @@ static void ui_item_layout(uiItem *item)
case ITEM_LAYOUT_OVERLAP:
ui_litem_layout_overlap(litem);
break;
+ case ITEM_LAYOUT_RADIAL:
+ ui_litem_layout_radial(litem);
+ break;
default:
break;
}
@@ -2916,7 +3113,7 @@ uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int siz
layout->enabled = 1;
layout->context = NULL;
- if (type == UI_LAYOUT_MENU)
+ if (type == UI_LAYOUT_MENU || type == UI_LAYOUT_PIEMENU)
layout->space = 0;
if (dir == UI_LAYOUT_HORIZONTAL) {
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 316a4d34881..817445cc14e 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -35,6 +35,7 @@
#include "DNA_text_types.h" /* for UI_OT_reports_to_text */
#include "BLI_blenlib.h"
+#include "BLI_math_color.h"
#include "BLF_api.h"
#include "BLF_translation.h"
@@ -44,6 +45,7 @@
#include "BKE_global.h"
#include "BKE_text.h" /* for UI_OT_reports_to_text */
#include "BKE_report.h"
+#include "BKE_paint.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -55,6 +57,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_paint.h"
+
/* only for UI_OT_editsource */
#include "ED_screen.h"
#include "BKE_main.h"
@@ -258,28 +262,43 @@ static void UI_OT_unset_property_button(wmOperatorType *ot)
/* Copy To Selected Operator ------------------------ */
-static bool copy_to_selected_list(bContext *C, PointerRNA *ptr, ListBase *lb, bool *use_path)
+static bool copy_to_selected_list(
+ bContext *C, PointerRNA *ptr, PropertyRNA *prop,
+ ListBase *r_lb, bool *r_use_path_from_id, char **r_path)
{
- *use_path = false;
+ *r_use_path_from_id = false;
+ *r_path = NULL;
- if (RNA_struct_is_a(ptr->type, &RNA_EditBone))
- *lb = CTX_data_collection_get(C, "selected_editable_bones");
- else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone))
- *lb = CTX_data_collection_get(C, "selected_pose_bones");
- else if (RNA_struct_is_a(ptr->type, &RNA_Sequence))
- *lb = CTX_data_collection_get(C, "selected_editable_sequences");
- else {
+ if (RNA_struct_is_a(ptr->type, &RNA_EditBone)) {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_bones");
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
+ *r_lb = CTX_data_collection_get(C, "selected_pose_bones");
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
+ }
+ else if (ptr->id.data) {
ID *id = ptr->id.data;
- if (id && GS(id->name) == ID_OB) {
- *lb = CTX_data_collection_get(C, "selected_editable_objects");
- *use_path = true;
+ if (GS(id->name) == ID_OB) {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_objects");
+ *r_use_path_from_id = true;
+ *r_path = RNA_path_from_ID_to_property(ptr, prop);
}
- else {
- return false;
+ else if (GS(id->name) == ID_SCE) {
+ /* Sequencer's ID is scene :/ */
+ /* Try to recursively find an RNA_Sequence ancestor, to handle situations like T41062... */
+ if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence)) != NULL) {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
+ }
}
+ return (*r_path != NULL);
}
-
+ else {
+ return false;
+ }
+
return true;
}
@@ -303,47 +322,54 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll)
/* if there is a valid property that is editable... */
if (ptr.data && prop) {
char *path = NULL;
- bool use_path;
+ bool use_path_from_id;
CollectionPointerLink *link;
ListBase lb;
- if (!copy_to_selected_list(C, &ptr, &lb, &use_path))
+ if (!copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path))
return success;
- if (!use_path || (path = RNA_path_from_ID_to_property(&ptr, prop))) {
- for (link = lb.first; link; link = link->next) {
- if (link->ptr.data != ptr.data) {
- if (use_path) {
- lprop = NULL;
- RNA_id_pointer_create(link->ptr.id.data, &idptr);
- RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
- }
- else {
- lptr = link->ptr;
- lprop = prop;
- }
+ 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 (lprop == prop) {
- if (RNA_property_editable(&lptr, lprop)) {
- if (poll) {
+ 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);
success = true;
- break;
- }
- else {
- if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
- RNA_property_update(C, &lptr, prop);
- success = true;
- }
}
}
}
}
}
-
- if (path)
- MEM_freeN(path);
}
+ MEM_SAFE_FREE(path);
BLI_freelistN(&lb);
}
@@ -693,6 +719,7 @@ static int edittranslation_exec(bContext *C, wmOperator *op)
int ret = OPERATOR_CANCELLED;
if (but) {
+ wmOperatorType *ot;
PointerRNA ptr;
char popath[FILE_MAX];
const char *root = U.i18ndir;
@@ -714,7 +741,8 @@ static int edittranslation_exec(bContext *C, wmOperator *op)
"Directory' path to a valid directory");
return OPERATOR_CANCELLED;
}
- if (!WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0)) {
+ ot = WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0);
+ if (ot == NULL) {
BKE_reportf(op->reports, RPT_ERROR, "Could not find operator '%s'! Please enable ui_translate addon "
"in the User Preferences", EDTSRC_I18N_OP_NAME);
return OPERATOR_CANCELLED;
@@ -730,7 +758,7 @@ static int edittranslation_exec(bContext *C, wmOperator *op)
uiButGetStrInfo(C, but, &but_label, &rna_label, &enum_label, &but_tip, &rna_tip, &enum_tip,
&rna_struct, &rna_prop, &rna_enum, &rna_ctxt, NULL);
- WM_operator_properties_create(&ptr, EDTSRC_I18N_OP_NAME);
+ WM_operator_properties_create_ptr(&ptr, ot);
RNA_string_set(&ptr, "lang", uilng);
RNA_string_set(&ptr, "po_file", popath);
RNA_string_set(&ptr, "but_label", but_label.strinfo);
@@ -743,7 +771,7 @@ static int edittranslation_exec(bContext *C, wmOperator *op)
RNA_string_set(&ptr, "rna_prop", rna_prop.strinfo);
RNA_string_set(&ptr, "rna_enum", rna_enum.strinfo);
RNA_string_set(&ptr, "rna_ctxt", rna_ctxt.strinfo);
- ret = WM_operator_name_call(C, EDTSRC_I18N_OP_NAME, WM_OP_INVOKE_DEFAULT, &ptr);
+ ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
/* Clean up */
if (but_label.strinfo)
@@ -808,6 +836,99 @@ static void UI_OT_reloadtranslation(wmOperatorType *ot)
ot->exec = reloadtranslation_exec;
}
+int UI_drop_color_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(event))
+{
+ /* should only return true for regions that include buttons, for now
+ * return true always */
+ if (drag->type == WM_DRAG_COLOR) {
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ if (UI_but_active_drop_color(C))
+ return 1;
+
+ if (sima && (sima->mode == SI_MODE_PAINT) &&
+ sima->image && (ar && ar->regiontype == RGN_TYPE_WINDOW))
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void UI_drop_color_copy(wmDrag *drag, wmDropBox *drop)
+{
+ uiDragColorHandle *drag_info = (uiDragColorHandle *)drag->poin;
+
+ RNA_float_set_array(drop->ptr, "color", drag_info->color);
+ RNA_boolean_set(drop->ptr, "gamma", drag_info->gamma_corrected);
+}
+
+static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ ARegion *ar = CTX_wm_region(C);
+ uiBut *but = NULL;
+ float color[4];
+ bool gamma;
+
+ RNA_float_get_array(op->ptr, "color", color);
+ gamma = RNA_boolean_get(op->ptr, "gamma");
+
+ /* find button under mouse, check if it has RNA color property and
+ * if it does copy the data */
+ but = ui_but_find_activated(ar);
+
+ if (but && but->type == COLOR && but->rnaprop) {
+ const int color_len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
+ BLI_assert(color_len <= 4);
+
+ /* keep alpha channel as-is */
+ if (color_len == 4) {
+ color[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
+ }
+
+ if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ if (!gamma)
+ ui_block_to_display_space_v3(but->block, color);
+ RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ }
+ else if (RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
+ if (gamma)
+ ui_block_to_scene_linear_v3(but->block, color);
+ RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ }
+ }
+ else {
+ if (gamma) {
+ srgb_to_linearrgb_v3_v3(color, color);
+ }
+
+ ED_imapaint_bucket_fill(C, color, op);
+ }
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+}
+
+
+static void UI_OT_drop_color(wmOperatorType *ot)
+{
+ ot->name = "Drop Color";
+ ot->idname = "UI_OT_drop_color";
+ ot->description = "Drop colors to buttons";
+
+ ot->invoke = drop_color_invoke;
+
+ RNA_def_float_color(ot->srna, "color", 3, NULL, 0.0, FLT_MAX, "Color", "Source color", 0.0, 1.0);
+ RNA_def_boolean(ot->srna, "gamma", 0, "Gamma Corrected", "The source color is gamma corrected ");
+}
+
+
+
/* ********************************************************* */
/* Registration */
@@ -819,7 +940,7 @@ void UI_buttons_operatortypes(void)
WM_operatortype_append(UI_OT_unset_property_button);
WM_operatortype_append(UI_OT_copy_to_selected_button);
WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
-
+ WM_operatortype_append(UI_OT_drop_color);
#ifdef WITH_PYTHON
WM_operatortype_append(UI_OT_editsource);
WM_operatortype_append(UI_OT_edittranslation_init);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 2ccb3740777..9265ca0d4b9 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -120,7 +120,7 @@ static int panel_aligned(ScrArea *sa, ARegion *ar)
return BUT_VERTICAL;
else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW)
return BUT_VERTICAL;
- else if (ELEM3(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS))
+ else if (ELEM(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS))
return BUT_VERTICAL;
return 0;
@@ -201,20 +201,33 @@ static void ui_panel_copy_offset(Panel *pa, Panel *papar)
pa->ofsy = papar->ofsy + papar->sizey - pa->sizey;
}
+
+/* XXX Disabled paneltab handling for now. Old 2.4x feature, *DO NOT* confuse it with new tool tabs in 2.70. ;)
+ * See also T41704.
+ */
+/* #define UI_USE_PANELTAB */
+
Panel *uiPanelFindByType(ARegion *ar, PanelType *pt)
{
Panel *pa;
-
const char *idname = pt->idname;
- const char *tabname = pt->idname;
+#ifdef UI_USE_PANELTAB
+ const char *tabname = pt->idname;
for (pa = ar->panels.first; pa; pa = pa->next) {
if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
- if (STREQLEN(pa->tabname, tabname, sizeof(pa->panelname))) {
+ if (STREQLEN(pa->tabname, tabname, sizeof(pa->tabname))) {
return pa;
}
}
}
+#else
+ for (pa = ar->panels.first; pa; pa = pa->next) {
+ if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
+ return pa;
+ }
+ }
+#endif
return NULL;
}
@@ -224,11 +237,13 @@ Panel *uiPanelFindByType(ARegion *ar, PanelType *pt)
*/
Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, Panel *pa, bool *r_open)
{
- Panel *patab, *palast, *panext;
+ Panel *palast, *panext;
const char *drawname = CTX_IFACE_(pt->translation_context, pt->label);
const char *idname = pt->idname;
+#ifdef UI_USE_PANELTAB
const char *tabname = pt->idname;
const char *hookname = NULL;
+#endif
const bool newpanel = (pa == NULL);
int align = panel_aligned(sa, ar);
@@ -240,7 +255,6 @@ Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, Pan
pa = MEM_callocN(sizeof(Panel), "new panel");
pa->type = pt;
BLI_strncpy(pa->panelname, idname, sizeof(pa->panelname));
- BLI_strncpy(pa->tabname, tabname, sizeof(pa->tabname));
if (pt->flag & PNL_DEFAULT_CLOSED) {
if (align == BUT_VERTICAL)
@@ -256,9 +270,13 @@ Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, Pan
pa->runtime_flag |= PNL_NEW_ADDED;
BLI_addtail(&ar->panels, pa);
-
+
+#ifdef UI_USE_PANELTAB
+ BLI_strncpy(pa->tabname, tabname, sizeof(pa->tabname));
+
/* make new Panel tabbed? */
if (hookname) {
+ Panel *patab;
for (patab = ar->panels.first; patab; patab = patab->next) {
if ((patab->runtime_flag & PNL_ACTIVE) && patab->paneltab == NULL) {
if (STREQLEN(hookname, patab->panelname, sizeof(patab->panelname))) {
@@ -271,6 +289,9 @@ Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, Pan
}
}
}
+#else
+ BLI_strncpy(pa->tabname, idname, sizeof(pa->tabname));
+#endif
}
/* Do not allow closed panels without headers! Else user could get "disappeared" UI! */
@@ -462,31 +483,41 @@ static void ui_draw_panel_scalewidget(const rcti *rect)
fdrawline(xmin + dx, ymin + 1, xmax, ymax - dy + 1);
glDisable(GL_BLEND);
}
-
static void ui_draw_panel_dragwidget(const rctf *rect)
{
- float xmin, xmax, dx;
- float ymin, ymax, dy;
-
- xmin = rect->xmin;
- xmax = rect->xmax;
- ymin = rect->ymin;
- ymax = rect->ymax;
-
- dx = (xmax - xmin) / 3.0f;
- dy = (ymax - ymin) / 3.0f;
-
- glEnable(GL_BLEND);
- glColor4ub(255, 255, 255, 50);
- fdrawline(xmin, ymax, xmax, ymin);
- fdrawline(xmin + dx, ymax, xmax, ymin + dy);
- fdrawline(xmin + 2 * dx, ymax, xmax, ymin + 2 * dy);
-
- glColor4ub(0, 0, 0, 50);
- fdrawline(xmin, ymax + 1, xmax, ymin + 1);
- fdrawline(xmin + dx, ymax + 1, xmax, ymin + dy + 1);
- fdrawline(xmin + 2 * dx, ymax + 1, xmax, ymin + 2 * dy + 1);
- glDisable(GL_BLEND);
+ unsigned char col_back[3], col_high[3], col_dark[3];
+ const int col_tint = 84;
+
+ const int px = (int)U.pixelsize;
+ const int px_zoom = max_ii(iroundf(BLI_rctf_size_y(rect) / 22.0f), 1);
+
+ const int box_margin = max_ii(iroundf((float)(px_zoom * 2.0f)), px);
+ const int box_size = max_ii(iroundf((BLI_rctf_size_y(rect) / 8.0f) - px), px);
+
+ const int x_min = rect->xmin;
+ const int y_min = rect->ymin;
+ const int y_ofs = max_ii(iroundf(BLI_rctf_size_y(rect) / 3.0f), px);
+ const int x_ofs = y_ofs;
+ int i_x, i_y;
+
+
+ UI_GetThemeColor3ubv(UI_GetThemeValue(TH_PANEL_SHOW_HEADER) ? TH_PANEL_HEADER : TH_PANEL_BACK, col_back);
+ UI_GetColorPtrShade3ubv(col_back, col_high, col_tint);
+ UI_GetColorPtrShade3ubv(col_back, col_dark, -col_tint);
+
+
+ /* draw multiple boxes */
+ for (i_x = 0; i_x < 4; i_x++) {
+ for (i_y = 0; i_y < 2; i_y++) {
+ const int x_co = (x_min + x_ofs) + (i_x * (box_size + box_margin));
+ const int y_co = (y_min + y_ofs) + (i_y * (box_size + box_margin));
+
+ glColor3ubv(col_dark);
+ glRectf(x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom);
+ glColor3ubv(col_high);
+ glRectf(x_co - box_size, y_co, x_co, y_co + box_size);
+ }
+ }
}
@@ -1131,7 +1162,7 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
button = 1;
else if (event == AKEY)
button = 1;
- else if (ELEM3(event, 0, RETKEY, LEFTMOUSE) && shift) {
+ else if (ELEM(event, 0, RETKEY, LEFTMOUSE) && shift) {
block->panel->flag ^= PNL_PIN;
button = 2;
}
@@ -1524,6 +1555,12 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
const bool is_active = STREQ(category_id, category_id_active);
+#ifdef DEBUG
+ if (STREQ(category_id, PNL_CATEGORY_FALLBACK)) {
+ printf("WARNING: Panel has no 'bl_category', script needs updating!\n");
+ }
+#endif
+
glEnable(GL_BLEND);
#ifdef USE_FLAT_INACTIVE
@@ -1716,7 +1753,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
/* XXX hardcoded key warning */
if ((inside || inside_header) && event->val == KM_PRESS) {
- if (event->type == AKEY && !ELEM4(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift, event->alt)) {
+ if (event->type == AKEY && !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift, event->alt)) {
if (pa->flag & PNL_CLOSEDY) {
if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my))
@@ -1902,7 +1939,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
data = MEM_callocN(sizeof(uiHandlePanelData), "uiHandlePanelData");
pa->activedata = data;
- WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa);
+ WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, false);
}
if (ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG))
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index c32f0de937e..1960c77bc95 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -43,6 +43,8 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "PIL_time.h"
+
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_report.h"
@@ -392,7 +394,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
data->totline++;
}
- if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
/* better not show the value of a password */
if ((but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) == 0) {
/* full string */
@@ -1163,8 +1165,9 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
/* widget rect, in region coords */
data->bbox.xmin = width;
data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - width;
- data->bbox.ymin = width;
- data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - width;
+ /* Do not use shadow width for height, gives insane margin with big shadows, and issue T41548 with small ones */
+ data->bbox.ymin = 8 * UI_DPI_FAC;
+ data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - 8 * UI_DPI_FAC;
/* check if button is lower half */
if (but->rect.ymax < BLI_rctf_cent_y(&but->block->rect)) {
@@ -1704,18 +1707,69 @@ uiBlock *ui_popup_block_refresh(
BLI_addhead(&block->saferct, saferct);
}
- /* clip block with window boundary */
- ui_popup_block_clip(window, block);
-
- /* the block and buttons were positioned in window space as in 2.4x, now
- * these menu blocks are regions so we bring it back to region space.
- * additionally we add some padding for the menu shadow or rounded menus */
- ar->winrct.xmin = block->rect.xmin - width;
- ar->winrct.xmax = block->rect.xmax + width;
- ar->winrct.ymin = block->rect.ymin - width;
- ar->winrct.ymax = block->rect.ymax + MENU_TOP;
-
- ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
+ if (block->flag & UI_BLOCK_RADIAL) {
+ uiBut *but;
+ int win_width = UI_SCREEN_MARGIN;
+ int winx, winy;
+
+ int x_offset = 0, y_offset = 0;
+
+ winx = WM_window_pixels_x(window);
+ winy = WM_window_pixels_y(window);
+
+ copy_v2_v2(block->pie_data.pie_center_init, block->pie_data.pie_center_spawned);
+
+ /* only try translation if area is large enough */
+ if (BLI_rctf_size_x(&block->rect) < winx - (2.0f * win_width)) {
+ if (block->rect.xmin < win_width ) x_offset += win_width - block->rect.xmin;
+ if (block->rect.xmax > winx - win_width) x_offset += winx - win_width - block->rect.xmax;
+ }
+
+ if (BLI_rctf_size_y(&block->rect) < winy - (2.0f * win_width)) {
+ if (block->rect.ymin < win_width ) y_offset += win_width - block->rect.ymin;
+ if (block->rect.ymax > winy - win_width) y_offset += winy - win_width - block->rect.ymax;
+ }
+ /* if we are offsetting set up initial data for timeout functionality */
+
+ if ((x_offset != 0) || (y_offset != 0)) {
+ block->pie_data.pie_center_spawned[0] += x_offset;
+ block->pie_data.pie_center_spawned[1] += y_offset;
+
+ ui_block_translate(block, x_offset, y_offset);
+
+ if (U.pie_initial_timeout > 0)
+ block->pie_data.flags |= UI_PIE_INITIAL_DIRECTION;
+ }
+
+ ar->winrct.xmin = 0;
+ ar->winrct.xmax = winx;
+ ar->winrct.ymin = 0;
+ ar->winrct.ymax = winy;
+
+ ui_block_calculate_pie_segment(block, block->pie_data.pie_center_init);
+
+ /* lastly set the buttons at the center of the pie menu, ready for animation */
+ if (U.pie_animation_timeout > 0) {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->pie_dir != UI_RADIAL_NONE) {
+ BLI_rctf_recenter(&but->rect, UNPACK2(block->pie_data.pie_center_spawned));
+ }
+ }
+ }
+ }
+ else {
+ /* clip block with window boundary */
+ ui_popup_block_clip(window, block);
+ /* the block and buttons were positioned in window space as in 2.4x, now
+ * these menu blocks are regions so we bring it back to region space.
+ * additionally we add some padding for the menu shadow or rounded menus */
+ ar->winrct.xmin = block->rect.xmin - width;
+ ar->winrct.xmax = block->rect.xmax + width;
+ ar->winrct.ymin = block->rect.ymin - width;
+ ar->winrct.ymax = block->rect.ymax + MENU_TOP;
+
+ ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
+ }
if (block_old) {
block->oldblock = block_old;
@@ -1872,7 +1926,7 @@ static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3], bool is
if (rgb_gamma[2] > 1.0f) rgb_gamma[2] = modf(rgb_gamma[2], &intpart);
rgb_float_to_uchar(rgb_gamma_uchar, rgb_gamma);
- BLI_snprintf(col, sizeof(col), "%02X%02X%02X", UNPACK3OP((unsigned int), rgb_gamma_uchar));
+ BLI_snprintf(col, sizeof(col), "%02X%02X%02X", UNPACK3_EX((unsigned int), rgb_gamma_uchar, ));
strcpy(bt->poin, col);
}
@@ -2160,7 +2214,7 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
}
rgb_float_to_uchar(rgb_gamma_uchar, rgb_gamma);
- BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3OP((unsigned int), rgb_gamma_uchar));
+ BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3_EX((unsigned int), rgb_gamma_uchar, ));
yco = -3.0f * UI_UNIT_Y;
bt = uiDefBut(block, TEX, 0, IFACE_("Hex: "), 0, yco, butwidth, UI_UNIT_Y, hexcol, 0, 8, 0, 0, TIP_("Hex triplet for color (#RRGGBB)"));
@@ -2353,6 +2407,12 @@ struct uiPopupMenu {
void *menu_arg;
};
+struct uiPieMenu {
+ uiBlock *block_radial; /* radial block of the pie menu (more could be added later) */
+ uiLayout *layout;
+ int mx, my;
+};
+
static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
{
uiBlock *block;
@@ -2408,6 +2468,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
if (pup->popup) {
+ uiBut *but_activate = NULL;
uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_NUMSELECT);
uiBlockSetDirection(block, direction);
@@ -2421,6 +2482,10 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
* block to be under the mouse */
offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect));
offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y);
+
+ if (ui_but_is_editable(bt)) {
+ but_activate = bt;
+ }
}
else {
/* position mouse at 0.8*width of the button and below the tile
@@ -2430,6 +2495,20 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
offset[0] = min_ii(offset[0], -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)));
offset[1] = 2.1 * UI_UNIT_Y;
+
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (ui_but_is_editable(bt)) {
+ but_activate = bt;
+ break;
+ }
+ }
+ }
+
+ /* in rare cases this is needed since moving the popup
+ * to be within the window bounds may move it away from the mouse,
+ * This ensures we set an item to be active. */
+ if (but_activate) {
+ ui_button_activate_over(C, handle->region, but_activate);
}
block->minbounds = minwidth;
@@ -2507,7 +2586,7 @@ uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut
if (!but) {
handle->popup = true;
- UI_add_popup_handlers(C, &window->modalhandlers, handle);
+ UI_add_popup_handlers(C, &window->modalhandlers, handle, false);
WM_event_add_mousemove(C);
}
@@ -2569,7 +2648,7 @@ void uiPupMenuEnd(bContext *C, uiPopupMenu *pup)
menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPUP, pup);
menu->popup = true;
- UI_add_popup_handlers(C, &window->modalhandlers, menu);
+ UI_add_popup_handlers(C, &window->modalhandlers, menu, false);
WM_event_add_mousemove(C);
MEM_freeN(pup);
@@ -2580,6 +2659,178 @@ uiLayout *uiPupMenuLayout(uiPopupMenu *pup)
return pup->layout;
}
+/*************************** Pie Menus ***************************************/
+
+static uiBlock *ui_block_func_PIE(bContext *UNUSED(C), uiPopupBlockHandle *handle, void *arg_pie)
+{
+ uiBlock *block;
+ uiPieMenu *pie = arg_pie;
+ int minwidth, width, height;
+
+ minwidth = 50;
+ block = pie->block_radial;
+
+ /* in some cases we create the block before the region,
+ * so we set it delayed here if necessary */
+ if (BLI_findindex(&handle->region->uiblocks, block) == -1)
+ uiBlockSetRegion(block, handle->region);
+
+ uiBlockLayoutResolve(block, &width, &height);
+
+ uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_NUMSELECT);
+
+ block->minbounds = minwidth;
+ block->bounds = 1;
+ block->mx = 0;
+ block->my = 0;
+ block->bounds_type = UI_BLOCK_BOUNDS_PIE_CENTER;
+
+ block->pie_data.pie_center_spawned[0] = pie->mx;
+ block->pie_data.pie_center_spawned[1] = pie->my;
+
+ return pie->block_radial;
+}
+
+static float uiPieTitleWidth(const char *name, int icon)
+{
+ return (UI_GetStringWidth(name) +
+ (UI_UNIT_X * (1.50f + (icon ? 0.25f : 0.0f))));
+}
+
+uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const wmEvent *event)
+{
+ uiStyle *style = UI_GetStyleDraw();
+ uiPieMenu *pie = MEM_callocN(sizeof(uiPopupMenu), "pie menu");
+
+ pie->block_radial = uiBeginBlock(C, NULL, __func__, UI_EMBOSS);
+ /* may be useful later to allow spawning pies
+ * from old positions */
+ /* pie->block_radial->flag |= UI_BLOCK_POPUP_MEMORY; */
+ pie->block_radial->puphash = ui_popup_menu_hash(title);
+ pie->block_radial->flag |= UI_BLOCK_RADIAL;
+ pie->block_radial->pie_data.event = event->type;
+
+ pie->layout = uiBlockLayout(pie->block_radial, UI_LAYOUT_VERTICAL, UI_LAYOUT_PIEMENU, 0, 0, 200, 0, 0, style);
+ pie->mx = event->x;
+ pie->my = event->y;
+
+ /* create title button */
+ if (title[0]) {
+ uiBut *but;
+ char titlestr[256];
+ int w;
+ if (icon) {
+ BLI_snprintf(titlestr, sizeof(titlestr), " %s", title);
+ w = uiPieTitleWidth(titlestr, icon);
+ but = uiDefIconTextBut(pie->block_radial, LABEL, 0, icon, titlestr, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ else {
+ w = uiPieTitleWidth(title, 0);
+ but = uiDefBut(pie->block_radial, LABEL, 0, title, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ /* do not align left */
+ but->drawflag &= ~UI_BUT_TEXT_LEFT;
+ }
+
+ return pie;
+}
+
+void uiPieMenuEnd(bContext *C, uiPieMenu *pie)
+{
+ wmWindow *window = CTX_wm_window(C);
+ uiPopupBlockHandle *menu;
+
+ menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie);
+ menu->popup = true;
+ menu->towardstime = PIL_check_seconds_timer();
+
+ UI_add_popup_handlers(C, &window->modalhandlers, menu, true);
+ WM_event_add_mousemove(C);
+
+ MEM_freeN(pie);
+}
+
+uiLayout *uiPieMenuLayout(uiPieMenu *pie)
+{
+ return pie->layout;
+}
+
+void uiPieMenuInvoke(struct bContext *C, const char *idname, const wmEvent *event)
+{
+ uiPieMenu *pie;
+ uiLayout *layout;
+ Menu menu;
+ MenuType *mt = WM_menutype_find(idname, true);
+
+ if (mt == NULL) {
+ printf("%s: named menu \"%s\" not found\n", __func__, idname);
+ return;
+ }
+
+ if (mt->poll && mt->poll(C, mt) == 0)
+ return;
+
+ pie = uiPieMenuBegin(C, IFACE_(mt->label), ICON_NONE, event);
+ layout = uiPieMenuLayout(pie);
+
+ menu.layout = layout;
+ menu.type = mt;
+
+ if (G.debug & G_DEBUG_WM) {
+ printf("%s: opening menu \"%s\"\n", __func__, idname);
+ }
+
+ mt->draw(C, &menu);
+
+ uiPieMenuEnd(C, pie);
+}
+
+void uiPieOperatorEnumInvoke(struct bContext *C, const char *title, const char *opname,
+ const char *propname, const wmEvent *event)
+{
+ uiPieMenu *pie;
+ uiLayout *layout;
+
+ pie = uiPieMenuBegin(C, IFACE_(title), ICON_NONE, event);
+ layout = uiPieMenuLayout(pie);
+
+ layout = uiLayoutRadial(layout);
+ uiItemsEnumO(layout, opname, propname);
+
+ uiPieMenuEnd(C, pie);
+}
+
+void uiPieEnumInvoke(struct bContext *C, const char *title, const char *path,
+ const wmEvent *event)
+{
+ PointerRNA ctx_ptr;
+ PointerRNA r_ptr;
+ PropertyRNA *r_prop;
+ uiPieMenu *pie;
+ uiLayout *layout;
+
+ RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr);
+
+ if (!RNA_path_resolve(&ctx_ptr, path, &r_ptr, &r_prop)) {
+ return;
+ }
+
+ /* invalid property, only accept enums */
+ if (RNA_property_type(r_prop) != PROP_ENUM) {
+ BLI_assert(0);
+ return;
+ }
+
+ pie = uiPieMenuBegin(C, IFACE_(title), ICON_NONE, event);
+ layout = uiPieMenuLayout(pie);
+
+ layout = uiLayoutRadial(layout);
+ uiItemFullR(layout, &r_ptr, r_prop, RNA_NO_INDEX, 0, UI_ITEM_R_EXPAND, NULL, 0);
+
+ uiPieMenuEnd(C, pie);
+}
+
+
/*************************** Standard Popup Menus ****************************/
void uiPupMenuReports(bContext *C, ReportList *reports)
@@ -2676,7 +2927,7 @@ void uiPupBlockO(bContext *C, uiBlockCreateFunc func, void *arg, const char *opn
handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL;
handle->opcontext = opcontext;
- UI_add_popup_handlers(C, &window->modalhandlers, handle);
+ UI_add_popup_handlers(C, &window->modalhandlers, handle, false);
WM_event_add_mousemove(C);
}
@@ -2699,7 +2950,7 @@ void uiPupBlockEx(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_f
handle->cancel_func = cancel_func;
// handle->opcontext = opcontext;
- UI_add_popup_handlers(C, &window->modalhandlers, handle);
+ UI_add_popup_handlers(C, &window->modalhandlers, handle, false);
WM_event_add_mousemove(C);
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 243aa452f17..364a62bd2a0 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -36,6 +36,8 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
+#include "DNA_brush_types.h"
+#include "DNA_texture_types.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
@@ -60,6 +62,7 @@
#include "BKE_object.h"
#include "BKE_packedFile.h"
#include "BKE_particle.h"
+#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_sca.h"
#include "BKE_screen.h"
@@ -349,6 +352,8 @@ static const char *template_id_browse_tip(StructRNA *type)
case ID_BR: return N_("Browse Brush to be linked");
case ID_PA: return N_("Browse Particle Settings to be linked");
case ID_GD: return N_("Browse Grease Pencil Data to be linked");
+ case ID_PAL: return N_("Browse Palette Data to be linked");
+ case ID_PC: return N_("Browse Paint Curve Data to be linked");
}
}
return N_("Browse ID data to be linked");
@@ -489,7 +494,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
- if (id->lib == NULL && !(ELEM5(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
+ if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
uiDefButR(block, TOG, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
}
}
@@ -571,24 +576,33 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
/* delete button */
/* don't use RNA_property_is_unlink here */
- if (id && (flag & UI_ID_DELETE) && (RNA_property_flag(template->prop) & PROP_NEVER_UNLINK) == 0) {
+ if (id && (flag & UI_ID_DELETE)) {
+ /* allow unlink if 'unlinkop' is passed, even when 'PROP_NEVER_UNLINK' is set */
+ but = NULL;
+
if (unlinkop) {
but = uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
/* so we can access the template from operators, font unlinking needs this */
uiButSetNFunc(but, NULL, MEM_dupallocN(template), NULL);
}
else {
- but = uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
- TIP_("Unlink datablock "
- "(Shift + Click to set users to zero, data will then not be saved)"));
- uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
+ if ((RNA_property_flag(template->prop) & PROP_NEVER_UNLINK) == 0) {
+ but = uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
+ TIP_("Unlink datablock "
+ "(Shift + Click to set users to zero, data will then not be saved)"));
+ uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
- if (RNA_property_flag(template->prop) & PROP_NEVER_NULL)
- uiButSetFlag(but, UI_BUT_DISABLED);
+ if (RNA_property_flag(template->prop) & PROP_NEVER_NULL) {
+ uiButSetFlag(but, UI_BUT_DISABLED);
+ }
+ }
}
- if ((idfrom && idfrom->lib) || !editable)
- uiButSetFlag(but, UI_BUT_DISABLED);
+ if (but) {
+ if ((idfrom && idfrom->lib) || !editable) {
+ uiButSetFlag(but, UI_BUT_DISABLED);
+ }
+ }
}
if (idcode == ID_TE)
@@ -751,28 +765,6 @@ void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propna
#define ERROR_LIBDATA_MESSAGE IFACE_("Can't edit external libdata")
-static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ob_v;
- ModifierData *md = md_v;
- int i, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 0);
-
- /* undo button operation */
- md->mode ^= eModifierMode_OnCage;
-
- for (i = 0, md = ob->modifiers.first; md; ++i, md = md->next) {
- if (md == md_v) {
- if (i >= cageIndex)
- md->mode ^= eModifierMode_OnCage;
- break;
- }
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-}
-
static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
{
Object *ob = ob_v;
@@ -808,7 +800,7 @@ static int modifier_can_delete(ModifierData *md)
static int modifier_is_simulation(ModifierData *md)
{
/* Physic Tab */
- if (ELEM7(md->type, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim, eModifierType_Smoke,
+ if (ELEM(md->type, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim, eModifierType_Smoke,
eModifierType_Softbody, eModifierType_Surface, eModifierType_DynamicPaint))
{
return 1;
@@ -829,7 +821,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
PointerRNA ptr;
uiBut *but;
uiBlock *block;
- uiLayout *box, *column, *row;
+ uiLayout *box, *column, *row, *sub;
uiLayout *result = NULL;
int isVirtual = (md->mode & eModifierMode_Virtual);
char str[128];
@@ -870,7 +862,11 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
uiBlockSetEmboss(block, UI_EMBOSS);
/* modifier name */
+ if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ uiLayoutSetRedAlert(row, true);
+ }
uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
+ uiLayoutSetRedAlert(row, false);
/* mode enabling buttons */
uiBlockBeginAlign(block);
@@ -881,39 +877,32 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
- if (mti->flags & eModifierTypeFlag_SupportsEditmode)
- uiItemR(row, &ptr, "show_in_editmode", 0, "", ICON_NONE);
+ if (mti->flags & eModifierTypeFlag_SupportsEditmode) {
+ sub = uiLayoutRow(row, true);
+ if (!(md->mode & eModifierMode_Realtime)) {
+ uiLayoutSetActive(sub, false);
+ }
+ uiItemR(sub, &ptr, "show_in_editmode", 0, "", ICON_NONE);
+ }
}
if (ob->type == OB_MESH) {
- if (modifier_couldBeCage(scene, md) && (index <= lastCageIndex)) {
- /* -- convert to rna ? */
- but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0,
- UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0,
- TIP_("Apply modifier to editing cage during Edit mode"));
- if (index < cageIndex)
- uiButSetFlag(but, UI_BUT_DISABLED);
- uiButSetFunc(but, modifiers_setOnCage, ob, md);
- }
- else if (modifier_supportsCage(scene, md) && (index <= lastCageIndex)) {
- uiBlockEndAlign(block);
-
- /* place holder button */
- uiBlockSetEmboss(block, UI_EMBOSSN);
- but = uiDefIconBut(block, BUT, 0, ICON_NONE, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, NULL);
- uiButSetFlag(but, UI_BUT_DISABLED);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ if (modifier_supportsCage(scene, md) && (index <= lastCageIndex)) {
+ sub = uiLayoutRow(row, true);
+ if (index < cageIndex || !modifier_couldBeCage(scene, md)) {
+ uiLayoutSetActive(sub, false);
+ }
+ uiItemR(sub, &ptr, "show_on_cage", 0, "", ICON_NONE);
}
} /* tessellation point for curve-typed objects */
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
/* some modifiers could work with pre-tessellated curves only */
- if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
+ if (ELEM(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
/* add disabled pre-tessellated button, so users could have
* message for this modifiers */
but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0,
UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0,
- TIP_("This modifier could be applied on splines' points only"));
+ TIP_("This modifier can only be applied on splines' points"));
uiButSetFlag(but, UI_BUT_DISABLED);
}
else if (mti->type != eModifierTypeType_Constructive) {
@@ -979,7 +968,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
uiBlockClearButLock(block);
uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
- if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem,
+ if (!ELEM(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem,
eModifierType_Cloth, eModifierType_Smoke))
{
uiItemO(row, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"), ICON_NONE,
@@ -1298,7 +1287,7 @@ void uiTemplatePreview(uiLayout *layout, bContext *C, ID *id, int show_buttons,
char _preview_id[UI_MAX_NAME_STR];
- if (id && !ELEM5(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA, ID_LS)) {
+ if (id && !ELEM(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA, ID_LS)) {
RNA_warning("Expected ID of type material, texture, lamp, world or line style");
return;
}
@@ -1525,7 +1514,15 @@ static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand
row = uiLayoutRow(split, false);
- uiItemR(row, &ptr, "interpolation", 0, "", ICON_NONE);
+ uiBlockBeginAlign(block);
+ uiItemR(row, &ptr, "color_mode", 0, "", ICON_NONE);
+ if (ELEM(coba->color_mode, COLBAND_BLEND_HSV, COLBAND_BLEND_HSL)) {
+ uiItemR(row, &ptr, "hue_interpolation", 0, "", ICON_NONE);
+ }
+ else { /* COLBAND_BLEND_RGB */
+ uiItemR(row, &ptr, "interpolation", 0, "", ICON_NONE);
+ }
+ uiBlockEndAlign(block);
row = uiLayoutRow(layout, false);
@@ -1563,7 +1560,7 @@ static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand
uiDefButS(block, NUM, 0, "", 0, 0, 5.0f * UI_UNIT_X, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)),
0, 0, TIP_("Choose active color stop"));
row = uiLayoutRow(subsplit, false);
- uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE);
+ uiItemR(row, &ptr, "position", UI_ITEM_R_SLIDER, IFACE_("Pos"), ICON_NONE);
bt = block->buttons.last;
uiButSetFunc(bt, colorband_update_cb, bt, coba);
@@ -2363,6 +2360,61 @@ void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propna
}
}
+void uiTemplatePalette(uiLayout *layout, PointerRNA *ptr, const char *propname, int UNUSED(colors))
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ PointerRNA cptr;
+ Palette *palette;
+ PaletteColor *color;
+ uiBlock *block;
+ uiLayout *col;
+ int row_cols = 0, col_id = 0;
+ int cols_per_row = MAX2(uiLayoutGetWidth(layout) / UI_UNIT_X, 1);
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ cptr = RNA_property_pointer_get(ptr, prop);
+ if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Palette))
+ return;
+
+ block = uiLayoutGetBlock(layout);
+
+ palette = cptr.data;
+
+ /* first delete any pending colors */
+ BKE_palette_cleanup(palette);
+
+ color = palette->colors.first;
+
+ col = uiLayoutColumn(layout, true);
+ uiLayoutRow(col, true);
+ uiDefIconButO(block, BUT, "PALETTE_OT_color_add", WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ uiDefIconButO(block, BUT, "PALETTE_OT_color_delete", WM_OP_INVOKE_DEFAULT, ICON_ZOOMOUT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+
+ col = uiLayoutColumn(layout, true);
+ uiLayoutRow(col, true);
+
+ for (; color; color = color->next) {
+ PointerRNA ptr;
+
+ if (row_cols >= cols_per_row) {
+ uiLayoutRow(col, true);
+ row_cols = 0;
+ }
+
+ RNA_pointer_create(&palette->id, &RNA_PaletteColor, color, &ptr);
+ uiDefButR(block, COLOR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, &ptr, "color", -1, 0.0, 1.0,
+ UI_PALETTE_COLOR, (col_id == palette->active_color) ? UI_PALETTE_COLOR_ACTIVE : 0.0, "");
+
+ row_cols++;
+ col_id++;
+ }
+}
+
+
/********************* Layer Buttons Template ************************/
static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
@@ -2593,8 +2645,8 @@ static void uilist_filter_items_default(struct uiList *ui_list, struct bContext
const char *filter_raw = ui_list->filter_byname;
char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = NULL;
- bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
- bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_ALPHA) != 0;
+ const bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
+ const bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_ALPHA) != 0;
int len = RNA_property_collection_length(dataptr, prop);
dyn_data->items_shown = dyn_data->items_len = len;
@@ -2903,8 +2955,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
/* Filter list items! (not for compact layout, though) */
if (dataptr->data && prop) {
- int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
- bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0;
+ const int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
+ const bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0;
int items_shown, idx = 0;
#if 0
int prev_ii = -1, prev_i;
@@ -3188,7 +3240,7 @@ static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2)
wmOperatorType *ot = arg2;
if (ot)
- WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL);
}
static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items)
@@ -3443,13 +3495,9 @@ static void template_keymap_item_properties(uiLayout *layout, const char *title,
RNA_STRUCT_BEGIN (ptr, prop)
{
- int flag = RNA_property_flag(prop);
- bool is_set = RNA_property_is_set(ptr, prop);
+ const bool is_set = RNA_property_is_set(ptr, prop);
uiBut *but;
- if (flag & PROP_HIDDEN)
- continue;
-
/* recurse for nested properties */
if (RNA_property_type(prop) == PROP_POINTER) {
PointerRNA propptr = RNA_property_pointer_get(ptr, prop);
@@ -3543,7 +3591,7 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), P
col = uiLayoutColumn(layout, false);
row = uiLayoutRow(col, false);
- uiItemR(row, &view_transform_ptr, "view_transform", UI_ITEM_R_EXPAND, IFACE_("View"), ICON_NONE);
+ uiItemR(row, &view_transform_ptr, "view_transform", 0, IFACE_("View"), ICON_NONE);
col = uiLayoutColumn(layout, false);
uiItemR(col, &view_transform_ptr, "exposure", 0, NULL, ICON_NONE);
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 744ed7e5b72..008ea84b607 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -151,7 +151,7 @@ int uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr,
const char *name;
int tot = 0;
- assert(ELEM3(label_align, '\0', 'H', 'V'));
+ assert(ELEM(label_align, '\0', 'H', 'V'));
RNA_STRUCT_BEGIN (ptr, prop)
{
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 1a614bc7012..6d497fa474c 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -33,6 +33,7 @@
#include <string.h>
#include <assert.h>
+#include "DNA_brush_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
@@ -845,7 +846,7 @@ static void widget_draw_icon(const uiBut *but, BIFIconID icon, float alpha, cons
height = ICON_DEFAULT_HEIGHT / aspect;
/* calculate blend color */
- if (ELEM4(but->type, TOG, ROW, TOGN, LISTROW)) {
+ if (ELEM(but->type, TOG, ROW, TOGN, LISTROW)) {
if (but->flag & UI_SELECT) {}
else if (but->flag & UI_ACTIVE) {}
else alpha = 0.5f;
@@ -918,45 +919,12 @@ static void ui_text_clip_give_next_off(uiBut *but, const char *str)
but->ofs += bytes;
}
-/**
- * Cut off the start of the text to fit into the width of \a rect
- *
- * \note Sets but->ofs to make sure text is correctly visible.
- * \note Clips right in some cases, this function could be cleaned up.
- */
-static void ui_text_clip_left(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
-{
- /* We are not supposed to use labels with that clipping, so we can always apply margins. */
- const int border = (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
- const int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0);
-
- /* need to set this first */
- uiStyleFontSet(fstyle);
-
- if (fstyle->kerning == 1) /* for BLF_width */
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
-
- but->ofs = 0;
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr, sizeof(but->drawstr));
-
- if ((okwidth > 0.0f) && (but->strwidth > okwidth)) {
- float strwidth;
- but->ofs = BLF_width_to_rstrlen(fstyle->uifont_id, but->drawstr,
- sizeof(but->drawstr), okwidth, &strwidth);
- but->strwidth = strwidth;
- }
-
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
-}
-
/* Helper.
* This func assumes things like kerning handling have already been handled!
* Return the length of modified (right-clipped + ellipsis) string.
*/
static void ui_text_clip_right_ex(uiFontStyle *fstyle, char *str, const size_t max_len, const float okwidth,
- const char *sep, const int sep_len, const float sep_strwidth)
+ const char *sep, const int sep_len, const float sep_strwidth, size_t *r_final_len)
{
float tmp;
int l_end;
@@ -969,19 +937,27 @@ static void ui_text_clip_right_ex(uiFontStyle *fstyle, char *str, const size_t m
if (sep_strwidth / okwidth > 0.2f) {
l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, &tmp);
str[l_end] = '\0';
+ if (r_final_len) {
+ *r_final_len = (size_t)l_end;
+ }
}
else {
l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth - sep_strwidth, &tmp);
memcpy(str + l_end, sep, sep_len + 1); /* +1 for trailing '\0'. */
+ if (r_final_len) {
+ *r_final_len = (size_t)(l_end + sep_len);
+ }
}
}
/**
* Cut off the middle of the text to fit into the given width.
* Note in case this middle clipping would just remove a few chars, it rather clips right, which is more readable.
+ * If rpart_sep is not Null, the part of str starting to first occurrence of rpart_sep is preserved at all cost (useful
+ * for strings with shortcuts, like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O').
*/
-static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, const float okwidth, const float minwidth,
- const size_t max_len)
+static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, float okwidth, const float minwidth,
+ const size_t max_len, const char *rpart_sep)
{
float strwidth;
@@ -1000,37 +976,76 @@ static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, const float
/* utf8 ellipsis '...', some compilers complain */
const char sep[] = {0xe2, 0x80, 0xa6, 0x0};
const int sep_len = sizeof(sep) - 1;
+ const float sep_strwidth = BLF_width(fstyle->uifont_id, sep, sep_len + 1);
+ float parts_strwidth;
size_t l_end;
- const float sep_strwidth = BLF_width(fstyle->uifont_id, sep, sep_len + 1);
- const float parts_strwidth = ((float)okwidth - sep_strwidth) / 2.0f;
+ char *rpart = NULL, rpart_buf[UI_MAX_DRAW_STR];
+ float rpart_width = 0.0f;
+ size_t rpart_len = 0;
+ size_t final_lpart_len;
+
+ if (rpart_sep) {
+ rpart = strstr(str, rpart_sep);
+
+ if (rpart) {
+ rpart_len = strlen(rpart);
+ rpart_width = BLF_width(fstyle->uifont_id, rpart, rpart_len);
+ okwidth -= rpart_width;
+ strwidth -= rpart_width;
+
+ if (okwidth < 0.0f) {
+ /* Not enough place for actual label, just display protected right part.
+ * Here just for safety, should never happen in real life! */
+ memmove(str, rpart, rpart_len + 1);
+ rpart = NULL;
+ okwidth += rpart_width;
+ strwidth = rpart_width;
+ }
+ }
+ }
+
+ parts_strwidth = (okwidth - sep_strwidth) / 2.0f;
+
+ if (rpart) {
+ strcpy(rpart_buf, rpart);
+ *rpart = '\0';
+ rpart = rpart_buf;
+ }
- if (min_ff(parts_strwidth, strwidth - okwidth) < minwidth) {
+ l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, parts_strwidth, &rpart_width);
+ if (l_end < 10 || min_ff(parts_strwidth, strwidth - okwidth) < minwidth) {
/* If we really have no place, or we would clip a very small piece of string in the middle,
* only show start of string.
*/
- ui_text_clip_right_ex(fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth);
+ ui_text_clip_right_ex(fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len);
}
else {
size_t r_offset, r_len;
- l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, parts_strwidth, &strwidth);
- r_offset = BLF_width_to_rstrlen(fstyle->uifont_id, str, max_len, parts_strwidth, &strwidth);
- r_len = strlen(str + r_offset) + 1; /* +1 for the trailing '\0'... */
+ r_offset = BLF_width_to_rstrlen(fstyle->uifont_id, str, max_len, parts_strwidth, &rpart_width);
+ r_len = strlen(str + r_offset) + 1; /* +1 for the trailing '\0'. */
- if (l_end + sep_len + r_len > max_len) {
+ if (l_end + sep_len + r_len + rpart_len > max_len) {
/* Corner case, the str already takes all available mem, and the ellipsis chars would actually
* add more chars...
* Better to just trim one or two letters to the right in this case...
* Note: with a single-char ellipsis, this should never happen! But better be safe here...
*/
- ui_text_clip_right_ex(fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth);
+ ui_text_clip_right_ex(fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len);
}
else {
memmove(str + l_end + sep_len, str + r_offset, r_len);
memcpy(str + l_end, sep, sep_len);
+ final_lpart_len = (size_t)(l_end + sep_len + r_len - 1); /* -1 to remove trailing '\0'! */
}
}
+
+ if (rpart) {
+ /* Add back preserved right part to our shorten str. */
+ memcpy(str + final_lpart_len, rpart, rpart_len + 1); /* +1 for trailing '\0'. */
+ }
+
strwidth = BLF_width(fstyle->uifont_id, str, max_len);
}
@@ -1041,6 +1056,9 @@ static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, const float
return strwidth;
}
+/**
+ * Wrapper around ui_text_clip_middle_ex.
+ */
static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
{
/* No margin for labels! */
@@ -1050,7 +1068,23 @@ static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rec
const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
but->ofs = 0;
- but->strwidth = ui_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len);
+ but->strwidth = ui_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, NULL);
+}
+
+/**
+ * Like ui_text_clip_middle(), but protect/preserve at all cost the right part of the string after sep.
+ * Useful for strings with shortcuts (like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O').
+ */
+static void ui_text_clip_middle_protect_right(uiFontStyle *fstyle, uiBut *but, const rcti *rect, const char *rsep)
+{
+ /* No margin for labels! */
+ const int border = ELEM(but->type, LABEL, MENU) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
+ const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
+ const size_t max_len = sizeof(but->drawstr);
+ const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
+
+ but->ofs = 0;
+ but->strwidth = ui_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep);
}
/**
@@ -1427,14 +1461,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
else if (ELEM(but->type, NUM, NUMSLI)) {
ui_text_clip_right_label(fstyle, but, rect);
}
-#if 0
- /* Special hack for non-embossed TEX buttons in uiList (we want them to behave as much as possible as labels). */
- else if ((but->type == TEX) && (but->flag & UI_BUT_LIST_ITEM) && (but->dt & UI_EMBOSSN)) {
- but->ofs = 0;
- }
-#endif
else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == BUT)) {
- ui_text_clip_left(fstyle, but, rect);
+ /* Clip middle, but protect in all case right part containing the shortcut, if any. */
+ ui_text_clip_middle_protect_right(fstyle, but, rect, "|");
}
else {
ui_text_clip_middle(fstyle, but, rect);
@@ -1592,6 +1621,21 @@ static struct uiWidgetColors wcol_menu_back = {
25, -20
};
+/* pie menus */
+static struct uiWidgetColors wcol_pie_menu = {
+ {10, 10, 10, 200},
+ {25, 25, 25, 230},
+ {140, 140, 140, 255},
+ {45, 45, 45, 230},
+
+ {160, 160, 160, 255},
+ {255, 255, 255, 255},
+
+ 1,
+ 10, -10
+};
+
+
/* tooltip color */
static struct uiWidgetColors wcol_tooltip = {
{0, 0, 0, 255},
@@ -1739,6 +1783,7 @@ void ui_widget_color_init(ThemeUI *tui)
tui->wcol_menu = wcol_menu;
tui->wcol_pulldown = wcol_pulldown;
tui->wcol_menu_back = wcol_menu_back;
+ tui->wcol_pie_menu = wcol_pie_menu;
tui->wcol_tooltip = wcol_tooltip;
tui->wcol_menu_item = wcol_menu_item;
tui->wcol_box = wcol_box;
@@ -1887,6 +1932,34 @@ static void widget_state_pulldown(uiWidgetType *wt, int state)
copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
}
+/* special case, pie menu items */
+static void widget_state_pie_menu_item(uiWidgetType *wt, int state)
+{
+ wt->wcol = *(wt->wcol_theme);
+
+ /* active and disabled (not so common) */
+ if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) {
+ widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f);
+ /* draw the backdrop at low alpha, helps navigating with keys
+ * when disabled items are active */
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
+ wt->wcol.inner[3] = 64;
+ }
+ /* regular disabled */
+ else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
+ }
+ /* regular active */
+ else if (state & UI_SELECT) {
+ copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel);
+ copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ }
+ else if (state & UI_ACTIVE) {
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
+ copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ }
+}
+
/* special case, menu items */
static void widget_state_menu_item(uiWidgetType *wt, int state)
{
@@ -2822,6 +2895,17 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
widgetbase_draw(&wtb, wcol);
+ if (but->a1 == UI_PALETTE_COLOR && but->a2 == UI_PALETTE_COLOR_ACTIVE) {
+ float width = rect->xmax - rect->xmin;
+ float height = rect->ymax - rect->ymin;
+
+ glColor4ubv((unsigned char *)wcol->outline);
+ glBegin(GL_TRIANGLES);
+ glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.9f * height);
+ glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.5f * height);
+ glVertex2f(rect->xmin + 0.5f * width, rect->ymin + 0.9f * height);
+ glEnd();
+ }
}
static void widget_normal(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
@@ -2958,6 +3042,29 @@ static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(sta
widgetbase_draw(&wtb, wcol);
}
+static void widget_menu_radial_itembut(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
+{
+ uiWidgetBase wtb;
+ float rad;
+ float fac = but->block->pie_data.alphafac;
+
+ widget_init(&wtb);
+
+ wtb.emboss = 0;
+
+ rad = 0.5f * BLI_rcti_size_y(rect);
+ round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
+
+ wcol->inner[3] *= fac;
+ wcol->inner_sel[3] *= fac;
+ wcol->item[3] *= fac;
+ wcol->text[3] *= fac;
+ wcol->text_sel[3] *= fac;
+ wcol->outline[3] *= fac;
+
+ widgetbase_draw(&wtb, wcol);
+}
+
static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
{
uiWidgetBase wtb;
@@ -3276,6 +3383,12 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.wcol_theme = &btheme->tui.wcol_progress;
wt.custom = widget_progressbar;
break;
+
+ case UI_WTYPE_MENU_ITEM_RADIAL:
+ wt.wcol_theme = &btheme->tui.wcol_pie_menu;
+ wt.custom = widget_menu_radial_itembut;
+ wt.state = widget_state_pie_menu_item;
+ break;
}
return &wt;
@@ -3382,6 +3495,9 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
/* "nothing" */
wt = widget_type(UI_WTYPE_ICON);
}
+ else if (but->dt == UI_EMBOSSR) {
+ wt = widget_type(UI_WTYPE_MENU_ITEM_RADIAL);
+ }
else {
switch (but->type) {
@@ -3634,6 +3750,125 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
}
}
+static void draw_disk_shaded(
+ float start, float angle,
+ float radius_int, float radius_ext, int subd,
+ const char col1[4], const char col2[4],
+ bool shaded)
+{
+ const float radius_ext_scale = (0.5f / radius_ext); /* 1 / (2 * radius_ext) */
+ int i;
+
+ float s, c;
+ float y1, y2;
+ float fac;
+ unsigned char r_col[4];
+
+ glBegin(GL_TRIANGLE_STRIP);
+
+ s = sinf(start);
+ c = cosf(start);
+
+ y1 = s * radius_int;
+ y2 = s * radius_ext;
+
+ if (shaded) {
+ fac = (y1 + radius_ext) * radius_ext_scale;
+ round_box_shade_col4_r(r_col, col1, col2, fac);
+
+ glColor4ubv(r_col);
+ }
+
+ glVertex2f(c * radius_int, s * radius_int);
+
+ if (shaded) {
+ fac = (y2 + radius_ext) * radius_ext_scale;
+ round_box_shade_col4_r(r_col, col1, col2, fac);
+
+ glColor4ubv(r_col);
+ }
+ glVertex2f(c * radius_ext, s * radius_ext);
+
+ for (i = 1; i < subd; i++) {
+ float a;
+
+ a = start + ((i) / (float)(subd - 1)) * angle;
+ s = sinf(a);
+ c = cosf(a);
+ y1 = s * radius_int;
+ y2 = s * radius_ext;
+
+ if (shaded) {
+ fac = (y1 + radius_ext) * radius_ext_scale;
+ round_box_shade_col4_r(r_col, col1, col2, fac);
+
+ glColor4ubv(r_col);
+ }
+ glVertex2f(c * radius_int, s * radius_int);
+
+ if (shaded) {
+ fac = (y2 + radius_ext) * radius_ext_scale;
+ round_box_shade_col4_r(r_col, col1, col2, fac);
+
+ glColor4ubv(r_col);
+ }
+ glVertex2f(c * radius_ext, s * radius_ext);
+ }
+ glEnd();
+
+}
+
+void ui_draw_pie_center(uiBlock *block)
+{
+ bTheme *btheme = UI_GetTheme();
+ float cx = block->pie_data.pie_center_spawned[0];
+ float cy = block->pie_data.pie_center_spawned[1];
+
+ float *pie_dir = block->pie_data.pie_dir;
+
+ float pie_radius_internal = U.pixelsize * U.pie_menu_threshold;
+ float pie_radius_external = U.pixelsize * (U.pie_menu_threshold + 7.0f);
+
+ int subd = 40;
+
+ float angle = atan2(pie_dir[1], pie_dir[0]);
+ float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? ((float)M_PI / 2.0f) : ((float)M_PI / 4.0f);
+
+ glPushMatrix();
+ glTranslatef(cx, cy, 0.0f);
+
+ glEnable(GL_BLEND);
+ if (btheme->tui.wcol_pie_menu.shaded) {
+ char col1[4], col2[4];
+ shadecolors4(col1, col2, btheme->tui.wcol_pie_menu.inner, btheme->tui.wcol_pie_menu.shadetop, btheme->tui.wcol_pie_menu.shadedown);
+ draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, col1, col2, true);
+ }
+ else {
+ glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner);
+ draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, NULL, NULL, false);
+ }
+
+ if (!(block->pie_data.flags & UI_PIE_INVALID_DIR)) {
+ if (btheme->tui.wcol_pie_menu.shaded) {
+ char col1[4], col2[4];
+ shadecolors4(col1, col2, btheme->tui.wcol_pie_menu.inner_sel, btheme->tui.wcol_pie_menu.shadetop, btheme->tui.wcol_pie_menu.shadedown);
+ draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, col1, col2, true);
+ }
+ else {
+ glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner_sel);
+ draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, NULL, NULL, false);
+ }
+ }
+
+ glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.outline);
+ glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_internal, subd);
+ glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_external, subd);
+
+ glDisable(GL_BLEND);
+ glPopMatrix();
+}
+
+
uiWidgetColors *ui_tooltip_get_theme(void)
{
uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
@@ -3711,7 +3946,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
const float minwidth = (float)(UI_DPI_ICON_SIZE);
BLI_strncpy(drawstr, name, sizeof(drawstr));
- ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len);
+ ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL);
glColor4ubv((unsigned char *)wt->wcol.text);
uiStyleFontDraw(fstyle, rect, drawstr);
@@ -3786,7 +4021,7 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
const float minwidth = (float)(UI_DPI_ICON_SIZE);
BLI_strncpy(drawstr, name, sizeof(drawstr));
- ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len);
+ ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL);
glColor4ubv((unsigned char *)wt->wcol.text);
uiStyleFontDraw(fstyle, &trect, drawstr);
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 372ced0a6fd..0879f335c68 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -36,11 +36,10 @@
#include "MEM_guardedalloc.h"
#include "DNA_curve_types.h"
-#include "DNA_userdef_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"
-#include "DNA_mesh_types.h" /* init_userdef_factory */
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -51,7 +50,6 @@
#include "BKE_main.h"
#include "BKE_texture.h"
-
#include "BIF_gl.h"
#include "UI_interface.h"
@@ -337,6 +335,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->normal; break;
case TH_VNORMAL:
cp = ts->vertex_normal; break;
+ case TH_LNORMAL:
+ cp = ts->loop_normal; break;
case TH_BONE_SOLID:
cp = ts->bone_solid; break;
case TH_BONE_POSE:
@@ -537,6 +537,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->preview_stitch_active;
break;
+ case TH_PAINT_CURVE_HANDLE:
+ cp = ts->paint_curve_handle;
+ break;
+ case TH_PAINT_CURVE_PIVOT:
+ cp = ts->paint_curve_pivot;
+ break;
+
case TH_UV_OTHERS:
cp = ts->uv_others;
break;
@@ -774,6 +781,8 @@ static void ui_theme_space_init_handles_color(ThemeSpace *theme_space)
rgba_char_args_set(theme_space->handle_sel_auto, 0xf0, 0xff, 0x40, 255);
rgba_char_args_set(theme_space->handle_sel_vect, 0x40, 0xc0, 0x30, 255);
rgba_char_args_set(theme_space->handle_sel_align, 0xf0, 0x90, 0xa0, 255);
+ rgba_char_args_set(theme_space->handle_vertex, 0x00, 0x00, 0x00, 0xff);
+ rgba_char_args_set(theme_space->handle_vertex_select, 0xff, 0xff, 0, 0xff);
rgba_char_args_set(theme_space->act_spline, 0xdb, 0x25, 0x12, 255);
}
@@ -859,6 +868,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tv3d.face_select, 255, 133, 0, 60);
rgba_char_args_set(btheme->tv3d.normal, 0x22, 0xDD, 0xDD, 255);
rgba_char_args_set(btheme->tv3d.vertex_normal, 0x23, 0x61, 0xDD, 255);
+ rgba_char_args_set(btheme->tv3d.loop_normal, 0xDD, 0x23, 0xDD, 255);
rgba_char_args_set(btheme->tv3d.face_dot, 255, 133, 0, 255);
rgba_char_args_set(btheme->tv3d.editmesh_active, 255, 255, 255, 128);
rgba_char_args_set_fl(btheme->tv3d.edge_crease, 0.8, 0, 0.6, 1.0);
@@ -871,6 +881,8 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tv3d.title, 0, 0, 0, 255);
rgba_char_args_set(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255);
rgba_char_args_set(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51);
+ rgba_char_args_set_fl(btheme->tv3d.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
+ rgba_char_args_set_fl(btheme->tv3d.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
btheme->tv3d.facedot_size = 4;
@@ -1129,8 +1141,6 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tclip.path_after, 0x00, 0x00, 0xff, 255);
rgba_char_args_set(btheme->tclip.grid, 0x5e, 0x5e, 0x5e, 255);
rgba_char_args_set(btheme->tclip.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tclip.handle_vertex, 0x00, 0x00, 0x00, 0xff);
- rgba_char_args_set(btheme->tclip.handle_vertex_select, 0xff, 0xff, 0, 0xff);
rgba_char_args_set(btheme->tclip.list, 0x66, 0x66, 0x66, 0xff);
rgba_char_args_set(btheme->tclip.strip, 0x0c, 0x0a, 0x0a, 0x80);
rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff);
@@ -2427,9 +2437,39 @@ void init_userdef_do_versions(void)
}
}
- {
+ if (U.versionfile < 272 || (U.versionfile == 272 && U.subversionfile < 2)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_set_fl(btheme->tv3d.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
+ rgba_char_args_set_fl(btheme->tv3d.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
+ rgba_char_args_set_fl(btheme->tima.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
+ rgba_char_args_set_fl(btheme->tima.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
+ }
+ }
+
+ if (U.versionfile < 271 || (U.versionfile == 271 && U.subversionfile < 5)) {
bTheme *btheme;
+
+ struct uiWidgetColors wcol_pie_menu = {
+ {10, 10, 10, 200},
+ {25, 25, 25, 230},
+ {140, 140, 140, 255},
+ {45, 45, 45, 230},
+
+ {160, 160, 160, 255},
+ {255, 255, 255, 255},
+
+ 1,
+ 10, -10
+ };
+
+ U.pie_menu_radius = 100;
+ U.pie_menu_threshold = 12;
+ U.pie_animation_timeout = 6;
+
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ btheme->tui.wcol_pie_menu = wcol_pie_menu;
+
ui_theme_space_init_handles_color(&btheme->tclip);
ui_theme_space_init_handles_color(&btheme->tima);
btheme->tima.handle_vertex_size = 5;
@@ -2437,6 +2477,16 @@ void init_userdef_do_versions(void)
}
}
+ if (U.versionfile < 271 || (U.versionfile == 271 && U.subversionfile < 6)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ /* check for (alpha == 0) is safe, then color was never set */
+ if (btheme->tv3d.loop_normal[3] == 0) {
+ rgba_char_args_set(btheme->tv3d.loop_normal, 0xDD, 0x23, 0xDD, 255);
+ }
+ }
+ }
+
if (U.pixelsize == 0.0f)
U.pixelsize = 1.0f;
@@ -2449,25 +2499,3 @@ void init_userdef_do_versions(void)
// XXX reset_autosave();
}
-
-/**
- * Override values in in-memory startup.blend, avoids resaving for small changes.
- */
-void init_userdef_factory(void)
-{
- /* defaults from T37518 */
-
- U.uiflag |= USER_ZBUF_CURSOR;
- U.uiflag |= USER_QUIT_PROMPT;
- U.uiflag |= USER_CONTINUOUS_MOUSE;
-
- U.versions = 1;
- U.savetime = 2;
-
- {
- Mesh *me;
- for (me = G.main->mesh.first; me; me = me->id.next) {
- me->flag &= ~ME_TWOSIDED;
- }
- }
-}
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 45dd47097f5..ccc6f6de94e 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -384,7 +384,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_
* - cur must not fall outside of tot
* - axis locks (zoom and offset) must be maintained
* - zoom must not be excessive (check either sizes or zoom values)
- * - aspect ratio should be respected (NOTE: this is quite closely realted to zoom too)
+ * - aspect ratio should be respected (NOTE: this is quite closely related to zoom too)
*/
/* Step 1: if keepzoom, adjust the sizes of the rects only
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index e30c6ca61ba..2b84c0678ae 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -767,6 +767,8 @@ static int view_zoomin_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void VIEW2D_OT_zoom_in(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Zoom In";
ot->description = "Zoom in the view";
@@ -778,10 +780,12 @@ static void VIEW2D_OT_zoom_in(wmOperatorType *ot)
ot->poll = view_zoom_poll;
/* rna - must keep these in sync with the other operators */
- RNA_def_float(ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX);
- RNA_def_float(ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX);
+ prop = RNA_def_float(ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_float(ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
-
+
/* this operator only needs this single callback, where it calls the view_zoom_*() methods */
static int view_zoomout_exec(bContext *C, wmOperator *op)
{
@@ -828,6 +832,8 @@ static int view_zoomout_invoke(bContext *C, wmOperator *op, const wmEvent *event
static void VIEW2D_OT_zoom_out(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Zoom Out";
ot->description = "Zoom out the view";
@@ -839,8 +845,10 @@ static void VIEW2D_OT_zoom_out(wmOperatorType *ot)
ot->poll = view_zoom_poll;
/* rna - must keep these in sync with the other operators */
- RNA_def_float(ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX);
- RNA_def_float(ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX);
+ prop = RNA_def_float(ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_float(ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* ********************************************************* */
@@ -1139,6 +1147,7 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event
static void VIEW2D_OT_zoom(wmOperatorType *ot)
{
+ PropertyRNA *prop;
/* identifiers */
ot->name = "Zoom 2D View";
ot->description = "Zoom in/out the view";
@@ -1156,8 +1165,10 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
/* rna - must keep these in sync with the other operators */
- RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX);
- RNA_def_float(ot->srna, "deltay", 0, -FLT_MAX, FLT_MAX, "Delta Y", "", -FLT_MAX, FLT_MAX);
+ prop = RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_float(ot->srna, "deltay", 0, -FLT_MAX, FLT_MAX, "Delta Y", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* ********************************************************* */
@@ -1522,6 +1533,7 @@ typedef struct v2dScrollerMove {
short zone; /* -1 is min zoomer, 0 is bar, 1 is max zoomer */ // XXX find some way to provide visual feedback of this (active color?)
float fac; /* view adjustment factor, based on size of region */
+ float fac_round; /* for pixel rounding (avoid visible UI jitter) */
float delta; /* amount moved by mouse on axis of interest */
float scrollbarwidth; /* width of the scrollbar itself, used for page up/down clicks */
@@ -1560,7 +1572,7 @@ enum {
*/
static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_min, int sh_max)
{
- short in_min, in_max, in_bar, out_min, out_max, in_view = 1;
+ bool in_min, in_max, in_bar, out_min, out_max, in_view = 1;
/* firstly, check if
* - 'bubble' fills entire scroller
@@ -1583,9 +1595,9 @@ static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_
/* check if mouse is in or past either handle */
/* TODO: check if these extents are still valid or not */
- in_max = ( (mouse >= (sh_max - V2D_SCROLLER_HANDLE_SIZE)) && (mouse <= (sh_max + V2D_SCROLLER_HANDLE_SIZE)) );
- in_min = ( (mouse <= (sh_min + V2D_SCROLLER_HANDLE_SIZE)) && (mouse >= (sh_min - V2D_SCROLLER_HANDLE_SIZE)) );
- in_bar = ( (mouse < (sh_max - V2D_SCROLLER_HANDLE_SIZE)) && (mouse > (sh_min + V2D_SCROLLER_HANDLE_SIZE)) );
+ in_max = ((mouse >= (sh_max - V2D_SCROLLER_HANDLE_SIZE)) && (mouse <= (sh_max + V2D_SCROLLER_HANDLE_SIZE)));
+ in_min = ((mouse <= (sh_min + V2D_SCROLLER_HANDLE_SIZE)) && (mouse >= (sh_min - V2D_SCROLLER_HANDLE_SIZE)));
+ in_bar = ((mouse < (sh_max - V2D_SCROLLER_HANDLE_SIZE)) && (mouse > (sh_min + V2D_SCROLLER_HANDLE_SIZE)));
out_min = mouse < (sh_min - V2D_SCROLLER_HANDLE_SIZE);
out_max = mouse > (sh_max + V2D_SCROLLER_HANDLE_SIZE);
@@ -1640,7 +1652,10 @@ static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *e
/* horizontal scroller - calculate adjustment factor first */
mask_size = (float)BLI_rcti_size_x(&v2d->hor);
vsm->fac = BLI_rctf_size_x(&tot_cur_union) / mask_size;
-
+
+ /* pixel rounding */
+ vsm->fac_round = (BLI_rctf_size_x(&v2d->cur)) / (float)(BLI_rcti_size_x(&ar->winrct) + 1);
+
/* get 'zone' (i.e. which part of scroller is activated) */
vsm->zone = mouse_in_scroller_handle(event->mval[0],
v2d->hor.xmin, v2d->hor.xmax,
@@ -1659,6 +1674,9 @@ static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *e
mask_size = (float)BLI_rcti_size_y(&v2d->vert);
vsm->fac = BLI_rctf_size_y(&tot_cur_union) / mask_size;
+ /* pixel rounding */
+ vsm->fac_round = (BLI_rctf_size_y(&v2d->cur)) / (float)(BLI_rcti_size_y(&ar->winrct) + 1);
+
/* get 'zone' (i.e. which part of scroller is activated) */
vsm->zone = mouse_in_scroller_handle(event->mval[1],
v2d->vert.ymin, v2d->vert.ymax,
@@ -1706,6 +1724,9 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
/* calculate amount to move view by */
temp = vsm->fac * vsm->delta;
+
+ /* round to pixel */
+ temp = roundf(temp / vsm->fac_round) * vsm->fac_round;
/* type of movement */
switch (vsm->zone) {
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 4d2ea0e64f4..a4130540b1b 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -250,7 +250,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
- uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
+ uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE);
row = uiLayoutRow(box, false);
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 25888a5fef0..8018d549b09 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -133,9 +133,12 @@ static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float c
}
static void draw_circle(const float x, const float y,
- const float size, const float xscale, const float yscale)
+ const float size, const bool fill,
+ const float xscale, const float yscale)
{
- static GLuint displist = 0;
+ static GLuint wire_displist = 0;
+ static GLuint fill_displist = 0;
+ GLuint displist = fill ? fill_displist : wire_displist;
/* Initialize round circle shape. */
if (displist == 0) {
@@ -145,11 +148,18 @@ static void draw_circle(const float x, const float y,
glNewList(displist, GL_COMPILE);
qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+ gluQuadricDrawStyle(qobj, fill ? GLU_FILL : GLU_SILHOUETTE);
gluDisk(qobj, 0, 0.7, 8, 1);
gluDeleteQuadric(qobj);
glEndList();
+
+ if (fill) {
+ fill_displist = displist;
+ }
+ else {
+ wire_displist = displist;
+ }
}
glPushMatrix();
@@ -219,7 +229,7 @@ static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoin
UI_ThemeColor(TH_HANDLE_VERTEX);
}
- draw_circle(handle_pos[0], handle_pos[1], handle_size, xscale, yscale);
+ draw_circle(handle_pos[0], handle_pos[1], handle_size, false, xscale, yscale);
}
/* return non-zero if spline is selected */
@@ -237,6 +247,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
int i, handle_size, tot_feather_point;
float (*feather_points)[2], (*fp)[2];
+ float min[2], max[2];
if (!spline->tot_point)
return;
@@ -301,6 +312,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
}
/* control points */
+ INIT_MINMAX2(min, max);
for (i = 0; i < spline->tot_point; i++) {
/* watch it! this is intentionally not the deform array, only check for sel */
@@ -353,6 +365,25 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
glBegin(GL_POINTS);
glVertex2fv(vert);
glEnd();
+
+ minmax_v2v2_v2(min, max, vert);
+ }
+
+ if (is_spline_sel) {
+ float x = (min[0] + max[0]) / 2.0f;
+ float y = (min[1] + max[1]) / 2.0f;
+ /* TODO(sergey): Remove hardcoded colors. */
+ if (masklay->act_spline == spline) {
+ glColor3ub(255, 255, 255);
+ }
+ else {
+ glColor3ub(255, 255, 0);
+ }
+
+ draw_circle(x, y, 6.0f, true, xscale, yscale);
+
+ glColor3ub(0, 0, 0);
+ draw_circle(x, y, 6.0f, false, xscale, yscale);
}
glPointSize(1.0f);
@@ -801,13 +832,14 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
/* apply transformation so mask editing tools will assume drawing from the origin in normalized space */
glPushMatrix();
- glTranslatef(x + xofs, y + yofs, 0);
- glScalef(maxdim * zoomx, maxdim * zoomy, 0);
if (stabmat) {
glMultMatrixf(stabmat);
}
+ glTranslatef(x + xofs, y + yofs, 0);
+ glScalef(maxdim * zoomx, maxdim * zoomy, 0);
+
if (do_draw_cb) {
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
}
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index a882284f5e3..9f8388f1fe0 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -458,7 +458,8 @@ enum {
SLIDE_ACTION_NONE = 0,
SLIDE_ACTION_POINT = 1,
SLIDE_ACTION_HANDLE = 2,
- SLIDE_ACTION_FEATHER = 3
+ SLIDE_ACTION_FEATHER = 3,
+ SLIDE_ACTION_SPLINE = 4
};
typedef struct SlidePointData {
@@ -497,6 +498,96 @@ typedef struct SlidePointData {
float weight, weight_scalar;
} SlidePointData;
+static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float co[2])
+{
+ BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co);
+ ED_clip_point_undistorted_pos(sc, r_co, r_co);
+ BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
+}
+
+static bool spline_under_mouse_get(const bContext *C,
+ Mask *mask, const float co[2],
+ MaskLayer **mask_layer_r,
+ MaskSpline **mask_spline_r)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MaskLayer *mask_layer;
+ int width, height;
+ float pixel_co[2];
+ float closest_dist_squared;
+ MaskLayer *closest_layer = NULL;
+ MaskSpline *closest_spline = NULL;
+ bool undistort = false;
+ *mask_layer_r = NULL;
+ *mask_spline_r = NULL;
+ ED_mask_get_size(sa, &width, &height);
+ pixel_co[0] = co[0] * width;
+ pixel_co[1] = co[1] * height;
+ if (sc != NULL) {
+ undistort = (sc->clip != NULL) &&
+ (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
+ }
+ for (mask_layer = mask->masklayers.first;
+ mask_layer != NULL;
+ mask_layer = mask_layer->next)
+ {
+ MaskSpline *spline;
+ if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) {
+ continue;
+ }
+
+ for (spline = mask_layer->splines.first;
+ spline != NULL;
+ spline = spline->next)
+ {
+ MaskSplinePoint *points_array;
+ float min[2], max[2], center[2];
+ float dist_squared;
+ int i;
+ float max_bb_side;
+ if ((spline->flag & SELECT) == 0) {
+ continue;
+ }
+
+ points_array = BKE_mask_spline_point_array(spline);
+ INIT_MINMAX2(min, max);
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point_deform = &points_array[i];
+ BezTriple *bezt = &point_deform->bezt;
+
+ float vert[2];
+
+ copy_v2_v2(vert, bezt->vec[1]);
+
+ if (undistort) {
+ mask_point_undistort_pos(sc, vert, vert);
+ }
+
+ minmax_v2v2_v2(min, max, vert);
+ }
+
+ center[0] = (min[0] + max[0]) / 2.0f * width;
+ center[1] = (min[1] + max[1]) / 2.0f * height;
+ dist_squared = len_squared_v2v2(pixel_co, center);
+ max_bb_side = min_ff((max[0] - min[0]) * width, (max[1] - min[1]) * height);
+ if (dist_squared <= max_bb_side * max_bb_side * 0.5f &&
+ (closest_spline == NULL || dist_squared < closest_dist_squared))
+ {
+ closest_layer = mask_layer;
+ closest_spline = spline;
+ closest_dist_squared = dist_squared;
+ }
+ }
+ }
+ if (closest_spline != NULL) {
+ *mask_layer_r = closest_layer;
+ *mask_spline_r = closest_spline;
+ return true;
+ }
+ return false;
+}
+
static bool slide_point_check_initial_feather(MaskSpline *spline)
{
int i;
@@ -607,9 +698,14 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
point = cv_point;
}
- if (action != SLIDE_ACTION_NONE) {
- select_sliding_point(mask, masklay, spline, point, which_handle);
+ if (action == SLIDE_ACTION_NONE) {
+ if (spline_under_mouse_get(C, mask, co, &masklay, &spline)) {
+ action = SLIDE_ACTION_SPLINE;
+ point = NULL;
+ }
+ }
+ if (action != SLIDE_ACTION_NONE) {
customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data");
customdata->event_invoke_type = event->type;
customdata->mask = mask;
@@ -621,12 +717,14 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
customdata->action = action;
customdata->uw = uw;
- customdata->old_h1 = point->bezt.h1;
- customdata->old_h2 = point->bezt.h2;
-
customdata->is_sliding_new_point = RNA_boolean_get(op->ptr, "is_new_point");
- check_sliding_handle_type(point, which_handle);
+ if (customdata->action != SLIDE_ACTION_SPLINE) {
+ customdata->old_h1 = point->bezt.h1;
+ customdata->old_h2 = point->bezt.h2;
+ select_sliding_point(mask, masklay, spline, point, which_handle);
+ check_sliding_handle_type(point, which_handle);
+ }
if (uw) {
float co_uw[2];
@@ -639,7 +737,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
madd_v2_v2v2fl(customdata->prev_feather_coord, co_uw, customdata->no, uw->w * weight_scalar);
}
- else {
+ else if (customdata->action != SLIDE_ACTION_SPLINE) {
BezTriple *bezt = &point->bezt;
customdata->weight = bezt->weight;
@@ -653,10 +751,12 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
customdata->is_initial_feather = slide_point_check_initial_feather(spline);
}
- copy_m3_m3(customdata->vec, point->bezt.vec);
- if (which_handle != MASK_WHICH_HANDLE_NONE) {
- BKE_mask_point_handle(point, which_handle, customdata->orig_handle_coord);
- copy_v2_v2(customdata->prev_handle_coord, customdata->orig_handle_coord);
+ if (customdata->action != SLIDE_ACTION_SPLINE) {
+ copy_m3_m3(customdata->vec, point->bezt.vec);
+ if (which_handle != MASK_WHICH_HANDLE_NONE) {
+ BKE_mask_point_handle(point, which_handle, customdata->orig_handle_coord);
+ copy_v2_v2(customdata->prev_handle_coord, customdata->orig_handle_coord);
+ }
}
customdata->which_handle = which_handle;
@@ -738,7 +838,7 @@ static void cancel_slide_point(SlidePointData *data)
else
data->point->bezt.weight = data->weight;
}
- else {
+ else if (data->action != SLIDE_ACTION_SPLINE) {
copy_m3_m3(data->point->bezt.vec, data->vec);
data->point->bezt.h1 = data->old_h1;
data->point->bezt.h2 = data->old_h2;
@@ -935,6 +1035,20 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
copy_v2_v2(data->prev_feather_coord, offco);
}
}
+ else if (data->action == SLIDE_ACTION_SPLINE) {
+ int i;
+
+ if (data->orig_spline == NULL) {
+ data->orig_spline = BKE_mask_spline_copy(data->spline);
+ }
+
+ for (i = 0; i < data->spline->tot_point; i++) {
+ MaskSplinePoint *point = &data->spline->points[i];
+ add_v2_v2(point->bezt.vec[0], delta);
+ add_v2_v2(point->bezt.vec[1], delta);
+ add_v2_v2(point->bezt.vec[2], delta);
+ }
+ }
WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
DAG_id_tag_update(&data->mask->id, 0);
@@ -970,8 +1084,12 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
free_slide_point_data(op->customdata); /* keep this last! */
return OPERATOR_FINISHED;
}
-
- break;
+ else if (event->type != data->event_invoke_type && event->val == KM_PRESS) {
+ /* pass to ESCKEY */
+ }
+ else {
+ break;
+ }
case ESCKEY:
cancel_slide_point(op->customdata);
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index a5e98b651a3..db20d42f39d 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -46,6 +46,7 @@ set(SRC
editmesh_bisect.c
editmesh_extrude.c
editmesh_inset.c
+ editmesh_intersect.c
editmesh_knife.c
editmesh_knife_project.c
editmesh_loopcut.c
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index e25919b7400..48d5113a279 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -73,9 +73,9 @@ typedef struct {
#define HEADER_LENGTH 180
-static void edbm_bevel_update_header(wmOperator *op, bContext *C)
+static void edbm_bevel_update_header(bContext *C, wmOperator *op)
{
- const char *str = IFACE_("Confirm: (Enter/LMB), Cancel: (Esc/RMB), Offset: %s, Segments: %d");
+ const char *str = IFACE_("Confirm: (Enter/LMB), Cancel: (Esc/RMB), Mode: %s (M), Offset: %s, Segments: %d");
char msg[HEADER_LENGTH];
ScrArea *sa = CTX_wm_area(C);
@@ -84,15 +84,19 @@ static void edbm_bevel_update_header(wmOperator *op, bContext *C)
if (sa) {
BevelData *opdata = op->customdata;
char offset_str[NUM_STR_REP_LEN];
+ const char *type_str;
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "offset_type");
if (hasNumInput(&opdata->num_input)) {
- outputNumInput(&opdata->num_input, offset_str, sce->unit.scale_length);
+ outputNumInput(&opdata->num_input, offset_str, &sce->unit);
}
else {
BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset"));
}
- BLI_snprintf(msg, HEADER_LENGTH, str, offset_str, RNA_int_get(op->ptr, "segments"));
+ RNA_property_enum_name_gettexted(C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &type_str);
+
+ BLI_snprintf(msg, HEADER_LENGTH, str, type_str, offset_str, RNA_int_get(op->ptr, "segments"));
ED_area_headerprint(sa, msg);
}
@@ -146,15 +150,19 @@ static bool edbm_bevel_calc(wmOperator *op)
const int segments = RNA_int_get(op->ptr, "segments");
const float profile = RNA_float_get(op->ptr, "profile");
const bool vertex_only = RNA_boolean_get(op->ptr, "vertex_only");
+ int material = RNA_int_get(op->ptr, "material");
/* revert to original mesh */
if (opdata->is_modal) {
EDBM_redo_state_restore(opdata->mesh_backup, em, false);
}
+ if (em->ob)
+ material = CLAMPIS(material, -1, em->ob->totcol - 1);
+
EDBM_op_init(em, &bmop, op,
- "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f",
- BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile);
+ "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f material=%i",
+ BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile, material);
BMO_op_exec(em->bm, &bmop);
@@ -254,7 +262,7 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
opdata->initial_length = len_v2(mlen);
opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
- edbm_bevel_update_header(op, C);
+ edbm_bevel_update_header(C, op);
if (!edbm_bevel_calc(op)) {
edbm_bevel_cancel(C, op);
@@ -269,44 +277,40 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static float edbm_bevel_mval_factor(wmOperator *op, const wmEvent *event)
{
BevelData *opdata = op->customdata;
- bool use_dist = true;
- bool is_percent = false;
+ bool use_dist;
+ bool is_percent;
float mdiff[2];
float factor;
mdiff[0] = opdata->mcenter[0] - event->mval[0];
mdiff[1] = opdata->mcenter[1] - event->mval[1];
is_percent = (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT);
+ use_dist = !is_percent;
- if (use_dist) {
- factor = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length) * opdata->pixel_size;
- }
- else {
- factor = (len_v2(mdiff) - MVAL_PIXEL_MARGIN) / opdata->initial_length;
- factor = factor - 1.0f; /* a different kind of buffer where nothing happens */
- }
+ factor = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length) * opdata->pixel_size;
/* Fake shift-transform... */
if (event->shift) {
if (opdata->shift_factor < 0.0f) {
opdata->shift_factor = RNA_float_get(op->ptr, "offset");
+ if (is_percent) {
+ opdata->shift_factor /= 100.0f;
+ }
}
factor = (factor - opdata->shift_factor) * 0.1f + opdata->shift_factor;
}
- else if (opdata->shift_factor >= 0.0f)
+ else if (opdata->shift_factor >= 0.0f) {
opdata->shift_factor = -1.0f;
+ }
/* clamp differently based on distance/factor */
if (use_dist) {
if (factor < 0.0f) factor = 0.0f;
}
else {
+ CLAMP(factor, 0.0f, 1.0f);
if (is_percent) {
factor *= 100.0f;
- CLAMP(factor, 0.0f, 100.0f);
- }
- else {
- CLAMP(factor, 0.0f, 1.0f);
}
}
@@ -317,17 +321,16 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
BevelData *opdata = op->customdata;
int segments = RNA_int_get(op->ptr, "segments");
-
- if (event->val == KM_PRESS && hasNumInput(&opdata->num_input)) {
- /* Modal numinput active, try to handle numeric inputs first... */
- if (handleNumInput(C, &opdata->num_input, event)) {
- float value = RNA_float_get(op->ptr, "offset");
- applyNumInput(&opdata->num_input, &value);
- RNA_float_set(op->ptr, "offset", value);
- edbm_bevel_calc(op);
- edbm_bevel_update_header(op, C);
- return OPERATOR_RUNNING_MODAL;
- }
+ const bool has_numinput = hasNumInput(&opdata->num_input);
+
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &opdata->num_input, event)) {
+ float value = RNA_float_get(op->ptr, "offset");
+ applyNumInput(&opdata->num_input, &value);
+ RNA_float_set(op->ptr, "offset", value);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ return OPERATOR_RUNNING_MODAL;
}
else {
bool handled = false;
@@ -338,12 +341,12 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
case MOUSEMOVE:
- if (!hasNumInput(&opdata->num_input)) {
+ if (!has_numinput) {
const float factor = edbm_bevel_mval_factor(op, event);
RNA_float_set(op->ptr, "offset", factor);
edbm_bevel_calc(op);
- edbm_bevel_update_header(op, C);
+ edbm_bevel_update_header(C, op);
handled = true;
}
break;
@@ -368,7 +371,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
segments++;
RNA_int_set(op->ptr, "segments", segments);
edbm_bevel_calc(op);
- edbm_bevel_update_header(op, C);
+ edbm_bevel_update_header(C, op);
handled = true;
break;
@@ -380,21 +383,41 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
segments = max_ii(segments - 1, 1);
RNA_int_set(op->ptr, "segments", segments);
edbm_bevel_calc(op);
- edbm_bevel_update_header(op, C);
+ edbm_bevel_update_header(C, op);
handled = true;
break;
- }
- if (!handled && event->val == KM_PRESS) {
- /* Modal numinput inactive, try to handle numeric inputs last... */
- if (handleNumInput(C, &opdata->num_input, event)) {
- float value = RNA_float_get(op->ptr, "offset");
- applyNumInput(&opdata->num_input, &value);
- RNA_float_set(op->ptr, "offset", value);
+ case MKEY:
+ if (event->val == KM_RELEASE)
+ break;
+
+ {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "offset_type");
+ int type = RNA_property_enum_get(op->ptr, prop);
+ type++;
+ if (type > BEVEL_AMT_PERCENT) {
+ type = BEVEL_AMT_OFFSET;
+ }
+ RNA_property_enum_set(op->ptr, prop, type);
+ }
+ /* Update factor accordingly to new offset_type. */
+ if (!has_numinput) {
+ RNA_float_set(op->ptr, "offset", edbm_bevel_mval_factor(op, event));
+ }
edbm_bevel_calc(op);
- edbm_bevel_update_header(op, C);
- return OPERATOR_RUNNING_MODAL;
- }
+ edbm_bevel_update_header(C, op);
+ handled = true;
+ break;
+ }
+
+ /* Modal numinput inactive, try to handle numeric inputs last... */
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &opdata->num_input, event)) {
+ float value = RNA_float_get(op->ptr, "offset");
+ applyNumInput(&opdata->num_input, &value);
+ RNA_float_set(op->ptr, "offset", value);
+ edbm_bevel_calc(op);
+ edbm_bevel_update_header(C, op);
+ return OPERATOR_RUNNING_MODAL;
}
}
@@ -445,4 +468,5 @@ void MESH_OT_bevel(wmOperatorType *ot)
RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8);
RNA_def_float(ot->srna, "profile", 0.5f, 0.15f, 1.0f, "Profile", "Controls profile shape (0.5 = round)", 0.15f, 1.0f);
RNA_def_boolean(ot->srna, "vertex_only", false, "Vertex only", "Bevel only vertices");
+ RNA_def_int(ot->srna, "material", -1, -1, INT_MAX, "Material", "Material for bevel faces (-1 means use adjacent faces)", -1, 100);
}
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 595c43c1060..3e403387a67 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -33,6 +33,7 @@
#include "DNA_object_types.h"
#include "BLI_math.h"
+#include "BLI_listbase.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -65,6 +66,75 @@ static void add_normal_aligned(float nor[3], const float add[3])
}
}
+static void edbm_extrude_edge_exclude_mirror(
+ Object *obedit, BMEditMesh *em,
+ const char hflag,
+ BMOperator *op, BMOpSlot *slot_edges_exclude)
+{
+ BMesh *bm = em->bm;
+ ModifierData *md;
+
+ /* If a mirror modifier with clipping is on, we need to adjust some
+ * of the cases above to handle edges on the line of symmetry.
+ */
+ for (md = obedit->modifiers.first; md; md = md->next) {
+ if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
+ MirrorModifierData *mmd = (MirrorModifierData *) md;
+
+ if (mmd->flag & MOD_MIR_CLIPPING) {
+ BMIter iter;
+ BMEdge *edge;
+
+ float mtx[4][4];
+ if (mmd->mirror_ob) {
+ float imtx[4][4];
+ invert_m4_m4(imtx, mmd->mirror_ob->obmat);
+ mul_m4_m4m4(mtx, imtx, obedit->obmat);
+ }
+
+ BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(edge, hflag) &&
+ BM_edge_is_boundary(edge) &&
+ BM_elem_flag_test(edge->l->f, hflag))
+ {
+ float co1[3], co2[3];
+
+ copy_v3_v3(co1, edge->v1->co);
+ copy_v3_v3(co2, edge->v2->co);
+
+ if (mmd->mirror_ob) {
+ mul_v3_m4v3(co1, mtx, co1);
+ mul_v3_m4v3(co2, mtx, co2);
+ }
+
+ if (mmd->flag & MOD_MIR_AXIS_X) {
+ if ((fabsf(co1[0]) < mmd->tolerance) &&
+ (fabsf(co2[0]) < mmd->tolerance))
+ {
+ BMO_slot_map_empty_insert(op, slot_edges_exclude, edge);
+ }
+ }
+ if (mmd->flag & MOD_MIR_AXIS_Y) {
+ if ((fabsf(co1[1]) < mmd->tolerance) &&
+ (fabsf(co2[1]) < mmd->tolerance))
+ {
+ BMO_slot_map_empty_insert(op, slot_edges_exclude, edge);
+ }
+ }
+ if (mmd->flag & MOD_MIR_AXIS_Z) {
+ if ((fabsf(co1[2]) < mmd->tolerance) &&
+ (fabsf(co2[2]) < mmd->tolerance))
+ {
+ BMO_slot_map_empty_insert(op, slot_edges_exclude, edge);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
/* individual face extrude */
/* will use vertex normals for extrusion directions, so *nor is unaffected */
static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
@@ -75,7 +145,10 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c
BMLoop *l;
BMOperator bmop;
- EDBM_op_init(em, &bmop, op, "extrude_discrete_faces faces=%hf", hflag);
+ EDBM_op_init(
+ em, &bmop, op,
+ "extrude_discrete_faces faces=%hf use_select_history=%b",
+ hflag, true);
/* deselect original verts */
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
@@ -101,12 +174,18 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c
/* extrudes individual edges */
static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
{
+ BMesh *bm = em->bm;
BMOperator bmop;
- EDBM_op_init(em, &bmop, op, "extrude_edge_only edges=%he", hflag);
+ EDBM_op_init(
+ em, &bmop, op,
+ "extrude_edge_only edges=%he use_select_history=%b",
+ hflag, true);
/* deselect original verts */
+ BM_SELECT_HISTORY_BACKUP(bm);
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BM_SELECT_HISTORY_RESTORE(bm);
BMO_op_exec(em->bm, &bmop);
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
@@ -123,7 +202,10 @@ static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char
{
BMOperator bmop;
- EDBM_op_init(em, &bmop, op, "extrude_vert_indiv verts=%hv", hflag);
+ EDBM_op_init(
+ em, &bmop, op,
+ "extrude_vert_indiv verts=%hv use_select_history=%b",
+ hflag, true);
/* deselect original verts */
BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "verts", BM_VERT, BM_ELEM_SELECT, true);
@@ -138,82 +220,32 @@ static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char
return 'g'; /* g is grab */
}
-static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, float nor[3])
+static short edbm_extrude_edge_ex(
+ Object *obedit, BMEditMesh *em,
+ const char hflag, float nor[3],
+ const bool use_mirror,
+ const bool use_select_history)
{
BMesh *bm = em->bm;
- BMIter iter;
BMOIter siter;
BMOperator extop;
- BMEdge *edge;
BMFace *f;
- ModifierData *md;
BMElem *ele;
- BMOpSlot *slot_edges_exclude;
BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region");
+ BMO_slot_bool_set(extop.slots_in, "use_select_history", use_select_history);
BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE, hflag);
- slot_edges_exclude = BMO_slot_get(extop.slots_in, "edges_exclude");
+ if (use_mirror) {
+ BMOpSlot *slot_edges_exclude;
+ slot_edges_exclude = BMO_slot_get(extop.slots_in, "edges_exclude");
- /* If a mirror modifier with clipping is on, we need to adjust some
- * of the cases above to handle edges on the line of symmetry.
- */
- md = obedit->modifiers.first;
- for (; md; md = md->next) {
- if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
- MirrorModifierData *mmd = (MirrorModifierData *) md;
-
- if (mmd->flag & MOD_MIR_CLIPPING) {
- float mtx[4][4];
- if (mmd->mirror_ob) {
- float imtx[4][4];
- invert_m4_m4(imtx, mmd->mirror_ob->obmat);
- mul_m4_m4m4(mtx, imtx, obedit->obmat);
- }
-
- BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(edge, hflag) &&
- BM_edge_is_boundary(edge) &&
- BM_elem_flag_test(edge->l->f, hflag))
- {
- float co1[3], co2[3];
-
- copy_v3_v3(co1, edge->v1->co);
- copy_v3_v3(co2, edge->v2->co);
-
- if (mmd->mirror_ob) {
- mul_v3_m4v3(co1, mtx, co1);
- mul_v3_m4v3(co2, mtx, co2);
- }
-
- if (mmd->flag & MOD_MIR_AXIS_X) {
- if ((fabsf(co1[0]) < mmd->tolerance) &&
- (fabsf(co2[0]) < mmd->tolerance))
- {
- BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge);
- }
- }
- if (mmd->flag & MOD_MIR_AXIS_Y) {
- if ((fabsf(co1[1]) < mmd->tolerance) &&
- (fabsf(co2[1]) < mmd->tolerance))
- {
- BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge);
- }
- }
- if (mmd->flag & MOD_MIR_AXIS_Z) {
- if ((fabsf(co1[2]) < mmd->tolerance) &&
- (fabsf(co2[2]) < mmd->tolerance))
- {
- BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge);
- }
- }
- }
- }
- }
- }
+ edbm_extrude_edge_exclude_mirror(obedit, em, hflag, &extop, slot_edges_exclude);
}
+ BM_SELECT_HISTORY_BACKUP(bm);
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BM_SELECT_HISTORY_RESTORE(bm);
BMO_op_exec(bm, &extop);
@@ -236,6 +268,13 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag,
return is_zero_v3(nor) ? 'g' : 'n';
}
+static short edbm_extrude_edge(
+ Object *obedit, BMEditMesh *em,
+ const char hflag, float nor[3])
+{
+ return edbm_extrude_edge_ex(obedit, em, hflag, nor, true, true);
+}
+
static short edbm_extrude_vert(Object *obedit, BMEditMesh *em, const char hflag, float nor[3])
{
BMIter iter;
@@ -288,13 +327,12 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
mul_m3_v3(tmat, dvec);
for (a = 0; a < steps; a++) {
- edbm_extrude_edge(obedit, em, BM_ELEM_SELECT, nor);
- //BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "extrude_face_region geom=%hef", BM_ELEM_SELECT);
- BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS,
- "translate vec=%v verts=%hv",
- dvec, BM_ELEM_SELECT);
- //extrudeflag(obedit, em, SELECT, nor);
- //translateflag(em, SELECT, dvec);
+ edbm_extrude_edge_ex(obedit, em, BM_ELEM_SELECT, nor, false, false);
+
+ BMO_op_callf(
+ em->bm, BMO_FLAG_DEFAULTS,
+ "translate vec=%v verts=%hv",
+ dvec, BM_ELEM_SELECT);
}
EDBM_mesh_normals_update(em);
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index dc40330b309..a4942d01671 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -90,7 +90,7 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C)
if (sa) {
char flts_str[NUM_STR_REP_LEN * 2];
if (hasNumInput(&opdata->num_input))
- outputNumInput(&opdata->num_input, flts_str, sce->unit.scale_length);
+ outputNumInput(&opdata->num_input, flts_str, &sce->unit);
else {
BLI_snprintf(flts_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "thickness"));
BLI_snprintf(flts_str + NUM_STR_REP_LEN, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "depth"));
@@ -297,25 +297,24 @@ static int edbm_inset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
InsetData *opdata = op->customdata;
-
- if (event->val == KM_PRESS && hasNumInput(&opdata->num_input)) {
- /* Modal numinput active, try to handle numeric inputs first... */
- if (handleNumInput(C, &opdata->num_input, event)) {
- float amounts[2] = {RNA_float_get(op->ptr, "thickness"),
- RNA_float_get(op->ptr, "depth")};
- applyNumInput(&opdata->num_input, amounts);
- amounts[0] = max_ff(amounts[0], 0.0f);
- RNA_float_set(op->ptr, "thickness", amounts[0]);
- RNA_float_set(op->ptr, "depth", amounts[1]);
-
- if (edbm_inset_calc(op)) {
- edbm_inset_update_header(op, C);
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- edbm_inset_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
+ const bool has_numinput = hasNumInput(&opdata->num_input);
+
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &opdata->num_input, event)) {
+ float amounts[2] = {RNA_float_get(op->ptr, "thickness"),
+ RNA_float_get(op->ptr, "depth")};
+ applyNumInput(&opdata->num_input, amounts);
+ amounts[0] = max_ff(amounts[0], 0.0f);
+ RNA_float_set(op->ptr, "thickness", amounts[0]);
+ RNA_float_set(op->ptr, "depth", amounts[1]);
+
+ if (edbm_inset_calc(op)) {
+ edbm_inset_update_header(op, C);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ edbm_inset_cancel(C, op);
+ return OPERATOR_CANCELLED;
}
}
else {
@@ -327,7 +326,7 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
case MOUSEMOVE:
- if (!hasNumInput(&opdata->num_input)) {
+ if (!has_numinput) {
float mdiff[2];
float amount;
@@ -455,24 +454,22 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
- if (!handled && event->val == KM_PRESS) {
- /* Modal numinput inactive, try to handle numeric inputs last... */
- if (handleNumInput(C, &opdata->num_input, event)) {
- float amounts[2] = {RNA_float_get(op->ptr, "thickness"),
- RNA_float_get(op->ptr, "depth")};
- applyNumInput(&opdata->num_input, amounts);
- amounts[0] = max_ff(amounts[0], 0.0f);
- RNA_float_set(op->ptr, "thickness", amounts[0]);
- RNA_float_set(op->ptr, "depth", amounts[1]);
-
- if (edbm_inset_calc(op)) {
- edbm_inset_update_header(op, C);
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- edbm_inset_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
+ /* Modal numinput inactive, try to handle numeric inputs last... */
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &opdata->num_input, event)) {
+ float amounts[2] = {RNA_float_get(op->ptr, "thickness"),
+ RNA_float_get(op->ptr, "depth")};
+ applyNumInput(&opdata->num_input, amounts);
+ amounts[0] = max_ff(amounts[0], 0.0f);
+ RNA_float_set(op->ptr, "thickness", amounts[0]);
+ RNA_float_set(op->ptr, "depth", amounts[1]);
+
+ if (edbm_inset_calc(op)) {
+ edbm_inset_update_header(op, C);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ edbm_inset_cancel(C, op);
+ return OPERATOR_CANCELLED;
}
}
}
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
new file mode 100644
index 00000000000..df6776950d7
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -0,0 +1,400 @@
+/*
+ * ***** 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 *****
+ */
+
+/** \file blender/editors/mesh/editmesh_intersect.c
+ * \ingroup edmesh
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+
+#include "BLI_math.h"
+#include "BLI_array.h"
+#include "BLI_linklist_stack.h"
+
+
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_editmesh.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+
+#include "intern/bmesh_private.h"
+
+#include "mesh_intern.h" /* own include */
+
+#include "tools/bmesh_intersect.h"
+
+
+/* -------------------------------------------------------------------- */
+/* Cut intersections into geometry */
+
+/**
+ * Compare selected with its self.
+ */
+static int bm_face_isect_self(BMFace *f, void *UNUSED(user_data))
+{
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
+}
+
+/**
+ * Compare selected/unselected.
+ */
+static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
+{
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ return -1;
+ }
+ else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+enum {
+ ISECT_SEL = 0,
+ ISECT_SEL_UNSEL = 1,
+};
+
+static EnumPropertyItem isect_mode_items[] = {
+ {ISECT_SEL, "SELECT", 0, "Self Intersect",
+ "Self intersect selected faces"},
+ {ISECT_SEL_UNSEL, "SELECT_UNSELECT", 0, "Selected/Unselected",
+ "Intersect selected with unselected faces"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int edbm_intersect_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ int (*test_fn)(BMFace *, void *);
+ bool use_separate = RNA_boolean_get(op->ptr, "use_separate");
+ const float eps = RNA_float_get(op->ptr, "threshold");
+ bool use_self;
+ bool has_isect;
+
+ switch (mode) {
+ case ISECT_SEL:
+ test_fn = bm_face_isect_self;
+ use_self = true;
+ break;
+ default: /* ISECT_SEL_UNSEL */
+ test_fn = bm_face_isect_pair;
+ use_self = false;
+ break;
+ }
+
+
+ has_isect = BM_mesh_intersect(
+ bm,
+ em->looptris, em->tottri,
+ test_fn, NULL,
+ use_self, use_separate,
+ eps);
+
+
+ if (has_isect) {
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+
+ if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
+ BMIter iter;
+ BMEdge *e;
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BM_edge_select_set(bm, e, true);
+ }
+ }
+ }
+
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "No intersections found");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_intersect(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Intersect";
+ ot->description = "Cut an intersection into faces";
+ ot->idname = "MESH_OT_intersect";
+
+ /* api callbacks */
+ ot->exec = edbm_intersect_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* props */
+ RNA_def_enum(ot->srna, "mode", isect_mode_items, ISECT_SEL_UNSEL, "Source", "");
+ RNA_def_boolean(ot->srna, "use_separate", true, "Separate", "");
+ RNA_def_float(ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Face Split by Edges */
+
+
+/** \name Face/Edge Split
+ * \{ */
+
+static void bm_face_split_by_edges(BMesh *bm, BMFace *f, const char hflag)
+{
+ BMEdge **edge_net = NULL;
+ BLI_array_declare(edge_net);
+
+ const int f_index = BM_elem_index_get(f);
+
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ BMVert *v;
+
+ BMFace **face_arr;
+ int face_arr_len;
+
+ /* likely this will stay very small
+ * all verts pushed into this stack _must_ have their previous edges set! */
+ BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *);
+ BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *);
+
+
+ /* collect all edges */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMIter iter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &iter, l_iter->v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, hflag) &&
+ (BM_elem_index_get(e) == f_index))
+ {
+ v = BM_edge_other_vert(e, l_iter->v);
+ v->e = e;
+
+ BLI_SMALLSTACK_PUSH(vert_stack, v);
+ BLI_array_append(edge_net, e);
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+
+
+ /* now assign all */
+ /* pop free values into the next stack */
+ while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) {
+ BMIter eiter;
+ BMEdge *e_next;
+
+ BM_ITER_ELEM (e_next, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_next, hflag) &&
+ (BM_elem_index_get(e_next) == -1))
+ {
+ BMVert *v_next;
+ v_next = BM_edge_other_vert(e_next, v);
+ BM_elem_index_set(e_next, f_index);
+ BLI_SMALLSTACK_PUSH(vert_stack_next, v_next);
+ BLI_array_append(edge_net, e_next);
+ }
+ }
+
+ if (BLI_SMALLSTACK_IS_EMPTY(vert_stack)) {
+ BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next);
+ }
+ }
+
+ BM_face_split_edgenet(bm, f, edge_net, BLI_array_count(edge_net), &face_arr, &face_arr_len);
+ BLI_array_free(edge_net);
+
+ if (face_arr_len) {
+ int i;
+ for (i = 0; i < face_arr_len; i++) {
+ BM_face_select_set(bm, face_arr[i], true);
+ BM_elem_flag_disable(face_arr[i], hflag);
+ }
+ }
+
+ if (face_arr) {
+ MEM_freeN(face_arr);
+ }
+}
+
+static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ const char hflag = BM_ELEM_TAG;
+
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+ BMIter iter;
+
+ BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_disable(v, hflag);
+ }
+
+ /* edge index is set to -1 then used to assosiate them with faces */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
+ BM_elem_flag_enable(e, hflag);
+
+ BM_elem_flag_enable(e->v1, hflag);
+ BM_elem_flag_enable(e->v2, hflag);
+
+ }
+ else {
+ BM_elem_flag_disable(e, hflag);
+ }
+ BM_elem_index_set(e, -1); /* set_dirty */
+ }
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(f, hflag);
+ }
+ else {
+ BM_elem_flag_disable(f, hflag);
+ }
+ }
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, hflag)) {
+ BMIter viter;
+ BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
+ BMIter liter;
+ BMLoop *l;
+
+ unsigned int loop_stack_len;
+ BMLoop *l_best = NULL;
+
+ BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
+ loop_stack_len = 0;
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BM_elem_flag_test(l->f, hflag)) {
+ BLI_SMALLSTACK_PUSH(loop_stack, l);
+ loop_stack_len++;
+ }
+ }
+
+ if (loop_stack_len == 0) {
+ /* pass */
+ }
+ else if (loop_stack_len == 1) {
+ l_best = BLI_SMALLSTACK_POP(loop_stack);
+ }
+ else {
+ /* complicated case, match the edge with a face-loop */
+
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ float e_dir[3];
+
+ /* we wan't closest to zero */
+ float dot_best = FLT_MAX;
+
+ sub_v3_v3v3(e_dir, v_other->co, v->co);
+ normalize_v3(e_dir);
+
+ while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
+ float dot_test;
+
+ /* Check dot first to save on expensive angle-comparison.
+ * ideal case is 90d difference == 0.0 dot */
+ dot_test = fabsf(dot_v3v3(e_dir, l->f->no));
+ if (dot_test < dot_best) {
+
+ /* check we're in the correct corner (works with convex loops too) */
+ if (angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, v_other->co, l->f->no) <
+ angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, l->next->v->co, l->f->no))
+ {
+ dot_best = dot_test;
+ l_best = l;
+ }
+ }
+ }
+ }
+
+ if (l_best) {
+ BM_elem_index_set(e, BM_elem_index_get(l_best->f)); /* set_dirty */
+ }
+ }
+ }
+ }
+
+ bm->elem_index_dirty |= BM_EDGE;
+
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, hflag)) {
+ bm_face_split_by_edges(bm, f, hflag);
+ }
+ }
+
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void MESH_OT_face_split_by_edges(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Split by Edges";
+ ot->description = "Split faces by loose edges";
+ ot->idname = "MESH_OT_face_split_by_edges";
+
+ /* api callbacks */
+ ot->exec = edbm_face_split_by_edges_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 3dc0c85699a..4828fa02d42 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -27,6 +27,8 @@
/** \file blender/editors/mesh/editmesh_knife.c
* \ingroup edmesh
+ *
+ * Interactive editmesh knife tool.
*/
#ifdef _MSC_VER
@@ -71,13 +73,12 @@
#include "mesh_intern.h" /* own include */
-/* this code here is kindof messy. . .I might need to eventually rework it - joeedh */
-
#define KMAXDIST 10 /* max mouse distance from edge before not detecting it */
#define KNIFE_FLT_EPS 0.00001f
#define KNIFE_FLT_EPS_SQUARED (KNIFE_FLT_EPS * KNIFE_FLT_EPS)
#define KNIFE_FLT_EPSBIG 0.0005f
+#define KNIFE_FLT_EPS_PX 0.2f
typedef struct KnifeColors {
unsigned char line[3];
@@ -115,7 +116,7 @@ typedef struct KnifeEdge {
typedef struct KnifeLineHit {
float hit[3], cagehit[3];
- float schit[2];
+ float schit[2]; /* screen coordinates for cagehit */
float l; /* lambda along cut line */
float perc; /* lambda along hit line */
float m; /* depth front-to-back */
@@ -343,7 +344,7 @@ static KnifeVert *new_knife_vert(KnifeTool_OpData *kcd, const float co[3], const
copy_v3_v3(kfv->co, co);
copy_v3_v3(kfv->cageco, cageco);
- knife_project_v2(kcd, kfv->co, kfv->sco);
+ knife_project_v2(kcd, kfv->cageco, kfv->sco);
return kfv;
}
@@ -486,21 +487,14 @@ static void knife_edge_append_face(KnifeTool_OpData *kcd, KnifeEdge *kfe, BMFace
knife_append_list(kcd, &kfe->faces, f);
}
-static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd, KnifeEdge *kfe, float co[3], KnifeEdge **newkfe_out)
+static KnifeVert *knife_split_edge(
+ KnifeTool_OpData *kcd, KnifeEdge *kfe,
+ const float co[3], const float cageco[3],
+ KnifeEdge **r_kfe)
{
KnifeEdge *newkfe = new_knife_edge(kcd);
Ref *ref;
BMFace *f;
- float perc, cageco[3], l12;
-
- l12 = len_v3v3(kfe->v1->co, kfe->v2->co);
- if (l12 < KNIFE_FLT_EPS) {
- copy_v3_v3(cageco, kfe->v1->cageco);
- }
- else {
- perc = len_v3v3(co, kfe->v1->co) / l12;
- interp_v3_v3v3(cageco, kfe->v1->cageco, kfe->v2->cageco, perc);
- }
newkfe->v1 = kfe->v1;
newkfe->v2 = new_knife_vert(kcd, co, cageco);
@@ -532,7 +526,7 @@ static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd, KnifeEdge *kfe, float
newkfe->draw = kfe->draw;
newkfe->e = kfe->e;
- *newkfe_out = newkfe;
+ *r_kfe = newkfe;
return newkfe->v2;
}
@@ -670,7 +664,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife
kfe->v1 = lh1->v;
}
else if (lh1->kfe) {
- kfe->v1 = knife_split_edge(kcd, lh1->kfe, lh1->cagehit, &kfe2);
+ kfe->v1 = knife_split_edge(kcd, lh1->kfe, lh1->hit, lh1->cagehit, &kfe2);
lh1->v = kfe->v1; /* record the KnifeVert for this hit */
}
else {
@@ -686,7 +680,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife
kfe->v2 = lh2->v;
}
else if (lh2->kfe) {
- kfe->v2 = knife_split_edge(kcd, lh2->kfe, lh2->cagehit, &kfe2);
+ kfe->v2 = knife_split_edge(kcd, lh2->kfe, lh2->hit, lh2->cagehit, &kfe2);
lh2->v = kfe->v2; /* future uses of lh2 won't split again */
}
else {
@@ -1070,21 +1064,22 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
-/* Find intersection of v1-v2 with face f.
- * Only take intersections that are at least face_tol (in screen space) away
+/**
+ * Find intersection of v1-v2 with face f.
+ * Only take intersections that are at least \a face_tol_sq (in screen space) away
* from other intersection elements.
* If v1-v2 is coplanar with f, call that "no intersection though
* it really means "infinite number of intersections".
- * In such a case we should have gotten hits on edges or verts of the face. */
-static bool knife_ray_intersect_face(KnifeTool_OpData *kcd,
- const float s[2],
- const float v1[3], const float v2[3],
- BMFace *f,
- const float face_tol,
- float intersectp[3])
+ * In such a case we should have gotten hits on edges or verts of the face.
+ */
+static bool knife_ray_intersect_face(
+ KnifeTool_OpData *kcd,
+ const float s[2], const float v1[3], const float v2[3],
+ BMFace *f, const float face_tol_sq,
+ float hit_co[3], float hit_cageco[3])
{
int tottri, tri_i;
- float lv1[3], lv2[3], lv3[3], raydir[3];
+ float raydir[3];
float tri_norm[3], tri_plane[4];
float se1[2], se2[2];
float d, lambda;
@@ -1100,12 +1095,14 @@ static bool knife_ray_intersect_face(KnifeTool_OpData *kcd,
BLI_assert(tri_i >= 0 && tri_i < tottri);
for (; tri_i < tottri; tri_i++) {
+ const float *lv1, *lv2, *lv3;
+
tri = kcd->em->looptris[tri_i];
if (tri[0]->f != f)
break;
- copy_v3_v3(lv1, kcd->cagecos[BM_elem_index_get(tri[0]->v)]);
- copy_v3_v3(lv2, kcd->cagecos[BM_elem_index_get(tri[1]->v)]);
- copy_v3_v3(lv3, kcd->cagecos[BM_elem_index_get(tri[2]->v)]);
+ lv1 = kcd->cagecos[BM_elem_index_get(tri[0]->v)];
+ lv2 = kcd->cagecos[BM_elem_index_get(tri[1]->v)];
+ lv3 = kcd->cagecos[BM_elem_index_get(tri[2]->v)];
/* using epsilon test in case ray is directly through an internal
* tesselation edge and might not hit either tesselation tri with
* an exact test;
@@ -1114,24 +1111,29 @@ static bool knife_ray_intersect_face(KnifeTool_OpData *kcd,
/* check if line coplanar with tri */
normal_tri_v3(tri_norm, lv1, lv2, lv3);
plane_from_point_normal_v3(tri_plane, lv1, tri_norm);
- if ((fabsf(dist_squared_to_plane_v3(v1, tri_plane)) < KNIFE_FLT_EPS) &&
- (fabsf(dist_squared_to_plane_v3(v2, tri_plane)) < KNIFE_FLT_EPS))
+ if ((dist_squared_to_plane_v3(v1, tri_plane) < KNIFE_FLT_EPS) &&
+ (dist_squared_to_plane_v3(v2, tri_plane) < KNIFE_FLT_EPS))
{
return false;
}
- copy_v3_v3(intersectp, v1);
- madd_v3_v3fl(intersectp, raydir, lambda);
+ copy_v3_v3(hit_cageco, v1);
+ madd_v3_v3fl(hit_cageco, raydir, lambda);
/* 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) {
kfe = ref->ref;
knife_project_v2(kcd, kfe->v1->cageco, se1);
knife_project_v2(kcd, kfe->v2->cageco, se2);
- d = dist_to_line_segment_v2(s, se1, se2);
- if (d < face_tol) {
+ d = dist_squared_to_line_segment_v2(s, se1, se2);
+ if (d < face_tol_sq) {
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);
return true;
}
}
@@ -1221,16 +1223,7 @@ static void clip_to_ortho_planes(float v1[3], float v2[3], float d)
static void set_linehit_depth(KnifeTool_OpData *kcd, KnifeLineHit *lh)
{
- float vnear[3], vfar[3];
-
- ED_view3d_win_to_segment(kcd->ar, kcd->vc.v3d, lh->schit, vnear, vfar, true);
- mul_m4_v3(kcd->ob->imat, vnear);
- if (kcd->is_ortho && (kcd->vc.rv3d->persp != RV3D_CAMOB)) {
- if (kcd->ortho_extent == 0.0f)
- calc_ortho_extent(kcd);
- clip_to_ortho_planes(vnear, vfar, kcd->ortho_extent + 10.0f);
- }
- lh->m = len_v3v3(vnear, lh->cagehit);
+ lh->m = dot_m4_v3_row_z(kcd->vc.rv3d->persmatob, lh->cagehit);
}
/* Finds visible (or all, if cutting through) edges that intersects the current screen drag line */
@@ -1254,9 +1247,12 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
void *val;
float plane_cos[12];
float s[2], se1[2], se2[2], sint[2];
- float p[3], p2[3], r1[3], r2[3];
+ float r1[3], r2[3];
float d, d1, d2, lambda;
- float vert_tol, vert_tol_sq, line_tol, face_tol;
+ float vert_tol, vert_tol_sq;
+ float line_tol, line_tol_sq;
+ float face_tol, face_tol_sq;
+ float eps_scale;
int isect_kind;
unsigned int tot;
int i;
@@ -1359,10 +1355,22 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
/* Now go through the candidates and find intersections */
/* These tolerances, in screen space, are for intermediate hits, as ends are already snapped to screen */
- vert_tol = KNIFE_FLT_EPS * 2000.0f;
- line_tol = KNIFE_FLT_EPS * 2000.0f;
- vert_tol_sq = vert_tol * vert_tol;
+ {
+ /* Scale the epsilon by the zoom level
+ * to compensate for projection imprecision, see T41164 */
+ float zoom_xy[2] = {kcd->vc.rv3d->winmat[0][0],
+ kcd->vc.rv3d->winmat[1][1]};
+ eps_scale = len_v2(zoom_xy);
+ }
+
+ vert_tol = KNIFE_FLT_EPS_PX * eps_scale;
+ line_tol = KNIFE_FLT_EPS_PX * eps_scale;
face_tol = max_ff(vert_tol, line_tol);
+
+ vert_tol_sq = vert_tol * vert_tol;
+ line_tol_sq = line_tol * line_tol;
+ face_tol_sq = face_tol * face_tol;
+
/* Assume these tolerances swamp floating point rounding errors in calculations below */
/* first look for vertex hits */
@@ -1375,7 +1383,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
if (point_is_visible(kcd, v->cageco, s, &mats)) {
memset(&hit, 0, sizeof(hit));
hit.v = v;
- copy_v3_v3(hit.hit, v->cageco);
+ copy_v3_v3(hit.hit, v->co);
copy_v3_v3(hit.cagehit, v->cageco);
copy_v2_v2(hit.schit, s);
set_linehit_depth(kcd, &hit);
@@ -1393,35 +1401,39 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
if (isect_kind == -1) {
/* isect_seg_seg_v2 doesn't do tolerance test around ends of s1-s2 */
closest_to_line_segment_v2(sint, s1, se1, se2);
- if (len_squared_v2v2(sint, s1) <= vert_tol_sq)
+ if (len_squared_v2v2(sint, s1) <= line_tol_sq)
isect_kind = 1;
else {
closest_to_line_segment_v2(sint, s2, se1, se2);
- if (len_squared_v2v2(sint, s2) <= vert_tol_sq)
+ if (len_squared_v2v2(sint, s2) <= line_tol_sq)
isect_kind = 1;
}
}
if (isect_kind == 1) {
d1 = len_v2v2(sint, se1);
d2 = len_v2v2(se2, se1);
- if (!(d1 <= vert_tol || d2 <= vert_tol || fabsf(d1 - d2) <= vert_tol)) {
+ if (!(d1 <= line_tol || d2 <= line_tol || fabsf(d1 - d2) <= line_tol)) {
+ float p_cage[3], p_cage_tmp[3];
lambda = d1 / d2;
/* Can't just interpolate between ends of kfe because
* that doesn't work with perspective transformation.
* Need to find 3d intersection of ray through sint */
knife_input_ray_segment(kcd, sint, 1.0f, r1, r2);
- isect_kind = isect_line_line_v3(kfe->v1->cageco, kfe->v2->cageco, r1, r2, p, p2);
- if (isect_kind >= 1 && point_is_visible(kcd, p, sint, &mats)) {
+ isect_kind = isect_line_line_v3(kfe->v1->cageco, kfe->v2->cageco, r1, r2, p_cage, p_cage_tmp);
+ if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, &mats)) {
memset(&hit, 0, sizeof(hit));
if (kcd->snap_midpoints) {
/* choose intermediate point snap too */
- mid_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco);
+ mid_v3_v3v3(p_cage, kfe->v1->cageco, kfe->v2->cageco);
mid_v2_v2v2(sint, se1, se2);
lambda = 0.5f;
}
hit.kfe = kfe;
- copy_v3_v3(hit.hit, p);
- copy_v3_v3(hit.cagehit, p);
+ transform_point_by_seg_v3(
+ hit.hit, p_cage,
+ kfe->v1->co, kfe->v2->co,
+ kfe->v1->cageco, kfe->v2->cageco);
+ copy_v3_v3(hit.cagehit, p_cage);
copy_v2_v2(hit.schit, sint);
hit.perc = lambda;
set_linehit_depth(kcd, &hit);
@@ -1434,23 +1446,25 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
for (val = BLI_smallhash_iternew(&faces, &hiter, (uintptr_t *)&f); val;
val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f))
{
- if (knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol, p)) {
- if (point_is_visible(kcd, p, s1, &mats)) {
+ float p[3], p_cage[3];
+
+ if (knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) {
+ if (point_is_visible(kcd, p_cage, s1, &mats)) {
memset(&hit, 0, sizeof(hit));
hit.f = f;
copy_v3_v3(hit.hit, p);
- copy_v3_v3(hit.cagehit, p);
+ copy_v3_v3(hit.cagehit, p_cage);
copy_v2_v2(hit.schit, s1);
set_linehit_depth(kcd, &hit);
BLI_array_append(linehits, hit);
}
}
- if (knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol, p)) {
- if (point_is_visible(kcd, p, s2, &mats)) {
+ if (knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) {
+ if (point_is_visible(kcd, p_cage, s2, &mats)) {
memset(&hit, 0, sizeof(hit));
hit.f = f;
copy_v3_v3(hit.hit, p);
- copy_v3_v3(hit.cagehit, p);
+ copy_v3_v3(hit.cagehit, p_cage);
copy_v2_v2(hit.schit, s2);
set_linehit_depth(kcd, &hit);
BLI_array_append(linehits, hit);
@@ -1858,7 +1872,7 @@ static int knife_update_active(KnifeTool_OpData *kcd)
copy_v2_v2(kcd->curr.mval, kcd->mval);
/* view matrix may have changed, reproject */
- knife_project_v2(kcd, kcd->prev.co, kcd->prev.mval);
+ knife_project_v2(kcd, kcd->prev.cage, kcd->prev.mval);
if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING) {
kcd->is_angle_snapping = knife_snap_angle(kcd);
@@ -2252,31 +2266,28 @@ static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, L
static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f)
{
- BMLoop *l1, *l2, *l;
- float mid[3];
- BMIter iter;
- int v1inside, v2inside;
+ bool v1_inside, v2_inside;
+ bool v1_inface, v2_inface;
if (!f || !v1 || !v2)
return false;
- l1 = NULL;
- l2 = NULL;
-
/* find out if v1 and v2, if set, are part of the face */
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- if (v1->v && l->v == v1->v)
- l1 = l;
- if (v2->v && l->v == v2->v)
- l2 = l;
- }
+ v1_inface = v1->v ? BM_vert_in_face(f, v1->v) : false;
+ v2_inface = v2->v ? BM_vert_in_face(f, v2->v) : false;
/* BM_face_point_inside_test uses best-axis projection so this isn't most accurate test... */
- v1inside = l1 ? 0 : BM_face_point_inside_test(f, v1->co);
- v2inside = l2 ? 0 : BM_face_point_inside_test(f, v2->co);
- if ((l1 && v2inside) || (l2 && v1inside) || (v1inside && v2inside))
+ v1_inside = v1_inface ? false : BM_face_point_inside_test(f, v1->co);
+ v2_inside = v2_inface ? false : BM_face_point_inside_test(f, v2->co);
+ if ((v1_inface && v2_inside) ||
+ (v2_inface && v1_inside) ||
+ (v1_inside && v2_inside))
+ {
return true;
- if (l1 && l2) {
+ }
+
+ if (v1_inface && v2_inface) {
+ float mid[3];
/* Can have case where v1 and v2 are on shared chain between two faces.
* BM_face_splits_check_legal does visibility and self-intersection tests,
* but it is expensive and maybe a bit buggy, so use a simple
@@ -2375,12 +2386,12 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe
KnifeEdge *kfe;
BMFace *fnew, *fnew2, *fhole;
ListBase *chain, *hole, *sidechain;
- ListBase *fnew_kfedges, *fnew2_kfedges;
Ref *ref, *refnext;
int count, oldcount;
oldcount = BLI_countlist(kfedges);
while ((chain = find_chain(kcd, kfedges)) != NULL) {
+ ListBase fnew_kfedges;
knife_make_chain_cut(kcd, f, chain, &fnew);
if (!fnew) {
return;
@@ -2388,18 +2399,22 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe
/* Move kfedges to fnew_kfedges if they are now in fnew.
* The chain edges were removed already */
- fnew_kfedges = knife_empty_list(kcd);
+ BLI_listbase_clear(&fnew_kfedges);
for (ref = kfedges->first; ref; ref = refnext) {
kfe = ref->ref;
refnext = ref->next;
if (knife_edge_in_face(kfe, fnew)) {
BLI_remlink(kfedges, ref);
kfe->basef = fnew;
- knife_append_list(kcd, fnew_kfedges, kfe);
+ BLI_addtail(&fnew_kfedges, ref);
+ }
+ else if (!knife_edge_in_face(kfe, f)) {
+ /* Concave ngon's - this edge might not be in either faces, T41730 */
+ BLI_remlink(kfedges, ref);
}
}
- if (fnew_kfedges->first)
- knife_make_face_cuts(kcd, fnew, fnew_kfedges);
+ if (fnew_kfedges.first)
+ knife_make_face_cuts(kcd, fnew, &fnew_kfedges);
/* find_chain should always remove edges if it returns true,
* but guard against infinite loop anyway */
@@ -2413,6 +2428,8 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe
while ((hole = find_hole(kcd, kfedges)) != NULL) {
if (find_hole_chains(kcd, hole, f, &chain, &sidechain)) {
+ ListBase fnew_kfedges, fnew2_kfedges;
+
/* chain goes across f and sidechain comes back
* from the second last vertex to the second vertex.
*/
@@ -2443,28 +2460,28 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe
BM_face_kill(bm, fhole);
/* Move kfedges to either fnew or fnew2 if appropriate.
* The hole edges were removed already */
- fnew_kfedges = knife_empty_list(kcd);
- fnew2_kfedges = knife_empty_list(kcd);
+ BLI_listbase_clear(&fnew_kfedges);
+ BLI_listbase_clear(&fnew2_kfedges);
for (ref = kfedges->first; ref; ref = refnext) {
kfe = ref->ref;
refnext = ref->next;
if (knife_edge_in_face(kfe, fnew)) {
BLI_remlink(kfedges, ref);
kfe->basef = fnew;
- knife_append_list(kcd, fnew_kfedges, kfe);
+ BLI_addtail(&fnew_kfedges, ref);
}
else if (knife_edge_in_face(kfe, fnew2)) {
BLI_remlink(kfedges, ref);
kfe->basef = fnew2;
- knife_append_list(kcd, fnew2_kfedges, kfe);
+ BLI_addtail(&fnew2_kfedges, ref);
}
}
/* We'll skip knife edges that are in the newly formed hole.
* (Maybe we shouldn't have made a hole in the first place?) */
- if (fnew != fhole && fnew_kfedges->first)
- knife_make_face_cuts(kcd, fnew, fnew_kfedges);
- if (fnew2 != fhole && fnew2_kfedges->first)
- knife_make_face_cuts(kcd, fnew2, fnew2_kfedges);
+ if (fnew != fhole && fnew_kfedges.first)
+ knife_make_face_cuts(kcd, fnew, &fnew_kfedges);
+ if (fnew2 != fhole && fnew2_kfedges.first)
+ knife_make_face_cuts(kcd, fnew2, &fnew2_kfedges);
if (f == fhole)
break;
/* find_hole should always remove edges if it returns true,
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index cc26d6079a9..553c1faa36a 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -65,7 +65,7 @@ static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object
dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
dm_needsFree = false;
}
- else if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+ else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
dm = CDDM_from_curve(ob);
dm_needsFree = true;
}
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index bb044f39fba..59fbe739d03 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -555,39 +555,27 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
int cuts = RNA_int_get(op->ptr, "number_cuts");
RingSelOpData *lcd = op->customdata;
bool show_cuts = false;
+ const bool has_numinput = hasNumInput(&lcd->num);
view3d_operator_needs_opengl(C);
/* using the keyboard to input the number of cuts */
- if (event->val == KM_PRESS && hasNumInput(&lcd->num)) {
- /* Modal numinput active, try to handle numeric inputs first... */
- if (handleNumInput(C, &lcd->num, event)) {
- float values[2] = {(float)cuts, smoothness};
- applyNumInput(&lcd->num, values);
-
- /* allow zero so you can backspace and type in a value
- * otherwise 1 as minimum would make more sense */
- cuts = CLAMPIS(values[0], 0, SUBD_CUTS_MAX);
- smoothness = CLAMPIS(values[1], -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX);
-
- RNA_int_set(op->ptr, "number_cuts", cuts);
- ringsel_find_edge(lcd, cuts);
- show_cuts = true;
- RNA_float_set(op->ptr, "smoothness", smoothness);
-
- ED_region_tag_redraw(lcd->ar);
- }
- else {
- switch (event->type) {
- case RETKEY:
- case PADENTER:
- case LEFTMOUSE: /* confirm */ // XXX hardcoded
- return loopcut_finish(lcd, C, op);
- default:
- /* do nothing */;
- break;
- }
- }
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &lcd->num, event)) {
+ float values[2] = {(float)cuts, smoothness};
+ applyNumInput(&lcd->num, values);
+
+ /* allow zero so you can backspace and type in a value
+ * otherwise 1 as minimum would make more sense */
+ cuts = CLAMPIS(values[0], 0, SUBD_CUTS_MAX);
+ smoothness = CLAMPIS(values[1], -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX);
+
+ RNA_int_set(op->ptr, "number_cuts", cuts);
+ ringsel_find_edge(lcd, cuts);
+ show_cuts = true;
+ RNA_float_set(op->ptr, "smoothness", smoothness);
+
+ ED_region_tag_redraw(lcd->ar);
}
else {
bool handled = false;
@@ -663,35 +651,33 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
handled = true;
break;
case MOUSEMOVE: /* mouse moved somewhere to select another loop */
- {
- lcd->vc.mval[0] = event->mval[0];
- lcd->vc.mval[1] = event->mval[1];
- loopcut_mouse_move(lcd, cuts);
+ if (!has_numinput) {
+ lcd->vc.mval[0] = event->mval[0];
+ lcd->vc.mval[1] = event->mval[1];
+ loopcut_mouse_move(lcd, cuts);
- ED_region_tag_redraw(lcd->ar);
- handled = true;
+ ED_region_tag_redraw(lcd->ar);
+ handled = true;
+ }
break;
- }
}
- if (!handled && event->val == KM_PRESS) {
- /* Modal numinput inactive, try to handle numeric inputs last... */
- if (handleNumInput(C, &lcd->num, event)) {
- float values[2] = {(float)cuts, smoothness};
- applyNumInput(&lcd->num, values);
-
- /* allow zero so you can backspace and type in a value
- * otherwise 1 as minimum would make more sense */
- cuts = CLAMPIS(values[0], 0, SUBD_CUTS_MAX);
- smoothness = CLAMPIS(values[1], -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX);
-
- RNA_int_set(op->ptr, "number_cuts", cuts);
- ringsel_find_edge(lcd, cuts);
- show_cuts = true;
- RNA_float_set(op->ptr, "smoothness", smoothness);
-
- ED_region_tag_redraw(lcd->ar);
- }
+ /* Modal numinput inactive, try to handle numeric inputs last... */
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &lcd->num, event)) {
+ float values[2] = {(float)cuts, smoothness};
+ applyNumInput(&lcd->num, values);
+
+ /* allow zero so you can backspace and type in a value
+ * otherwise 1 as minimum would make more sense */
+ cuts = CLAMPIS(values[0], 0, SUBD_CUTS_MAX);
+ smoothness = CLAMPIS(values[1], -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX);
+
+ RNA_int_set(op->ptr, "number_cuts", cuts);
+ ringsel_find_edge(lcd, cuts);
+ show_cuts = true;
+ RNA_float_set(op->ptr, "smoothness", smoothness);
+
+ ED_region_tag_redraw(lcd->ar);
}
}
@@ -700,7 +686,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
char buf[64 + NUM_STR_REP_LEN * 2];
char str_rep[NUM_STR_REP_LEN * 2];
if (hasNumInput(&lcd->num)) {
- outputNumInput(&lcd->num, str_rep, sce->unit.scale_length);
+ outputNumInput(&lcd->num, str_rep, &sce->unit);
}
else {
BLI_snprintf(str_rep, NUM_STR_REP_LEN, "%d", cuts);
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 3d3e41d31cc..3b993332db0 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -993,6 +993,12 @@ static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
+ /* we could support this, but not for now */
+ if ((bm->totvertsel > 1) && (bm->totedgesel == 0)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot rip multiple disconnected vertices");
+ return OPERATOR_CANCELLED;
+ }
+
/* note on selection:
* When calling edge split we operate on tagged edges rather then selected
* this is important because the edges to operate on are extended by one,
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 23828098940..9cdfb43ae15 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -2807,6 +2807,13 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
BMEdge *e;
BMIter iter;
+ const bool use_wire = RNA_boolean_get(op->ptr, "use_wire");
+ const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
+ const bool use_multi_face = RNA_boolean_get(op->ptr, "use_multi_face");
+ const bool use_non_contiguous = RNA_boolean_get(op->ptr, "use_non_contiguous");
+ const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
+
+
if (!RNA_boolean_get(op->ptr, "extend"))
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
@@ -2819,15 +2826,30 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN) && !BM_vert_is_manifold(v)) {
- BM_vert_select_set(em->bm, v, true);
+ if (use_verts) {
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
+ if (!BM_vert_is_manifold(v)) {
+ BM_vert_select_set(em->bm, v, true);
+ }
+ }
}
}
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN) && !BM_edge_is_manifold(e)) {
- BM_edge_select_set(em->bm, e, true);
+ if (use_wire || use_boundary || use_multi_face || use_non_contiguous) {
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ if ((use_wire && BM_edge_is_wire(e)) ||
+ (use_boundary && BM_edge_is_boundary(e)) ||
+ (use_non_contiguous && (BM_edge_is_manifold(e) && !BM_edge_is_contiguous(e))) ||
+ (use_multi_face && (BM_edge_face_count(e) > 2)))
+ {
+ /* check we never select perfect edge (in test above) */
+ BLI_assert(!(BM_edge_is_manifold(e) && BM_edge_is_contiguous(e)));
+
+ BM_edge_select_set(em->bm, e, true);
+ }
+ }
}
}
@@ -2854,6 +2876,18 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot)
/* props */
RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
+ /* edges */
+ RNA_def_boolean(ot->srna, "use_wire", true, "Wire",
+ "Wire edges");
+ RNA_def_boolean(ot->srna, "use_boundary", true, "Boundaries",
+ "Boundary edges");
+ RNA_def_boolean(ot->srna, "use_multi_face", true,
+ "Multiple Faces", "Edges shared by 3+ faces");
+ RNA_def_boolean(ot->srna, "use_non_contiguous", true, "Non Contiguous",
+ "Edges between faces pointing in alternate directions");
+ /* verts */
+ RNA_def_boolean(ot->srna, "use_verts", true, "Vertices",
+ "Vertices connecting multiple face regions");
}
static int edbm_select_random_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 55ad303d0e1..3f1023b7fb4 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -881,12 +881,18 @@ static int edbm_vert_connect_exec(bContext *C, wmOperator *op)
int len;
if (is_pair) {
- if (!EDBM_op_init(em, &bmop, op, "connect_vert_pair verts=%hv", BM_ELEM_SELECT)) {
+ if (!EDBM_op_init(em, &bmop, op,
+ "connect_vert_pair verts=%hv verts_exclude=%hv faces_exclude=%hf",
+ BM_ELEM_SELECT, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN))
+ {
return OPERATOR_CANCELLED;
}
}
else {
- if (!EDBM_op_init(em, &bmop, op, "connect_verts verts=%hv check_degenerate=%b", BM_ELEM_SELECT, true)) {
+ if (!EDBM_op_init(em, &bmop, op,
+ "connect_verts verts=%hv faces_exclude=%hf check_degenerate=%b",
+ BM_ELEM_SELECT, BM_ELEM_HIDDEN, true))
+ {
return OPERATOR_CANCELLED;
}
}
@@ -1019,28 +1025,23 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(ob);
BMesh *bm = em->bm;
BMOperator bmop;
- ListBase bm_selected_store = {NULL, NULL};
- /* de-select all would clear otherwise */
- SWAP(ListBase, bm->selected, bm_selected_store);
+ EDBM_op_init(
+ em, &bmop, op,
+ "duplicate geom=%hvef use_select_history=%b",
+ BM_ELEM_SELECT, true);
- EDBM_op_init(em, &bmop, op, "duplicate geom=%hvef", BM_ELEM_SELECT);
-
BMO_op_exec(bm, &bmop);
+
+ /* de-select all would clear otherwise */
+ BM_SELECT_HISTORY_BACKUP(bm);
+
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
/* rebuild editselection */
- bm->selected = bm_selected_store;
-
- if (bm->selected.first) {
- BMOpSlot *slot_vert_map_out = BMO_slot_get(bmop.slots_out, "vert_map.out");
- BMOpSlot *slot_edge_map_out = BMO_slot_get(bmop.slots_out, "edge_map.out");
- BMOpSlot *slot_face_map_out = BMO_slot_get(bmop.slots_out, "face_map.out");
-
- BMO_mesh_selected_remap(bm, slot_vert_map_out, slot_edge_map_out, slot_face_map_out);
- }
+ BM_SELECT_HISTORY_RESTORE(bm);
if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
@@ -2424,7 +2425,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
float (*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2];
/* edit-object needed for matrix, and ar->regiondata for projections to work */
- if (ELEM3(NULL, obedit, ar, ar->regiondata))
+ if (ELEM(NULL, obedit, ar, ar->regiondata))
return OPERATOR_CANCELLED;
if (bm->totvertsel < 2) {
@@ -3047,7 +3048,7 @@ static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span
}
/* set this vertex first */
- BLI_rotatelist_first(verts, v_act_link);
+ BLI_listbase_rotate_first(verts, v_act_link);
BM_edgeloop_edges_get(el_store, edges);
@@ -3479,6 +3480,11 @@ static void edbm_dissolve_prop__use_face_split(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_face_split", 0, "Face Split",
"Split off face corners to maintain surrounding geometry");
}
+static void edbm_dissolve_prop__use_boundary_tear(wmOperatorType *ot)
+{
+ RNA_def_boolean(ot->srna, "use_boundary_tear", 0, "Tear Boundary",
+ "Split off face corners instead of merging faces");
+}
static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
{
@@ -3486,9 +3492,14 @@ static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
+ const bool use_boundary_tear = RNA_boolean_get(op->ptr, "use_boundary_tear");
- if (!EDBM_op_callf(em, op, "dissolve_verts verts=%hv use_face_split=%b", BM_ELEM_SELECT, use_face_split))
+ if (!EDBM_op_callf(em, op,
+ "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
+ BM_ELEM_SELECT, use_face_split, use_boundary_tear))
+ {
return OPERATOR_CANCELLED;
+ }
EDBM_update_generic(em, true, true);
@@ -3510,6 +3521,7 @@ void MESH_OT_dissolve_verts(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
edbm_dissolve_prop__use_face_split(ot);
+ edbm_dissolve_prop__use_boundary_tear(ot);
}
static int edbm_dissolve_edges_exec(bContext *C, wmOperator *op)
@@ -3621,6 +3633,7 @@ void MESH_OT_dissolve_mode(wmOperatorType *ot)
edbm_dissolve_prop__use_verts(ot);
edbm_dissolve_prop__use_face_split(ot);
+ edbm_dissolve_prop__use_boundary_tear(ot);
}
static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 8adaae5fe42..c7d1d883537 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -1328,6 +1328,15 @@ void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_d
/* don't keep stale derivedMesh data around, see: [#38872] */
BKE_editmesh_free_derivedmesh(em);
+
+#ifdef DEBUG
+ {
+ BMEditSelection *ese;
+ for (ese = em->bm->selected.first; ese; ese = ese->next) {
+ BLI_assert(BM_elem_flag_test(ese->ele, BM_ELEM_SELECT));
+ }
+ }
+#endif
}
/* poll call for mesh operators requiring a view3d context */
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 83947534d06..bf8559add6f 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -880,17 +880,6 @@ static void mesh_add_verts(Mesh *mesh, int len)
mesh->totvert = totvert;
}
-void ED_mesh_transform(Mesh *me, float mat[4][4])
-{
- int i;
- MVert *mvert = me->mvert;
-
- for (i = 0; i < me->totvert; i++, mvert++)
- mul_m4_v3(mat, mvert->co);
-
- /* don't update normals, caller can do this explicitly */
-}
-
static void mesh_add_edges(Mesh *mesh, int len)
{
CustomData edata;
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 655d96ae6e5..76f6cb5ebb8 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -112,6 +112,10 @@ void MESH_OT_screw(struct wmOperatorType *ot);
/* *** editmesh_inset.c *** */
void MESH_OT_inset(struct wmOperatorType *ot);
+/* *** editmesh_intersect.c *** */
+void MESH_OT_intersect(struct wmOperatorType *ot);
+void MESH_OT_face_split_by_edges(struct wmOperatorType *ot);
+
/* *** editmesh_knife.c *** */
void MESH_OT_knife_tool(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index 433fd176217..440ab14dacd 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -407,7 +407,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
BM_vert_at_index(em->bm, face[0]),
BM_vert_at_index(em->bm, face[2]),
BM_vert_at_index(em->bm, face[1]), NULL,
- NULL, false);
+ NULL, BM_CREATE_NOP);
/* set navigation polygon idx to the custom layer */
polygonIdx = (int *)CustomData_bmesh_get(&em->bm->pdata, newFace->head.data, CD_RECAST);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 0f65ed2c4ad..31653efa735 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -170,6 +170,8 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_bridge_edge_loops);
WM_operatortype_append(MESH_OT_inset);
+ WM_operatortype_append(MESH_OT_intersect);
+ WM_operatortype_append(MESH_OT_face_split_by_edges);
WM_operatortype_append(MESH_OT_poke);
WM_operatortype_append(MESH_OT_wireframe);
WM_operatortype_append(MESH_OT_edge_split);
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 36c7bb404da..f6a54beb8c8 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -594,7 +594,7 @@ bool mouse_mball(bContext *C, const int mval[2], bool extend, bool deselect, boo
rect.ymin = mval[1] - 12;
rect.ymax = mval[1] + 12;
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+ hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
/* does startelem exist? */
ml = mb->editelems->first;
@@ -743,28 +743,3 @@ void undo_push_mball(bContext *C, const char *name)
{
undo_editmode_push(C, name, get_data, free_undoMball, undoMball_to_editMball, editMball_to_undoMball, NULL);
}
-
-void ED_mball_transform(MetaBall *mb, float mat[4][4])
-{
- MetaElem *me;
- float quat[4];
- const float scale = mat4_to_scale(mat);
- const float scale_sqrt = sqrtf(scale);
-
- mat4_to_quat(quat, mat);
-
- 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);
- }
- }
- DAG_id_tag_update(&mb->id, 0);
-}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 99dd8b75609..8972dd7cf08 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -34,6 +34,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_anim_types.h"
+#include "DNA_camera_types.h"
#include "DNA_curve_types.h"
#include "DNA_group_types.h"
#include "DNA_lamp_types.h"
@@ -83,6 +84,7 @@
#include "BKE_report.h"
#include "BKE_sca.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "BKE_speaker.h"
#include "BKE_texture.h"
@@ -95,6 +97,7 @@
#include "ED_armature.h"
#include "ED_curve.h"
+#include "ED_lattice.h"
#include "ED_mball.h"
#include "ED_mesh.h"
#include "ED_node.h"
@@ -336,10 +339,7 @@ bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view
}
else {
Scene *scene = CTX_data_scene(C);
- if (v3d)
- *layer = (v3d->scenelock && !v3d->localvd) ? scene->layact : v3d->layact;
- else
- *layer = scene->layact;
+ *layer = BKE_screen_view3d_layer_active_ex(v3d, scene, false);
for (a = 0; a < 20; a++) {
layer_values[a] = *layer & (1 << a);
}
@@ -446,14 +446,17 @@ Object *ED_object_add_type(bContext *C, int type, const float loc[3], const floa
/* for object add operator */
static int object_add_exec(bContext *C, wmOperator *op)
{
+ Object *ob;
bool enter_editmode;
unsigned int layer;
float loc[3], rot[3];
+ WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
- ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), loc, rot, enter_editmode, layer);
+ ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), loc, rot, enter_editmode, layer);
+ BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
return OPERATOR_FINISHED;
}
@@ -472,6 +475,8 @@ void OBJECT_OT_add(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* properties */
+ ED_object_add_unit_props(ot);
RNA_def_enum(ot->srna, "type", object_type_items, 0, "Type", "");
ED_object_add_generic_props(ot, true);
@@ -488,32 +493,31 @@ static int effector_add_exec(bContext *C, wmOperator *op)
unsigned int layer;
float loc[3], rot[3];
float mat[4][4];
+ float dia;
+ WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
type = RNA_enum_get(op->ptr, "type");
+ dia = RNA_float_get(op->ptr, "radius");
if (type == PFIELD_GUIDE) {
Curve *cu;
ob = ED_object_add_type(C, OB_CURVE, loc, rot, false, layer);
- if (!ob)
- return OPERATOR_CANCELLED;
rename_id(&ob->id, CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "CurveGuide"));
cu = ob->data;
cu->flag |= CU_PATH | CU_3D;
ED_object_editmode_enter(C, 0);
ED_object_new_primitive_matrix(C, ob, loc, rot, mat, false);
- BLI_addtail(&cu->editnurb->nurbs, add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, 1));
+ BLI_addtail(&cu->editnurb->nurbs, add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, dia));
if (!enter_editmode)
ED_object_editmode_exit(C, EM_FREEDATA);
}
else {
ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer);
- if (!ob)
- return OPERATOR_CANCELLED;
-
+ BKE_object_obdata_size_init(ob, dia);
rename_id(&ob->id, CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "Field"));
if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX))
ob->empty_drawtype = OB_SINGLE_ARROW;
@@ -540,8 +544,10 @@ void OBJECT_OT_effector_add(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* properties */
ot->prop = RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", "");
+ ED_object_add_unit_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -552,6 +558,7 @@ static int object_camera_add_exec(bContext *C, wmOperator *op)
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
Object *ob;
+ Camera *cam;
bool enter_editmode;
unsigned int layer;
float loc[3], rot[3];
@@ -572,6 +579,9 @@ static int object_camera_add_exec(bContext *C, wmOperator *op)
}
}
+ cam = ob->data;
+ cam->drawsize = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL);
+
return OPERATOR_FINISHED;
}
@@ -668,6 +678,7 @@ static int object_add_text_exec(bContext *C, wmOperator *op)
unsigned int layer;
float loc[3], rot[3];
+ WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
@@ -675,6 +686,7 @@ static int object_add_text_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
obedit = ED_object_add_type(C, OB_FONT, loc, rot, enter_editmode, layer);
+ BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius"));
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
@@ -694,6 +706,9 @@ void OBJECT_OT_text_add(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ED_object_add_unit_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -706,9 +721,10 @@ static int object_armature_add_exec(bContext *C, wmOperator *op)
bool newob = false;
bool enter_editmode;
unsigned int layer;
- float loc[3], rot[3];
+ float loc[3], rot[3], dia;
bool view_aligned = rv3d && (U.flag & USER_ADD_VIEWALIGNED);
+ WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
@@ -726,7 +742,8 @@ static int object_armature_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- add_primitive_bone(obedit, view_aligned);
+ dia = RNA_float_get(op->ptr, "radius");
+ ED_armature_edit_bone_add_primitive(obedit, dia, view_aligned);
/* userdef */
if (newob && !enter_editmode)
@@ -750,6 +767,9 @@ void OBJECT_OT_armature_add(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ED_object_add_unit_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -762,12 +782,14 @@ static int object_empty_add_exec(bContext *C, wmOperator *op)
unsigned int layer;
float loc[3], rot[3];
+ WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer);
BKE_object_empty_draw_type_set(ob, type);
+ BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
return OPERATOR_FINISHED;
}
@@ -790,6 +812,7 @@ void OBJECT_OT_empty_add(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", object_empty_drawtype_items, 0, "Type", "");
+ ED_object_add_unit_props(ot);
ED_object_add_generic_props(ot, false);
}
@@ -899,12 +922,14 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op)
unsigned int layer;
float loc[3], rot[3];
+ WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
ob = ED_object_add_type(C, OB_LAMP, loc, rot, false, layer);
- la = (Lamp *)ob->data;
+ BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
+ la = (Lamp *)ob->data;
la->type = type;
rename_id(&ob->id, get_lamp_defname(type));
rename_id(&la->id, get_lamp_defname(type));
@@ -936,6 +961,7 @@ void OBJECT_OT_lamp_add(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", lamp_type_items, 0, "Type", "");
RNA_def_property_translation_context(ot->prop, BLF_I18NCONTEXT_ID_LAMP);
+ ED_object_add_unit_props(ot);
ED_object_add_generic_props(ot, false);
}
@@ -1470,7 +1496,7 @@ static void convert_ensure_curve_cache(Main *bmain, Scene *scene, Object *ob)
/* Force creation. This is normally not needed but on operator
* redo we might end up with an object which isn't evaluated yet.
*/
- if (ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
+ if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
BKE_displist_make_curveTypes(scene, ob, false);
}
else if (ob->type == OB_MBALL) {
@@ -2191,6 +2217,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
wmWindow *win = CTX_wm_window(C);
const wmEvent *event = win ? win->eventstate : NULL;
Main *bmain = CTX_data_main(C);
+ View3D *v3d = CTX_wm_view3d(C); /* may be NULL */
Scene *scene = CTX_data_scene(C);
Base *basen, *base;
Object *ob;
@@ -2223,7 +2250,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- basen->lay = basen->object->lay = scene->lay;
+ basen->lay = basen->object->lay = BKE_screen_view3d_layer_active(v3d, scene);
basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
if (event) {
@@ -2274,7 +2301,7 @@ static int join_poll(bContext *C)
if (!ob || ob->id.lib) return 0;
- if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE))
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE))
return ED_operator_screenactive(C);
else
return 0;
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index 94574e81b81..2402ecb498d 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -770,7 +770,7 @@ static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), const
static bool is_multires_bake(Scene *scene)
{
- if (ELEM4(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_AO))
+ if (ELEM(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_AO))
return scene->r.bake_flag & R_BAKE_MULTIRES;
return 0;
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index b45ac124b43..372ca33fa4b 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_node.h"
#include "BKE_report.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
@@ -74,6 +75,63 @@
#include "object_intern.h"
+
+typedef struct BakeAPIRender {
+ Object *ob;
+ Main *main;
+ Scene *scene;
+ ReportList *reports;
+ ListBase selected_objects;
+
+ ScenePassType pass_type;
+ int margin;
+
+ int save_mode;
+
+ bool is_clear;
+ bool is_split_materials;
+ bool is_automatic_name;
+ bool is_selected_to_active;
+ bool is_cage;
+
+ float cage_extrusion;
+ int normal_space;
+ BakeNormalSwizzle normal_swizzle[3];
+
+ char uv_layer[MAX_CUSTOMDATA_LAYER_NAME];
+ char custom_cage[MAX_NAME];
+ char filepath[FILE_MAX];
+
+ int width;
+ int height;
+ const char *identifier;
+
+ int result;
+ bool ready;
+
+ /* callbacks */
+ Render *render;
+ float *progress;
+ short *do_update;
+
+ /* for redrawing */
+ ScrArea *sa;
+} BakeAPIRender;
+
+/* callbacks */
+
+static void bake_progress_update(void *bjv, float progress)
+{
+ BakeAPIRender *bj = bjv;
+
+ if (bj->progress && *bj->progress != progress) {
+ *bj->progress = progress;
+
+ /* make jobs timer to send notifier */
+ *(bj->do_update) = true;
+ }
+}
+
/* catch esc */
static int bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
@@ -120,7 +178,7 @@ static bool write_internal_bake_pixels(
void *lock;
bool is_float;
char *mask_buffer = NULL;
- const int num_pixels = width * height;
+ const size_t num_pixels = (size_t)width * (size_t)height;
ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
@@ -156,7 +214,7 @@ static bool write_internal_bake_pixels(
IMB_buffer_float_from_float(
ibuf->rect_float, buffer, ibuf->channels,
IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
- ibuf->x, ibuf->y, ibuf->x, ibuf->y);
+ ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
else {
IMB_buffer_byte_from_float(
@@ -169,7 +227,7 @@ static bool write_internal_bake_pixels(
if (is_float) {
IMB_buffer_float_from_float_mask(
ibuf->rect_float, buffer, ibuf->channels,
- ibuf->x, ibuf->y, ibuf->x, ibuf->y, mask_buffer);
+ ibuf->x, ibuf->y, ibuf->x, ibuf->x, mask_buffer);
}
else {
IMB_buffer_byte_from_float_mask(
@@ -235,7 +293,7 @@ static bool write_external_bake_pixels(
IMB_buffer_float_from_float(
ibuf->rect_float, buffer, ibuf->channels,
IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
- ibuf->x, ibuf->y, ibuf->x, ibuf->y);
+ ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
else {
if (!is_noncolor) {
@@ -253,7 +311,7 @@ static bool write_external_bake_pixels(
/* margins */
if (margin > 0) {
char *mask_buffer = NULL;
- const int num_pixels = width * height;
+ const size_t num_pixels = (size_t)width * (size_t)height;
mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
@@ -278,14 +336,14 @@ static bool write_external_bake_pixels(
static bool is_noncolor_pass(ScenePassType pass_type)
{
- return ELEM7(pass_type,
- SCE_PASS_Z,
- SCE_PASS_NORMAL,
- SCE_PASS_VECTOR,
- SCE_PASS_INDEXOB,
- SCE_PASS_UV,
- SCE_PASS_RAYHITS,
- SCE_PASS_INDEXMA);
+ return ELEM(pass_type,
+ SCE_PASS_Z,
+ SCE_PASS_NORMAL,
+ SCE_PASS_VECTOR,
+ SCE_PASS_INDEXOB,
+ SCE_PASS_UV,
+ SCE_PASS_RAYHITS,
+ SCE_PASS_INDEXMA);
}
/* if all is good tag image and return true */
@@ -310,10 +368,22 @@ static bool bake_object_check(Object *ob, ReportList *reports)
}
for (i = 0; i < ob->totcol; i++) {
- ED_object_get_active_image(ob, i + 1, &image, NULL, NULL);
+ bNodeTree *ntree = NULL;
+ bNode *node = NULL;
+ ED_object_get_active_image(ob, i + 1, &image, NULL, &node, &ntree);
if (image) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+ ImBuf *ibuf;
+
+ if (node) {
+ if (BKE_node_is_connected_to_output(ntree, node)) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Circular dependency for image \"%s\" from object \"%s\"",
+ image->id.name + 2, ob->id.name + 2);
+ }
+ }
+
+ ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
if (ibuf) {
BKE_image_release_ibuf(image, ibuf, lock);
@@ -372,7 +442,7 @@ static bool bake_objects_check(Main *bmain, Object *ob, ListBase *selected_objec
if (ob_iter == ob)
continue;
- if (ELEM5(ob_iter->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL) == false) {
+ if (ELEM(ob_iter->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL) == false) {
BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh or can't be converted to a mesh (Curve, Text, Surface or Metaball)", ob_iter->id.name + 2);
return false;
}
@@ -420,7 +490,7 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
for (i = 0; i < tot_mat; i++) {
Image *image;
- ED_object_get_active_image(ob, i + 1, &image, NULL, NULL);
+ ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
if ((image->id.flag & LIB_DOIT)) {
for (j = 0; j < i; j++) {
@@ -444,10 +514,10 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
/*
* returns the total number of pixels
*/
-static int initialize_internal_images(BakeImages *bake_images, ReportList *reports)
+static size_t initialize_internal_images(BakeImages *bake_images, ReportList *reports)
{
int i;
- int tot_size = 0;
+ size_t tot_size = 0;
for (i = 0; i < bake_images->size; i++) {
ImBuf *ibuf;
@@ -461,7 +531,7 @@ static int initialize_internal_images(BakeImages *bake_images, ReportList *repor
bk_image->height = ibuf->y;
bk_image->offset = tot_size;
- tot_size += ibuf->x * ibuf->y;
+ tot_size += (size_t)ibuf->x * (size_t)ibuf->y;
}
else {
BKE_image_release_ibuf(bk_image->image, ibuf, lock);
@@ -473,45 +543,8 @@ static int initialize_internal_images(BakeImages *bake_images, ReportList *repor
return tot_size;
}
-typedef struct BakeAPIRender {
- Object *ob;
- Main *main;
- Scene *scene;
- ReportList *reports;
- ListBase selected_objects;
-
- ScenePassType pass_type;
- int margin;
-
- int save_mode;
-
- bool is_clear;
- bool is_split_materials;
- bool is_automatic_name;
- bool is_selected_to_active;
- bool is_cage;
-
- float cage_extrusion;
- int normal_space;
- BakeNormalSwizzle normal_swizzle[3];
-
- char uv_layer[MAX_CUSTOMDATA_LAYER_NAME];
- char custom_cage[MAX_NAME];
- char filepath[FILE_MAX];
-
- int width;
- int height;
- const char *identifier;
-
- int result;
- bool ready;
-
- /* for redrawing */
- ScrArea *sa;
-} BakeAPIRender;
-
static int bake(
- Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports,
+ Render *re, Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports,
const ScenePassType pass_type, const int margin,
const BakeSaveMode save_mode, const bool is_clear, const bool is_split_materials,
const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage,
@@ -528,11 +561,10 @@ static int bake(
int tot_highpoly;
char restrict_flag_low = ob_low->restrictflag;
- char restrict_flag_cage;
+ char restrict_flag_cage = 0;
Mesh *me_low = NULL;
Mesh *me_cage = NULL;
- Render *re;
float *result = NULL;
@@ -544,13 +576,10 @@ static int bake(
BakeImages bake_images = {NULL};
- int num_pixels;
+ size_t num_pixels;
int tot_materials;
int i;
- re = RE_NewRender(scene->id.name);
- RE_SetReports(re, NULL);
-
RE_bake_engine_set_engine_parameters(re, bmain, scene);
if (!RE_bake_has_engine(re)) {
@@ -589,8 +618,8 @@ static int bake(
}
/* we overallocate in case there is more materials than images */
- bake_images.data = MEM_callocN(sizeof(BakeImage) * tot_materials, "bake images dimensions (width, height, offset)");
- bake_images.lookup = MEM_callocN(sizeof(int) * tot_materials, "bake images lookup (from material to BakeImage)");
+ bake_images.data = MEM_mallocN(sizeof(BakeImage) * tot_materials, "bake images dimensions (width, height, offset)");
+ bake_images.lookup = MEM_mallocN(sizeof(int) * tot_materials, "bake images lookup (from material to BakeImage)");
build_image_lookup(bmain, ob_low, &bake_images);
@@ -604,7 +633,7 @@ static int bake(
else {
/* when saving extenally always use the size specified in the UI */
- num_pixels = width * height * bake_images.size;
+ num_pixels = (size_t)width * (size_t)height * bake_images.size;
for (i = 0; i < bake_images.size; i++) {
bake_images.data[i].width = width;
@@ -647,12 +676,7 @@ static int bake(
}
}
- /* blender_test_break uses this global */
- G.is_break = false;
-
- RE_test_break_cb(re, NULL, bake_break);
-
- pixel_array_low = MEM_callocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
+ pixel_array_low = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");
/* get the mesh as it arrives in the renderer */
@@ -719,10 +743,8 @@ static int bake(
/* initialize highpoly_data */
highpoly[i].ob = ob_iter;
- highpoly[i].me = NULL;
- highpoly[i].tri_mod = NULL;
highpoly[i].restrict_flag = ob_iter->restrictflag;
- highpoly[i].pixel_array = MEM_callocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
+ highpoly[i].pixel_array = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
/* triangulating so BVH returns the primitive_id that will be used for rendering */
@@ -1038,6 +1060,8 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
bkr->result = OPERATOR_CANCELLED;
+ bkr->render = RE_NewRender(bkr->scene->id.name);
+
/* XXX hack to force saving to always be internal. Whether (and how) to support
* external saving will be addressed later */
bkr->save_mode = R_BAKE_SAVE_INTERNAL;
@@ -1045,10 +1069,15 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
static int bake_exec(bContext *C, wmOperator *op)
{
+ Render *re;
int result = OPERATOR_CANCELLED;
BakeAPIRender bkr = {NULL};
bake_init_api_data(op, C, &bkr);
+ re = bkr.render;
+
+ /* setup new render */
+ RE_test_break_cb(re, NULL, bake_break);
if (!bake_objects_check(bkr.main, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active))
return OPERATOR_CANCELLED;
@@ -1058,9 +1087,11 @@ static int bake_exec(bContext *C, wmOperator *op)
bake_images_clear(bkr.main, is_tangent);
}
+ RE_SetReports(re, bkr.reports);
+
if (bkr.is_selected_to_active) {
result = bake(
- bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports,
+ bkr.render, bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports,
bkr.pass_type, bkr.margin, bkr.save_mode,
bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage,
bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
@@ -1073,7 +1104,7 @@ static int bake_exec(bContext *C, wmOperator *op)
for (link = bkr.selected_objects.first; link; link = link->next) {
Object *ob_iter = link->ptr.data;
result = bake(
- bkr.main, bkr.scene, ob_iter, NULL, bkr.reports,
+ bkr.render, bkr.main, bkr.scene, ob_iter, NULL, bkr.reports,
bkr.pass_type, bkr.margin, bkr.save_mode,
is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage,
bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
@@ -1082,14 +1113,22 @@ static int bake_exec(bContext *C, wmOperator *op)
}
}
+ RE_SetReports(re, NULL);
+
BLI_freelistN(&bkr.selected_objects);
return result;
}
-static void bake_startjob(void *bkv, short *UNUSED(stop), short *UNUSED(do_update), float *UNUSED(progress))
+static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, float *progress)
{
BakeAPIRender *bkr = (BakeAPIRender *)bkv;
+ /* setup new render */
+ bkr->do_update = do_update;
+ bkr->progress = progress;
+
+ RE_SetReports(bkr->render, bkr->reports);
+
if (!bake_objects_check(bkr->main, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) {
bkr->result = OPERATOR_CANCELLED;
return;
@@ -1102,7 +1141,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *UNUSED(do_updat
if (bkr->is_selected_to_active) {
bkr->result = bake(
- bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports,
+ bkr->render, bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports,
bkr->pass_type, bkr->margin, bkr->save_mode,
bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true, bkr->is_cage,
bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
@@ -1115,7 +1154,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *UNUSED(do_updat
for (link = bkr->selected_objects.first; link; link = link->next) {
Object *ob_iter = link->ptr.data;
bkr->result = bake(
- bkr->main, bkr->scene, ob_iter, NULL, bkr->reports,
+ bkr->render, bkr->main, bkr->scene, ob_iter, NULL, bkr->reports,
bkr->pass_type, bkr->margin, bkr->save_mode,
is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage,
bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
@@ -1126,6 +1165,8 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *UNUSED(do_updat
return;
}
}
+
+ RE_SetReports(bkr->render, NULL);
}
static void bake_freejob(void *bkv)
@@ -1228,6 +1269,7 @@ static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)
{
wmJob *wm_job;
BakeAPIRender *bkr;
+ Render *re;
Scene *scene = CTX_data_scene(C);
bake_set_props(op, scene);
@@ -1236,10 +1278,15 @@ static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)
if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_OBJECT_BAKE))
return OPERATOR_CANCELLED;
- bkr = MEM_callocN(sizeof(BakeAPIRender), "render bake");
+ bkr = MEM_mallocN(sizeof(BakeAPIRender), "render bake");
/* init bake render */
bake_init_api_data(op, C, bkr);
+ re = bkr->render;
+
+ /* setup new render */
+ RE_test_break_cb(re, NULL, bake_break);
+ RE_progress_cb(re, bkr, bake_progress_update);
/* setup job */
wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Texture Bake",
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 85e4bbce8dc..92ed84b7f5e 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -485,7 +485,7 @@ static void test_constraints(Object *owner, bPoseChannel *pchan)
}
/* target checks for specific constraints */
- if (ELEM3(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) {
+ if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) {
if (ct->tar) {
if (ct->tar->type != OB_CURVE) {
ct->tar = NULL;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index aba792413af..93956128b84 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -139,7 +139,9 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
/* XXX need a context loop to handle such cases */
for (base = FIRSTBASE; base; base = base->next) {
if ((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
- base->flag |= SELECT;
+ if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) {
+ base->flag |= SELECT;
+ }
base->object->flag = base->flag;
base->object->restrictflag &= ~OB_RESTRICT_VIEW;
changed = true;
@@ -361,6 +363,11 @@ static bool ED_object_editmode_load_ex(Object *obedit, const bool freedata)
if (freedata) free_editMball(obedit);
}
+ /* Tag update so no access to freed data referenced from
+ * derived cache will happen.
+ */
+ DAG_id_tag_update((ID *)obedit->data, 0);
+
return true;
}
@@ -447,7 +454,7 @@ void ED_object_editmode_enter(bContext *C, int flag)
base = scene->basact;
}
- if (ELEM3(NULL, base, base->object, base->object->data)) return;
+ if (ELEM(NULL, base, base->object, base->object->data)) return;
ob = base->object;
@@ -589,7 +596,7 @@ static int editmode_toggle_poll(bContext *C)
if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT))
return 0;
- return (ELEM7(ob->type, OB_MESH, OB_ARMATURE, OB_FONT, OB_MBALL, OB_LATTICE, OB_SURF, OB_CURVE));
+ return OB_TYPE_SUPPORT_EDITMODE(ob->type);
}
void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
@@ -760,7 +767,7 @@ static void copy_texture_space(Object *to, Object *ob)
texflag = ((Mesh *)ob->data)->texflag;
poin2 = ((Mesh *)ob->data)->loc;
}
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
texflag = ((Curve *)ob->data)->texflag;
poin2 = ((Curve *)ob->data)->loc;
}
@@ -775,7 +782,7 @@ static void copy_texture_space(Object *to, Object *ob)
((Mesh *)to->data)->texflag = texflag;
poin1 = ((Mesh *)to->data)->loc;
}
- else if (ELEM3(to->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(to->type, OB_CURVE, OB_SURF, OB_FONT)) {
((Curve *)to->data)->texflag = texflag;
poin1 = ((Curve *)to->data)->loc;
}
@@ -1112,7 +1119,7 @@ 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 (ELEM4(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE))
+ if (ELEM(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE))
ED_object_modifier_add(NULL, bmain, scene, object, NULL, eModifierType_Surface);
}
else {
@@ -1453,7 +1460,7 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
BKE_mesh_texspace_get(ob->data, NULL, NULL, size);
space = size[0] / size[1];
}
- else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
float size[3];
BKE_curve_texspace_get(ob->data, NULL, NULL, size);
space = size[0] / size[1];
@@ -1500,7 +1507,7 @@ static EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *UNUSED(
if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
(input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
(input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
- (ELEM4(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT,
+ (ELEM(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT,
OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
(input->value == OB_MODE_OBJECT))
{
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 47b5f1605e7..20e2e22cdf8 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -563,3 +563,67 @@ void OBJECT_OT_group_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+static int group_unlink_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+
+ if (!group)
+ return OPERATOR_CANCELLED;
+
+ BKE_group_unlink(group);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_group_unlink(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Unlink Group";
+ ot->idname = "OBJECT_OT_group_unlink";
+ ot->description = "Unlink the group from all objects";
+
+ /* api callbacks */
+ ot->exec = group_unlink_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select objects in the same group as the active */
+{
+ Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+
+ if (!group)
+ return OPERATOR_CANCELLED;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ {
+ if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) {
+ ED_base_object_select(base, BA_SELECT);
+ }
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_grouped_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Grouped";
+ ot->idname = "OBJECT_OT_grouped_select";
+ ot->description = "Select all objects in group";
+
+ /* api callbacks */
+ ot->exec = select_grouped_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index afff367b939..9f9a647c9f1 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -528,8 +528,7 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob
invert_m4_m4(ob->imat, ob->obmat);
/* apparently this call goes from right to left... */
- mul_serie_m4(hmd->parentinv, pose_mat, ob->imat, obedit->obmat,
- NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(hmd->parentinv, pose_mat, ob->imat, obedit->obmat);
DAG_relations_tag_update(bmain);
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index fd6b9a1bad0..6fa3caa6172 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -72,6 +72,7 @@ void OBJECT_OT_make_links_scene(struct wmOperatorType *ot);
void OBJECT_OT_make_links_data(struct wmOperatorType *ot);
void OBJECT_OT_move_to_layer(struct wmOperatorType *ot);
void OBJECT_OT_drop_named_material(struct wmOperatorType *ot);
+void OBJECT_OT_unlink_data(struct wmOperatorType *ot);
/* object_edit.c */
void OBJECT_OT_mode_set(struct wmOperatorType *ot);
@@ -251,6 +252,8 @@ void OBJECT_OT_shape_key_move(struct wmOperatorType *ot);
void OBJECT_OT_group_add(struct wmOperatorType *ot);
void OBJECT_OT_group_link(struct wmOperatorType *ot);
void OBJECT_OT_group_remove(struct wmOperatorType *ot);
+void OBJECT_OT_group_unlink(struct wmOperatorType *ot);
+void OBJECT_OT_grouped_select(struct wmOperatorType *ot);
/* object_bake.c */
void OBJECT_OT_bake_image(wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c
index 3897e452d0d..c24a127ed8b 100644
--- a/source/blender/editors/object/object_lattice.c
+++ b/source/blender/editors/object/object_lattice.c
@@ -174,21 +174,6 @@ void load_editLatt(Object *obedit)
}
}
-/*************************** Transform Operator ************************/
-
-void ED_lattice_transform(Lattice *lt, float mat[4][4])
-{
- BPoint *bp = lt->def;
- int a = lt->pntsu * lt->pntsv * lt->pntsw;
-
- while (a--) {
- mul_m4_v3(mat, bp->vec);
- bp++;
- }
-
- DAG_id_tag_update(&lt->id, 0);
-}
-
static void bpoint_select_set(BPoint *bp, bool select)
{
if (select) {
diff --git a/source/blender/editors/object/object_lod.c b/source/blender/editors/object/object_lod.c
index 8bcbba6be96..48e980015a7 100644
--- a/source/blender/editors/object/object_lod.c
+++ b/source/blender/editors/object/object_lod.c
@@ -29,15 +29,11 @@
* \ingroup edobj
*/
-
#include "DNA_object_types.h"
#include "BKE_context.h"
#include "BKE_object.h"
-#include "ED_screen.h"
-#include "ED_object.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -45,6 +41,9 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "ED_screen.h"
+#include "ED_object.h"
+
#include "object_intern.h"
static int object_lod_add_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 1249beb4517..b05840b5823 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -98,7 +98,7 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
ModifierTypeInfo *mti = modifierType_getInfo(type);
/* only geometry objects should be able to get modifiers [#25291] */
- if (!ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
+ if (!ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
return NULL;
}
@@ -1876,7 +1876,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
else if (ob->type == OB_MBALL) {
BKE_displist_make_mball(CTX_data_main(C)->eval_ctx, scene, ob);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
BKE_displist_make_curveTypes(scene, ob, 0);
}
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index a8f07747d3a..7cf661de52c 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -229,6 +229,8 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_group_add);
WM_operatortype_append(OBJECT_OT_group_link);
WM_operatortype_append(OBJECT_OT_group_remove);
+ WM_operatortype_append(OBJECT_OT_group_unlink);
+ WM_operatortype_append(OBJECT_OT_grouped_select);
WM_operatortype_append(OBJECT_OT_hook_add_selob);
WM_operatortype_append(OBJECT_OT_hook_add_newob);
@@ -241,6 +243,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_bake_image);
WM_operatortype_append(OBJECT_OT_bake);
WM_operatortype_append(OBJECT_OT_drop_named_material);
+ WM_operatortype_append(OBJECT_OT_unlink_data);
WM_operatortype_append(OBJECT_OT_laplaciandeform_bind);
WM_operatortype_append(OBJECT_OT_lod_add);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 3059d84a085..0d58eaee5fa 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -444,7 +444,7 @@ EnumPropertyItem prop_clear_parent_types[] = {
/* Helper for ED_object_parent_clear() - Remove deform-modifiers associated with parent */
static void object_remove_parent_deform_modifiers(Object *ob, const Object *par)
{
- if (ELEM3(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVE)) {
+ if (ELEM(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVE)) {
ModifierData *md, *mdn;
/* assume that we only need to remove the first instance of matching deform modifier here */
@@ -593,7 +593,7 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
int partype, bool xmirror, bool keep_transform, const int vert_par[3])
{
bPoseChannel *pchan = NULL;
- int pararm = ELEM4(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
+ int pararm = ELEM(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
DAG_id_tag_update(&par->id, OB_RECALC_OB);
@@ -678,7 +678,7 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
* assuming that the parent is selected too...
*/
// XXX currently this should only happen for meshes, curves, surfaces, and lattices - this stuff isn't available for metas yet
- if (ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
ModifierData *md;
switch (partype) {
@@ -1128,7 +1128,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
/* also remove all tracking constraints */
for (con = ob->constraints.last; con; con = pcon) {
pcon = con->prev;
- if (ELEM3(con->type, CONSTRAINT_TYPE_TRACKTO, CONSTRAINT_TYPE_LOCKTRACK, CONSTRAINT_TYPE_DAMPTRACK))
+ if (ELEM(con->type, CONSTRAINT_TYPE_TRACKTO, CONSTRAINT_TYPE_LOCKTRACK, CONSTRAINT_TYPE_DAMPTRACK))
BKE_constraint_remove(&ob->constraints, con);
}
@@ -1192,7 +1192,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
- if (ELEM3(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
data->trackflag = TRACK_nZ;
}
}
@@ -1213,7 +1213,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
- if (ELEM3(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
data->reserved1 = TRACK_nZ;
data->reserved2 = UP_Y;
}
@@ -1235,7 +1235,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
- if (ELEM3(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
data->trackflag = TRACK_nZ;
data->lockflag = LOCK_Y;
}
@@ -2143,9 +2143,40 @@ static void tag_localizable_objects(bContext *C, int mode)
/* TODO(sergey): Drivers targets? */
}
+/**
+ * Instance indirectly referenced zero user objects,
+ * otherwise they're lost on reload, see T40595.
+ */
+static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene)
+{
+ Object *ob;
+ bool changed = false;
+
+ for (ob = bmain->object.first; ob; ob = ob->id.next) {
+ if (ob->id.lib && (ob->id.us == 0)) {
+ Base *base;
+
+ ob->id.us = 1;
+
+ /* not essential, but for correctness */
+ id_lib_extern(&ob->id);
+
+ base = BKE_scene_base_add(scene, ob);
+ base->flag |= SELECT;
+ base->object->flag = base->flag;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
static int make_local_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
AnimData *adt;
ParticleSystem *psys;
Material *ma, ***matarar;
@@ -2154,6 +2185,14 @@ static int make_local_exec(bContext *C, wmOperator *op)
int a, b, mode = RNA_enum_get(op->ptr, "type");
if (mode == MAKE_LOCAL_ALL) {
+ /* de-select so the user can differentiate newly instanced from existing objects */
+ BKE_scene_base_deselect_all(scene);
+
+ 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");
+ }
+
BKE_library_make_local(bmain, NULL, false); /* NULL is all libs */
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
@@ -2399,3 +2438,55 @@ void OBJECT_OT_drop_named_material(wmOperatorType *ot)
/* properties */
RNA_def_string(ot->srna, "name", "Material", MAX_ID_NAME - 2, "Name", "Material name to assign");
}
+
+static int object_unlink_data_exec(bContext *C, wmOperator *op)
+{
+ ID *id;
+ PropertyPointerRNA pprop;
+
+ uiIDContextProperty(C, &pprop.ptr, &pprop.prop);
+
+ if (pprop.prop == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Incorrect context for running object data unlink");
+ return OPERATOR_CANCELLED;
+ }
+
+ id = pprop.ptr.id.data;
+
+ if (GS(id->name) == ID_OB) {
+ Object *ob = (Object *)id;
+ if (ob->data) {
+ ID *id_data = ob->data;
+
+ if (GS(id_data->name) == ID_IM) {
+ id_us_min(id_data);
+ ob->data = NULL;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Can't unlink this object data");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
+
+ RNA_property_update(C, &pprop.ptr, pprop.prop);
+
+ return OPERATOR_FINISHED;
+}
+
+/**
+ * \note Only for empty-image objects, this operator is needed
+ */
+void OBJECT_OT_unlink_data(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Unlink";
+ ot->idname = "OBJECT_OT_unlink_data";
+ ot->description = "";
+
+ /* api callbacks */
+ ot->exec = object_unlink_data_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
+}
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 9b1aa054f84..e295a63848a 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -753,11 +753,11 @@ static bool select_grouped_color(bContext *C, Object *ob)
static bool objects_share_gameprop(Object *a, Object *b)
{
bProperty *prop;
- /*make a copy of all its properties*/
for (prop = a->prop.first; prop; prop = prop->next) {
- if (BKE_bproperty_object_get(b, prop->name) )
+ if (BKE_bproperty_object_get(b, prop->name)) {
return 1;
+ }
}
return 0;
}
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index cfd1c4d3b0a..85104c14395 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -485,27 +485,22 @@ void OBJECT_OT_shape_key_mirror(wmOperatorType *ot)
static int shape_key_move_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
-
- int type = RNA_enum_get(op->ptr, "type");
Key *key = BKE_key_from_object(ob);
- if (key) {
- KeyBlock *kb, *kb_other;
- int shapenr_act = ob->shapenr - 1;
- int shapenr_swap = shapenr_act + type;
- kb = BLI_findlink(&key->block, shapenr_act);
+ if (!key) {
+ return OPERATOR_CANCELLED;
+ }
- if ((type == -1 && kb->prev == NULL) || (type == 1 && kb->next == NULL)) {
- return OPERATOR_CANCELLED;
- }
+ {
+ KeyBlock *kb, *kb_other, *kb_iter;
+ const int type = RNA_enum_get(op->ptr, "type");
+ const int shape_tot = key->totkey;
+ const int shapenr_act = ob->shapenr - 1;
+ const int shapenr_swap = (shape_tot + shapenr_act + type) % shape_tot;
- for (kb_other = key->block.first; kb_other; kb_other = kb_other->next) {
- if (kb_other->relative == shapenr_act) {
- kb_other->relative += type;
- }
- else if (kb_other->relative == shapenr_swap) {
- kb_other->relative -= type;
- }
+ kb = BLI_findlink(&key->block, shapenr_act);
+ if (!kb || shape_tot == 1) {
+ return OPERATOR_CANCELLED;
}
if (type == -1) {
@@ -513,17 +508,57 @@ static int shape_key_move_exec(bContext *C, wmOperator *op)
kb_other = kb->prev;
BLI_remlink(&key->block, kb);
BLI_insertlinkbefore(&key->block, kb_other, kb);
- ob->shapenr--;
}
else {
/* move next */
kb_other = kb->next;
BLI_remlink(&key->block, kb);
BLI_insertlinkafter(&key->block, kb_other, kb);
- ob->shapenr++;
}
- SWAP(float, kb_other->pos, kb->pos); /* for absolute shape keys */
+ ob->shapenr = shapenr_swap + 1;
+
+ /* for relative shape keys */
+ if (kb_other) {
+ for (kb_iter = key->block.first; kb_iter; kb_iter = kb_iter->next) {
+ if (kb_iter->relative == shapenr_act) {
+ kb_iter->relative = shapenr_swap;
+ }
+ else if (kb_iter->relative == shapenr_swap) {
+ kb_iter->relative = shapenr_act;
+ }
+ }
+ }
+ /* First key became last, or vice-versa, we have to change all keys' relative value. */
+ else {
+ for (kb_iter = key->block.first; kb_iter; kb_iter = kb_iter->next) {
+ if (kb_iter->relative == shapenr_act) {
+ kb_iter->relative = shapenr_swap;
+ }
+ else {
+ kb_iter->relative += type;
+ }
+ }
+ }
+
+ /* for absolute shape keys */
+ if (kb_other) {
+ SWAP(float, kb_other->pos, kb->pos);
+ }
+ /* First key became last, or vice-versa, we have to change all keys' pos value. */
+ else {
+ float pos = kb->pos;
+ if (type == -1) {
+ for (kb_iter = key->block.first; kb_iter; kb_iter = kb_iter->next) {
+ SWAP(float, kb_iter->pos, pos);
+ }
+ }
+ else {
+ for (kb_iter = key->block.last; kb_iter; kb_iter = kb_iter->prev) {
+ SWAP(float, kb_iter->pos, pos);
+ }
+ }
+ }
/* First key is refkey, matches interface and BKE_key_sort */
key->refkey = key->block.first;
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 6e59f9f4aea..a1b8478a0e1 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -385,7 +385,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l
/* first check if we can execute */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
- if (ELEM6(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF)) {
+ if (ELEM(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF)) {
ID *obdata = ob->data;
if (ID_REAL_USERS(obdata) > 1) {
BKE_reportf(reports, RPT_ERROR,
@@ -472,27 +472,12 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l
/* apply to object data */
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
- MVert *mvert;
- int a;
if (apply_scale)
multiresModifier_scale_disp(scene, ob);
/* adjust data */
- mvert = me->mvert;
- for (a = 0; a < me->totvert; a++, mvert++)
- mul_m4_v3(mat, mvert->co);
-
- if (me->key) {
- KeyBlock *kb;
-
- for (kb = me->key->block.first; kb; kb = kb->next) {
- float *fp = kb->data;
-
- for (a = 0; a < kb->totelem; a++, fp += 3)
- mul_m4_v3(mat, fp);
- }
- }
+ BKE_mesh_transform(me, mat, true);
/* update normals */
BKE_mesh_calc_normals(me);
@@ -502,45 +487,17 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l
}
else if (ob->type == OB_LATTICE) {
Lattice *lt = ob->data;
- BPoint *bp = lt->def;
- int a = lt->pntsu * lt->pntsv * lt->pntsw;
-
- while (a--) {
- mul_m4_v3(mat, bp->vec);
- bp++;
- }
+
+ BKE_lattice_transform(lt, mat, true);
}
else if (ob->type == OB_MBALL) {
MetaBall *mb = ob->data;
- ED_mball_transform(mb, mat);
+ BKE_mball_transform(mb, mat);
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu = ob->data;
-
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
-
scale = mat3_to_scale(rsmat);
-
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- for (bezt = nu->bezt; a--; bezt++) {
- mul_m4_v3(mat, bezt->vec[0]);
- mul_m4_v3(mat, bezt->vec[1]);
- mul_m4_v3(mat, bezt->vec[2]);
- bezt->radius *= scale;
- }
- BKE_nurb_handles_calc(nu);
- }
- else {
- a = nu->pntsu * nu->pntsv;
- for (bp = nu->bp; a--; bp++)
- mul_m4_v3(mat, bp->vec);
- }
- }
+ BKE_curve_transform_ex(cu, mat, true, scale);
}
else if (ob->type == OB_CAMERA) {
MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
@@ -784,7 +741,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
}
if (ctx_ob_act) {
- BLI_rotatelist_first(&ctx_data_list, (LinkData *)ctx_ob_act);
+ BLI_listbase_rotate_first(&ctx_data_list, (LinkData *)ctx_ob_act);
}
for (tob = bmain->object.first; tob; tob = tob->id.next) {
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index ccc3e2e8278..6897861c81c 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -62,6 +62,7 @@
#include "BKE_depsgraph.h"
#include "BKE_mesh_mapping.h"
#include "BKE_editmesh.h"
+#include "BKE_modifier.h"
#include "BKE_report.h"
#include "BKE_DerivedMesh.h"
#include "BKE_object_deform.h"
@@ -2301,7 +2302,6 @@ static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const i
if (dvert_array)
MEM_freeN(dvert_array);
- BLI_SMALLSTACK_FREE(dv_stack);
/* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */
if (use_mirror) {
@@ -4324,7 +4324,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int vgroup_sort(void *def_a_ptr, void *def_b_ptr)
+static int vgroup_sort_name(void *def_a_ptr, void *def_b_ptr)
{
bDeformGroup *def_a = (bDeformGroup *)def_a_ptr;
bDeformGroup *def_b = (bDeformGroup *)def_b_ptr;
@@ -4332,18 +4332,59 @@ static int vgroup_sort(void *def_a_ptr, void *def_b_ptr)
return BLI_natstrcmp(def_a->name, def_b->name);
}
+/* Sorts the weight groups according to the bone hierarchy of the
+ associated armature (similar to how bones are ordered in the Outliner) */
+static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase)
+{
+ if (bonebase == NULL) {
+ Object *armobj = modifiers_isDeformedByArmature(ob);
+ if (armobj != NULL) {
+ bArmature *armature = armobj->data;
+ bonebase = &armature->bonebase;
+ }
+ }
+
+ if (bonebase != NULL) {
+ Bone *bone;
+ for (bone = bonebase->last; bone; bone = bone->prev) {
+ bDeformGroup *dg = defgroup_find_name(ob, bone->name);
+ vgroup_sort_bone_hierarchy(ob, &bone->childbase);
+
+ if (dg != NULL) {
+ BLI_remlink(&ob->defbase, dg);
+ BLI_addhead(&ob->defbase, dg);
+ }
+ }
+ }
+
+ return;
+}
+
+enum {
+ SORT_TYPE_NAME = 0,
+ SORT_TYPE_BONEHIERARCHY = 1
+};
+
static int vertex_group_sort_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
char *name_array;
int ret;
+ int sort_type = RNA_enum_get(op->ptr, "sort_type");
/*init remapping*/
name_array = vgroup_init_remap(ob);
/*sort vgroup names*/
- BLI_sortlist(&ob->defbase, vgroup_sort);
-
+ switch (sort_type) {
+ case SORT_TYPE_NAME:
+ BLI_sortlist(&ob->defbase, vgroup_sort_name);
+ break;
+ case SORT_TYPE_BONEHIERARCHY:
+ vgroup_sort_bone_hierarchy(ob, NULL);
+ break;
+ }
+
/*remap vgroup data to map to correct names*/
ret = vgroup_do_remap(ob, name_array, op);
@@ -4359,9 +4400,15 @@ static int vertex_group_sort_exec(bContext *C, wmOperator *op)
void OBJECT_OT_vertex_group_sort(wmOperatorType *ot)
{
+ static EnumPropertyItem vgroup_sort_type[] = {
+ {SORT_TYPE_NAME, "NAME", 0, "Name", ""},
+ {SORT_TYPE_BONEHIERARCHY, "BONE_HIERARCHY", 0, "Bone Hierarchy", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
ot->name = "Sort Vertex Groups";
ot->idname = "OBJECT_OT_vertex_group_sort";
- ot->description = "Sort vertex groups alphabetically";
+ ot->description = "Sort vertex groups";
/* api callbacks */
ot->poll = vertex_group_poll;
@@ -4369,6 +4416,8 @@ void OBJECT_OT_vertex_group_sort(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "sort_type", vgroup_sort_type, SORT_TYPE_NAME, "Sort type", "Sort type");
}
static int vgroup_move_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index b46d79fc82e..13a3d7a523f 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -485,78 +485,6 @@ static EnumPropertyItem *rigidbody_materials_itemf(bContext *UNUSED(C), PointerR
/* ------------------------------------------ */
-/* helper function to calculate volume of rigidbody object */
-// TODO: allow a parameter to specify method used to calculate this?
-static float rigidbody_object_calc_volume(Object *ob)
-{
- RigidBodyOb *rbo = ob->rigidbody_object;
-
- float size[3] = {1.0f, 1.0f, 1.0f};
- float radius = 1.0f;
- float height = 1.0f;
-
- float volume = 0.0f;
-
- /* if automatically determining dimensions, use the Object's boundbox
- * - assume that all quadrics are standing upright on local z-axis
- * - assume even distribution of mass around the Object's pivot
- * (i.e. Object pivot is centralised in boundbox)
- * - boundbox gives full width
- */
- // XXX: all dimensions are auto-determined now... later can add stored settings for this
- BKE_object_dimensions_get(ob, size);
-
- if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
- /* take radius as largest x/y dimension, and height as z-dimension */
- radius = MAX2(size[0], size[1]) * 0.5f;
- height = size[2];
- }
- else if (rbo->shape == RB_SHAPE_SPHERE) {
- /* take radius to the the largest dimension to try and encompass everything */
- radius = max_fff(size[0], size[1], size[2]) * 0.5f;
- }
-
- /* calculate volume as appropriate */
- switch (rbo->shape) {
- case RB_SHAPE_BOX:
- volume = size[0] * size[1] * size[2];
- break;
-
- case RB_SHAPE_SPHERE:
- volume = 4.0f / 3.0f * (float)M_PI * radius * radius * radius;
- break;
-
- /* for now, assume that capsule is close enough to a cylinder... */
- case RB_SHAPE_CAPSULE:
- case RB_SHAPE_CYLINDER:
- volume = (float)M_PI * radius * radius * height;
- break;
-
- case RB_SHAPE_CONE:
- volume = (float)M_PI / 3.0f * radius * radius * height;
- break;
-
- /* for now, all mesh shapes are just treated as boxes...
- * NOTE: this may overestimate the volume, but other methods are overkill
- */
- case RB_SHAPE_CONVEXH:
- case RB_SHAPE_TRIMESH:
- volume = size[0] * size[1] * size[2];
- break;
-
-#if 0 // XXX: not defined yet
- case RB_SHAPE_COMPOUND:
- volume = 0.0f;
- break;
-#endif
- }
-
- /* return the volume calculated */
- return volume;
-}
-
-/* ------------------------------------------ */
-
static int rigidbody_objects_calc_mass_exec(bContext *C, wmOperator *op)
{
int material = RNA_enum_get(op->ptr, "material");
@@ -589,7 +517,7 @@ static int rigidbody_objects_calc_mass_exec(bContext *C, wmOperator *op)
/* mass is calculated from the approximate volume of the object,
* and the density of the material we're simulating
*/
- volume = rigidbody_object_calc_volume(ob);
+ BKE_rigidbody_calc_volume(ob, &volume);
mass = volume * density;
/* use RNA-system to change the property and perform all necessary changes */
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index 8f8cc542821..f9377d576bf 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -72,6 +72,7 @@ void SCENE_OT_freestyle_geometry_modifier_add(struct wmOperatorType *ot);
void SCENE_OT_freestyle_modifier_remove(struct wmOperatorType *ot);
void SCENE_OT_freestyle_modifier_move(struct wmOperatorType *ot);
void SCENE_OT_freestyle_modifier_copy(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_stroke_material_create(struct wmOperatorType *ot);
#endif
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index fd67115808f..baf25a49f7c 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -1032,6 +1032,7 @@ typedef struct RenderPreview {
int start_resolution_divider;
int resolution_divider;
+ bool has_freestyle;
} RenderPreview;
static int render_view3d_disprect(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, rcti *disprect)
@@ -1150,6 +1151,15 @@ static void render_update_resolution(Render *re, const RenderPreview *rp,
else {
RE_ChangeResolution(re, winx, winy, NULL);
}
+
+ if (rp->has_freestyle) {
+ if (rp->resolution_divider == 1) {
+ RE_ChangeModeFlag(re, R_EDGE_FRS, false);
+ }
+ else {
+ RE_ChangeModeFlag(re, R_EDGE_FRS, true);
+ }
+ }
}
static void render_view3d_startjob(void *customdata, short *stop, short *do_update, float *UNUSED(progress))
@@ -1163,7 +1173,7 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
bool orth, restore = 0;
char name[32];
int update_flag;
- bool use_border = false;
+ bool use_border;
update_flag = rp->engine->job_update_flag;
rp->engine->job_update_flag = 0;
@@ -1192,7 +1202,17 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
rstats = RE_GetStats(re);
if (update_flag & PR_UPDATE_VIEW) {
+ Object *object;
rp->resolution_divider = rp->start_resolution_divider;
+
+ /* Same as database_init_objects(), loop over all objects.
+ * We might consider de-duplicating the code between this two cases.
+ */
+ for (object = rp->bmain->object.first; object; object = object->id.next) {
+ float mat[4][4];
+ mul_m4_m4m4(mat, rp->viewmat, object->obmat);
+ invert_m4_m4(object->imat_ren, mat);
+ }
}
use_border = render_view3d_disprect(rp->scene, rp->ar, rp->v3d,
@@ -1419,6 +1439,7 @@ static void render_view3d_do(RenderEngine *engine, const bContext *C)
rp->bmain = CTX_data_main(C);
rp->resolution_divider = divider;
rp->start_resolution_divider = divider;
+ rp->has_freestyle = scene->r.mode & R_EDGE_FRS;
copy_m4_m4(rp->viewmat, rp->rv3d->viewmat);
/* clear info text */
diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c
index 3401577ee55..0d334082a2b 100644
--- a/source/blender/editors/render/render_ops.c
+++ b/source/blender/editors/render/render_ops.c
@@ -75,6 +75,7 @@ void ED_operatortypes_render(void)
WM_operatortype_append(SCENE_OT_freestyle_modifier_remove);
WM_operatortype_append(SCENE_OT_freestyle_modifier_move);
WM_operatortype_append(SCENE_OT_freestyle_modifier_copy);
+ WM_operatortype_append(SCENE_OT_freestyle_stroke_material_create);
#endif
WM_operatortype_append(TEXTURE_OT_slot_copy);
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 9cc672fe8ae..72b4da64c3e 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -891,10 +891,10 @@ static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
}
if (lineset->linestyle) {
lineset->linestyle->id.us--;
- lineset->linestyle = BKE_copy_linestyle(lineset->linestyle);
+ lineset->linestyle = BKE_linestyle_copy(lineset->linestyle);
}
else {
- lineset->linestyle = BKE_new_linestyle("LineStyle", NULL);
+ lineset->linestyle = BKE_linestyle_new("LineStyle", NULL);
}
DAG_id_tag_update(&lineset->linestyle->id, 0);
WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
@@ -928,7 +928,7 @@ static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (BKE_add_linestyle_color_modifier(lineset->linestyle, NULL, type) == NULL) {
+ if (BKE_linestyle_color_modifier_add(lineset->linestyle, NULL, type) == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type");
return OPERATOR_CANCELLED;
}
@@ -968,7 +968,7 @@ static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (BKE_add_linestyle_alpha_modifier(lineset->linestyle, NULL, type) == NULL) {
+ if (BKE_linestyle_alpha_modifier_add(lineset->linestyle, NULL, type) == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
return OPERATOR_CANCELLED;
}
@@ -1008,7 +1008,7 @@ static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (BKE_add_linestyle_thickness_modifier(lineset->linestyle, NULL, type) == NULL) {
+ if (BKE_linestyle_thickness_modifier_add(lineset->linestyle, NULL, type) == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
return OPERATOR_CANCELLED;
}
@@ -1048,7 +1048,7 @@ static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (BKE_add_linestyle_geometry_modifier(lineset->linestyle, NULL, type) == NULL) {
+ if (BKE_linestyle_geometry_modifier_add(lineset->linestyle, NULL, type) == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
return OPERATOR_CANCELLED;
}
@@ -1104,16 +1104,16 @@ static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
switch (freestyle_get_modifier_type(&ptr)) {
case LS_MODIFIER_TYPE_COLOR:
- BKE_remove_linestyle_color_modifier(lineset->linestyle, modifier);
+ BKE_linestyle_color_modifier_remove(lineset->linestyle, modifier);
break;
case LS_MODIFIER_TYPE_ALPHA:
- BKE_remove_linestyle_alpha_modifier(lineset->linestyle, modifier);
+ BKE_linestyle_alpha_modifier_remove(lineset->linestyle, modifier);
break;
case LS_MODIFIER_TYPE_THICKNESS:
- BKE_remove_linestyle_thickness_modifier(lineset->linestyle, modifier);
+ BKE_linestyle_thickness_modifier_remove(lineset->linestyle, modifier);
break;
case LS_MODIFIER_TYPE_GEOMETRY:
- BKE_remove_linestyle_geometry_modifier(lineset->linestyle, modifier);
+ BKE_linestyle_geometry_modifier_remove(lineset->linestyle, modifier);
break;
default:
BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
@@ -1154,16 +1154,16 @@ static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
switch (freestyle_get_modifier_type(&ptr)) {
case LS_MODIFIER_TYPE_COLOR:
- BKE_copy_linestyle_color_modifier(lineset->linestyle, modifier);
+ BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier);
break;
case LS_MODIFIER_TYPE_ALPHA:
- BKE_copy_linestyle_alpha_modifier(lineset->linestyle, modifier);
+ BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier);
break;
case LS_MODIFIER_TYPE_THICKNESS:
- BKE_copy_linestyle_thickness_modifier(lineset->linestyle, modifier);
+ BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier);
break;
case LS_MODIFIER_TYPE_GEOMETRY:
- BKE_copy_linestyle_geometry_modifier(lineset->linestyle, modifier);
+ BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier);
break;
default:
BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
@@ -1205,16 +1205,16 @@ static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
switch (freestyle_get_modifier_type(&ptr)) {
case LS_MODIFIER_TYPE_COLOR:
- BKE_move_linestyle_color_modifier(lineset->linestyle, modifier, dir);
+ BKE_linestyle_color_modifier_move(lineset->linestyle, modifier, dir);
break;
case LS_MODIFIER_TYPE_ALPHA:
- BKE_move_linestyle_alpha_modifier(lineset->linestyle, modifier, dir);
+ BKE_linestyle_alpha_modifier_move(lineset->linestyle, modifier, dir);
break;
case LS_MODIFIER_TYPE_THICKNESS:
- BKE_move_linestyle_thickness_modifier(lineset->linestyle, modifier, dir);
+ BKE_linestyle_thickness_modifier_move(lineset->linestyle, modifier, dir);
break;
case LS_MODIFIER_TYPE_GEOMETRY:
- BKE_move_linestyle_geometry_modifier(lineset->linestyle, modifier, dir);
+ BKE_linestyle_geometry_modifier_move(lineset->linestyle, modifier, dir);
break;
default:
BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
@@ -1250,6 +1250,36 @@ void SCENE_OT_freestyle_modifier_move(wmOperatorType *ot)
RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move, UP or DOWN");
}
+static int freestyle_stroke_material_create_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ FreestyleLineStyle *linestyle = BKE_linestyle_active_from_scene(scene);
+
+ if (!linestyle) {
+ BKE_report(op->reports, RPT_ERROR, "No active line style in the current scene");
+ return OPERATOR_CANCELLED;
+ }
+
+ FRS_create_stroke_material(bmain, linestyle);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_stroke_material_create(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Create Freestyle Stroke Material";
+ ot->idname = "SCENE_OT_freestyle_stroke_material_create";
+ ot->description = "Create Freestyle stroke material for testing";
+
+ /* api callbacks */
+ ot->exec = freestyle_stroke_material_create_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
#endif /* WITH_FREESTYLE */
static int texture_slot_move_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index 94d8d78de1a..6b58d3d55aa 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -45,6 +45,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_icons.h"
#include "BKE_main.h"
@@ -165,6 +166,7 @@ void ED_render_engine_changed(Main *bmain)
bScreen *sc;
ScrArea *sa;
Scene *scene;
+ Material *ma;
for (sc = bmain->screen.first; sc; sc = sc->id.next)
for (sa = sc->areabase.first; sa; sa = sa->next)
@@ -174,6 +176,13 @@ void ED_render_engine_changed(Main *bmain)
for (scene = bmain->scene.first; scene; scene = scene->id.next)
ED_render_id_flush_update(bmain, &scene->id);
+
+ /* reset texture painting. Sending one dependency graph signal for any material should
+ * refresh any texture slots */
+ ma = bmain->mat.first;
+ if (ma) {
+ DAG_id_tag_update(&ma->id, 0);
+ }
}
/***************************** Updates ***********************************
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index f42dae6530a..aa0ae22a003 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -470,8 +470,8 @@ void ED_region_tag_redraw(ARegion *ar)
* but python scripts can cause this to happen indirectly */
if (ar && !(ar->do_draw & RGN_DRAWING)) {
/* zero region means full region redraw */
- ar->do_draw &= ~RGN_DRAW_PARTIAL; /* just incase */
- ar->do_draw = RGN_DRAW;
+ ar->do_draw &= ~RGN_DRAW_PARTIAL;
+ ar->do_draw |= RGN_DRAW;
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
}
}
@@ -492,9 +492,9 @@ void ED_region_tag_refresh_ui(ARegion *ar)
void ED_region_tag_redraw_partial(ARegion *ar, rcti *rct)
{
if (ar && !(ar->do_draw & RGN_DRAWING)) {
- if (!ar->do_draw) {
+ if (!(ar->do_draw & RGN_DRAW)) {
/* no redraw set yet, set partial region */
- ar->do_draw = RGN_DRAW_PARTIAL;
+ ar->do_draw |= RGN_DRAW_PARTIAL;
ar->drawrct = *rct;
}
else if (ar->drawrct.xmin != ar->drawrct.xmax) {
@@ -889,38 +889,59 @@ static int rct_fits(rcti *rect, char dir, int size)
/* function checks if some overlapping region was defined before - on same place */
static void region_overlap_fix(ScrArea *sa, ARegion *ar)
{
- ARegion *ar1 = ar->prev;
-
+ ARegion *ar1;
+ const int align = ar->alignment & ~RGN_SPLIT_PREV;
+ int align1 = 0;
+
/* find overlapping previous region on same place */
- while (ar1) {
- if (ar1->overlap) {
- if ((ar1->alignment & RGN_SPLIT_PREV) == 0)
- if (BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL))
- break;
+ for (ar1 = ar->prev; ar1; ar1 = ar1->prev) {
+ if (ar1->overlap && ((ar1->alignment & RGN_SPLIT_PREV) == 0)) {
+ align1 = ar1->alignment;
+ if (BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) {
+ if (align1 != align) {
+ /* Left overlapping right or vice-versa, forbid this! */
+ ar->flag |= RGN_FLAG_TOO_SMALL;
+ return;
+ }
+ /* Else, we have our previous region on same side. */
+ break;
+ }
}
- ar1 = ar1->prev;
}
-
+
/* translate or close */
if (ar1) {
- int align1 = ar1->alignment & ~RGN_SPLIT_PREV;
-
if (align1 == RGN_ALIGN_LEFT) {
- if (ar->winrct.xmax + ar1->winx > sa->winx - U.widget_unit)
+ if (ar->winrct.xmax + ar1->winx > sa->winx - U.widget_unit) {
ar->flag |= RGN_FLAG_TOO_SMALL;
- else
+ return;
+ }
+ else {
BLI_rcti_translate(&ar->winrct, ar1->winx, 0);
+ }
}
else if (align1 == RGN_ALIGN_RIGHT) {
- if (ar->winrct.xmin - ar1->winx < U.widget_unit)
+ if (ar->winrct.xmin - ar1->winx < U.widget_unit) {
ar->flag |= RGN_FLAG_TOO_SMALL;
- else
+ return;
+ }
+ else {
BLI_rcti_translate(&ar->winrct, -ar1->winx, 0);
+ }
}
}
-
-
+ /* At this point, 'ar' is in its final position and still open.
+ * Make a final check it does not overlap any previous 'other side' region. */
+ for (ar1 = ar->prev; ar1; ar1 = ar1->prev) {
+ if (ar1->overlap && (ar1->alignment & RGN_SPLIT_PREV) == 0) {
+ if ((ar1->alignment != align) && BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) {
+ /* Left overlapping right or vice-versa, forbid this! */
+ ar->flag |= RGN_FLAG_TOO_SMALL;
+ return;
+ }
+ }
+ }
}
/* overlapping regions only in the following restricted cases */
@@ -929,11 +950,11 @@ static bool region_is_overlap(wmWindow *win, ScrArea *sa, ARegion *ar)
if (U.uiflag2 & USER_REGION_OVERLAP) {
if (WM_is_draw_triple(win)) {
if (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_SEQ)) {
- if (ELEM3(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS))
+ if (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS))
return 1;
}
else if (sa->spacetype == SPACE_IMAGE) {
- if (ELEM4(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS, RGN_TYPE_PREVIEW))
+ if (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS, RGN_TYPE_PREVIEW))
return 1;
}
}
@@ -1232,7 +1253,9 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand
/* time space only has this keymap, the others get a boundbox restricted map */
if (sa->spacetype != SPACE_TIME) {
ARegion *ar;
- static rcti rect = {0, 10000, 0, 30}; /* same local check for all areas */
+ /* same local check for all areas */
+ static rcti rect = {0, 10000, 0, -1};
+ rect.ymax = (30 * UI_DPI_FAC);
ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
if (ar) {
WM_event_add_keymap_handler_bb(handlers, keymap, &rect, &ar->winrct);
@@ -1764,9 +1787,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
break;
}
}
-
- BLI_SMALLSTACK_FREE(pt_stack);
-
+
/* clear */
if (ar->overlap) {
/* view should be in pixelspace */
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 5d65bdfa11b..290923b2331 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -378,7 +378,7 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
if (split == 0) return NULL;
/* note regarding (fac > 0.5f) checks below.
- * notmally it shouldn't matter which is used since the copy should match the original
+ * normally it shouldn't matter which is used since the copy should match the original
* however with viewport rendering and python console this isn't the case. - campbell */
if (dir == 'h') {
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 2ddda19fb28..7c7574b3af3 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -201,7 +201,7 @@ int ED_operator_animview_active(bContext *C)
{
if (ED_operator_areaactive(C)) {
SpaceLink *sl = (SpaceLink *)CTX_wm_space_data(C);
- if (sl && (ELEM5(sl->spacetype, SPACE_SEQ, SPACE_ACTION, SPACE_NLA, SPACE_IPO, SPACE_TIME)))
+ if (sl && (ELEM(sl->spacetype, SPACE_SEQ, SPACE_ACTION, SPACE_NLA, SPACE_IPO, SPACE_TIME)))
return true;
}
@@ -3220,6 +3220,16 @@ static int match_region_with_redraws(int spacetype, int regiontype, int redraws)
}
}
+ else if (regiontype == RGN_TYPE_CHANNELS) {
+ switch (spacetype) {
+ case SPACE_IPO:
+ case SPACE_ACTION:
+ case SPACE_NLA:
+ if (redraws & TIME_ALL_ANIM_WIN)
+ return 1;
+ break;
+ }
+ }
else if (regiontype == RGN_TYPE_UI) {
if (spacetype == SPACE_CLIP) {
/* Track Preview button is on Properties Editor in SpaceClip,
@@ -4154,7 +4164,8 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
/* dropbox for entire window */
lb = WM_dropboxmap_find("Window", 0, 0);
WM_dropbox_add(lb, "WM_OT_open_mainfile", open_file_drop_poll, open_file_drop_copy);
-
+ WM_dropbox_add(lb, "UI_OT_drop_color", UI_drop_color_poll, UI_drop_color_copy);
+
keymap_modal_set(keyconf);
}
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 180f7d14c25..0fa5f2d9837 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -41,6 +41,7 @@ set(INC_SYS
set(SRC
paint_cursor.c
+ paint_curve.c
paint_hide.c
paint_image.c
paint_image_2d.c
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index b1e4696cd02..7b9ede38b39 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -44,6 +44,7 @@
#include "BKE_brush.h"
#include "BKE_context.h"
+#include "BKE_curve.h"
#include "BKE_image.h"
#include "BKE_node.h"
#include "BKE_paint.h"
@@ -58,6 +59,8 @@
#include "ED_view3d.h"
+#include "UI_resources.h"
+
#include "paint_intern.h"
/* still needed for sculpt_stroke_get_location, should be
* removed eventually (TODO) */
@@ -756,7 +759,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
ViewContext *vc, int x, int y, float zoom, PaintMode mode)
{
/* color means that primary brush texture is colured and secondary is used for alpha/mask control */
- bool col = ELEM3(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX) ? true : false;
+ bool col = ELEM(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX) ? true : false;
OverlayControlFlags flags = BKE_paint_get_overlay_flags();
/* save lots of GL state
* TODO: check on whether all of these are needed? */
@@ -791,6 +794,138 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
glPopAttrib();
}
+
+BLI_INLINE void draw_tri_point(float *co, float width, bool selected)
+{
+ float w = width / 2.0f;
+ if (selected)
+ UI_ThemeColor4(TH_VERTEX_SELECT);
+ else
+ UI_ThemeColor4(TH_PAINT_CURVE_PIVOT);
+
+ glLineWidth(3.0);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(co[0], co[1] + w);
+ glVertex2f(co[0] - w, co[1] - w);
+ glVertex2f(co[0] + w, co[1] - w);
+ glEnd();
+
+ glColor4f(1.0, 1.0, 1.0, 0.5);
+ glLineWidth(1.0);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(co[0], co[1] + w);
+ glVertex2f(co[0] - w, co[1] - w);
+ glVertex2f(co[0] + w, co[1] - w);
+ glEnd();
+}
+
+BLI_INLINE void draw_rect_point(float *co, float width, bool selected)
+{
+ float w = width / 2.0f;
+ if (selected)
+ UI_ThemeColor4(TH_VERTEX_SELECT);
+ else
+ UI_ThemeColor4(TH_PAINT_CURVE_HANDLE);
+ glLineWidth(3.0);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(co[0] + w, co[1] + w);
+ glVertex2f(co[0] - w, co[1] + w);
+ glVertex2f(co[0] - w, co[1] - w);
+ glVertex2f(co[0] + w, co[1] - w);
+ glEnd();
+
+ glColor4f(1.0, 1.0, 1.0, 0.5);
+ glLineWidth(1.0);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(co[0] + w, co[1] + w);
+ glVertex2f(co[0] - w, co[1] + w);
+ glVertex2f(co[0] - w, co[1] - w);
+ glVertex2f(co[0] + w, co[1] - w);
+ glEnd();
+}
+
+
+BLI_INLINE void draw_bezier_handle_lines(BezTriple *bez)
+{
+ short line1[] = {0, 1};
+ short line2[] = {1, 2};
+
+ glVertexPointer(2, GL_FLOAT, 3 * sizeof(float), bez->vec);
+ glColor4f(0.0, 0.0, 0.0, 0.5);
+ glLineWidth(3.0);
+ glDrawArrays(GL_LINE_STRIP, 0, 3);
+
+ glLineWidth(1.0);
+ if (bez->f1 || bez->f2)
+ UI_ThemeColor4(TH_VERTEX_SELECT);
+ else
+ glColor4f(1.0, 1.0, 1.0, 0.5);
+ glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line1);
+ if (bez->f3 || bez->f2)
+ UI_ThemeColor4(TH_VERTEX_SELECT);
+ else
+ glColor4f(1.0, 1.0, 1.0, 0.5);
+ glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line2);
+}
+
+static void paint_draw_curve_cursor(Brush *brush)
+{
+ if (brush->paint_curve && brush->paint_curve->points) {
+ int i;
+ PaintCurve *pc = brush->paint_curve;
+ PaintCurvePoint *cp = pc->points;
+
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ /* draw the bezier handles and the curve segment between the current and next point */
+ for (i = 0; i < pc->tot_points - 1; i++, cp++) {
+ int j;
+ PaintCurvePoint *cp_next = cp + 1;
+ float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
+ /* use color coding to distinguish handles vs curve segments */
+ draw_bezier_handle_lines(&cp->bez);
+ draw_tri_point(&cp->bez.vec[1][0], 10.0, cp->bez.f2);
+ draw_rect_point(&cp->bez.vec[0][0], 8.0, cp->bez.f1 || cp->bez.f2);
+ draw_rect_point(&cp->bez.vec[2][0], 8.0, cp->bez.f3 || cp->bez.f2);
+
+ for (j = 0; j < 2; j++)
+ BKE_curve_forward_diff_bezier(
+ cp->bez.vec[1][j],
+ cp->bez.vec[2][j],
+ cp_next->bez.vec[0][j],
+ cp_next->bez.vec[1][j],
+ data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
+
+ glVertexPointer(2, GL_FLOAT, 0, data);
+ glLineWidth(3.0);
+ glColor4f(0.0, 0.0, 0.0, 0.5);
+ glDrawArrays(GL_LINE_STRIP, 0, PAINT_CURVE_NUM_SEGMENTS + 1);
+
+ glLineWidth(1.0);
+ glColor4f(0.9, 0.9, 1.0, 0.5);
+ glDrawArrays(GL_LINE_STRIP, 0, PAINT_CURVE_NUM_SEGMENTS + 1);
+ }
+
+ /* draw last line segment */
+ draw_bezier_handle_lines(&cp->bez);
+ draw_tri_point(&cp->bez.vec[1][0], 10.0, cp->bez.f2);
+ draw_rect_point(&cp->bez.vec[0][0], 8.0, cp->bez.f1 || cp->bez.f2);
+ draw_rect_point(&cp->bez.vec[2][0], 8.0, cp->bez.f3 || cp->bez.f2);
+
+ glLineWidth(1.0);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ }
+}
+
/* Special actions taken when paint cursor goes over mesh */
/* TODO: sculpt only for now */
static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc,
@@ -848,6 +983,12 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
zoomx = max_ff(zoomx, zoomy);
mode = BKE_paintmode_get_active_from_context(C);
+ /* skip everything and draw brush here */
+ if (brush->flag & BRUSH_CURVE) {
+ paint_draw_curve_cursor(brush);
+ return;
+ }
+
/* set various defaults */
translation[0] = x;
translation[1] = y;
@@ -857,8 +998,11 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* don't calculate rake angles while a stroke is active because the rake variables are global and
* we may get interference with the stroke itself. For line strokes, such interference is visible */
- if (!ups->stroke_active && (brush->flag & BRUSH_RAKE))
- paint_calculate_rake_rotation(ups, translation);
+ if (!ups->stroke_active) {
+ if (brush->flag & BRUSH_RAKE)
+ /* here, translation contains the mouse coordinates. */
+ paint_calculate_rake_rotation(ups, translation);
+ }
/* draw overlay */
paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode);
@@ -878,9 +1022,9 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* check if brush is subtracting, use different color then */
/* TODO: no way currently to know state of pen flip or
* invert key modifier without starting a stroke */
- if ((!(brush->flag & BRUSH_INVERTED) ^
+ if ((!(ups->draw_inverted) ^
!(brush->flag & BRUSH_DIR_IN)) &&
- ELEM5(brush->sculpt_tool, SCULPT_TOOL_DRAW,
+ ELEM(brush->sculpt_tool, SCULPT_TOOL_DRAW,
SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY,
SCULPT_TOOL_PINCH, SCULPT_TOOL_CREASE))
{
@@ -890,12 +1034,12 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* only do if brush is over the mesh */
if (hit)
paint_cursor_on_hit(ups, brush, &vc, location);
+ }
- if (ups->draw_anchored) {
- final_radius = ups->anchored_size;
- translation[0] = ups->anchored_initial_mouse[0];
- translation[1] = ups->anchored_initial_mouse[1];
- }
+ if (ups->draw_anchored) {
+ final_radius = ups->anchored_size;
+ translation[0] = ups->anchored_initial_mouse[0];
+ translation[1] = ups->anchored_initial_mouse[1];
}
/* make lines pretty */
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
new file mode 100644
index 00000000000..8c7c3b102e3
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -0,0 +1,787 @@
+/*
+ * ***** 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 *****
+ */
+
+/** \file blender/editors/sculpt_paint/paint_curve.c
+ * \ingroup edsculpt
+ */
+
+#include <string.h>
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_context.h"
+#include "BKE_main.h"
+#include "BKE_paint.h"
+
+#include "BLI_math_vector.h"
+#include "BLI_string.h"
+
+#include "ED_paint.h"
+#include "ED_view3d.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_view2d.h"
+
+#include "paint_intern.h"
+
+#define PAINT_CURVE_SELECT_THRESHOLD 40.0f
+#define PAINT_CURVE_POINT_SELECT(pcp, i) (*(&pcp->bez.f1 + i) = SELECT)
+
+
+int paint_curve_poll(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ Paint *p;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ SpaceImage *sima;
+
+ if (rv3d && !(ob && ((ob->mode & OB_MODE_ALL_PAINT) != 0)))
+ return false;
+
+ sima = CTX_wm_space_image(C);
+
+ if (sima && sima->mode != SI_MODE_PAINT)
+ return false;
+
+ p = BKE_paint_get_active_from_context(C);
+
+ if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
+ return true;
+ }
+
+ return false;
+}
+
+/* Paint Curve Undo*/
+
+typedef struct UndoCurve {
+ struct UndoImageTile *next, *prev;
+
+ PaintCurvePoint *points; /* points of curve */
+ int tot_points;
+ int active_point;
+
+ char idname[MAX_ID_NAME]; /* name instead of pointer*/
+} UndoCurve;
+
+static void paintcurve_undo_restore(bContext *C, ListBase *lb)
+{
+ Paint *p = BKE_paint_get_active_from_context(C);
+ UndoCurve *uc;
+ PaintCurve *pc = NULL;
+
+ if (p->brush) {
+ pc = p->brush->paint_curve;
+ }
+
+ if (!pc)
+ return;
+
+ uc = (UndoCurve *)lb->first;
+
+ if (strncmp(uc->idname, pc->id.name, BLI_strnlen(uc->idname, sizeof(uc->idname))) == 0) {
+ SWAP(PaintCurvePoint *, pc->points, uc->points);
+ SWAP(int, pc->tot_points, uc->tot_points);
+ SWAP(int, pc->add_index, uc->active_point);
+ }
+}
+
+static void paintcurve_undo_delete(ListBase *lb)
+{
+ UndoCurve *uc;
+ uc = (UndoCurve *)lb->first;
+
+ if (uc->points)
+ MEM_freeN(uc->points);
+ uc->points = NULL;
+}
+
+
+static void paintcurve_undo_begin(bContext *C, wmOperator *op, PaintCurve *pc)
+{
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
+ ListBase *lb = NULL;
+ int undo_stack_id;
+ UndoCurve *uc;
+
+ switch (mode) {
+ case PAINT_TEXTURE_2D:
+ case PAINT_TEXTURE_PROJECTIVE:
+ undo_stack_id = UNDO_PAINT_IMAGE;
+ break;
+
+ case PAINT_SCULPT:
+ undo_stack_id = UNDO_PAINT_MESH;
+ break;
+
+ default:
+ /* do nothing, undo is handled by global */
+ return;
+ }
+
+
+ ED_undo_paint_push_begin(undo_stack_id, op->type->name,
+ paintcurve_undo_restore, paintcurve_undo_delete, NULL);
+ lb = undo_paint_push_get_list(undo_stack_id);
+
+ uc = MEM_callocN(sizeof(*uc), "Undo_curve");
+
+ lb->first = uc;
+
+ BLI_strncpy(uc->idname, pc->id.name, sizeof(uc->idname));
+ uc->tot_points = pc->tot_points;
+ uc->active_point = pc->add_index;
+ uc->points = MEM_dupallocN(pc->points);
+
+ undo_paint_push_count_alloc(undo_stack_id, sizeof(*uc) + sizeof(*pc->points) * pc->tot_points);
+
+ ED_undo_paint_push_end(undo_stack_id);
+}
+#define SEL_F1 (1 << 0)
+#define SEL_F2 (1 << 1)
+#define SEL_F3 (1 << 2)
+
+/* returns 0, 1, or 2 in point according to handle 1, pivot or handle 2 */
+static PaintCurvePoint *paintcurve_point_get_closest(PaintCurve *pc, const float pos[2], bool ignore_pivot, const float threshold, char *point)
+{
+ PaintCurvePoint *pcp, *closest = NULL;
+ int i;
+ float dist, closest_dist = FLT_MAX;
+
+ for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
+ dist = len_manhattan_v2v2(pos, pcp->bez.vec[0]);
+ if (dist < threshold) {
+ if (dist < closest_dist) {
+ closest = pcp;
+ closest_dist = dist;
+ if (point)
+ *point = SEL_F1;
+ }
+ }
+ if (!ignore_pivot) {
+ dist = len_manhattan_v2v2(pos, pcp->bez.vec[1]);
+ if (dist < threshold) {
+ if (dist < closest_dist) {
+ closest = pcp;
+ closest_dist = dist;
+ if (point)
+ *point = SEL_F2;
+ }
+ }
+ }
+ dist = len_manhattan_v2v2(pos, pcp->bez.vec[2]);
+ if (dist < threshold) {
+ if (dist < closest_dist) {
+ closest = pcp;
+ closest_dist = dist;
+ if (point)
+ *point = SEL_F3;
+ }
+ }
+ }
+
+ return closest;
+}
+
+static int paintcurve_point_co_index(char sel)
+{
+ char i = 0;
+ while (sel != 1) {
+ sel >>= 1;
+ i++;
+ }
+ return i;
+}
+
+/******************* Operators *********************************/
+
+static int paintcurve_new_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Main *bmain = CTX_data_main(C);
+
+ if (p && p->brush) {
+ p->brush->paint_curve = BKE_paint_curve_add(bmain, "PaintCurve");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void PAINTCURVE_OT_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add New Paint Curve";
+ ot->description = "Add new paint curve";
+ ot->idname = "PAINTCURVE_OT_new";
+
+ /* api callbacks */
+ ot->exec = paintcurve_new_exec;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
+{
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Brush *br = p->brush;
+ Main *bmain = CTX_data_main(C);
+ PaintCurve *pc;
+ PaintCurvePoint *pcp;
+ wmWindow *window = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+ float vec[3] = {loc[0], loc[1], 0.0};
+ int add_index;
+ int i;
+
+ pc = br->paint_curve;
+ if (!pc) {
+ br->paint_curve = pc = BKE_paint_curve_add(bmain, "PaintCurve");
+ }
+
+ paintcurve_undo_begin(C, op, pc);
+
+ pcp = MEM_mallocN((pc->tot_points + 1) * sizeof(PaintCurvePoint), "PaintCurvePoint");
+ add_index = pc->add_index;
+
+ if (pc->points) {
+ if (add_index > 0)
+ memcpy(pcp, pc->points, add_index * sizeof(PaintCurvePoint));
+ if (add_index < pc->tot_points)
+ memcpy(pcp + add_index + 1, pc->points + add_index, (pc->tot_points - add_index) * sizeof(PaintCurvePoint));
+
+ MEM_freeN(pc->points);
+ }
+ pc->points = pcp;
+ pc->tot_points++;
+
+ /* initialize new point */
+ memset(&pcp[add_index], 0, sizeof(PaintCurvePoint));
+ copy_v3_v3(pcp[add_index].bez.vec[0], vec);
+ copy_v3_v3(pcp[add_index].bez.vec[1], vec);
+ copy_v3_v3(pcp[add_index].bez.vec[2], vec);
+
+ /* last step, clear selection from all bezier handles expect the next */
+ for (i = 0; i < pc->tot_points; i++) {
+ pcp[i].bez.f1 = pcp[i].bez.f2 = pcp[i].bez.f3 = 0;
+ }
+ pcp[add_index].bez.f3 = SELECT;
+ pcp[add_index].bez.h2 = HD_ALIGN;
+
+ pc->add_index = add_index + 1;
+
+ WM_paint_cursor_tag_redraw(window, ar);
+}
+
+
+static int paintcurve_add_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int loc[2] = {event->mval[0], event->mval[1]};
+ paintcurve_point_add(C, op, loc);
+ RNA_int_set_array(op->ptr, "location", loc);
+ return OPERATOR_FINISHED;
+}
+
+static int paintcurve_add_point_exec(bContext *C, wmOperator *op)
+{
+ int loc[2];
+
+ if (RNA_struct_property_is_set(op->ptr, "location")) {
+ RNA_int_get_array(op->ptr, "location", loc);
+ paintcurve_point_add(C, op, loc);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void PAINTCURVE_OT_add_point(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add New Paint Curve Point";
+ ot->description = "Add new paint curve point";
+ ot->idname = "PAINTCURVE_OT_add_point";
+
+ /* api callbacks */
+ ot->invoke = paintcurve_add_point_invoke;
+ ot->exec = paintcurve_add_point_exec;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, SHRT_MAX,
+ "Location", "Location of vertex in area space", 0, SHRT_MAX);
+}
+
+static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
+{
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Brush *br = p->brush;
+ PaintCurve *pc;
+ PaintCurvePoint *pcp;
+ wmWindow *window = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+ int i;
+ int tot_del = 0;
+ pc = br->paint_curve;
+
+ if (!pc || pc->tot_points == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ paintcurve_undo_begin(C, op, pc);
+
+#define DELETE_TAG 2
+
+ for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
+ if ((pcp->bez.f1 & SELECT) || (pcp->bez.f2 & SELECT) || (pcp->bez.f3 & SELECT)) {
+ pcp->bez.f2 |= DELETE_TAG;
+ tot_del++;
+ }
+ }
+
+ if (tot_del > 0) {
+ int j = 0;
+ int new_tot = pc->tot_points - tot_del;
+ PaintCurvePoint *points_new = NULL;
+ if (new_tot > 0)
+ points_new = MEM_mallocN(new_tot * sizeof(PaintCurvePoint), "PaintCurvePoint");
+
+ for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
+ if (!(pcp->bez.f2 & DELETE_TAG)) {
+ points_new[j] = pc->points[i];
+
+ if ((i + 1) == pc->add_index) {
+ pc->add_index = j + 1;
+ }
+ j++;
+ }
+ else if ((i + 1) == pc->add_index) {
+ /* prefer previous point */
+ pc->add_index = j;
+ }
+ }
+ MEM_freeN(pc->points);
+
+ pc->points = points_new;
+ pc->tot_points = new_tot;
+ }
+
+#undef DELETE_TAG
+
+ WM_paint_cursor_tag_redraw(window, ar);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void PAINTCURVE_OT_delete_point(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add New Paint Curve Point";
+ ot->description = "Add new paint curve point";
+ ot->idname = "PAINTCURVE_OT_delete_point";
+
+ /* api callbacks */
+ ot->exec = paintcurve_delete_point_exec;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
+
+static bool paintcurve_point_select(bContext *C, wmOperator *op, const int loc[2], bool toggle, bool extend)
+{
+ wmWindow *window = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Brush *br = p->brush;
+ PaintCurve *pc;
+ PaintCurvePoint *pcp;
+ int i;
+ const float loc_fl[2] = {UNPACK2(loc)};
+
+ pc = br->paint_curve;
+
+ if (!pc)
+ return false;
+
+ paintcurve_undo_begin(C, op, pc);
+
+ pcp = pc->points;
+
+ if (toggle) {
+ char select = 0;
+ bool selected = false;
+
+ for (i = 0; i < pc->tot_points; i++) {
+ if (pcp[i].bez.f1 || pcp[i].bez.f2 || pcp[i].bez.f3) {
+ selected = true;
+ break;
+ }
+ }
+
+ if (!selected) {
+ select = SELECT;
+ }
+
+ for (i = 0; i < pc->tot_points; i++) {
+ pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = select;
+ }
+ }
+ else {
+ PaintCurvePoint *pcp;
+ char selflag;
+
+ pcp = paintcurve_point_get_closest(pc, loc_fl, false, PAINT_CURVE_SELECT_THRESHOLD, &selflag);
+
+ if (pcp) {
+ pc->add_index = (pcp - pc->points) + 1;
+
+ if (selflag == SEL_F2) {
+ if (extend)
+ pcp->bez.f2 ^= SELECT;
+ else
+ pcp->bez.f2 |= SELECT;
+ }
+ else if (selflag == SEL_F1) {
+ if (extend)
+ pcp->bez.f1 ^= SELECT;
+ else
+ pcp->bez.f1 |= SELECT;
+ }
+ else if (selflag == SEL_F3) {
+ if (extend)
+ pcp->bez.f3 ^= SELECT;
+ else
+ pcp->bez.f3 |= SELECT;
+ }
+ }
+
+ /* clear selection for unselected points if not extending and if a point has been selected */
+ if (!extend && pcp) {
+ for (i = 0; i < pc->tot_points; i++) {
+ pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = 0;
+
+ if ((pc->points + i) == pcp) {
+ char index = paintcurve_point_co_index(selflag);
+ PAINT_CURVE_POINT_SELECT(pcp, index);
+ }
+ }
+ }
+
+ if (!pcp)
+ return false;
+ }
+
+ WM_paint_cursor_tag_redraw(window, ar);
+
+ return true;
+}
+
+
+static int paintcurve_select_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int loc[2] = {UNPACK2(event->mval)};
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ if (paintcurve_point_select(C, op, loc, toggle, extend)) {
+ RNA_int_set_array(op->ptr, "location", loc);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static int paintcurve_select_point_exec(bContext *C, wmOperator *op)
+{
+ int loc[2];
+
+ if (RNA_struct_property_is_set(op->ptr, "location")) {
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ RNA_int_get_array(op->ptr, "location", loc);
+ if (paintcurve_point_select(C, op, loc, toggle, extend))
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void PAINTCURVE_OT_select(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Paint Curve Point";
+ ot->description = "Select a paint curve point";
+ ot->idname = "PAINTCURVE_OT_select";
+
+ /* api callbacks */
+ ot->invoke = paintcurve_select_point_invoke;
+ ot->exec = paintcurve_select_point_exec;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, SHRT_MAX,
+ "Location", "Location of vertex in area space", 0, SHRT_MAX);
+ prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", "(De)select all");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+typedef struct PointSlideData {
+ PaintCurvePoint *pcp;
+ char select;
+ int initial_loc[2];
+ float point_initial_loc[3][2];
+ int event;
+ bool align;
+} PointSlideData;
+
+static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Paint *p = BKE_paint_get_active_from_context(C);
+ const float loc_fl[2] = {UNPACK2(event->mval)};
+ char select;
+ int i;
+ bool do_select = RNA_boolean_get(op->ptr, "select");
+ bool align = RNA_boolean_get(op->ptr, "align");
+ Brush *br = p->brush;
+ PaintCurve *pc = br->paint_curve;
+ PaintCurvePoint *pcp;
+
+ if (!pc)
+ return OPERATOR_PASS_THROUGH;
+
+ if (do_select) {
+ pcp = paintcurve_point_get_closest(pc, loc_fl, align, PAINT_CURVE_SELECT_THRESHOLD, &select);
+ }
+ else {
+ pcp = NULL;
+ /* just find first selected point */
+ for (i = 0; i < pc->tot_points; i++) {
+ if (pc->points[i].bez.f1 || pc->points[i].bez.f2 || pc->points[i].bez.f3) {
+ pcp = &pc->points[i];
+ select = SEL_F3;
+ break;
+ }
+ }
+ }
+
+
+ if (pcp) {
+ ARegion *ar = CTX_wm_region(C);
+ wmWindow *window = CTX_wm_window(C);
+ PointSlideData *psd = MEM_mallocN(sizeof(PointSlideData), "PointSlideData");
+ copy_v2_v2_int(psd->initial_loc, event->mval);
+ psd->event = event->type;
+ psd->pcp = pcp;
+ psd->select = paintcurve_point_co_index(select);
+ for (i = 0; i < 3; i++) {
+ copy_v2_v2(psd->point_initial_loc[i], pcp->bez.vec[i]);
+ }
+ psd->align = align;
+ op->customdata = psd;
+
+ if (do_select)
+ paintcurve_undo_begin(C, op, pc);
+
+ /* first, clear all selection from points */
+ for (i = 0; i < pc->tot_points; i++)
+ pc->points[i].bez.f1 = pc->points[i].bez.f3 = pc->points[i].bez.f2 = 0;
+
+ /* only select the active point */
+ PAINT_CURVE_POINT_SELECT(pcp, psd->select);
+ pc->add_index = (pcp - pc->points) + 1;
+
+ WM_event_add_modal_handler(C, op);
+ WM_paint_cursor_tag_redraw(window, ar);
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int paintcurve_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ PointSlideData *psd = op->customdata;
+
+ if (event->type == psd->event && event->val == KM_RELEASE) {
+ MEM_freeN(psd);
+ return OPERATOR_FINISHED;
+ }
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ {
+ ARegion *ar = CTX_wm_region(C);
+ wmWindow *window = CTX_wm_window(C);
+ float diff[2] = {event->mval[0] - psd->initial_loc[0],
+ event->mval[1] - psd->initial_loc[1]};
+ if (psd->select == 1) {
+ int i;
+ for (i = 0; i < 3; i++)
+ add_v2_v2v2(psd->pcp->bez.vec[i], diff, psd->point_initial_loc[i]);
+ }
+ else {
+ add_v2_v2(diff, psd->point_initial_loc[psd->select]);
+ copy_v2_v2(psd->pcp->bez.vec[psd->select], diff);
+
+ if (psd->align) {
+ char opposite = (psd->select == 0) ? 2 : 0;
+ sub_v2_v2v2(diff, psd->pcp->bez.vec[1], psd->pcp->bez.vec[psd->select]);
+ add_v2_v2v2(psd->pcp->bez.vec[opposite], psd->pcp->bez.vec[1], diff);
+ }
+ }
+ WM_paint_cursor_tag_redraw(window, ar);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+
+void PAINTCURVE_OT_slide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Slide Paint Curve Point";
+ ot->description = "Select and slide paint curve point";
+ ot->idname = "PAINTCURVE_OT_slide";
+
+ /* api callbacks */
+ ot->invoke = paintcurve_slide_invoke;
+ ot->modal = paintcurve_slide_modal;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "align", false, "Align Handles", "Aligns opposite point handle during transform");
+ RNA_def_boolean(ot->srna, "select", true, "Select", "Attempt to select a point handle before transform");
+}
+
+static int paintcurve_draw_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
+ const char *name;
+
+ switch (mode) {
+ case PAINT_TEXTURE_2D:
+ case PAINT_TEXTURE_PROJECTIVE:
+ name = "PAINT_OT_image_paint";
+ break;
+ case PAINT_WEIGHT:
+ name = "PAINT_OT_weight_paint";
+ break;
+ case PAINT_VERTEX:
+ name = "PAINT_OT_vertex_paint";
+ break;
+ case PAINT_SCULPT:
+ name = "SCULPT_OT_brush_stroke";
+ break;
+ default:
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ return WM_operator_name_call(C, name, WM_OP_INVOKE_DEFAULT, NULL);
+}
+
+void PAINTCURVE_OT_draw(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Draw Curve";
+ ot->description = "Draw curve";
+ ot->idname = "PAINTCURVE_OT_draw";
+
+ /* api callbacks */
+ ot->exec = paintcurve_draw_exec;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
+static int paintcurve_cursor_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
+
+ switch (mode) {
+ case PAINT_TEXTURE_2D:
+ {
+ ARegion *ar = CTX_wm_region(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ float location[2];
+
+ if (!sima)
+ return OPERATOR_CANCELLED;
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
+ copy_v2_v2(sima->cursor, location);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
+ break;
+ }
+ default:
+ ED_view3d_cursor3d_update(C, event->mval);
+ break;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void PAINTCURVE_OT_cursor(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Place Cursor";
+ ot->description = "Place cursor";
+ ot->idname = "PAINTCURVE_OT_cursor";
+
+ /* api callbacks */
+ ot->invoke = paintcurve_cursor_invoke;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = 0;
+}
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 34232c51ff7..ebfb17d25ef 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -43,6 +43,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_threads.h"
#include "PIL_time.h"
@@ -59,9 +60,14 @@
#include "BKE_brush.h"
#include "BKE_image.h"
#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_node.h"
#include "BKE_paint.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_texture.h"
+#include "BKE_colortools.h"
#include "BKE_editmesh.h"
@@ -82,6 +88,9 @@
#include "GPU_draw.h"
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
#include "IMB_colormanagement.h"
#include "paint_intern.h"
@@ -102,14 +111,27 @@ typedef struct UndoImageTile {
int x, y;
+ Image *ima;
short source, use_float;
char gen_type;
+ bool valid;
} UndoImageTile;
/* this is a static resource for non-globality,
* Maybe it should be exposed as part of the
* paint operation, but for now just give a public interface */
static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0};
+static SpinLock undolock;
+
+void image_undo_init_locks(void)
+{
+ BLI_spin_init(&undolock);
+}
+
+void image_undo_end_locks(void)
+{
+ BLI_spin_end(&undolock);
+}
ImagePaintPartialRedraw *get_imapaintpartial(void)
{
@@ -122,26 +144,53 @@ void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr)
}
/* UNDO */
+typedef enum {
+ COPY = 0,
+ RESTORE = 1,
+ RESTORE_COPY = 2
+} CopyMode;
-static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int restore)
+static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, CopyMode mode)
{
- /* copy or swap contents of tile->rect and region in ibuf->rect */
- IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
- tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+ if (mode == COPY) {
+ /* copy or swap contents of tile->rect and region in ibuf->rect */
+ IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
+ tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
- if (ibuf->rect_float) {
- SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ if (ibuf->rect_float) {
+ SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ }
+ else {
+ SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+ }
}
else {
- SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
- }
-
- if (restore)
+ if (mode == RESTORE_COPY)
+ IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
+ tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+ /* swap to the tmpbuf for easy copying */
+ if (ibuf->rect_float) {
+ SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ }
+ else {
+ SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+ }
+
IMB_rectcpy(ibuf, tmpibuf, tile->x * IMAPAINT_TILE_SIZE,
tile->y * IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+
+ if (mode == RESTORE) {
+ if (ibuf->rect_float) {
+ SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ }
+ else {
+ SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+ }
+ }
+ }
}
-void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask)
+void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate)
{
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
UndoImageTile *tile;
@@ -160,6 +209,8 @@ void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsi
*mask = tile->mask;
}
+ if (validate)
+ tile->valid = true;
return tile->rect.pt;
}
@@ -170,7 +221,7 @@ void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsi
return NULL;
}
-void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile)
+void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid, bool proj)
{
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
UndoImageTile *tile;
@@ -179,10 +230,14 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile,
void *data;
/* check if tile is already pushed */
- data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, NULL);
- if (data)
- return data;
-
+
+ /* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */
+ if (!proj) {
+ data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, mask, true);
+ if (data)
+ return data;
+ }
+
if (*tmpibuf == NULL)
*tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
@@ -191,6 +246,11 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile,
tile->x = x_tile;
tile->y = y_tile;
+ /* add mask explicitly here */
+ if (mask)
+ *mask = tile->mask = MEM_callocN(sizeof(unsigned short) * IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE,
+ "UndoImageTile.mask");
+
allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
allocsize *= (ibuf->rect_float) ? sizeof(float) : sizeof(char);
tile->rect.pt = MEM_mapallocN(allocsize, "UndeImageTile.rect");
@@ -200,12 +260,23 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile,
tile->gen_type = ima->gen_type;
tile->source = ima->source;
tile->use_float = use_float;
+ tile->valid = true;
+ tile->ima = ima;
- undo_copy_tile(tile, *tmpibuf, ibuf, 0);
- undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, allocsize);
+ if (valid)
+ *valid = &tile->valid;
+ undo_copy_tile(tile, *tmpibuf, ibuf, COPY);
+
+ if (proj)
+ BLI_spin_lock(&undolock);
+
+ undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, allocsize);
BLI_addtail(lb, tile);
-
+
+ if (proj)
+ BLI_spin_unlock(&undolock);
+
return tile->rect.pt;
}
@@ -222,6 +293,33 @@ void image_undo_remove_masks(void)
}
}
+static void image_undo_restore_runtime(ListBase *lb)
+{
+ ImBuf *ibuf, *tmpibuf;
+ UndoImageTile *tile;
+
+ tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32,
+ IB_rectfloat | IB_rect);
+
+ for (tile = lb->first; tile; tile = tile->next) {
+ Image *ima = tile->ima;
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+
+ undo_copy_tile(tile, tmpibuf, ibuf, RESTORE);
+
+ GPU_free_image(ima); /* force OpenGL reload (maybe partial update will operate better?) */
+ if (ibuf->rect_float)
+ ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
+ if (ibuf->mipmap[0])
+ ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+
+ IMB_freeImBuf(tmpibuf);
+}
+
void ED_image_undo_restore(bContext *C, ListBase *lb)
{
Main *bmain = CTX_data_main(C);
@@ -247,7 +345,7 @@ void ED_image_undo_restore(bContext *C, ListBase *lb)
if (ima && ibuf && strcmp(tile->ibufname, ibuf->name) != 0) {
/* current ImBuf filename was changed, probably current frame
- * was changed when paiting on image sequence, rather than storing
+ * was changed when painting on image sequence, rather than storing
* full image user (which isn't so obvious, btw) try to find ImBuf with
* matched file name in list of already loaded images */
@@ -273,7 +371,7 @@ void ED_image_undo_restore(bContext *C, ListBase *lb)
continue;
}
- undo_copy_tile(tile, tmpibuf, ibuf, 1);
+ undo_copy_tile(tile, tmpibuf, ibuf, RESTORE_COPY);
GPU_free_image(ima); /* force OpenGL reload */
if (ibuf->rect_float)
@@ -282,6 +380,8 @@ void ED_image_undo_restore(bContext *C, ListBase *lb)
ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ DAG_id_tag_update(&ima->id, 0);
+
BKE_image_release_ibuf(ima, ibuf, NULL);
}
@@ -296,6 +396,42 @@ void ED_image_undo_free(ListBase *lb)
MEM_freeN(tile->rect.pt);
}
+static void image_undo_end(void)
+{
+ ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+ UndoImageTile *tile;
+ int deallocsize = 0;
+ int allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
+
+ /* first dispose of invalid tiles (may happen due to drag dot for instance) */
+ for (tile = lb->first; tile;) {
+ if (!tile->valid) {
+ UndoImageTile *tmp_tile = tile->next;
+ deallocsize += allocsize * ((tile->use_float) ? sizeof(float) : sizeof(char));
+ MEM_freeN(tile->rect.pt);
+ BLI_freelinkN (lb, tile);
+ tile = tmp_tile;
+ }
+ else {
+ tile = tile->next;
+ }
+ }
+
+ /* don't forget to remove the size of deallocated tiles */
+ undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, -deallocsize);
+
+ ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
+}
+
+static void image_undo_invalidate(void)
+{
+ UndoImageTile *tile;
+ ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+
+ for (tile = lb->first; tile; tile = tile->next)
+ tile->valid = false;
+}
+
/* Imagepaint Partial Redraw & Dirty Region */
void ED_imapaint_clear_partial_redraw(void)
@@ -344,7 +480,7 @@ void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int
for (ty = tiley; ty <= tileh; ty++)
for (tx = tilex; tx <= tilew; tx++)
- image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty);
+ image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false);
ibuf->userflags |= IB_BITMAPDIRTY;
@@ -373,6 +509,76 @@ void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short te
}
}
+/* paint blur kernels. Projective painting enforces use of a 2x2 kernel due to lagging */
+BlurKernel *paint_new_blur_kernel(Brush *br, bool proj)
+{
+ int i, j;
+ BlurKernel *kernel = MEM_mallocN(sizeof(BlurKernel), "blur kernel");
+ float radius;
+ int side;
+ BlurKernelType type = br->blur_mode;
+
+ if (proj) {
+ radius = 0.5f;
+
+ side = kernel->side = 2;
+ kernel->side_squared = kernel->side * kernel->side;
+ kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data");
+ kernel->pixel_len = radius;
+ }
+ else {
+ radius = br->blur_kernel_radius;
+
+ side = kernel->side = radius * 2 + 1;
+ kernel->side_squared = kernel->side * kernel->side;
+ kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data");
+ kernel->pixel_len = br->blur_kernel_radius;
+ }
+
+ switch (type) {
+ case KERNEL_BOX:
+ for (i = 0; i < kernel->side_squared; i++)
+ kernel->wdata[i] = 1.0;
+ break;
+
+ case KERNEL_GAUSSIAN:
+ {
+ /* at standard deviation of 3.0 kernel is at about zero */
+ float standard_dev = radius / 3.0f;
+
+ /* make the necessary adjustment to the value for use in the normal distribution formula */
+ standard_dev = standard_dev * standard_dev * 2;
+
+ for (i = 0; i < side; i++) {
+ for (j = 0; j < side; j++) {
+ float idist = radius - i;
+ float jdist = radius - j;
+ float value = exp((idist * idist + jdist * jdist) / standard_dev);
+
+ kernel->wdata[i + j * side] = value;
+ }
+ }
+
+ break;
+ }
+
+ default:
+ printf("unidentified kernel type, aborting\n");
+ MEM_freeN(kernel->wdata);
+ MEM_freeN(kernel);
+ return NULL;
+ break;
+ }
+
+ return kernel;
+}
+
+void paint_delete_blur_kernel(BlurKernel *kernel)
+{
+ if (kernel->wdata)
+ MEM_freeN(kernel->wdata);
+}
+
/************************ image paint poll ************************/
static Brush *image_paint_brush(bContext *C)
@@ -432,11 +638,57 @@ typedef struct PaintOperation {
void *custom_paint;
float prevmouse[2];
+ float startmouse[2];
double starttime;
+ void *cursor;
ViewContext vc;
} PaintOperation;
+bool paint_use_opacity_masking(Brush *brush)
+{
+ return (brush->flag & BRUSH_AIRBRUSH) ||
+ (brush->flag & BRUSH_DRAG_DOT) ||
+ (brush->flag & BRUSH_ANCHORED) ||
+ (brush->imagepaint_tool == PAINT_TOOL_SMEAR) ||
+ (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) ||
+ (brush->imagepaint_tool == PAINT_TOOL_FILL) ||
+ (brush->flag & BRUSH_USE_GRADIENT) ||
+ (brush->mtex.tex && !ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_3D)) ?
+ false : true;
+}
+
+void paint_brush_color_get(struct Scene *scene, struct Brush *br, bool color_correction, bool invert, float distance,
+ float pressure, float color[3], struct ColorManagedDisplay *display)
+{
+ if (invert)
+ copy_v3_v3(color, BKE_brush_secondary_color_get(scene, br));
+ else {
+ if (br->flag & BRUSH_USE_GRADIENT) {
+ switch (br->gradient_stroke_mode) {
+ case BRUSH_GRADIENT_PRESSURE:
+ do_colorband(br->gradient, pressure, color);
+ break;
+ case BRUSH_GRADIENT_SPACING_REPEAT:
+ {
+ float coord = fmod(distance / br->gradient_spacing, 1.0);
+ do_colorband(br->gradient, coord, color);
+ break;
+ }
+ case BRUSH_GRADIENT_SPACING_CLAMP:
+ {
+ do_colorband(br->gradient, distance / br->gradient_spacing, color);
+ break;
+ }
+ }
+ }
+ else
+ copy_v3_v3(color, BKE_brush_color_get(scene, br));
+ }
+ if (color_correction)
+ IMB_colormanagement_display_to_scene_linear_v3(color, display);
+}
+
void paint_brush_init_tex(Brush *brush)
{
/* init mtex nodes */
@@ -462,26 +714,54 @@ void paint_brush_exit_tex(Brush *brush)
}
}
+static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customdata)
+{
+ PaintOperation *pop = (PaintOperation *)customdata;
+
+ if (pop) {
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ glLineWidth(4.0);
+ glColor4ub(0, 0, 0, 255);
+ sdrawline(x, y, pop->startmouse[0], pop->startmouse[1]);
+ glLineWidth(2.0);
+ glColor4ub(255, 255, 255, 255);
+ sdrawline(x, y, pop->startmouse[0], pop->startmouse[1]);
+ glLineWidth(1.0);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+ }
+}
-static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, float mouse[2])
+
+static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const float mouse[2])
{
Scene *scene = CTX_data_scene(C);
ToolSettings *settings = scene->toolsettings;
PaintOperation *pop = MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */
+ Brush *brush = BKE_paint_brush(&settings->imapaint.paint);
int mode = RNA_enum_get(op->ptr, "mode");
view3d_set_viewcontext(C, &pop->vc);
- pop->prevmouse[0] = mouse[0];
- pop->prevmouse[1] = mouse[1];
+ copy_v2_v2(pop->prevmouse, mouse);
+ copy_v2_v2(pop->startmouse, mouse);
+
+ if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
+ pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, gradient_draw_line, pop);
+ }
/* initialize from context */
if (CTX_wm_region_view3d(C)) {
+ Object *ob = OBACT;
+ paint_proj_mesh_data_ensure(C, ob, op);
pop->mode = PAINT_MODE_3D_PROJECT;
- pop->custom_paint = paint_proj_new_stroke(C, OBACT, pop->prevmouse, mode);
+ pop->custom_paint = paint_proj_new_stroke(C, ob, mouse, mode);
}
else {
pop->mode = PAINT_MODE_2D;
- pop->custom_paint = paint_2d_new_stroke(C, op);
+ pop->custom_paint = paint_2d_new_stroke(C, op, mode);
}
if (!pop->custom_paint) {
@@ -491,52 +771,69 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, float mou
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free);
-
- {
- UnifiedPaintSettings *ups = &settings->unified_paint_settings;
- ups->stroke_active = true;
- }
+ ED_image_undo_restore, ED_image_undo_free, NULL);
return pop;
}
+/* restore painting image to previous state. Used for anchored and drag-dot style brushes*/
+static void paint_stroke_restore(void)
+{
+ ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+ image_undo_restore_runtime(lb);
+ image_undo_invalidate();
+}
+
static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
{
PaintOperation *pop = paint_stroke_mode_data(stroke);
Scene *scene = CTX_data_scene(C);
- Brush *brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);
+ ToolSettings *toolsettings = CTX_data_tool_settings(C);
+ UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
+ Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
+
+ float alphafac = (brush->flag & BRUSH_ACCUMULATE) ? ups->overlap_factor : 1.0f;
/* initial brush values. Maybe it should be considered moving these to stroke system */
- float startsize = (float)BKE_brush_size_get(scene, brush);
float startalpha = BKE_brush_alpha_get(scene, brush);
float mouse[2];
float pressure;
+ float size;
+ float distance = paint_stroke_distance_get(stroke);
int eraser;
RNA_float_get_array(itemptr, "mouse", mouse);
pressure = RNA_float_get(itemptr, "pressure");
eraser = RNA_boolean_get(itemptr, "pen_flip");
+ size = max_ff(1.0f, RNA_float_get(itemptr, "size"));
+
+ /* stroking with fill tool only acts on stroke end */
+ if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
+ copy_v2_v2(pop->prevmouse, mouse);
+ return;
+ }
if (BKE_brush_use_alpha_pressure(scene, brush))
- BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure));
- if (BKE_brush_use_size_pressure(scene, brush))
- BKE_brush_size_set(scene, brush, (int)max_ff(1.0f, startsize * pressure));
+ BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure * alphafac));
+ else
+ BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * alphafac));
+
+ if ((brush->flag & BRUSH_DRAG_DOT) || (brush->flag & BRUSH_ANCHORED)) {
+ paint_stroke_restore();
+ }
if (pop->mode == PAINT_MODE_3D_PROJECT) {
- paint_proj_stroke(C, pop->custom_paint, pop->prevmouse, mouse);
+ paint_proj_stroke(C, pop->custom_paint, pop->prevmouse, mouse, eraser, pressure, distance, size);
}
else {
- paint_2d_stroke(pop->custom_paint, pop->prevmouse, mouse, eraser);
+ paint_2d_stroke(pop->custom_paint, pop->prevmouse, mouse, eraser, pressure, distance, size);
}
- pop->prevmouse[0] = mouse[0];
- pop->prevmouse[1] = mouse[1];
+ copy_v2_v2(pop->prevmouse, mouse);
/* restore brush values */
BKE_brush_alpha_set(scene, brush, startalpha);
- BKE_brush_size_set(scene, brush, startsize);
}
static void paint_stroke_redraw(const bContext *C, struct PaintStroke *stroke, bool final)
@@ -554,11 +851,41 @@ static void paint_stroke_redraw(const bContext *C, struct PaintStroke *stroke, b
static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
{
Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
+ ToolSettings *toolsettings = scene->toolsettings;
PaintOperation *pop = paint_stroke_mode_data(stroke);
+ Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
- settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
+ toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
+
+ if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
+ if (brush->flag & BRUSH_USE_GRADIENT) {
+ if (pop->mode == PAINT_MODE_2D) {
+ paint_2d_gradient_fill(C, brush, pop->startmouse, pop->prevmouse, pop->custom_paint);
+ }
+ else {
+ paint_proj_stroke(C, pop->custom_paint, pop->startmouse, pop->prevmouse, paint_stroke_flipped(stroke),
+ 1.0, 0.0, BKE_brush_size_get(scene, brush));
+ /* two redraws, one for GPU update, one for notification */
+ paint_proj_redraw(C, pop->custom_paint, false);
+ paint_proj_redraw(C, pop->custom_paint, true);
+ }
+ }
+ else {
+ if (pop->mode == PAINT_MODE_2D) {
+ float color[3];
+ srgb_to_linearrgb_v3_v3(color, BKE_brush_color_get(scene, brush));
+ paint_2d_bucket_fill(C, color, brush, pop->prevmouse, pop->custom_paint);
+ }
+ else {
+ paint_proj_stroke(C, pop->custom_paint, pop->startmouse, pop->prevmouse, paint_stroke_flipped(stroke),
+ 1.0, 0.0, BKE_brush_size_get(scene, brush));
+ /* two redraws, one for GPU update, one for notification */
+ paint_proj_redraw(C, pop->custom_paint, false);
+ paint_proj_redraw(C, pop->custom_paint, true);
+ }
+ }
+ }
if (pop->mode == PAINT_MODE_3D_PROJECT) {
paint_proj_stroke_done(pop->custom_paint);
}
@@ -566,7 +893,11 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
paint_2d_stroke_done(pop->custom_paint);
}
- ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
+ if (pop->cursor) {
+ WM_paint_cursor_end(CTX_wm_manager(C), pop->cursor);
+ }
+
+ image_undo_end();
/* duplicate warning, see texpaint_init */
#if 0
@@ -576,43 +907,41 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile);
#endif
MEM_freeN(pop);
-
- {
- UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
- ups->stroke_active = false;
- }
}
-static bool paint_stroke_test_start(bContext *UNUSED(C), wmOperator *UNUSED(op), const float UNUSED(mouse[2]))
-{
- return true;
-}
-
-
-static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static bool paint_stroke_test_start(bContext *C, wmOperator *op, const float mouse[2])
{
PaintOperation *pop;
- float mouse[2];
- int retval;
/* TODO Should avoid putting this here. Instead, last position should be requested
* from stroke system. */
- mouse[0] = event->mval[0];
- mouse[1] = event->mval[1];
if (!(pop = texture_paint_init(C, op, mouse))) {
- return OPERATOR_CANCELLED;
+ return false;
}
- op->customdata = paint_stroke_new(C, NULL, paint_stroke_test_start,
+ paint_stroke_set_mode_data(op->customdata, pop);
+
+ return true;
+}
+
+
+static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int retval;
+
+ op->customdata = paint_stroke_new(C, op, NULL, paint_stroke_test_start,
paint_stroke_update_step,
paint_stroke_redraw,
paint_stroke_done, event->type);
- paint_stroke_set_mode_data(op->customdata, pop);
+
+ if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ paint_stroke_data_free(op);
+ return OPERATOR_FINISHED;
+ }
/* add modal handler */
WM_event_add_modal_handler(C, op);
- retval = op->type->modal(C, op, event);
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
@@ -637,12 +966,10 @@ static int paint_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- op->customdata = paint_stroke_new(C, NULL, paint_stroke_test_start,
+ op->customdata = paint_stroke_new(C, op, NULL, paint_stroke_test_start,
paint_stroke_update_step,
paint_stroke_redraw,
paint_stroke_done, 0);
- paint_stroke_set_mode_data(op->customdata, pop);
-
/* frees op->customdata */
paint_stroke_exec(C, op);
@@ -651,12 +978,6 @@ static int paint_exec(bContext *C, wmOperator *op)
void PAINT_OT_image_paint(wmOperatorType *ot)
{
- static EnumPropertyItem stroke_mode_items[] = {
- {BRUSH_STROKE_NORMAL, "NORMAL", 0, "Normal", "Apply brush normally"},
- {BRUSH_STROKE_INVERT, "INVERT", 0, "Invert", "Invert action of brush for duration of stroke"},
- {0}
- };
-
/* identifiers */
ot->name = "Image Paint";
ot->idname = "PAINT_OT_image_paint";
@@ -672,11 +993,7 @@ void PAINT_OT_image_paint(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING;
- RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL,
- "Paint Stroke Mode",
- "Action taken when a paint stroke is made");
-
- RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+ paint_stroke_operator_properties(ot);
}
@@ -686,9 +1003,9 @@ int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
if (!rv3d) {
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
if (sima->mode == SI_MODE_PAINT) {
+ ARegion *ar = CTX_wm_region(C);
ED_space_image_get_zoom(sima, ar, zoomx, zoomy);
return 1;
@@ -847,17 +1164,39 @@ void PAINT_OT_grab_clone(wmOperatorType *ot)
typedef struct {
bool show_cursor;
short event_type;
-} SampleColorData;
+ float initcolor[3];
+ bool sample_palette;
+} SampleColorData;
+
+
+static void sample_color_update_header(SampleColorData *data, bContext *C)
+{
+#define HEADER_LENGTH 150
+ char msg[HEADER_LENGTH];
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (sa) {
+ BLI_snprintf(msg, HEADER_LENGTH,
+ "Sample color for %s",
+ !data->sample_palette ?
+ "Brush. Use Left Click to sample for palette instead" :
+ "Palette. Use Left Click to sample more colors");
+ ED_area_headerprint(sa, msg);
+ }
+
+#undef HEADER_LENGTH
+}
static int sample_color_exec(bContext *C, wmOperator *op)
{
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
ARegion *ar = CTX_wm_region(C);
wmWindow *win = CTX_wm_window(C);
bool show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
int location[2];
-
+ bool use_palette;
paint->flags &= ~PAINT_SHOW_BRUSH;
/* force redraw without cursor */
@@ -865,7 +1204,9 @@ static int sample_color_exec(bContext *C, wmOperator *op)
WM_redraw_windows(C);
RNA_int_get_array(op->ptr, "location", location);
- paint_sample_color(C, ar, location[0], location[1]);
+ use_palette = RNA_boolean_get(op->ptr, "palette");
+
+ paint_sample_color(C, ar, location[0], location[1], mode == PAINT_TEXTURE_PROJECTIVE, use_palette);
if (show_cursor) {
paint->flags |= PAINT_SHOW_BRUSH;
@@ -878,7 +1219,9 @@ static int sample_color_exec(bContext *C, wmOperator *op)
static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ Scene *scene = CTX_data_scene(C);
Paint *paint = BKE_paint_get_active_from_context(C);
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
SampleColorData *data = MEM_mallocN(sizeof(SampleColorData), "sample color custom data");
ARegion *ar = CTX_wm_region(C);
@@ -886,18 +1229,24 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event
data->event_type = event->type;
data->show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
+ copy_v3_v3(data->initcolor, BKE_brush_color_get(scene, brush));
+ data->sample_palette = false;
op->customdata = data;
paint->flags &= ~PAINT_SHOW_BRUSH;
+ sample_color_update_header(data, C);
+
+ WM_event_add_modal_handler(C, op);
+
/* force redraw without cursor */
WM_paint_cursor_tag_redraw(win, ar);
WM_redraw_windows(C);
RNA_int_set_array(op->ptr, "location", event->mval);
- paint_sample_color(C, ar, event->mval[0], event->mval[1]);
+
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, false);
WM_cursor_modal_set(win, BC_EYEDROPPER_CURSOR);
- WM_event_add_modal_handler(C, op);
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
return OPERATOR_RUNNING_MODAL;
@@ -905,17 +1254,27 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event
static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
+ Scene *scene = CTX_data_scene(C);
SampleColorData *data = op->customdata;
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
if ((event->type == data->event_type) && (event->val == KM_RELEASE)) {
+ ScrArea *sa = CTX_wm_area(C);
+
if (data->show_cursor) {
paint->flags |= PAINT_SHOW_BRUSH;
}
+ if (data->sample_palette) {
+ BKE_brush_color_set(scene, brush, data->initcolor);
+ RNA_boolean_set(op->ptr, "palette", true);
+ }
WM_cursor_modal_restore(CTX_wm_window(C));
MEM_freeN(data);
+ ED_area_headerprint(sa, NULL);
+
return OPERATOR_FINISHED;
}
@@ -924,10 +1283,22 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
RNA_int_set_array(op->ptr, "location", event->mval);
- paint_sample_color(C, ar, event->mval[0], event->mval[1]);
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, false);
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
break;
}
+
+ case LEFTMOUSE:
+ if (event->val == KM_PRESS) {
+ ARegion *ar = CTX_wm_region(C);
+ RNA_int_set_array(op->ptr, "location", event->mval);
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, true);
+ if (!data->sample_palette) {
+ data->sample_palette = true;
+ sample_color_update_header(data, C);
+ }
+ }
+ break;
}
return OPERATOR_RUNNING_MODAL;
@@ -956,6 +1327,7 @@ void PAINT_OT_sample_color(wmOperatorType *ot)
/* properties */
RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "Cursor location in region coordinates", 0, 16384);
+ RNA_def_boolean(ot->srna, "palette", 0, "Palette", "Add color to palette");
}
/******************** texture paint toggle operator ********************/
@@ -979,7 +1351,6 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_active_object(C);
const int mode_flag = OB_MODE_TEXTURE_PAINT;
const bool is_mode_set = (ob->mode & mode_flag) != 0;
- Mesh *me;
if (!is_mode_set) {
if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
@@ -987,8 +1358,6 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
}
}
- me = BKE_mesh_from_object(ob);
-
if (ob->mode & mode_flag) {
ob->mode &= ~mode_flag;
@@ -999,11 +1368,43 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
toggle_paint_cursor(C, 0);
}
else {
- ob->mode |= mode_flag;
+ bScreen *sc;
+ Main *bmain = CTX_data_main(C);
+ Image *ima = NULL;
+ ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+
+ /* This has to stay here to regenerate the texture paint
+ * cache in case we are loading a file */
+ BKE_texpaint_slots_refresh_object(scene, ob);
- if (me->mtface == NULL)
- me->mtface = CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT,
- NULL, me->totface);
+ paint_proj_mesh_data_ensure(C, ob, op);
+
+ /* entering paint mode also sets image to editors */
+ if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+ Material *ma = give_current_material(ob, ob->actcol); /* set the current material active paint slot on image editor */
+
+ if (ma->texpaintslot)
+ ima = ma->texpaintslot[ma->paint_active_slot].ima;
+ }
+ else if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+ ima = imapaint->canvas;
+ }
+
+ for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ ED_space_image_set(sima, scene, scene->obedit, ima);
+ }
+ }
+ }
+ }
+
+ ob->mode |= mode_flag;
BKE_paint_init(&scene->toolsettings->imapaint.paint, PAINT_CURSOR_TEXTURE_PAINT);
@@ -1035,6 +1436,60 @@ void PAINT_OT_texture_paint_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+static int brush_colors_flip_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
+ Brush *br = image_paint_brush(C);
+ if (ups->flag & UNIFIED_PAINT_COLOR) {
+ swap_v3_v3(ups->rgb, ups->secondary_rgb);
+ }
+ else if (br) {
+ swap_v3_v3(br->rgb, br->secondary_rgb);
+ }
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, br);
+
+ return OPERATOR_FINISHED;
+}
+
+static int brush_colors_flip_poll(bContext *C)
+{
+ if (image_paint_poll(C)) {
+ Brush *br = image_paint_brush(C);
+ if (br->imagepaint_tool == PAINT_TOOL_DRAW)
+ return 1;
+ }
+
+ return 0;
+}
+
+void PAINT_OT_brush_colors_flip(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Brush Colors Flip";
+ ot->idname = "PAINT_OT_brush_colors_flip";
+ ot->description = "Toggle foreground and background brush colors";
+
+ /* api callbacks */
+ ot->exec = brush_colors_flip_exec;
+ ot->poll = brush_colors_flip_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+void ED_imapaint_bucket_fill(struct bContext *C, float color[3], wmOperator *op)
+{
+ ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
+ ED_image_undo_restore, ED_image_undo_free, NULL);
+
+ paint_2d_bucket_fill(C, color, NULL, NULL, NULL);
+
+ ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
+}
+
+
static int texture_paint_poll(bContext *C)
{
if (texture_paint_toggle_poll(C))
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 4f67fc9cc87..165888b3c09 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -40,11 +40,18 @@
#include "BLI_math.h"
+#include "BLI_rect.h"
+#include "BLI_math_color_blend.h"
+#include "BLI_stack.h"
+#include "BLI_bitmap.h"
+
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_brush.h"
#include "BKE_image.h"
#include "BKE_paint.h"
#include "BKE_report.h"
+#include "BKE_texture.h"
#include "ED_paint.h"
#include "ED_screen.h"
@@ -69,24 +76,25 @@
/* Defines and Structs */
typedef struct BrushPainterCache {
- int size; /* size override, if 0 uses 2*BKE_brush_size_get(brush) */
-
bool use_float; /* need float imbuf? */
bool use_color_correction; /* use color correction for float */
- bool use_masking; /* use masking? */
+ bool invert;
bool is_texbrush;
bool is_maskbrush;
- int lastsize;
- float lastalpha;
- float lastjitter;
+ int lastdiameter;
float last_tex_rotation;
float last_mask_rotation;
+ float last_pressure;
ImBuf *ibuf;
ImBuf *texibuf;
- unsigned short *mask;
+ unsigned short *curve_mask;
+ unsigned short *tex_mask;
+ unsigned short *tex_mask_old;
+ unsigned int tex_mask_old_w;
+ unsigned int tex_mask_old_h;
} BrushPainterCache;
typedef struct BrushPainter {
@@ -136,43 +144,42 @@ typedef struct ImagePaintState {
int do_facesel;
bool need_redraw;
+
+ BlurKernel *blurkernel;
} ImagePaintState;
-static BrushPainter *brush_painter_2d_new(Scene *scene, Brush *brush)
+static BrushPainter *brush_painter_2d_new(Scene *scene, Brush *brush, bool invert)
{
BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
painter->brush = brush;
painter->scene = scene;
painter->firsttouch = 1;
- painter->cache.lastsize = -1; /* force ibuf create in refresh */
+ painter->cache.lastdiameter = -1; /* force ibuf create in refresh */
+ painter->cache.invert = invert;
return painter;
}
-static void brush_painter_2d_require_imbuf(BrushPainter *painter, bool use_float, bool use_color_correction, bool use_masking)
+static void brush_painter_2d_require_imbuf(BrushPainter *painter, bool use_float, bool use_color_correction)
{
Brush *brush = painter->brush;
if ((painter->cache.use_float != use_float)) {
if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
- if (painter->cache.mask) MEM_freeN(painter->cache.mask);
+ if (painter->cache.curve_mask) MEM_freeN(painter->cache.curve_mask);
+ if (painter->cache.tex_mask) MEM_freeN(painter->cache.tex_mask);
+ if (painter->cache.tex_mask_old) MEM_freeN(painter->cache.tex_mask_old);
painter->cache.ibuf = NULL;
- painter->cache.mask = NULL;
- painter->cache.lastsize = -1; /* force ibuf create in refresh */
- }
-
- if (painter->cache.use_float != use_float) {
- if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
- painter->cache.texibuf = NULL;
- painter->cache.lastsize = -1; /* force ibuf create in refresh */
+ painter->cache.curve_mask = NULL;
+ painter->cache.tex_mask = NULL;
+ painter->cache.lastdiameter = -1; /* force ibuf create in refresh */
}
painter->cache.use_float = use_float;
painter->cache.use_color_correction = use_float && use_color_correction;
- painter->cache.use_masking = use_masking;
painter->cache.is_texbrush = (brush->mtex.tex && brush->imagepaint_tool == PAINT_TOOL_DRAW) ? true : false;
painter->cache.is_maskbrush = (brush->mask_mtex.tex) ? true : false;
}
@@ -181,7 +188,9 @@ static void brush_painter_2d_free(BrushPainter *painter)
{
if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
- if (painter->cache.mask) MEM_freeN(painter->cache.mask);
+ if (painter->cache.curve_mask) MEM_freeN(painter->cache.curve_mask);
+ if (painter->cache.tex_mask) MEM_freeN(painter->cache.tex_mask);
+ if (painter->cache.tex_mask_old) MEM_freeN(painter->cache.tex_mask_old);
MEM_freeN(painter);
}
@@ -192,41 +201,177 @@ static void brush_imbuf_tex_co(rctf *mapping, int x, int y, float texco[3])
texco[2] = 0.0f;
}
-/* create a mask with the falloff strength and optionally brush alpha */
-static unsigned short *brush_painter_mask_new(BrushPainter *painter, int size)
+/* create a mask with the mask texture */
+static unsigned short *brush_painter_mask_ibuf_new(BrushPainter *painter, int size)
{
Scene *scene = painter->scene;
Brush *brush = painter->brush;
- bool use_masking = painter->cache.use_masking;
-
- float alpha = (use_masking) ? 1.0f : BKE_brush_alpha_get(scene, brush);
- int radius = BKE_brush_size_get(scene, brush);
- int xoff = -size * 0.5f + 0.5f;
- int yoff = -size * 0.5f + 0.5f;
+ rctf mask_mapping = painter->mask_mapping;
+ struct ImagePool *pool = painter->pool;
+ float texco[3];
unsigned short *mask, *m;
- int x, y;
+ int x, y, thread = 0;
- mask = MEM_callocN(sizeof(unsigned short) * size * size, "brush_painter_mask");
+ mask = MEM_mallocN(sizeof(unsigned short) * size * size, "brush_painter_mask");
m = mask;
for (y = 0; y < size; y++) {
for (x = 0; x < size; x++, m++) {
+ float res;
+ brush_imbuf_tex_co(&mask_mapping, x, y, texco);
+ res = BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
+ *m = (unsigned short)(65535.0f * res);
+ }
+ }
+
+ return mask;
+}
+
+/* update rectangular section of the brush image */
+static void brush_painter_mask_imbuf_update(
+ BrushPainter *painter, unsigned short *tex_mask_old,
+ int origx, int origy, int w, int h, int xt, int yt, int diameter)
+{
+ Scene *scene = painter->scene;
+ Brush *brush = painter->brush;
+ rctf tex_mapping = painter->mask_mapping;
+ struct ImagePool *pool = painter->pool;
+ unsigned short res;
+
+ bool use_texture_old = (tex_mask_old != NULL);
+
+ int x, y, thread = 0;
+
+ unsigned short *tex_mask = painter->cache.tex_mask;
+ unsigned short *tex_mask_cur = painter->cache.tex_mask_old;
+
+ /* fill pixels */
+ for (y = origy; y < h; y++) {
+ for (x = origx; x < w; x++) {
+ /* sample texture */
+ float texco[3];
+
+ /* handle byte pixel */
+ unsigned short *b = tex_mask + (y * diameter + x);
+ unsigned short *t = tex_mask_cur + (y * diameter + x);
+
+ if (!use_texture_old) {
+ brush_imbuf_tex_co(&tex_mapping, x, y, texco);
+ res = (unsigned short)(65535.0f * BKE_brush_sample_masktex(scene, brush, texco, thread, pool));
+ }
+
+ /* read from old texture buffer */
+ if (use_texture_old) {
+ res = *(tex_mask_old + ((y - origy + yt) * painter->cache.tex_mask_old_w + (x - origx + xt)));
+ }
+
+ /* write to new texture mask */
+ *t = res;
+ /* write to mask image buffer */
+ *b = res;
+ }
+ }
+}
+
+
+/**
+ * Update the brush mask image by trying to reuse the cached texture result.
+ * This can be considerably faster for brushes that change size due to pressure or
+ * textures that stick to the surface where only part of the pixels are new
+ */
+static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter, const float pos[2], int diameter)
+{
+ BrushPainterCache *cache = &painter->cache;
+ unsigned short *tex_mask_old;
+ int destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
+
+ /* create brush image buffer if it didn't exist yet */
+ if (!cache->tex_mask)
+ cache->tex_mask = MEM_mallocN(sizeof(unsigned short) * diameter * diameter, "brush_painter_mask");
+
+ /* create new texture image buffer with coordinates relative to old */
+ tex_mask_old = cache->tex_mask_old;
+ cache->tex_mask_old = MEM_mallocN(sizeof(unsigned short) * diameter * diameter, "brush_painter_mask");
+
+ if (tex_mask_old) {
+ ImBuf maskibuf;
+ ImBuf maskibuf_old;
+ maskibuf.x = maskibuf.y = diameter;
+ maskibuf_old.x = cache->tex_mask_old_w;
+ maskibuf_old.y = cache->tex_mask_old_h;
+
+ srcx = srcy = 0;
+ w = cache->tex_mask_old_w;
+ h = cache->tex_mask_old_h;
+ destx = (int)painter->lastpaintpos[0] - (int)pos[0] + (diameter / 2 - w / 2);
+ desty = (int)painter->lastpaintpos[1] - (int)pos[1] + (diameter / 2 - h / 2);
+
+ /* hack, use temporary rects so that clipping works */
+ IMB_rectclip(&maskibuf, &maskibuf_old, &destx, &desty, &srcx, &srcy, &w, &h);
+ }
+ else {
+ srcx = srcy = 0;
+ destx = desty = 0;
+ w = h = 0;
+ }
+
+ x1 = min_ii(destx, diameter);
+ y1 = min_ii(desty, diameter);
+ x2 = min_ii(destx + w, diameter);
+ y2 = min_ii(desty + h, diameter);
+
+ /* blend existing texture in new position */
+ if ((x1 < x2) && (y1 < y2))
+ brush_painter_mask_imbuf_update(painter, tex_mask_old, x1, y1, x2, y2, srcx, srcy, diameter);
+
+ if (tex_mask_old)
+ MEM_freeN(tex_mask_old);
+
+ /* sample texture in new areas */
+ if ((0 < x1) && (0 < diameter))
+ brush_painter_mask_imbuf_update(painter, NULL, 0, 0, x1, diameter, 0, 0, diameter);
+ if ((x2 < diameter) && (0 < diameter))
+ brush_painter_mask_imbuf_update(painter, NULL, x2, 0, diameter, diameter, 0, 0, diameter);
+ if ((x1 < x2) && (0 < y1))
+ brush_painter_mask_imbuf_update(painter, NULL, x1, 0, x2, y1, 0, 0, diameter);
+ if ((x1 < x2) && (y2 < diameter))
+ brush_painter_mask_imbuf_update(painter, NULL, x1, y2, x2, diameter, 0, 0, diameter);
+
+ /* through with sampling, now update sizes */
+ cache->tex_mask_old_w = diameter;
+ cache->tex_mask_old_h = diameter;
+}
+
+/* create a mask with the falloff strength */
+static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter, int diameter, float radius)
+{
+ Brush *brush = painter->brush;
+
+ int xoff = -diameter * 0.5f + 0.5f;
+ int yoff = -diameter * 0.5f + 0.5f;
+
+ unsigned short *mask, *m;
+ int x, y;
+
+ mask = MEM_mallocN(sizeof(unsigned short) * diameter * diameter, "brush_painter_mask");
+ m = mask;
+
+ for (y = 0; y < diameter; y++) {
+ for (x = 0; x < diameter; x++, m++) {
float xy[2] = {x + xoff, y + yoff};
float len = len_v2(xy);
- float strength = alpha;
-
- strength *= BKE_brush_curve_strength_clamp(brush, len, radius);
- *m = (unsigned short)(65535.0f * strength);
+ *m = (unsigned short)(65535.0f * BKE_brush_curve_strength_clamp(brush, len, radius));
}
}
return mask;
}
+
/* create imbuf with brush color */
-static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
+static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size, float pressure, float distance)
{
Scene *scene = painter->scene;
Brush *brush = painter->brush;
@@ -235,19 +380,11 @@ static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
rctf tex_mapping = painter->tex_mapping;
- rctf mask_mapping = painter->mask_mapping;
struct ImagePool *pool = painter->pool;
- bool use_masking = painter->cache.use_masking;
bool use_color_correction = painter->cache.use_color_correction;
bool use_float = painter->cache.use_float;
bool is_texbrush = painter->cache.is_texbrush;
- bool is_maskbrush = painter->cache.is_maskbrush;
-
- float alpha = (use_masking) ? 1.0f : BKE_brush_alpha_get(scene, brush);
- int radius = BKE_brush_size_get(scene, brush);
- int xoff = -size * 0.5f + 0.5f;
- int yoff = -size * 0.5f + 0.5f;
int x, y, thread = 0;
float brush_rgb[3];
@@ -257,11 +394,7 @@ static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
/* get brush color */
if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
- copy_v3_v3(brush_rgb, brush->rgb);
-
- if (use_color_correction) {
- IMB_colormanagement_display_to_scene_linear_v3(brush_rgb, display);
- }
+ paint_brush_color_get(scene, brush, use_color_correction, painter->cache.invert, distance, pressure, brush_rgb, display);
}
else {
brush_rgb[0] = 1.0f;
@@ -278,30 +411,17 @@ static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
if (is_texbrush) {
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
+ mul_v3_v3(rgba, brush_rgb);
/* TODO(sergey): Support texture paint color space. */
if (!use_float) {
IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
}
- mul_v3_v3(rgba, brush_rgb);
}
else {
copy_v3_v3(rgba, brush_rgb);
rgba[3] = 1.0f;
}
- if (is_maskbrush) {
- brush_imbuf_tex_co(&mask_mapping, x, y, texco);
- rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
- }
-
- /* when not using masking, multiply in falloff and strength */
- if (!use_masking) {
- float xy[2] = {x + xoff, y + yoff};
- float len = len_v2(xy);
-
- rgba[3] *= alpha * BKE_brush_curve_strength_clamp(brush, len, radius);
- }
-
if (use_float) {
/* write to float pixel */
float *dstf = ibuf->rect_float + (y * size + x) * 4;
@@ -332,14 +452,11 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
rctf tex_mapping = painter->tex_mapping;
- rctf mask_mapping = painter->mask_mapping;
struct ImagePool *pool = painter->pool;
- bool use_masking = painter->cache.use_masking;
bool use_color_correction = painter->cache.use_color_correction;
bool use_float = painter->cache.use_float;
bool is_texbrush = painter->cache.is_texbrush;
- bool is_maskbrush = painter->cache.is_maskbrush;
bool use_texture_old = (oldtexibuf != NULL);
int x, y, thread = 0;
@@ -347,15 +464,10 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
ImBuf *ibuf = painter->cache.ibuf;
ImBuf *texibuf = painter->cache.texibuf;
- unsigned short *mask = painter->cache.mask;
/* get brush color */
if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
- copy_v3_v3(brush_rgb, brush->rgb);
-
- if (use_color_correction) {
- IMB_colormanagement_display_to_scene_linear_v3(brush_rgb, display);
- }
+ paint_brush_color_get(scene, brush, use_color_correction, painter->cache.invert, 0.0, 1.0, brush_rgb, display);
}
else {
brush_rgb[0] = 1.0f;
@@ -363,7 +475,7 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
brush_rgb[2] = 1.0f;
}
- /* fill pixes */
+ /* fill pixels */
for (y = origy; y < h; y++) {
for (x = origx; x < w; x++) {
/* sample texture and multiply with brush color */
@@ -373,21 +485,16 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
if (is_texbrush) {
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
+ mul_v3_v3(rgba, brush_rgb);
/* TODO(sergey): Support texture paint color space. */
if (!use_float) {
IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
}
- mul_v3_v3(rgba, brush_rgb);
}
else {
copy_v3_v3(rgba, brush_rgb);
rgba[3] = 1.0f;
}
-
- if (is_maskbrush) {
- brush_imbuf_tex_co(&mask_mapping, x, y, texco);
- rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
- }
}
if (use_float) {
@@ -404,12 +511,6 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
/* write to new texture buffer */
copy_v4_v4(tf, rgba);
- /* if not using masking, multiply in the mask now */
- if (!use_masking) {
- unsigned short *m = mask + (y * ibuf->x + x);
- rgba[3] *= *m * (1.0f / 65535.0f);
- }
-
/* output premultiplied float image, mf was already premultiplied */
mul_v3_v3fl(bf, rgba, rgba[3]);
bf[3] = rgba[3];
@@ -438,12 +539,6 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
t[2] = crgba[2];
t[3] = crgba[3];
- /* if not using masking, multiply in the mask now */
- if (!use_masking) {
- unsigned short *m = mask + (y * ibuf->x + x);
- crgba[3] = (crgba[3] * (*m)) / 65535;
- }
-
/* write to brush image buffer */
b[0] = crgba[0];
b[1] = crgba[1];
@@ -457,14 +552,11 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
/* update the brush image by trying to reuse the cached texture result. this
* can be considerably faster for brushes that change size due to pressure or
* textures that stick to the surface where only part of the pixels are new */
-static void brush_painter_imbuf_partial_update(BrushPainter *painter, const float pos[2])
+static void brush_painter_imbuf_partial_update(BrushPainter *painter, const float pos[2], int diameter)
{
- const Scene *scene = painter->scene;
- Brush *brush = painter->brush;
BrushPainterCache *cache = &painter->cache;
ImBuf *oldtexibuf, *ibuf;
int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
- int diameter = 2 * BKE_brush_size_get(scene, brush);
/* create brush image buffer if it didn't exist yet */
imbflag = (cache->use_float) ? IB_rectfloat : IB_rect;
@@ -478,10 +570,10 @@ static void brush_painter_imbuf_partial_update(BrushPainter *painter, const floa
if (oldtexibuf) {
srcx = srcy = 0;
- destx = (int)painter->lastpaintpos[0] - (int)pos[0];
- desty = (int)painter->lastpaintpos[1] - (int)pos[1];
w = oldtexibuf->x;
h = oldtexibuf->y;
+ destx = (int)painter->lastpaintpos[0] - (int)pos[0] + (diameter / 2 - w / 2);
+ desty = (int)painter->lastpaintpos[1] - (int)pos[1] + (diameter / 2 - h / 2);
IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
}
@@ -514,7 +606,7 @@ static void brush_painter_imbuf_partial_update(BrushPainter *painter, const floa
brush_painter_imbuf_update(painter, NULL, x1, y2, x2, ibuf->y, 0, 0);
}
-static void brush_painter_2d_tex_mapping(ImagePaintState *s, int size, const float startpos[2], const float pos[2], const float mouse[2], int mapmode, rctf *mapping)
+static void brush_painter_2d_tex_mapping(ImagePaintState *s, int diameter, const float startpos[2], const float pos[2], const float mouse[2], int mapmode, rctf *mapping)
{
float invw = 1.0f / (float)s->canvas->x;
float invh = 1.0f / (float)s->canvas->y;
@@ -522,19 +614,19 @@ static void brush_painter_2d_tex_mapping(ImagePaintState *s, int size, const flo
int ipos[2];
/* find start coordinate of brush in canvas */
- ipos[0] = (int)floorf((pos[0] - size / 2) + 1.0f);
- ipos[1] = (int)floorf((pos[1] - size / 2) + 1.0f);
+ ipos[0] = (int)floorf((pos[0] - diameter / 2) + 1.0f);
+ ipos[1] = (int)floorf((pos[1] - diameter / 2) + 1.0f);
if (mapmode == MTEX_MAP_MODE_STENCIL) {
/* map from view coordinates of brush to region coordinates */
UI_view2d_view_to_region(s->v2d, ipos[0] * invw, ipos[1] * invh, &xmin, &ymin);
- UI_view2d_view_to_region(s->v2d, (ipos[0] + size) * invw, (ipos[1] + size) * invh, &xmax, &ymax);
+ UI_view2d_view_to_region(s->v2d, (ipos[0] + diameter) * invw, (ipos[1] + diameter) * invh, &xmax, &ymax);
/* output mapping from brush ibuf x/y to region coordinates */
mapping->xmin = xmin;
mapping->ymin = ymin;
- mapping->xmax = (xmax - xmin) / (float)size;
- mapping->ymax = (ymax - ymin) / (float)size;
+ mapping->xmax = (xmax - xmin) / (float)diameter;
+ mapping->ymax = (ymax - ymin) / (float)diameter;
}
else if (mapmode == MTEX_MAP_MODE_3D) {
/* 3D mapping, just mapping to canvas 0..1 */
@@ -545,104 +637,126 @@ static void brush_painter_2d_tex_mapping(ImagePaintState *s, int size, const flo
}
else if (ELEM(mapmode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_RANDOM)) {
/* view mapping */
- mapping->xmin = mouse[0] - size * 0.5f + 0.5f;
- mapping->ymin = mouse[1] - size * 0.5f + 0.5f;
+ mapping->xmin = mouse[0] - diameter * 0.5f + 0.5f;
+ mapping->ymin = mouse[1] - diameter * 0.5f + 0.5f;
mapping->xmax = 1.0f;
mapping->ymax = 1.0f;
}
else /* if (mapmode == MTEX_MAP_MODE_TILED) */ {
- mapping->xmin = -size * 0.5f + 0.5f + (int)pos[0] - (int)startpos[0];
- mapping->ymin = -size * 0.5f + 0.5f + (int)pos[1] - (int)startpos[1];
+ mapping->xmin = (int)(-diameter * 0.5) + (int)pos[0] - (int)startpos[0];
+ mapping->ymin = (int)(-diameter * 0.5) + (int)pos[1] - (int)startpos[1];
mapping->xmax = 1.0f;
mapping->ymax = 1.0f;
}
}
-static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *painter, const float pos[2], const float mouse[2])
+static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *painter, const float pos[2], const float mouse[2], float pressure, float distance, float size)
{
const Scene *scene = painter->scene;
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
Brush *brush = painter->brush;
BrushPainterCache *cache = &painter->cache;
- const int diameter = 2 * BKE_brush_size_get(scene, brush);
- const int size = (cache->size) ? cache->size : diameter;
- const float alpha = BKE_brush_alpha_get(scene, brush);
- const bool use_masking = painter->cache.use_masking;
+ const int diameter = 2 * size;
bool do_random = false;
bool do_partial_update = false;
- bool do_view = false;
+ bool update_color = (brush->flag & BRUSH_USE_GRADIENT) &&
+ ((ELEM(brush->gradient_stroke_mode,
+ BRUSH_GRADIENT_SPACING_REPEAT,
+ BRUSH_GRADIENT_SPACING_CLAMP)) ||
+ (cache->last_pressure != pressure));
float tex_rotation = -brush->mtex.rot;
float mask_rotation = -brush->mask_mtex.rot;
+ painter->pool = BKE_image_pool_new();
+
/* determine how can update based on textures used */
if (painter->cache.is_texbrush) {
if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
- do_view = true;
tex_rotation += ups->brush_rotation;
}
else if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
do_random = true;
- else
+ else if (!((brush->flag & BRUSH_ANCHORED) || update_color))
do_partial_update = true;
- brush_painter_2d_tex_mapping(s, size, painter->startpaintpos, pos, mouse,
+ brush_painter_2d_tex_mapping(s, diameter, painter->startpaintpos, pos, mouse,
brush->mtex.brush_map_mode, &painter->tex_mapping);
}
if (painter->cache.is_maskbrush) {
+ bool renew_maxmask = false;
+ bool do_partial_update_mask = false;
+ /* invalidate case for all mapping modes */
if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
- do_view = true;
mask_rotation += ups->brush_rotation;
}
- else if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
- do_random = true;
- else
- do_partial_update = true;
+ else if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) {
+ renew_maxmask = true;
+ }
+ else if (!(brush->flag & BRUSH_ANCHORED)) {
+ do_partial_update_mask = true;
+ renew_maxmask = true;
+ }
+ /* explicilty disable partial update even if it has been enabled above */
+ if (brush->mask_pressure) {
+ do_partial_update_mask = false;
+ renew_maxmask = true;
+ }
+
+ if ((diameter != cache->lastdiameter) ||
+ (mask_rotation != cache->last_mask_rotation) ||
+ renew_maxmask)
+ {
+ if (cache->tex_mask) {
+ MEM_freeN(cache->tex_mask);
+ cache->tex_mask = NULL;
+ }
- brush_painter_2d_tex_mapping(s, size, painter->startpaintpos, pos, mouse,
- brush->mask_mtex.brush_map_mode, &painter->mask_mapping);
+ brush_painter_2d_tex_mapping(s, diameter, painter->startpaintpos, pos, mouse,
+ brush->mask_mtex.brush_map_mode, &painter->mask_mapping);
+
+ if (do_partial_update_mask)
+ brush_painter_mask_imbuf_partial_update(painter, pos, diameter);
+ else
+ cache->tex_mask = brush_painter_mask_ibuf_new(painter, diameter);
+ cache->last_mask_rotation = mask_rotation;
+ }
}
- if (do_view || do_random)
- do_partial_update = false;
+ /* curve mask can only change if the size changes */
+ if (diameter != cache->lastdiameter) {
+ if (cache->curve_mask) {
+ MEM_freeN(cache->curve_mask);
+ cache->curve_mask = NULL;
+ }
- painter->pool = BKE_image_pool_new();
+ cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size);
+ }
/* detect if we need to recreate image brush buffer */
- if (diameter != cache->lastsize ||
- alpha != cache->lastalpha ||
- brush->jitter != cache->lastjitter ||
- tex_rotation != cache->last_tex_rotation ||
- mask_rotation != cache->last_mask_rotation ||
- do_random)
+ if ((diameter != cache->lastdiameter) ||
+ (tex_rotation != cache->last_tex_rotation) ||
+ do_random ||
+ update_color)
{
if (cache->ibuf) {
IMB_freeImBuf(cache->ibuf);
cache->ibuf = NULL;
}
- if (cache->mask) {
- MEM_freeN(cache->mask);
- cache->mask = NULL;
- }
if (do_partial_update) {
- /* do partial update of texture + recreate mask */
- cache->mask = brush_painter_mask_new(painter, size);
- brush_painter_imbuf_partial_update(painter, pos);
+ /* do partial update of texture */
+ brush_painter_imbuf_partial_update(painter, pos, diameter);
}
else {
- /* create brush and mask from scratch */
- if (use_masking)
- cache->mask = brush_painter_mask_new(painter, size);
- cache->ibuf = brush_painter_imbuf_new(painter, size);
+ /* create brush from scratch */
+ cache->ibuf = brush_painter_imbuf_new(painter, diameter, pressure, distance);
}
- cache->lastsize = diameter;
- cache->lastalpha = alpha;
- cache->lastjitter = brush->jitter;
+ cache->lastdiameter = diameter;
cache->last_tex_rotation = tex_rotation;
- cache->last_mask_rotation = mask_rotation;
+ cache->last_pressure = pressure;
}
else if (do_partial_update) {
/* do only partial update of texture */
@@ -650,7 +764,7 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *pai
int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
if ((dx != 0) || (dy != 0)) {
- brush_painter_imbuf_partial_update(painter, pos);
+ brush_painter_imbuf_partial_update(painter, pos, diameter);
}
}
@@ -703,7 +817,7 @@ static void paint_2d_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const bool is_torus
}
}
-static int paint_2d_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus)
+static float paint_2d_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus, float w)
{
float inrgb[4];
@@ -716,16 +830,23 @@ static int paint_2d_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, flo
paint_2d_ibuf_rgb_get(ibuf, x, y, 0, inrgb);
}
+ mul_v4_fl(inrgb, w);
add_v4_v4(outrgb, inrgb);
- return 1;
+ return w;
}
-static void paint_2d_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, const bool is_torus)
+static void paint_2d_lift_soften(ImagePaintState *s, ImBuf *ibuf, ImBuf *ibufb, int *pos, const short is_torus)
{
- int x, y, count, xi, yi, xo, yo;
+ bool sharpen = (s->painter->cache.invert ^ ((s->brush->flag & BRUSH_DIR_IN) != 0));
+ float threshold = s->brush->sharp_threshold;
+ int x, y, xi, yi, xo, yo, xk, yk;
+ float count;
int out_off[2], in_off[2], dim[2];
+ int diff_pos[2];
float outrgb[4];
+ float rgba[4];
+ BlurKernel *kernel = s->blurkernel;
dim[0] = ibufb->x;
dim[1] = ibufb->y;
@@ -741,28 +862,52 @@ static void paint_2d_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, const bool
return;
}
+ /* find offset inside mask buffers to sample them */
+ sub_v2_v2v2_int(diff_pos, out_off, in_off);
+
for (y = 0; y < dim[1]; y++) {
for (x = 0; x < dim[0]; x++) {
/* get input pixel */
xi = in_off[0] + x;
yi = in_off[1] + y;
- count = 1;
- paint_2d_ibuf_rgb_get(ibuf, xi, yi, is_torus, outrgb);
+ count = 0.0;
+ paint_2d_ibuf_rgb_get(ibuf, xi, yi, is_torus, rgba);
+ zero_v4(outrgb);
- count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi - 1, outrgb, is_torus);
- count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi, outrgb, is_torus);
- count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi + 1, outrgb, is_torus);
+ for (yk = 0; yk < kernel->side; yk++) {
+ for (xk = 0; xk < kernel->side; xk++) {
+ count += paint_2d_ibuf_add_if(ibuf, xi + xk - kernel->pixel_len,
+ yi + yk - kernel->pixel_len, outrgb, is_torus,
+ kernel->wdata[xk + yk * kernel->side]);
+ }
+ }
- count += paint_2d_ibuf_add_if(ibuf, xi, yi - 1, outrgb, is_torus);
- count += paint_2d_ibuf_add_if(ibuf, xi, yi + 1, outrgb, is_torus);
+ if (count > 0.0f) {
+ mul_v4_fl(outrgb, 1.0f / (float)count);
- count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi - 1, outrgb, is_torus);
- count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi, outrgb, is_torus);
- count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi + 1, outrgb, is_torus);
+ if (sharpen) {
+ /* subtract blurred image from normal image gives high pass filter */
+ sub_v3_v3v3(outrgb, rgba, outrgb);
- mul_v4_fl(outrgb, 1.0f / (float)count);
+ /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
+ * colored speckles appearing in final image, and also to check for threshold */
+ outrgb[0] = outrgb[1] = outrgb[2] = rgb_to_grayscale(outrgb);
+ if (fabsf(outrgb[0]) > threshold) {
+ float mask = BKE_brush_alpha_get(s->scene, s->brush);
+ float alpha = rgba[3];
+ rgba[3] = outrgb[3] = mask;
+ /* add to enhance edges */
+ blend_color_add_float(outrgb, rgba, outrgb);
+ outrgb[3] = alpha;
+ }
+ else
+ copy_v4_v4(outrgb, rgba);
+ }
+ }
+ else
+ copy_v4_v4(outrgb, rgba);
/* write into brush buffer */
xo = out_off[0] + x;
yo = out_off[1] + y;
@@ -830,10 +975,10 @@ static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos)
tot = paint_2d_torus_split_region(region, ibufb, ibuf);
for (a = 0; a < tot; a++)
- IMB_rectblend(ibufb, ibufb, ibuf, NULL, NULL, 0, region[a].destx, region[a].desty,
+ 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);
+ region[a].width, region[a].height, IMB_BLEND_COPY_RGB, false);
}
static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
@@ -844,10 +989,10 @@ static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags);
IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h);
- IMB_rectblend(clonebuf, clonebuf, ibufb, NULL, NULL, 0, destx, desty, destx, desty, destx, desty, w, h,
- IMB_BLEND_COPY_ALPHA);
- IMB_rectblend(clonebuf, clonebuf, ibuf, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, w, h,
- IMB_BLEND_COPY_RGB);
+ IMB_rectblend(clonebuf, clonebuf, ibufb, NULL, NULL, NULL, 0, destx, desty, destx, desty, destx, desty, w, h,
+ IMB_BLEND_COPY_ALPHA, false);
+ IMB_rectblend(clonebuf, clonebuf, ibuf, NULL, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, w, h,
+ IMB_BLEND_COPY_RGB, false);
return clonebuf;
}
@@ -858,17 +1003,16 @@ static void paint_2d_convert_brushco(ImBuf *ibufb, const float pos[2], int ipos[
ipos[1] = (int)floorf((pos[1] - ibufb->y / 2) + 1.0f);
}
-static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const float lastpos[2], const float pos[2])
+static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsigned short *texmaskb, const float lastpos[2], const float pos[2])
{
ImagePaintState *s = ((ImagePaintState *)state);
- ImBuf *clonebuf = NULL, *frombuf, *tmpbuf = NULL;
+ ImBuf *clonebuf = NULL, *frombuf;
ImagePaintRegion region[4];
short torus = s->brush->flag & BRUSH_TORUS;
short blend = s->blend;
const float *offset = s->brush->clone.offset;
float liftpos[2];
- float brush_alpha = BKE_brush_alpha_get(s->scene, s->brush);
- unsigned short mask_max = (unsigned short)(brush_alpha * 65535.0f);
+ float mask_max = BKE_brush_alpha_get(s->scene, s->brush);
int bpos[2], blastpos[2], bliftpos[2];
int a, tot;
@@ -876,7 +1020,7 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const f
/* lift from canvas */
if (s->tool == PAINT_TOOL_SOFTEN) {
- paint_2d_lift_soften(s->canvas, ibufb, bpos, torus);
+ paint_2d_lift_soften(s, s->canvas, ibufb, bpos, torus);
}
else if (s->tool == PAINT_TOOL_SMEAR) {
if (lastpos[0] == pos[0] && lastpos[1] == pos[1])
@@ -903,9 +1047,6 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const f
paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
tot = 1;
}
-
- if (s->do_masking)
- tmpbuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, 0);
/* blend into canvas */
for (a = 0; a < tot; a++) {
@@ -916,11 +1057,14 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const f
if (s->do_masking) {
/* masking, find original pixels tiles from undo buffer to composite over */
int tilex, tiley, tilew, tileh, tx, ty;
+ ImBuf *tmpbuf;
imapaint_region_tiles(s->canvas, region[a].destx, region[a].desty,
region[a].width, region[a].height,
&tilex, &tiley, &tilew, &tileh);
-
+
+ tmpbuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, 0);
+
for (ty = tiley; ty <= tileh; ty++) {
for (tx = tilex; tx <= tilew; tx++) {
/* retrieve original pixels + mask from undo buffer */
@@ -929,31 +1073,32 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const f
int origy = region[a].desty - ty * IMAPAINT_TILE_SIZE;
if (s->canvas->rect_float)
- tmpbuf->rect_float = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask);
+ tmpbuf->rect_float = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask, false);
else
- tmpbuf->rect = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask);
+ tmpbuf->rect = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask, false);
IMB_rectblend(s->canvas, tmpbuf, frombuf, mask,
- maskb, mask_max,
+ curveb, texmaskb, mask_max,
region[a].destx, region[a].desty,
origx, origy,
region[a].srcx, region[a].srcy,
- region[a].width, region[a].height, blend);
+ region[a].width, region[a].height, blend, ((s->brush->flag & BRUSH_ACCUMULATE) != 0));
}
}
+
+ IMB_freeImBuf(tmpbuf);
}
else {
/* no masking, composite brush directly onto canvas */
- IMB_rectblend(s->canvas, s->canvas, frombuf, NULL, NULL, 0,
+ IMB_rectblend(s->canvas, s->canvas, frombuf, NULL, curveb, texmaskb, mask_max,
region[a].destx, region[a].desty,
region[a].destx, region[a].desty,
region[a].srcx, region[a].srcy,
- region[a].width, region[a].height, blend);
+ region[a].width, region[a].height, blend, false);
}
}
if (clonebuf) IMB_freeImBuf(clonebuf);
- if (tmpbuf) IMB_freeImBuf(tmpbuf);
return 1;
}
@@ -1003,10 +1148,7 @@ static int paint_2d_canvas_set(ImagePaintState *s, Image *ima)
}
/* set masking */
- s->do_masking = (s->brush->flag & BRUSH_AIRBRUSH ||
- (s->brush->imagepaint_tool == PAINT_TOOL_SMEAR) ||
- (s->brush->mtex.tex && !ELEM3(s->brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_3D)))
- ? false : true;
+ s->do_masking = paint_use_opacity_masking(s->brush);
return 1;
}
@@ -1016,11 +1158,15 @@ static void paint_2d_canvas_free(ImagePaintState *s)
BKE_image_release_ibuf(s->image, s->canvas, NULL);
BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL);
- if (s->do_masking)
- image_undo_remove_masks();
+ if (s->blurkernel) {
+ paint_delete_blur_kernel(s->blurkernel);
+ MEM_freeN(s->blurkernel);
+ }
+
+ image_undo_remove_masks();
}
-void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], int eraser)
+void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], const bool eraser, float pressure, float distance, float size)
{
float newuv[2], olduv[2];
ImagePaintState *s = ps;
@@ -1063,17 +1209,17 @@ void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], in
/* OCIO_TODO: float buffers are now always linear, so always use color correction
* this should probably be changed when texture painting color space is supported
*/
- brush_painter_2d_require_imbuf(painter, (ibuf->rect_float != NULL), !is_data, s->do_masking);
+ brush_painter_2d_require_imbuf(painter, (ibuf->rect_float != NULL), !is_data);
- brush_painter_2d_refresh_cache(s, painter, newuv, mval);
+ brush_painter_2d_refresh_cache(s, painter, newuv, mval, pressure, distance, size);
- if (paint_2d_op(s, painter->cache.ibuf, painter->cache.mask, olduv, newuv))
+ if (paint_2d_op(s, painter->cache.ibuf, painter->cache.curve_mask, painter->cache.tex_mask, olduv, newuv))
s->need_redraw = true;
BKE_image_release_ibuf(s->image, ibuf, NULL);
}
-void *paint_2d_new_stroke(bContext *C, wmOperator *op)
+void *paint_2d_new_stroke(bContext *C, wmOperator *op, int mode)
{
Scene *scene = CTX_data_scene(C);
ToolSettings *settings = scene->toolsettings;
@@ -1102,10 +1248,14 @@ void *paint_2d_new_stroke(bContext *C, wmOperator *op)
return NULL;
}
+ if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) {
+ s->blurkernel = paint_new_blur_kernel(brush, false);
+ }
+
paint_brush_init_tex(s->brush);
/* create painter */
- s->painter = brush_painter_2d_new(scene, s->brush);
+ s->painter = brush_painter_2d_new(scene, s->brush, mode == BRUSH_STROKE_INVERT);
return s;
}
@@ -1134,6 +1284,7 @@ void paint_2d_redraw(const bContext *C, void *ps, bool final)
/* compositor listener deals with updating */
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
+ DAG_id_tag_update(&s->image->id, 0);
}
else {
if (!s->sima || !s->sima->lock)
@@ -1153,3 +1304,334 @@ void paint_2d_stroke_done(void *ps)
MEM_freeN(s);
}
+
+static void paint_2d_fill_add_pixel_byte(
+ const int x_px, const int y_px, ImBuf *ibuf, BLI_Stack *stack, BLI_bitmap *touched,
+ const float color[4], float threshold_sq)
+{
+ int coordinate;
+
+ if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0)
+ return;
+
+ coordinate = y_px * ibuf->x + x_px;
+
+ if (!BLI_BITMAP_TEST(touched, coordinate)) {
+ float color_f[4];
+ unsigned char *color_b = (unsigned char *)(ibuf->rect + coordinate);
+ rgba_uchar_to_float(color_f, color_b);
+
+ if (compare_len_squared_v3v3(color_f, color, threshold_sq)) {
+ BLI_stack_push(stack, &coordinate);
+ }
+ BLI_BITMAP_SET(touched, coordinate, true);
+ }
+}
+
+static void paint_2d_fill_add_pixel_float(
+ const int x_px, const int y_px, ImBuf *ibuf, BLI_Stack *stack, BLI_bitmap *touched,
+ const float color[4], float threshold_sq)
+{
+ int coordinate;
+
+ if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0)
+ return;
+
+ coordinate = y_px * ibuf->x + x_px;
+
+ if (!BLI_BITMAP_TEST(touched, coordinate)) {
+ if (compare_len_squared_v3v3(ibuf->rect_float + 4 * coordinate, color, threshold_sq)) {
+ BLI_stack_push(stack, &coordinate);
+ }
+ BLI_BITMAP_SET(touched, coordinate, true);
+ }
+}
+
+/* this function expects linear space color values */
+void paint_2d_bucket_fill(
+ const bContext *C, const float color[3], Brush *br,
+ const float mouse_init[2],
+ void *ps)
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = sima->image;
+
+ ImagePaintState *s = ps;
+
+ ImBuf *ibuf;
+ int x_px, y_px;
+ unsigned int color_b;
+ float color_f[4];
+ float strength = br ? br->alpha : 1.0f;
+
+ bool do_float;
+
+ if (!ima)
+ return;
+
+ ibuf = BKE_image_acquire_ibuf(ima, &sima->iuser, NULL);
+
+ if (!ibuf)
+ return;
+
+ do_float = (ibuf->rect_float != NULL);
+ /* first check if our image is float. If it is not we should correct the color to
+ * be in gamma space. strictly speaking this is not correct, but blender does not paint
+ * byte images in linear space */
+ if (!do_float) {
+ linearrgb_to_srgb_uchar3((unsigned char *)&color_b, color);
+ *(((char *)&color_b) + 3) = strength * 255;
+ }
+ else {
+ copy_v3_v3(color_f, color);
+ color_f[3] = strength;
+ }
+
+ if (!mouse_init || !br) {
+ /* first case, no image UV, fill the whole image */
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+
+ if (do_float) {
+ for (x_px = 0; x_px < ibuf->x; x_px++) {
+ for (y_px = 0; y_px < ibuf->y; y_px++) {
+ blend_color_mix_float(ibuf->rect_float + 4 * (y_px * ibuf->x + x_px),
+ ibuf->rect_float + 4 * (y_px * ibuf->x + x_px), color_f);
+ }
+ }
+ }
+ else {
+ for (x_px = 0; x_px < ibuf->x; x_px++) {
+ for (y_px = 0; y_px < ibuf->y; y_px++) {
+ blend_color_mix_byte((unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px),
+ (unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px), (unsigned char *)&color_b);
+ }
+ }
+ }
+ }
+ else {
+ /* second case, start sweeping the neighboring pixels, looking for pixels whose
+ * value is within the brush fill threshold from the fill color */
+ BLI_Stack *stack;
+ BLI_bitmap *touched;
+ int coordinate;
+ int width = ibuf->x;
+ float image_init[2];
+ int minx = ibuf->x, miny = ibuf->y, maxx = 0, maxy = 0;
+ float pixel_color[4];
+ float threshold_sq = br->fill_threshold * br->fill_threshold;
+
+ UI_view2d_region_to_view(s->v2d, mouse_init[0], mouse_init[1], &image_init[0], &image_init[1]);
+
+ x_px = image_init[0] * ibuf->x;
+ y_px = image_init[1] * ibuf->y;
+
+ if (x_px >= ibuf->x || x_px < 0 || y_px > ibuf->y || y_px < 0) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return;
+ }
+
+ /* change image invalidation method later */
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+
+ stack = BLI_stack_new(sizeof(int), __func__);
+ touched = BLI_BITMAP_NEW(ibuf->x * ibuf->y, "bucket_fill_bitmap");
+
+ coordinate = (y_px * ibuf->x + x_px);
+
+ if (do_float) {
+ copy_v4_v4(pixel_color, ibuf->rect_float + 4 * coordinate);
+ }
+ else {
+ int pixel_color_b = *(ibuf->rect + coordinate);
+ rgba_uchar_to_float(pixel_color, (unsigned char *)&pixel_color_b);
+ }
+
+ BLI_stack_push(stack, &coordinate);
+ BLI_BITMAP_SET(touched, coordinate, true);
+
+ if (do_float) {
+ while (!BLI_stack_is_empty(stack)) {
+ BLI_stack_pop(stack, &coordinate);
+
+ IMB_blend_color_float(ibuf->rect_float + 4 * (coordinate),
+ ibuf->rect_float + 4 * (coordinate),
+ color_f, br->blend);
+
+ /* reconstruct the coordinates here */
+ x_px = coordinate % width;
+ y_px = coordinate / width;
+
+ paint_2d_fill_add_pixel_float(x_px - 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px - 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px - 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px + 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px + 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px + 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+
+ if (x_px > maxx)
+ maxx = x_px;
+ if (x_px < minx)
+ minx = x_px;
+ if (y_px > maxy)
+ maxy = y_px;
+ if (x_px > miny)
+ miny = y_px;
+ }
+ }
+ else {
+ while (!BLI_stack_is_empty(stack)) {
+ BLI_stack_pop(stack, &coordinate);
+
+ IMB_blend_color_byte((unsigned char *)(ibuf->rect + coordinate),
+ (unsigned char *)(ibuf->rect + coordinate),
+ (unsigned char *)&color_b, br->blend);
+
+ /* reconstruct the coordinates here */
+ x_px = coordinate % width;
+ y_px = coordinate / width;
+
+ paint_2d_fill_add_pixel_byte(x_px - 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px - 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px - 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px + 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px + 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px + 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+
+ if (x_px > maxx)
+ maxx = x_px;
+ if (x_px < minx)
+ minx = x_px;
+ if (y_px > maxy)
+ maxy = y_px;
+ if (x_px > miny)
+ miny = y_px;
+ }
+ }
+
+ MEM_freeN(touched);
+ BLI_stack_free(stack);
+ }
+
+ imapaint_image_update(sima, ima, ibuf, false);
+ ED_imapaint_clear_partial_redraw();
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+}
+
+void paint_2d_gradient_fill(
+ const bContext *C, Brush *br,
+ const float mouse_init[2], const float mouse_final[2],
+ void *ps)
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = sima->image;
+ ImagePaintState *s = ps;
+
+ ImBuf *ibuf;
+ int x_px, y_px;
+ unsigned int color_b;
+ float color_f[4];
+ float image_init[2], image_final[2];
+ float tangent[2];
+ float line_len_sq_inv, line_len;
+
+ bool do_float;
+
+ if (!ima)
+ return;
+
+ ibuf = BKE_image_acquire_ibuf(ima, &sima->iuser, NULL);
+
+ if (!ibuf)
+ return;
+
+ UI_view2d_region_to_view(s->v2d, mouse_final[0], mouse_final[1], &image_final[0], &image_final[1]);
+ UI_view2d_region_to_view(s->v2d, mouse_init[0], mouse_init[1], &image_init[0], &image_init[1]);
+
+ image_final[0] *= ibuf->x;
+ image_final[1] *= ibuf->y;
+
+ image_init[0] *= ibuf->x;
+ image_init[1] *= ibuf->y;
+
+ /* some math to get needed gradient variables */
+ sub_v2_v2v2(tangent, image_final, image_init);
+ line_len = len_squared_v2(tangent);
+ line_len_sq_inv = 1.0f / line_len;
+ line_len = sqrt(line_len);
+
+ do_float = (ibuf->rect_float != NULL);
+
+ /* this will be substituted by something else when selection is available */
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+
+ if (do_float) {
+ for (x_px = 0; x_px < ibuf->x; x_px++) {
+ for (y_px = 0; y_px < ibuf->y; y_px++) {
+ float f;
+ float p[2] = {x_px - image_init[0], y_px - image_init[1]};
+
+ switch (br->gradient_fill_mode) {
+ case BRUSH_GRADIENT_LINEAR:
+ {
+ f = dot_v2v2(p, tangent) * line_len_sq_inv;
+ break;
+ }
+ case BRUSH_GRADIENT_RADIAL:
+ {
+ f = len_v2(p) / line_len;
+ break;
+ }
+ }
+ do_colorband(br->gradient, f, color_f);
+ /* convert to premultiplied */
+ mul_v3_fl(color_f, color_f[3]);
+ color_f[3] *= br->alpha;
+ IMB_blend_color_float(ibuf->rect_float + 4 * (y_px * ibuf->x + x_px),
+ ibuf->rect_float + 4 * (y_px * ibuf->x + x_px),
+ color_f, br->blend);
+ }
+ }
+ }
+ else {
+ for (x_px = 0; x_px < ibuf->x; x_px++) {
+ for (y_px = 0; y_px < ibuf->y; y_px++) {
+ float f;
+ float p[2] = {x_px - image_init[0], y_px - image_init[1]};
+
+ switch (br->gradient_fill_mode) {
+ case BRUSH_GRADIENT_LINEAR:
+ {
+ f = dot_v2v2(p, tangent) * line_len_sq_inv;
+ break;
+ }
+ case BRUSH_GRADIENT_RADIAL:
+ {
+ f = len_v2(p) / line_len;
+ break;
+ }
+ }
+
+ do_colorband(br->gradient, f, color_f);
+ rgba_float_to_uchar((unsigned char *)&color_b, color_f);
+ ((unsigned char *)&color_b)[3] *= br->alpha;
+ IMB_blend_color_byte((unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px),
+ (unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px),
+ (unsigned char *)&color_b, br->blend);
+ }
+ }
+ }
+
+ imapaint_image_update(sima, ima, ibuf, false);
+ ED_imapaint_clear_partial_redraw();
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 399b5044a05..ef4a4e9bf79 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -48,31 +48,42 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "PIL_time.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "DNA_brush_types.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "BKE_camera.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_idprop.h"
#include "BKE_brush.h"
#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "BKE_texture.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
+#include "ED_image.h"
+#include "ED_mesh.h"
#include "ED_paint.h"
#include "ED_screen.h"
#include "ED_uvedit.h"
@@ -88,6 +99,7 @@
#include "RNA_enum_types.h"
#include "GPU_draw.h"
+#include "GPU_buffers.h"
#include "IMB_colormanagement.h"
@@ -141,6 +153,7 @@ BLI_INLINE unsigned char f_to_char(const float val)
#define PROJ_SRC_VIEW 1
#define PROJ_SRC_IMAGE_CAM 2
#define PROJ_SRC_IMAGE_VIEW 3
+#define PROJ_SRC_VIEW_FILL 4
#define PROJ_VIEW_DATA_ID "view_data"
#define PROJ_VIEW_DATA_SIZE (4 * 4 + 4 * 4 + 3) /* viewmat + winmat + clipsta + clipend + is_ortho */
@@ -162,6 +175,9 @@ BLI_INLINE unsigned char f_to_char(const float val)
/* vert flags */
#define PROJ_VERT_CULL 1
+/* to avoid locking in tile initialization */
+#define TILE_PENDING SET_INT_IN_POINTER(-1)
+
/* This is mainly a convenience struct used so we can keep an array of images we use
* Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread
* because 'partRedrawRect' and 'touch' values would not be thread safe */
@@ -169,7 +185,10 @@ typedef struct ProjPaintImage {
Image *ima;
ImBuf *ibuf;
ImagePaintPartialRedraw *partRedrawRect;
- void **undoRect; /* only used to build undo tiles after painting */
+ volatile void **undoRect; /* only used to build undo tiles during painting */
+ unsigned short **maskRect; /* the mask accumulation must happen on canvas, not on space screen bucket.
+ * Here we store the mask rectangle */
+ bool **valid; /* store flag to enforce validation of undo rectangle */
int touch;
} ProjPaintImage;
@@ -181,9 +200,14 @@ typedef struct ProjPaintState {
Scene *scene;
int source; /* PROJ_SRC_**** */
+ /* the paint color. It can change depending of inverted mode or not */
+ float paint_color[3];
+ float paint_color_linear[3];
+
Brush *brush;
short tool, blend, mode;
int orig_brush_size;
+ float brush_size;
Object *ob;
/* end similarities with ImagePaintState */
@@ -194,10 +218,15 @@ typedef struct ProjPaintState {
MVert *dm_mvert;
MFace *dm_mface;
- MTFace *dm_mtface;
- MTFace *dm_mtface_clone; /* other UV map, use for cloning between layers */
+ MTFace **dm_mtface;
+ MTFace **dm_mtface_clone; /* other UV map, use for cloning between layers */
MTFace *dm_mtface_stencil;
+ Image *stencil_ima;
+ Image *canvas_ima;
+ Image *clone_ima;
+ float stencil_value;
+
/* projection painting only */
MemArena *arena_mt[BLENDER_MAX_THREADS]; /* for multithreading, the first item is sometimes used for non threaded cases too */
LinkNode **bucketRect; /* screen sized 2D array, each pixel has a linked list of ProjPixel's */
@@ -231,6 +260,8 @@ typedef struct ProjPaintState {
bool do_layer_clone;
bool do_layer_stencil;
bool do_layer_stencil_inv;
+ bool do_stencil_brush;
+ bool do_material_slots;
bool do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
bool do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
@@ -245,7 +276,6 @@ typedef struct ProjPaintState {
bool do_masking; /* use masking during painting. Some operations such as airbrush may disable */
bool is_texbrush; /* only to avoid running */
bool is_maskbrush; /* mask brush is applied before masking */
- bool is_maskbrush_tiled; /* mask brush is applied after masking */
#ifndef PROJ_DEBUG_NOSEAMBLEED
float seam_bleed_px;
#endif
@@ -269,6 +299,10 @@ typedef struct ProjPaintState {
/* redraw */
bool need_redraw;
+
+ BlurKernel *blurkernel;
+
+ SpinLock *tile_lock;
} ProjPaintState;
typedef union pixelPointer {
@@ -290,14 +324,16 @@ typedef struct ProjPixel {
* Store the max mask value to avoid painting over an area with a lower opacity
* with an advantage that we can avoid touching the pixel at all, if the
* new mask value is lower then mask_accum */
- unsigned short mask_accum;
+ unsigned short *mask_accum;
/* for various reasons we may want to mask out painting onto this pixel */
unsigned short mask;
short x_px, y_px;
+ /* horrible hack, store tile valid flag pointer here to re-validate tiles used for anchored and drag-dot strokes */
+ bool *valid;
- PixelStore origColor;
+ PixelPointer origColor;
PixelStore newColor;
PixelPointer pixel;
@@ -310,33 +346,51 @@ typedef struct ProjPixelClone {
PixelStore clonepx;
} ProjPixelClone;
-/* blur, store surrounding colors */
-#define PROJ_PIXEL_SOFTEN_TOT 4
-/* blur picking offset (in screenspace) */
-#define PROJ_PIXEL_SOFTEN_OFS_PX 1.0f
+/* undo tile pushing */
+typedef struct {
+ SpinLock *lock;
+ bool masked;
+ unsigned short tile_width;
+ ImBuf **tmpibuf;
+ ProjPaintImage *pjima;
+} TileInfo;
-static const float proj_pixel_soften_v2[PROJ_PIXEL_SOFTEN_TOT][2] = {
- {-PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f},
- { 0.0f, -PROJ_PIXEL_SOFTEN_OFS_PX},
- { 0.0f, PROJ_PIXEL_SOFTEN_OFS_PX},
- { PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f},
-};
/* Finish projection painting structs */
-static Image *project_paint_face_image(const ProjPaintState *ps, MTFace *dm_mtface, int face_index)
+static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int face_index)
{
- Image *ima;
+ MFace *mf = ps->dm_mface + face_index;
+ Material *ma = ps->dm->mat[mf->mat_nr];
+ return ma->texpaintslot + ma->paint_active_slot;
+}
- if (ps->do_new_shading_nodes) { /* cached BKE_scene_use_new_shading_nodes result */
- MFace *mf = ps->dm_mface + face_index;
- ED_object_get_active_image(ps->ob, mf->mat_nr + 1, &ima, NULL, NULL);
+static Image *project_paint_face_paint_image(const ProjPaintState *ps, int face_index)
+{
+ if (ps->do_stencil_brush) {
+ return ps->stencil_ima;
}
else {
- ima = dm_mtface[face_index].tpage;
+ MFace *mf = ps->dm_mface + face_index;
+ Material *ma = ps->dm->mat[mf->mat_nr];
+ TexPaintSlot *slot = ma->texpaintslot + ma->paint_active_slot;
+ return slot ? slot->ima : ps->canvas_ima;
}
+}
+
+static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int face_index)
+{
+ MFace *mf = ps->dm_mface + face_index;
+ Material *ma = ps->dm->mat[mf->mat_nr];
+ return ma->texpaintslot + ma->paint_clone_slot;
+}
- return ima;
+static Image *project_paint_face_clone_image(const ProjPaintState *ps, int face_index)
+{
+ MFace *mf = ps->dm_mface + face_index;
+ Material *ma = ps->dm->mat[mf->mat_nr];
+ TexPaintSlot *slot = ma->texpaintslot + ma->paint_clone_slot;
+ return slot ? slot->ima : ps->clone_ima;
}
/* fast projection bucket array lookup, use the safe version for bound checking */
@@ -477,8 +531,8 @@ static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], f
static void uvco_to_wrapped_pxco(const float uv[2], int ibuf_x, int ibuf_y, float *x, float *y)
{
/* use */
- *x = (float)fmodf(uv[0], 1.0f);
- *y = (float)fmodf(uv[1], 1.0f);
+ *x = fmodf(uv[0], 1.0f);
+ *y = fmodf(uv[1], 1.0f);
if (*x < 0.0f) *x += 1.0f;
if (*y < 0.0f) *y += 1.0f;
@@ -505,7 +559,7 @@ static bool project_paint_PickColor(const ProjPaintState *ps, const float pt[2],
if (face_index == -1)
return 0;
- tf = ps->dm_mtface + face_index;
+ tf = *(ps->dm_mtface + face_index);
if (side == 0) {
interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[1], tf->uv[2], w);
@@ -514,8 +568,9 @@ static bool project_paint_PickColor(const ProjPaintState *ps, const float pt[2],
interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[2], tf->uv[3], w);
}
- ima = project_paint_face_image(ps, ps->dm_mtface, face_index);
+ ima = project_paint_face_paint_image(ps, face_index);
ibuf = BKE_image_get_first_ibuf(ima); /* we must have got the imbuf before getting here */
+ if (!ibuf) return 0;
if (interp) {
float x, y;
@@ -762,11 +817,11 @@ static int line_isect_x(const float p1[2], const float p2[2], const float x_leve
static bool cmp_uv(const float vec2a[2], const float vec2b[2])
{
/* if the UV's are not between 0.0 and 1.0 */
- float xa = (float)fmodf(vec2a[0], 1.0f);
- float ya = (float)fmodf(vec2a[1], 1.0f);
+ float xa = fmodf(vec2a[0], 1.0f);
+ float ya = fmodf(vec2a[1], 1.0f);
- float xb = (float)fmodf(vec2b[0], 1.0f);
- float yb = (float)fmodf(vec2b[1], 1.0f);
+ float xb = fmodf(vec2b[0], 1.0f);
+ float yb = fmodf(vec2b[1], 1.0f);
if (xa < 0.0f) xa += 1.0f;
if (ya < 0.0f) ya += 1.0f;
@@ -843,7 +898,7 @@ static bool pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x
static void project_face_winding_init(const ProjPaintState *ps, const int face_index)
{
/* detect the winding of faces in uv space */
- MTFace *tf = ps->dm_mtface + face_index;
+ MTFace *tf = ps->dm_mtface[face_index];
float winding = cross_tri_v2(tf->uv[0], tf->uv[1], tf->uv[2]);
if (ps->dm_mface[face_index].v4)
@@ -868,7 +923,7 @@ static bool check_seam(const ProjPaintState *ps,
MFace *mf;
MTFace *tf;
const MFace *orig_mf = ps->dm_mface + orig_face;
- const MTFace *orig_tf = ps->dm_mtface + orig_face;
+ const MTFace *orig_tf = ps->dm_mtface[orig_face];
/* vert indices from face vert order indices */
i1 = (*(&orig_mf->v1 + orig_i1_fidx));
@@ -890,17 +945,19 @@ static bool check_seam(const ProjPaintState *ps,
/* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */
if (i2_fidx != -1) {
- Image *tpage = project_paint_face_image(ps, ps->dm_mtface, face_index);
- Image *orig_tpage = project_paint_face_image(ps, ps->dm_mtface, orig_face);
+ Image *tpage = project_paint_face_paint_image(ps, face_index);
+ Image *orig_tpage = project_paint_face_paint_image(ps, orig_face);
BLI_assert(i1_fidx != -1);
/* This IS an adjacent face!, now lets check if the UVs are ok */
- tf = ps->dm_mtface + face_index;
+ tf = ps->dm_mtface[face_index];
/* set up the other face */
*other_face = face_index;
- *orig_fidx = (i1_fidx < i2_fidx) ? i1_fidx : i2_fidx;
+
+ /* we check if difference is 1 here, else we might have a case of edge 2-0 or 3-0 for quads */
+ *orig_fidx = (i1_fidx < i2_fidx && (i2_fidx - i1_fidx == 1)) ? i1_fidx : i2_fidx;
/* initialize face winding if needed */
if ((ps->faceWindingFlags[face_index] & PROJ_FACE_WINDING_INIT) == 0)
@@ -909,7 +966,7 @@ static bool check_seam(const ProjPaintState *ps,
/* first test if they have the same image */
if ((orig_tpage == tpage) &&
cmp_uv(orig_tf->uv[orig_i1_fidx], tf->uv[i1_fidx]) &&
- cmp_uv(orig_tf->uv[orig_i2_fidx], tf->uv[i2_fidx]) )
+ cmp_uv(orig_tf->uv[orig_i2_fidx], tf->uv[i2_fidx]))
{
/* if faces don't have the same winding in uv space,
* they are on the same side so edge is boundary */
@@ -1168,7 +1225,7 @@ static float project_paint_uvpixel_mask(
if (ps->do_layer_stencil) {
/* another UV maps image is masking this one's */
ImBuf *ibuf_other;
- Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_stencil, face_index);
+ Image *other_tpage = ps->stencil_ima;
const MTFace *tf_other = ps->dm_mtface_stencil + face_index;
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
@@ -1296,24 +1353,70 @@ static int project_paint_pixel_sizeof(const short tool)
}
}
+static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
+{
+ ProjPaintImage *pjIma = tinf->pjima;
+ int tile_index = tx + ty * tinf->tile_width;
+ bool generate_tile = false;
+
+ /* double check lock to avoid locking */
+ if (UNLIKELY(!pjIma->undoRect[tile_index])) {
+ if (tinf->lock)
+ BLI_spin_lock(tinf->lock);
+ if (LIKELY(!pjIma->undoRect[tile_index])) {
+ pjIma->undoRect[tile_index] = TILE_PENDING;
+ generate_tile = true;
+ }
+ if (tinf->lock)
+ BLI_spin_unlock(tinf->lock);
+ }
+
+
+ if (generate_tile) {
+ volatile void *undorect;
+ if (tinf->masked) {
+ undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true);
+ }
+ else {
+ undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tile_index], true);
+ }
+
+ pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
+ /* tile ready, publish */
+ if (tinf->lock)
+ BLI_spin_lock(tinf->lock);
+ pjIma->undoRect[tile_index] = undorect;
+ if (tinf->lock)
+ BLI_spin_unlock(tinf->lock);
+
+ }
+
+ return tile_index;
+}
/* run this function when we know a bucket's, face's pixel can be initialized,
* return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */
static ProjPixel *project_paint_uvpixel_init(
const ProjPaintState *ps,
MemArena *arena,
- const ImBuf *ibuf,
+ const TileInfo *tinf,
int x_px, int y_px,
const float mask,
const int face_index,
- const int image_index,
const float pixelScreenCo[4],
const float world_spaceCo[3],
const int side,
const float w[3])
{
ProjPixel *projPixel;
-
+ int x_tile, y_tile;
+ int x_round, y_round;
+ int tile_offset;
+ /* volatile is important here to ensure pending check is not optimized away by compiler*/
+ volatile int tile_index;
+
+ ProjPaintImage *projima = tinf->pjima;
+ ImBuf *ibuf = projima->ibuf;
/* wrap pixel location */
x_px = mod_i(x_px, ibuf->x);
@@ -1321,19 +1424,36 @@ static ProjPixel *project_paint_uvpixel_init(
BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool));
projPixel = (ProjPixel *)BLI_memarena_alloc(arena, ps->pixel_sizeof);
+
+ /* calculate the undo tile offset of the pixel, used to store the original
+ * pixel color and accumulated mask if any */
+ x_tile = x_px >> IMAPAINT_TILE_BITS;
+ y_tile = y_px >> IMAPAINT_TILE_BITS;
+
+ x_round = x_tile * IMAPAINT_TILE_SIZE;
+ y_round = y_tile * IMAPAINT_TILE_SIZE;
//memset(projPixel, 0, size);
+ tile_offset = (x_px - x_round) + (y_px - y_round) * IMAPAINT_TILE_SIZE;
+ tile_index = project_paint_undo_subtiles(tinf, x_tile, y_tile);
+
+ /* other thread may be initializing the tile so wait here */
+ while (projima->undoRect[tile_index] == TILE_PENDING)
+ ;
+
+ BLI_assert(tile_index < (IMAPAINT_TILE_NUMBER(ibuf->x) * IMAPAINT_TILE_NUMBER(ibuf->y)));
+ BLI_assert(tile_offset < (IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE));
+
+ projPixel->valid = projima->valid[tile_index];
+
if (ibuf->rect_float) {
projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
- projPixel->origColor.f[0] = projPixel->pixel.f_pt[0];
- projPixel->origColor.f[1] = projPixel->pixel.f_pt[1];
- projPixel->origColor.f[2] = projPixel->pixel.f_pt[2];
- projPixel->origColor.f[3] = projPixel->pixel.f_pt[3];
+ projPixel->origColor.f_pt = (float *)projima->undoRect[tile_index] + 4 * tile_offset;
zero_v4(projPixel->newColor.f);
}
else {
- projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4));
- projPixel->origColor.uint = *projPixel->pixel.uint_pt;
+ projPixel->pixel.ch_pt = (unsigned char *)(ibuf->rect + (x_px + y_px * ibuf->x));
+ projPixel->origColor.uint_pt = (unsigned int *)projima->undoRect[tile_index] + tile_offset;
projPixel->newColor.uint = 0;
}
@@ -1348,7 +1468,10 @@ static ProjPixel *project_paint_uvpixel_init(
projPixel->y_px = y_px;
projPixel->mask = (unsigned short)(mask * 65535);
- projPixel->mask_accum = 0;
+ if (ps->do_masking)
+ projPixel->mask_accum = projima->maskRect[tile_index] + tile_offset;
+ else
+ projPixel->mask_accum = NULL;
/* which bounding box cell are we in?, needed for undo */
projPixel->bb_cell_index = ((int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV)) +
@@ -1358,8 +1481,8 @@ static ProjPixel *project_paint_uvpixel_init(
if (ps->tool == PAINT_TOOL_CLONE) {
if (ps->dm_mtface_clone) {
ImBuf *ibuf_other;
- Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_clone, face_index);
- const MTFace *tf_other = ps->dm_mtface_clone + face_index;
+ Image *other_tpage = project_paint_face_clone_image(ps, face_index);
+ const MTFace *tf_other = ps->dm_mtface_clone[face_index];
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
/* BKE_image_acquire_ibuf - TODO - this may be slow */
@@ -1423,7 +1546,8 @@ static ProjPixel *project_paint_uvpixel_init(
if (ibuf->rect_float) projPixel->pixel.f_pt[0] = 0;
else projPixel->pixel.ch_pt[0] = 0;
#endif
- projPixel->image_index = image_index;
+ /* pointer arithmetics */
+ projPixel->image_index = projima - ps->projImages;
return projPixel;
}
@@ -2131,15 +2255,24 @@ static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot
/* One of the most important function for projection painting, since it selects the pixels to be added into each bucket.
* initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */
-static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, const ImBuf *ibuf, const short clamp_u, const short clamp_v)
+static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf, const short clamp_u, const short clamp_v)
{
/* Projection vars, to get the 3D locations into screen space */
MemArena *arena = ps->arena_mt[thread_index];
LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index;
LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index];
+ bool threaded = (ps->thread_tot > 1);
+
+ TileInfo tinf = {
+ ps->tile_lock,
+ ps->do_masking,
+ IMAPAINT_TILE_NUMBER(ibuf->x),
+ tmpibuf,
+ ps->projImages + image_index
+ };
const MFace *mf = ps->dm_mface + face_index;
- const MTFace *tf = ps->dm_mtface + face_index;
+ const MTFace *tf = ps->dm_mtface[face_index];
/* UV/pixel seeking data */
int x; /* Image X-Pixel */
@@ -2183,8 +2316,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
/* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel
* this is done so we can avoid offsetting all the pixels by 0.5 which causes
* problems when wrapping negative coords */
- xhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE * (1.0f / 3.0f))) / ibuf_xf;
- yhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE * (1.0f / 4.0f))) / ibuf_yf;
+ xhalfpx = (0.5f + (PROJ_PIXEL_TOLERANCE * (1.0f / 3.0f))) / ibuf_xf;
+ yhalfpx = (0.5f + (PROJ_PIXEL_TOLERANCE * (1.0f / 4.0f))) / ibuf_yf;
/* Note about (PROJ_GEOM_TOLERANCE/x) above...
* Needed to add this offset since UV coords are often quads aligned to pixels.
@@ -2258,6 +2391,10 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
CLAMP(bounds_px.ymax, 0, ibuf->y);
}
+ /*
+ project_paint_undo_tiles_init(&bounds_px, ps->projImages + image_index, tmpibuf,
+ tile_width, threaded, ps->do_masking);
+ */
/* clip face and */
has_isect = 0;
@@ -2300,8 +2437,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
if (mask > 0.0f) {
BLI_linklist_prepend_arena(
bucketPixelNodes,
- project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index,
- image_index, pixelScreenCo, wco, side, w),
+ project_paint_uvpixel_init(ps, arena, &tinf, x, y, mask, face_index,
+ pixelScreenCo, wco, side, w),
arena
);
}
@@ -2333,7 +2470,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
if (ps->seam_bleed_px > 0.0f) {
int face_seam_flag;
- if (ps->thread_tot > 1)
+ if (threaded)
BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
face_seam_flag = ps->faceSeamFlags[face_index];
@@ -2351,7 +2488,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
if ((face_seam_flag & (PROJ_FACE_SEAM1 | PROJ_FACE_SEAM2 | PROJ_FACE_SEAM3 | PROJ_FACE_SEAM4)) == 0) {
- if (ps->thread_tot > 1)
+ if (threaded)
BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
}
@@ -2376,7 +2513,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
uv_image_outset(tf_uv_pxoffset, outset_uv, ps->seam_bleed_px, ibuf->x, ibuf->y, mf->v4 != 0);
/* ps->faceSeamUVs cant be modified when threading, now this is done we can unlock */
- if (ps->thread_tot > 1)
+ if (threaded)
BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
vCoSS[0] = ps->screenCoords[mf->v1];
@@ -2520,7 +2657,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
if (mask > 0.0f) {
BLI_linklist_prepend_arena(
bucketPixelNodes,
- project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, wco, side, w),
+ project_paint_uvpixel_init(ps, arena, &tinf, x, y, mask, face_index,
+ pixelScreenCo, wco, side, w),
arena
);
}
@@ -2589,6 +2727,7 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index
ImBuf *ibuf = NULL;
Image *tpage_last = NULL, *tpage;
Image *ima = NULL;
+ ImBuf *tmpibuf = NULL;
if (ps->image_tot == 1) {
/* Simple loop, no context switching */
@@ -2596,7 +2735,7 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index
ima = ps->projImages[0].ima;
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
- project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
+ project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, &tmpibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
}
}
else {
@@ -2606,7 +2745,7 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index
face_index = GET_INT_FROM_POINTER(node->link);
/* Image context switching */
- tpage = project_paint_face_image(ps, ps->dm_mtface, face_index);
+ tpage = project_paint_face_paint_image(ps, face_index);
if (tpage_last != tpage) {
tpage_last = tpage;
@@ -2620,10 +2759,13 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index
}
/* context switching done */
- project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
+ project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, &tmpibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
}
}
+ if (tmpibuf)
+ IMB_freeImBuf(tmpibuf);
+
ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT;
}
@@ -2771,11 +2913,17 @@ static void project_paint_begin(ProjPaintState *ps)
ProjPaintImage *projIma;
Image *tpage_last = NULL, *tpage;
+ TexPaintSlot *slot_last = NULL, *slot = NULL;
+ TexPaintSlot *slot_last_clone = NULL, *slot_clone;
/* Face vars */
MPoly *mpoly_orig;
MFace *mf;
- MTFace *tf;
+ MTFace **tf;
+ MTFace *tf_base;
+
+ MTFace **tf_clone;
+ MTFace *tf_clone_base = NULL;
int a, i; /* generic looping vars */
int image_index = -1, face_index;
@@ -2821,7 +2969,7 @@ static void project_paint_begin(ProjPaintState *ps)
ps->dm_release = true;
}
- if (!CustomData_has_layer(&ps->dm->faceData, CD_MTFACE) ) {
+ if (!CustomData_has_layer(&ps->dm->faceData, CD_MTFACE)) {
if (ps->dm_release)
ps->dm->release(ps->dm);
@@ -2830,13 +2978,15 @@ static void project_paint_begin(ProjPaintState *ps)
return;
}
- ps->dm_mvert = ps->dm->getVertArray(ps->dm);
- ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
- ps->dm_mtface = ps->dm->getTessFaceDataArray(ps->dm, CD_MTFACE);
+ DM_update_materials(ps->dm, ps->ob);
ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
ps->dm_totface = ps->dm->getNumTessFaces(ps->dm);
+ ps->dm_mvert = ps->dm->getVertArray(ps->dm);
+ ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
+ ps->dm_mtface = MEM_mallocN(ps->dm_totface * sizeof(MTFace *), "proj_paint_mtfaces");
+
if (ps->do_face_sel) {
index_mf_to_mpoly = ps->dm->getTessFaceDataArray(ps->dm, CD_ORIGINDEX);
index_mp_to_orig = ps->dm->getPolyDataArray(ps->dm, CD_ORIGINDEX);
@@ -2852,32 +3002,36 @@ static void project_paint_begin(ProjPaintState *ps)
}
/* use clone mtface? */
-
-
- /* Note, use the original mesh for getting the clone and mask layer index
- * this avoids re-generating the derived mesh just to get the new index */
if (ps->do_layer_clone) {
- //int layer_num = CustomData_get_clone_layer(&ps->dm->faceData, CD_MTFACE);
- int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
- if (layer_num != -1)
- ps->dm_mtface_clone = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
-
- if (ps->dm_mtface_clone == NULL || ps->dm_mtface_clone == ps->dm_mtface) {
- ps->do_layer_clone = false;
- ps->dm_mtface_clone = NULL;
- }
+ ps->dm_mtface_clone = MEM_mallocN(ps->dm_totface * sizeof(MTFace *), "proj_paint_mtfaces");
}
- if (ps->do_layer_stencil) {
+ if (ps->do_layer_stencil || ps->do_stencil_brush) {
//int layer_num = CustomData_get_stencil_layer(&ps->dm->faceData, CD_MTFACE);
int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
if (layer_num != -1)
ps->dm_mtface_stencil = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
- if (ps->dm_mtface_stencil == NULL || ps->dm_mtface_stencil == ps->dm_mtface) {
- ps->do_layer_stencil = false;
- ps->dm_mtface_stencil = NULL;
+ if (ps->dm_mtface_stencil == NULL) {
+ /* get active instead */
+ ps->dm_mtface_stencil = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
}
+
+ if (ps->do_stencil_brush)
+ tf_base = ps->dm_mtface_stencil;
+ }
+
+ if (ps->do_layer_clone) {
+ int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
+
+ if (layer_num != -1)
+ tf_clone_base = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
+
+ if (tf_clone_base == NULL) {
+ /* get active instead */
+ tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ }
+
}
/* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
@@ -3092,6 +3246,13 @@ static void project_paint_begin(ProjPaintState *ps)
if (reset_threads)
ps->thread_tot = 1;
+ if (ps->thread_tot > 1) {
+ ps->tile_lock = MEM_mallocN(sizeof(SpinLock), "projpaint_tile_lock");
+ BLI_spin_init(ps->tile_lock);
+ }
+
+ image_undo_init_locks();
+
for (a = 0; a < ps->thread_tot; a++) {
ps->arena_mt[a] = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "project paint arena");
}
@@ -3153,7 +3314,60 @@ static void project_paint_begin(ProjPaintState *ps)
is_face_sel = true;
}
- if (is_face_sel && (tpage = project_paint_face_image(ps, ps->dm_mtface, face_index))) {
+ if (!ps->do_stencil_brush) {
+ slot = project_paint_face_paint_slot(ps, face_index);
+ /* all faces should have a valid slot, reassert here */
+ if (slot == NULL) {
+ tf_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ tpage = ps->canvas_ima;
+ }
+ else {
+ if (slot != slot_last) {
+ if (!slot->uvname || !(tf_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot->uvname)))
+ tf_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ slot_last = slot;
+ }
+
+ /* don't allow using the same inage for painting and stencilling */
+ if (slot->ima == ps->stencil_ima)
+ continue;
+
+ tpage = slot->ima;
+ }
+ }
+ else {
+ tpage = ps->stencil_ima;
+ }
+
+ *tf = tf_base + face_index;
+
+ if (ps->do_layer_clone) {
+ if (ps->do_material_slots) {
+ slot_clone = project_paint_face_clone_slot(ps, face_index);
+ /* all faces should have a valid slot, reassert here */
+ if (ELEM(slot_clone, NULL, slot))
+ continue;
+ }
+ else if (ps->clone_ima == ps->canvas_ima)
+ continue;
+
+ tf_clone = ps->dm_mtface_clone + face_index;
+
+ if (ps->do_material_slots) {
+ if (slot_clone != slot_last_clone) {
+ if (!slot->uvname || !(tf_clone_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot_clone->uvname)))
+ tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ slot_last_clone = slot_clone;
+ }
+ }
+
+ *tf_clone = tf_clone_base + face_index;
+ }
+
+ /* tfbase here should be non-null! */
+ BLI_assert (tf_base != NULL);
+
+ if (is_face_sel && tpage) {
const float *v1coSS, *v2coSS, *v3coSS, *v4coSS = NULL;
v1coSS = ps->screenCoords[mf->v1];
@@ -3251,10 +3465,19 @@ static void project_paint_begin(ProjPaintState *ps)
projIma = ps->projImages = (ProjPaintImage *)BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) {
+ int size;
projIma->ima = node->link;
projIma->touch = 0;
projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
- projIma->partRedrawRect = BLI_memarena_calloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ size = sizeof(void **) * IMAPAINT_TILE_NUMBER(projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(projIma->ibuf->y);
+ projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ projIma->undoRect = (volatile void **) BLI_memarena_alloc(arena, size);
+ memset(projIma->undoRect, 0, size);
+ projIma->maskRect = (unsigned short **) BLI_memarena_alloc(arena, size);
+ memset(projIma->maskRect, 0, size);
+ projIma->valid = (bool **) BLI_memarena_alloc(arena, size);
+ memset(projIma->valid, 0, size);
}
/* we have built the array, discard the linked list */
@@ -3281,95 +3504,12 @@ static void project_paint_end(ProjPaintState *ps)
int a;
ProjPaintImage *projIma;
- /* build undo data from original pixel colors */
- if (U.uiflag & USER_GLOBALUNDO) {
- ProjPixel *projPixel;
- ImBuf *tmpibuf = NULL, *tmpibuf_float = NULL;
- LinkNode *pixel_node;
- void *tilerect;
- MemArena *arena = ps->arena_mt[0]; /* threaded arena re-used for non threaded case */
-
- int bucket_tot = (ps->buckets_x * ps->buckets_y); /* we could get an X/Y but easier to loop through all possible buckets */
- int bucket_index;
- int tile_index;
- int x_round, y_round;
- int x_tile, y_tile;
- int is_float = -1;
-
- /* context */
- ProjPaintImage *last_projIma;
- int last_image_index = -1;
- int last_tile_width = 0;
-
- for (a = 0, last_projIma = ps->projImages; a < ps->image_tot; a++, last_projIma++) {
- int size = sizeof(void **) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->y);
- last_projIma->undoRect = (void **) BLI_memarena_calloc(arena, size);
- last_projIma->ibuf->userflags |= IB_BITMAPDIRTY;
- }
-
- for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) {
- /* loop through all pixels */
- for (pixel_node = ps->bucketRect[bucket_index]; pixel_node; pixel_node = pixel_node->next) {
-
- /* ok we have a pixel, was it modified? */
- projPixel = (ProjPixel *)pixel_node->link;
-
- if (last_image_index != projPixel->image_index) {
- /* set the context */
- last_image_index = projPixel->image_index;
- last_projIma = ps->projImages + last_image_index;
- last_tile_width = IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x);
- is_float = last_projIma->ibuf->rect_float ? 1 : 0;
- }
-
-
- if ((is_float == 0 && projPixel->origColor.uint != *projPixel->pixel.uint_pt) ||
- (is_float == 1 &&
- (projPixel->origColor.f[0] != projPixel->pixel.f_pt[0] ||
- projPixel->origColor.f[1] != projPixel->pixel.f_pt[1] ||
- projPixel->origColor.f[2] != projPixel->pixel.f_pt[2] ||
- projPixel->origColor.f[3] != projPixel->pixel.f_pt[3]))
- )
- {
-
- x_tile = projPixel->x_px >> IMAPAINT_TILE_BITS;
- y_tile = projPixel->y_px >> IMAPAINT_TILE_BITS;
-
- x_round = x_tile * IMAPAINT_TILE_SIZE;
- y_round = y_tile * IMAPAINT_TILE_SIZE;
-
- tile_index = x_tile + y_tile * last_tile_width;
-
- if (last_projIma->undoRect[tile_index] == NULL) {
- /* add the undo tile from the modified image, then write the original colors back into it */
- tilerect = last_projIma->undoRect[tile_index] = image_undo_push_tile(last_projIma->ima, last_projIma->ibuf, is_float ? (&tmpibuf_float) : (&tmpibuf), x_tile, y_tile);
- }
- else {
- tilerect = last_projIma->undoRect[tile_index];
- }
-
- /* This is a BIT ODD, but overwrite the undo tiles image info with this pixels original color
- * because allocating the tiles along the way slows down painting */
-
- if (is_float) {
- float *rgba_fp = (float *)tilerect + (((projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE)) * 4;
- copy_v4_v4(rgba_fp, projPixel->origColor.f);
- }
- else {
- ((unsigned int *)tilerect)[(projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE] = projPixel->origColor.uint;
- }
- }
- }
- }
-
- if (tmpibuf) IMB_freeImBuf(tmpibuf);
- if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float);
- }
- /* done calculating undo data */
+ image_undo_remove_masks();
/* dereference used image buffers */
for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL);
+ DAG_id_tag_update(&projIma->ima->id, 0);
}
BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL);
@@ -3378,6 +3518,14 @@ static void project_paint_end(ProjPaintState *ps)
MEM_freeN(ps->bucketRect);
MEM_freeN(ps->bucketFaces);
MEM_freeN(ps->bucketFlags);
+ MEM_freeN(ps->dm_mtface);
+ if (ps->do_layer_clone)
+ MEM_freeN(ps->dm_mtface_clone);
+ if (ps->thread_tot > 1) {
+ BLI_spin_end(ps->tile_lock);
+ MEM_freeN((void *)ps->tile_lock);
+ }
+ image_undo_end_locks();
#ifndef PROJ_DEBUG_NOSEAMBLEED
if (ps->seam_bleed_px > 0.0f) {
@@ -3388,6 +3536,11 @@ static void project_paint_end(ProjPaintState *ps)
}
#endif
+ if (ps->blurkernel) {
+ paint_delete_blur_kernel(ps->blurkernel);
+ MEM_freeN(ps->blurkernel);
+ }
+
if (ps->vertFlags) MEM_freeN(ps->vertFlags);
for (a = 0; a < ps->thread_tot; a++) {
@@ -3480,7 +3633,7 @@ static bool project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
{
if (ps->source == PROJ_SRC_VIEW) {
float min_brush[2], max_brush[2];
- const float radius = (float)BKE_brush_size_get(ps->scene, ps->brush);
+ const float radius = ps->brush_size;
/* so we don't have a bucket bounds that is way too small to paint into */
// if (radius < 1.0f) radius = 1.0f; // this doesn't work yet :/
@@ -3518,7 +3671,7 @@ static bool project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
static bool project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2])
{
- const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
+ const int diameter = 2 * ps->brush_size;
if (ps->thread_tot > 1)
BLI_lock_thread(LOCK_CUSTOM1);
@@ -3580,7 +3733,7 @@ static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, floa
clone_rgba[3] = (unsigned char)(clone_pt[3] * mask);
if (ps->do_masking) {
- IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch, clone_rgba, ps->blend);
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, clone_rgba, ps->blend);
}
else {
IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, clone_rgba, ps->blend);
@@ -3598,7 +3751,7 @@ static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, fl
mul_v4_v4fl(clone_rgba, clone_pt, mask);
if (ps->do_masking) {
- IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f, clone_rgba, ps->blend);
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, clone_rgba, ps->blend);
}
else {
IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, clone_rgba, ps->blend);
@@ -3636,42 +3789,58 @@ static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, fl
BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena);
}
-/* do_projectpaint_soften for float & byte
- */
-static float inv_pow2(float f)
-{
- f = 1.0f - f;
- f = f * f;
- return 1.0f - f;
-}
-
static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, float mask,
MemArena *softenArena, LinkNode **softenPixels)
{
- unsigned int accum_tot = 0;
- unsigned int i;
-
+ float accum_tot = 0.0f;
+ int xk, yk;
+ BlurKernel *kernel = ps->blurkernel;
float *rgba = projPixel->newColor.f;
- /* sigh, mask values tend to need to be a _lot_ stronger with blur */
- mask = inv_pow2(mask);
-
/* rather then painting, accumulate surrounding colors */
zero_v4(rgba);
- for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) {
- float co_ofs[2];
- float rgba_tmp[4];
- sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]);
- if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
- add_v4_v4(rgba, rgba_tmp);
- accum_tot++;
+ for (yk = 0; yk < kernel->side; yk++) {
+ for (xk = 0; xk < kernel->side; xk++) {
+ float rgba_tmp[4];
+ float co_ofs[2] = {2.0f * xk - 1.0f, 2.0f * yk - 1.0f};
+
+ add_v2_v2(co_ofs, projPixel->projCoSS);
+
+ if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
+ float weight = kernel->wdata[xk + yk * kernel->side];
+ mul_v4_fl(rgba_tmp, weight);
+ add_v4_v4(rgba, rgba_tmp);
+ accum_tot += weight;
+ }
}
}
if (LIKELY(accum_tot != 0)) {
mul_v4_fl(rgba, 1.0f / (float)accum_tot);
- blend_color_interpolate_float(rgba, rgba, projPixel->pixel.f_pt, mask);
+
+ if (ps->mode == BRUSH_STROKE_INVERT) {
+ /* subtract blurred image from normal image gives high pass filter */
+ sub_v3_v3v3(rgba, projPixel->pixel.f_pt, rgba);
+
+ /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
+ * colored speckles appearing in final image, and also to check for threshold */
+ rgba[0] = rgba[1] = rgba[2] = rgb_to_grayscale(rgba);
+ if (fabsf(rgba[0]) > ps->brush->sharp_threshold) {
+ float alpha = projPixel->pixel.f_pt[3];
+ projPixel->pixel.f_pt[3] = rgba[3] = mask;
+
+ /* add to enhance edges */
+ blend_color_add_float(rgba, projPixel->pixel.f_pt, rgba);
+ rgba[3] = alpha;
+ }
+ else
+ return;
+ }
+ else {
+ blend_color_interpolate_float(rgba, rgba, projPixel->pixel.f_pt, mask);
+ }
+
BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
}
}
@@ -3679,24 +3848,27 @@ static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, f
static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, float mask,
MemArena *softenArena, LinkNode **softenPixels)
{
- unsigned int accum_tot = 0;
- unsigned int i;
-
+ float accum_tot = 0;
+ int xk, yk;
+ BlurKernel *kernel = ps->blurkernel;
float rgba[4]; /* convert to byte after */
- /* sigh, mask values tend to need to be a _lot_ stronger with blur */
- mask = inv_pow2(mask);
-
/* rather then painting, accumulate surrounding colors */
zero_v4(rgba);
- for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) {
- float co_ofs[2];
- float rgba_tmp[4];
- sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]);
- if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
- add_v4_v4(rgba, rgba_tmp);
- accum_tot++;
+ for (yk = 0; yk < kernel->side; yk++) {
+ for (xk = 0; xk < kernel->side; xk++) {
+ float rgba_tmp[4];
+ float co_ofs[2] = {2.0f * xk - 1.0f, 2.0f * yk - 1.0f};
+
+ add_v2_v2(co_ofs, projPixel->projCoSS);
+
+ if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
+ float weight = kernel->wdata[xk + yk * kernel->side];
+ mul_v4_fl(rgba_tmp, weight);
+ add_v4_v4(rgba, rgba_tmp);
+ accum_tot += weight;
+ }
}
}
@@ -3704,9 +3876,34 @@ static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, flo
unsigned char *rgba_ub = projPixel->newColor.ch;
mul_v4_fl(rgba, 1.0f / (float)accum_tot);
- premul_float_to_straight_uchar(rgba_ub, rgba);
- blend_color_interpolate_byte(rgba_ub, rgba_ub, projPixel->pixel.ch_pt, mask);
+ if (ps->mode == BRUSH_STROKE_INVERT) {
+ float rgba_pixel[4];
+
+ straight_uchar_to_premul_float(rgba_pixel, projPixel->pixel.ch_pt);
+
+ /* subtract blurred image from normal image gives high pass filter */
+ sub_v3_v3v3(rgba, rgba_pixel, rgba);
+ /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
+ * colored speckles appearing in final image, and also to check for threshold */
+ rgba[0] = rgba[1] = rgba[2] = rgb_to_grayscale(rgba);
+ if (fabsf(rgba[0]) > ps->brush->sharp_threshold) {
+ float alpha = rgba_pixel[3];
+ rgba[3] = rgba_pixel[3] = mask;
+
+ /* add to enhance edges */
+ blend_color_add_float(rgba, rgba_pixel, rgba);
+
+ rgba[3] = alpha;
+ premul_float_to_straight_uchar(rgba_ub, rgba);
+ }
+ else
+ return;
+ }
+ else {
+ premul_float_to_straight_uchar(rgba_ub, rgba);
+ blend_color_interpolate_byte(rgba_ub, rgba_ub, projPixel->pixel.ch_pt, mask);
+ }
BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
}
}
@@ -3716,7 +3913,7 @@ static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const
float rgb[3];
unsigned char rgba_ub[4];
- copy_v3_v3(rgb, ps->brush->rgb);
+ copy_v3_v3(rgb, ps->paint_color);
if (ps->is_texbrush) {
mul_v3_v3(rgb, texrgb);
@@ -3728,7 +3925,7 @@ static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const
rgba_ub[3] = f_to_char(mask);
if (ps->do_masking) {
- IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch, rgba_ub, ps->blend);
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, rgba_ub, ps->blend);
}
else {
IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, rgba_ub, ps->blend);
@@ -3739,7 +3936,7 @@ static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, con
{
float rgba[4];
- srgb_to_linearrgb_v3_v3(rgba, ps->brush->rgb);
+ copy_v3_v3(rgba, ps->paint_color_linear);
if (ps->is_texbrush)
mul_v3_v3(rgba, texrgb);
@@ -3748,13 +3945,42 @@ static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, con
rgba[3] = mask;
if (ps->do_masking) {
- IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f, rgba, ps->blend);
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, rgba, ps->blend);
}
else {
IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, ps->blend);
}
}
+static void do_projectpaint_mask(ProjPaintState *ps, ProjPixel *projPixel, float mask)
+{
+ unsigned char rgba_ub[4];
+ rgba_ub[0] = rgba_ub[1] = rgba_ub[2] = ps->stencil_value * 255.0f;
+ rgba_ub[3] = f_to_char(mask);
+
+ if (ps->do_masking) {
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, rgba_ub, ps->blend);
+ }
+ else {
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, rgba_ub, ps->blend);
+ }
+}
+
+static void do_projectpaint_mask_f(ProjPaintState *ps, ProjPixel *projPixel, float mask)
+{
+ float rgba[4];
+ rgba[0] = rgba[1] = rgba[2] = ps->stencil_value;
+ rgba[3] = mask;
+
+ if (ps->do_masking) {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, rgba, ps->blend);
+ }
+ else {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, ps->blend);
+ }
+}
+
+
/* run this for single and multithreaded painting */
static void *do_projectpaint_thread(void *ph_v)
{
@@ -3788,7 +4014,7 @@ static void *do_projectpaint_thread(void *ph_v)
float co[2];
unsigned short mask_short;
const float brush_alpha = BKE_brush_alpha_get(ps->scene, brush);
- const float brush_radius = (float)BKE_brush_size_get(ps->scene, brush);
+ const float brush_radius = ps->brush_size;
const float brush_radius_sq = brush_radius * brush_radius; /* avoid a square root with every dist comparison */
short lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : brush->flag & BRUSH_LOCK_ALPHA;
@@ -3838,32 +4064,107 @@ static void *do_projectpaint_thread(void *ph_v)
}
/* end copy */
- if (is_floatbuf) {
- /* re-project buffer is assumed byte - TODO, allow float */
- bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL,
- projPixel->projCoSS[0], projPixel->projCoSS[1]);
- if (projPixel->newColor.ch[3]) {
- float newColor_f[4];
- float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
+ /* fill tools */
+ if (ps->source == PROJ_SRC_VIEW_FILL) {
+ if (brush->flag & BRUSH_USE_GRADIENT) {
+ /* these could probably be cached instead of being done per pixel */
+ float tangent[2];
+ float line_len_sq_inv, line_len;
+ float f;
+ float color_f[4];
+ float p[2] = {projPixel->projCoSS[0] - lastpos[0], projPixel->projCoSS[1] - lastpos[1]};
+
+ sub_v2_v2v2(tangent, pos, lastpos);
+ line_len = len_squared_v2(tangent);
+ line_len_sq_inv = 1.0f / line_len;
+ line_len = sqrt(line_len);
+
+ switch (brush->gradient_fill_mode) {
+ case BRUSH_GRADIENT_LINEAR:
+ {
+ f = dot_v2v2(p, tangent) * line_len_sq_inv;
+ break;
+ }
+ case BRUSH_GRADIENT_RADIAL:
+ {
+ f = len_v2(p) / line_len;
+ break;
+ }
+ }
+ do_colorband(brush->gradient, f, color_f);
+ color_f[3] *= ((float)projPixel->mask) * (1.0f / 65535.0f) * brush->alpha;
+
+ if (is_floatbuf) {
+ /* convert to premultipied */
+ mul_v3_fl(color_f, color_f[3]);
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt,
+ color_f, ps->blend);
+ }
+ else {
+ rgba_float_to_uchar(projPixel->newColor.ch, color_f);
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt,
+ projPixel->newColor.ch, ps->blend);
+ }
+ }
+ else {
+ if (is_floatbuf) {
+ float newColor_f[4];
+ newColor_f[3] = ((float)projPixel->mask) * (1.0f / 65535.0f) * brush->alpha;
+ copy_v3_v3(newColor_f, ps->paint_color_linear);
- straight_uchar_to_premul_float(newColor_f, projPixel->newColor.ch);
- IMB_colormanagement_colorspace_to_scene_linear_v4(newColor_f, true, ps->reproject_ibuf->rect_colorspace);
- mul_v4_v4fl(newColor_f, newColor_f, mask);
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt,
+ newColor_f, ps->blend);
+ }
+ else {
+ float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
+ projPixel->newColor.ch[3] = mask * 255 * brush->alpha;
- blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f,
- newColor_f);
+ rgb_float_to_uchar(projPixel->newColor.ch, ps->paint_color);
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt,
+ projPixel->newColor.ch, ps->blend);
+ }
}
+
+ if (lock_alpha) {
+ if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f_pt[3];
+ else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3];
+ }
+
+ last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
+ last_partial_redraw_cell->x1 = min_ii(last_partial_redraw_cell->x1, (int)projPixel->x_px);
+ last_partial_redraw_cell->y1 = min_ii(last_partial_redraw_cell->y1, (int)projPixel->y_px);
+
+ last_partial_redraw_cell->x2 = max_ii(last_partial_redraw_cell->x2, (int)projPixel->x_px + 1);
+ last_partial_redraw_cell->y2 = max_ii(last_partial_redraw_cell->y2, (int)projPixel->y_px + 1);
}
else {
- /* re-project buffer is assumed byte - TODO, allow float */
- bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL,
- projPixel->projCoSS[0], projPixel->projCoSS[1]);
- if (projPixel->newColor.ch[3]) {
- float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
- projPixel->newColor.ch[3] *= mask;
-
- blend_color_mix_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch,
- projPixel->newColor.ch);
+ if (is_floatbuf) {
+ /* re-project buffer is assumed byte - TODO, allow float */
+ bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL,
+ projPixel->projCoSS[0], projPixel->projCoSS[1]);
+ if (projPixel->newColor.ch[3]) {
+ float newColor_f[4];
+ float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
+
+ straight_uchar_to_premul_float(newColor_f, projPixel->newColor.ch);
+ IMB_colormanagement_colorspace_to_scene_linear_v4(newColor_f, true, ps->reproject_ibuf->rect_colorspace);
+ mul_v4_v4fl(newColor_f, newColor_f, mask);
+
+ blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt,
+ newColor_f);
+ }
+ }
+ else {
+ /* re-project buffer is assumed byte - TODO, allow float */
+ bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL,
+ projPixel->projCoSS[0], projPixel->projCoSS[1]);
+ if (projPixel->newColor.ch[3]) {
+ float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
+ projPixel->newColor.ch[3] *= mask;
+
+ blend_color_mix_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt,
+ projPixel->newColor.ch);
+ }
}
}
}
@@ -3885,7 +4186,7 @@ static void *do_projectpaint_thread(void *ph_v)
if (falloff > 0.0f) {
float texrgb[3];
- float mask = falloff;
+ float mask;
if (ps->do_masking) {
/* masking to keep brush contribution to a pixel limited. note we do not do
@@ -3894,20 +4195,24 @@ static void *do_projectpaint_thread(void *ph_v)
*
* Instead we use a formula that adds up but approaches brush_alpha slowly
* and never exceeds it, which gives nice smooth results. */
- float mask_accum = projPixel->mask_accum;
+ float mask_accum = *projPixel->mask_accum;
+ float max_mask = brush_alpha * falloff * 65535.0f;
if (ps->is_maskbrush) {
float texmask = BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
- CLAMP(texmask, 0.0f, 1.0f);
- mask = mask_accum + (brush_alpha * texmask * 65535.0f - mask_accum) * mask;
- }
- else {
- mask = mask_accum + (brush_alpha * 65535.0f - mask_accum) * mask;
+ max_mask *= texmask;
}
+
+ if (brush->flag & BRUSH_ACCUMULATE)
+ mask = mask_accum + max_mask;
+ else
+ mask = mask_accum + (max_mask - mask_accum * falloff);
+
+ mask = min_ff(mask, 65535.0f);
mask_short = (unsigned short)mask;
- if (mask_short > projPixel->mask_accum) {
- projPixel->mask_accum = mask_short;
+ if (mask_short > *projPixel->mask_accum) {
+ *projPixel->mask_accum = mask_short;
mask = mask_short * (1.0f / 65535.0f);
}
else {
@@ -3916,7 +4221,7 @@ static void *do_projectpaint_thread(void *ph_v)
}
}
else {
- mask *= brush_alpha;
+ mask = brush_alpha * falloff;
if (ps->is_maskbrush) {
float texmask = BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
CLAMP(texmask, 0.0f, 1.0f);
@@ -3945,10 +4250,6 @@ static void *do_projectpaint_thread(void *ph_v)
mask *= texrgba[3];
}
- if (ps->is_maskbrush_tiled) {
- mask *= BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
- }
-
/* extra mask for normal, layer stencil, .. */
mask *= ((float)projPixel->mask) * (1.0f / 65535.0f);
@@ -3964,6 +4265,9 @@ static void *do_projectpaint_thread(void *ph_v)
}
/* end copy */
+ /* validate undo tile, since we will modify t*/
+ *projPixel->valid = true;
+
last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
last_partial_redraw_cell->x1 = min_ii(last_partial_redraw_cell->x1, (int)projPixel->x_px);
last_partial_redraw_cell->y1 = min_ii(last_partial_redraw_cell->y1, (int)projPixel->y_px);
@@ -3987,6 +4291,10 @@ static void *do_projectpaint_thread(void *ph_v)
if (is_floatbuf) do_projectpaint_soften_f(ps, projPixel, mask, softenArena, &softenPixels_f);
else do_projectpaint_soften(ps, projPixel, mask, softenArena, &softenPixels);
break;
+ case PAINT_TOOL_MASK:
+ if (is_floatbuf) do_projectpaint_mask_f(ps, projPixel, mask);
+ else do_projectpaint_mask(ps, projPixel, mask);
+ break;
default:
if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, texrgb, mask);
else do_projectpaint_draw(ps, projPixel, texrgb, mask);
@@ -3995,8 +4303,8 @@ static void *do_projectpaint_thread(void *ph_v)
}
if (lock_alpha) {
- if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f[3];
- else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch[3];
+ if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f_pt[3];
+ else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3];
}
/* done painting */
@@ -4114,14 +4422,20 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
}
-void paint_proj_stroke(bContext *C, void *pps, const float prev_pos[2], const float pos[2])
+void paint_proj_stroke(const bContext *C, void *pps, const float prev_pos[2], const float pos[2], const bool eraser, float pressure, float distance, float size)
{
ProjPaintState *ps = pps;
+ Brush *brush = ps->brush;
+ Scene *scene = ps->scene;
int a;
+ ps->brush_size = size;
+ ps->blend = brush->blend;
+ if (eraser)
+ ps->blend = IMB_BLEND_ERASE_ALPHA;
+
/* clone gets special treatment here to avoid going through image initialization */
if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) {
- Scene *scene = ps->scene;
View3D *v3d = ps->v3d;
float *cursor = ED_view3d_cursor3d_get(scene, v3d);
int mval_i[2] = {(int)pos[0], (int)pos[1]};
@@ -4136,6 +4450,25 @@ void paint_proj_stroke(bContext *C, void *pps, const float prev_pos[2], const fl
return;
}
+ /* handle gradient and inverted stroke color here */
+ if (ps->tool == PAINT_TOOL_DRAW) {
+ paint_brush_color_get(scene, brush, false, ps->mode == BRUSH_STROKE_INVERT, distance, pressure, ps->paint_color, NULL);
+ srgb_to_linearrgb_v3_v3(ps->paint_color_linear, ps->paint_color);
+ }
+ else if (ps->tool == PAINT_TOOL_FILL) {
+ copy_v3_v3(ps->paint_color, BKE_brush_color_get(scene, brush));
+ srgb_to_linearrgb_v3_v3(ps->paint_color_linear, ps->paint_color);
+ }
+ else if (ps->tool == PAINT_TOOL_MASK) {
+ ps->stencil_value = brush->weight;
+
+ if ((ps->mode == BRUSH_STROKE_INVERT) ^
+ ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0))
+ {
+ ps->stencil_value = 1.0f - ps->stencil_value;
+ }
+ }
+
/* continue adding to existing partial redraw rects until redraw */
if (!ps->need_redraw) {
for (a = 0; a < ps->image_tot; a++)
@@ -4160,30 +4493,24 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
Brush *brush = ps->brush;
ps->tool = brush->imagepaint_tool;
ps->blend = brush->blend;
+ /* only check for inversion for the soften tool, elsewhere, a resident brush inversion flag can cause issues */
+ if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) {
+ ps->mode = ((ps->mode == BRUSH_STROKE_INVERT) ^ ((brush->flag & BRUSH_DIR_IN) != 0) ?
+ BRUSH_STROKE_INVERT : BRUSH_STROKE_NORMAL);
+
+ ps->blurkernel = paint_new_blur_kernel(brush, true);
+ }
/* disable for 3d mapping also because painting on mirrored mesh can create "stripes" */
- ps->do_masking = (brush->flag & BRUSH_AIRBRUSH ||
- (brush->imagepaint_tool == PAINT_TOOL_SMEAR) ||
- (brush->mtex.tex && !ELEM3(brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_3D)))
- ? false : true;
+ ps->do_masking = paint_use_opacity_masking(brush);
ps->is_texbrush = (brush->mtex.tex && brush->imagepaint_tool == PAINT_TOOL_DRAW) ? true : false;
- ps->is_maskbrush = false;
- ps->is_maskbrush_tiled = false;
- if (brush->mask_mtex.tex) {
- if (ELEM(brush->mask_mtex.brush_map_mode, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_TILED)) {
- ps->is_maskbrush_tiled = true;
- }
- else {
- ps->is_maskbrush = true;
- }
- }
+ ps->is_maskbrush = (brush->mask_mtex.tex) ? true : false;
}
else {
/* brush may be NULL*/
ps->do_masking = false;
ps->is_texbrush = false;
ps->is_maskbrush = false;
- ps->is_maskbrush_tiled = false;
}
/* sizeof(ProjPixel), since we alloc this a _lot_ */
@@ -4198,6 +4525,13 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
ps->scene = scene;
ps->ob = ob; /* allow override of active object */
+ ps->do_material_slots = (settings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
+ ps->stencil_ima = settings->imapaint.stencil;
+ ps->canvas_ima = (!ps->do_material_slots) ?
+ settings->imapaint.canvas : NULL;
+ ps->clone_ima = (!ps->do_material_slots) ?
+ settings->imapaint.clone : NULL;
+
/* setup projection painting data */
ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1;
ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1;
@@ -4207,8 +4541,11 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
if (ps->tool == PAINT_TOOL_CLONE)
ps->do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) ? 1 : 0;
- ps->do_layer_stencil = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? 1 : 0;
- ps->do_layer_stencil_inv = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) ? 1 : 0;
+ ps->do_stencil_brush = ps->brush->imagepaint_tool == PAINT_TOOL_MASK;
+ /* deactivate stenciling for the stencil brush :) */
+ ps->do_layer_stencil = ((settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) &&
+ !(ps->do_stencil_brush) && ps->stencil_ima);
+ ps->do_layer_stencil_inv = ((settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0);
#ifndef PROJ_DEBUG_NOSEAMBLEED
@@ -4236,6 +4573,7 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int mode)
{
ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState");
+
project_state_init(C, ob, ps, mode);
if (ps->tool == PAINT_TOOL_CLONE && mode == BRUSH_STROKE_INVERT) {
@@ -4268,6 +4606,10 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
paint_proj_begin_clone(ps, mouse);
+ /* special full screen draw mode for fill tool */
+ if (ps->tool == PAINT_TOOL_FILL)
+ ps->source = PROJ_SRC_VIEW_FILL;
+
return ps;
}
@@ -4316,8 +4658,11 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
int orig_brush_size;
IDProperty *idgroup;
IDProperty *view_data = NULL;
+ Object *ob = OBACT;
+
+ paint_proj_mesh_data_ensure(C, ob, op);
- project_state_init(C, OBACT, &ps, BRUSH_STROKE_NORMAL);
+ project_state_init(C, ob, &ps, BRUSH_STROKE_NORMAL);
if (ps.ob == NULL || ps.ob->type != OB_MESH) {
BKE_report(op->reports, RPT_ERROR, "No active mesh object");
@@ -4365,7 +4710,6 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
/* override */
ps.is_texbrush = false;
ps.is_maskbrush = false;
- ps.is_maskbrush_tiled = false;
ps.do_masking = false;
orig_brush_size = BKE_brush_size_get(scene, ps.brush);
BKE_brush_size_set(scene, ps.brush, 32); /* cover the whole image */
@@ -4375,7 +4719,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free);
+ ED_image_undo_restore, ED_image_undo_free, NULL);
/* allocate and initialize spatial data structures */
project_paint_begin(&ps);
@@ -4508,3 +4852,338 @@ void PAINT_OT_image_from_view(wmOperatorType *ot)
RNA_def_string_file_name(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Name of the file");
}
+
+/*********************************************
+ * Data generation for projective texturing *
+ * *******************************************/
+
+
+/* Make sure that active object has a material, and assign UVs and image layers if they do not exist */
+void paint_proj_mesh_data_ensure(bContext *C, Object *ob, wmOperator *op)
+{
+ Mesh *me;
+ int layernum;
+ ImagePaintSettings *imapaint = &(CTX_data_tool_settings(C)->imapaint);
+ bScreen *sc;
+ Scene *scene = CTX_data_scene(C);
+ Main *bmain = CTX_data_main(C);
+ Brush *br = BKE_paint_brush(&imapaint->paint);
+
+ /* no material, add one */
+ if (ob->totcol == 0) {
+ Material *ma = BKE_material_add(CTX_data_main(C), "Material");
+ /* no material found, just assign to first slot */
+ assign_material(ob, ma, 1, BKE_MAT_ASSIGN_USERPREF);
+ proj_paint_add_slot(C, ma, NULL);
+ }
+ else {
+ /* there may be material slots but they may be empty, check */
+ int i;
+
+ for (i = 1; i < ob->totcol + 1; i++) {
+ Material *ma = give_current_material(ob, i);
+
+ if (ma) {
+ if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+ if (!ma->texpaintslot) {
+ /* refresh here just in case */
+ BKE_texpaint_slot_refresh_cache(scene, ma);
+
+ /* if still no slots, we have to add */
+ if (!ma->texpaintslot) {
+ proj_paint_add_slot(C, ma, NULL);
+
+ if (ma->texpaintslot) {
+ for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[0].ima);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ Material *ma = BKE_material_add(CTX_data_main(C), "Material");
+ /* no material found, just assign to first slot */
+ assign_material(ob, ma, i, BKE_MAT_ASSIGN_USERPREF);
+ proj_paint_add_slot(C, ma, NULL);
+ }
+ }
+ }
+
+ if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
+ if (imapaint->canvas == NULL) {
+ int width;
+ int height;
+ Main *bmain = CTX_data_main(C);
+ float color[4] = {0.0, 0.0, 0.0, 1.0};
+
+ width = 1024;
+ height = 1024;
+ imapaint->canvas = BKE_image_add_generated(bmain, width, height, "Canvas", 32, false, IMA_GENTYPE_BLANK, color);
+
+ GPU_drawobject_free(ob->derivedFinal);
+
+ for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ ED_space_image_set(sima, scene, scene->obedit, imapaint->canvas);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ me = BKE_mesh_from_object(ob);
+ layernum = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
+
+ if (layernum == 0) {
+ BKE_reportf(op->reports, RPT_WARNING, "Object did not have UV map, manual unwrap recommended");
+
+ ED_mesh_uv_texture_add(me, "UVMap", true);
+ }
+
+ /* Make sure we have a stencil to paint on! */
+ if (br && br->imagepaint_tool == PAINT_TOOL_MASK) {
+ imapaint->flag |= IMAGEPAINT_PROJECT_LAYER_STENCIL;
+
+ if (imapaint->stencil == NULL) {
+ int width;
+ int height;
+ Main *bmain = CTX_data_main(C);
+ float color[4] = {0.0, 0.0, 0.0, 1.0};
+
+ width = 1024;
+ height = 1024;
+ imapaint->stencil = BKE_image_add_generated(bmain, width, height, "Stencil", 32, false, IMA_GENTYPE_BLANK, color);
+ }
+ }
+}
+
+/* Add layer operator */
+
+static EnumPropertyItem layer_type_items[] = {
+ {MAP_COL, "DIFFUSE_COLOR", 0, "Diffuse Color", ""},
+ {MAP_REF, "DIFFUSE_INTENSITY", 0, "Diffuse Intensity", ""},
+ {MAP_ALPHA, "ALPHA", 0, "Alpha", ""},
+ {MAP_TRANSLU, "TRANSLUCENCY", 0, "Translucency", ""},
+ {MAP_COLSPEC, "SPECULAR_COLOR", 0, "Specular Color", ""},
+ {MAP_SPEC, "SPECULAR_INTENSITY", 0, "Specular Intensity", ""},
+ {MAP_HAR, "SPECULAR_HARDNESS", 0, "Specular Hardness", ""},
+ {MAP_AMB, "AMBIENT", 0, "Ambient", ""},
+ {MAP_EMIT, "EMMIT", 0, "Emmit", ""},
+ {MAP_COLMIR, "MIRROR_COLOR", 0, "Mirror Color", ""},
+ {MAP_RAYMIRR, "RAYMIRROR", 0, "Ray Mirror", ""},
+ {MAP_NORM, "NORMAL", 0, "Normal", ""},
+ {MAP_WARP, "WARP", 0, "Warp", ""},
+ {MAP_DISPLACE, "DISPLACE", 0, "Displace", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+bool proj_paint_add_slot(bContext *C, Material *ma, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ bool is_bi = BKE_scene_uses_blender_internal(scene);
+
+ if (!ob)
+ return false;
+
+ if (!ma)
+ ma = give_current_material(ob, ob->actcol);
+
+ if (ma) {
+
+ if (!is_bi || ma->use_nodes) {
+ /* not supported for now */
+ }
+ else {
+ MTex *mtex = add_mtex_id(&ma->id, -1);
+
+ /* successful creation of mtex layer, now create set */
+ if (mtex) {
+ Main *bmain = CTX_data_main(C);
+ Image *ima;
+ int type = MAP_COL;
+ int type_id = 0;
+
+ if (op) {
+ int i;
+ type = RNA_enum_get(op->ptr, "type");
+
+ for (i = 0; i < ARRAY_SIZE(layer_type_items); i++) {
+ if (layer_type_items[i].value == type) {
+ type_id = i;
+ break;
+ }
+ }
+ }
+
+ mtex->tex = add_texture(bmain, DATA_(layer_type_items[type_id].name));
+ mtex->mapto = type;
+
+ if (mtex->tex) {
+ float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color";
+ int width = 1024;
+ int height = 1024;
+ bool use_float = false;
+ short gen_type = IMA_GENTYPE_BLANK;
+ bool alpha = false;
+
+ if (op) {
+ width = RNA_int_get(op->ptr, "width");
+ height = RNA_int_get(op->ptr, "height");
+ use_float = RNA_boolean_get(op->ptr, "float");
+ gen_type = RNA_enum_get(op->ptr, "generated_type");
+ RNA_float_get_array(op->ptr, "color", color);
+ alpha = RNA_boolean_get(op->ptr, "alpha");
+ RNA_string_get(op->ptr, "name", imagename);
+ }
+
+ ima = mtex->tex->ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float,
+ gen_type, color);
+
+ BKE_texpaint_slot_refresh_cache(scene, ma);
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
+ WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, mtex->tex);
+ WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
+ DAG_id_tag_update(&ma->id, 0);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static int texture_paint_add_texture_paint_slot_exec(bContext *C, wmOperator *op)
+{
+ return proj_paint_add_slot(C, NULL, op);
+}
+
+
+static int texture_paint_add_texture_paint_slot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ char imagename[MAX_ID_NAME - 2];
+ Object *ob = CTX_data_active_object(C);
+ Material *ma = give_current_material(ob, ob->actcol);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ type = RNA_enum_from_value(layer_type_items, type);
+
+ /* get the name of the texture layer type */
+ BLI_assert(type != -1);
+
+ /* take the second letter to avoid the ID identifier */
+ BLI_snprintf(imagename, FILE_MAX, "%s %s", &ma->id.name[2], layer_type_items[type].name);
+
+ RNA_string_set(op->ptr, "name", imagename);
+ return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y);
+}
+
+#define IMA_DEF_NAME N_("Untitled")
+
+
+void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+ static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+
+ /* identifiers */
+ ot->name = "Add Texture Paint Slot";
+ ot->description = "Add a texture paint slot";
+ ot->idname = "PAINT_OT_add_texture_paint_slot";
+
+ /* api callbacks */
+ ot->invoke = texture_paint_add_texture_paint_slot_invoke;
+ ot->exec = texture_paint_add_texture_paint_slot_exec;
+ ot->poll = ED_operator_region_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "type", layer_type_items, 0, "Type", "Merge method to use");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "name", IMA_DEF_NAME, MAX_ID_NAME - 2, "Name", "Image datablock name");
+ prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+ prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+ prop = RNA_def_float_color(ot->srna, "color", 4, NULL, 0.0f, FLT_MAX, "Color", "Default fill color", 0.0f, 1.0f);
+ RNA_def_property_subtype(prop, PROP_COLOR_GAMMA);
+ RNA_def_property_float_array_default(prop, default_color);
+ RNA_def_boolean(ot->srna, "alpha", 1, "Alpha", "Create an image with an alpha channel");
+ RNA_def_enum(ot->srna, "generated_type", image_generated_type_items, IMA_GENTYPE_BLANK,
+ "Generated Type", "Fill the image with a grid for UV map testing");
+ RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
+}
+
+static int texture_paint_delete_texture_paint_slot_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Material *ma;
+ bool is_bi = BKE_scene_uses_blender_internal(scene);
+ TexPaintSlot *slot;
+
+ /* not supported for node-based engines */
+ if (!ob || !is_bi)
+ return OPERATOR_CANCELLED;
+
+ ma = give_current_material(ob, ob->actcol);
+
+ if (!ma->texpaintslot || ma->use_nodes)
+ return OPERATOR_CANCELLED;
+
+ slot = ma->texpaintslot + ma->paint_active_slot;
+
+ if (ma->mtex[slot->index]->tex)
+ id_us_min(&ma->mtex[slot->index]->tex->id);
+ MEM_freeN(ma->mtex[slot->index]);
+ ma->mtex[slot->index] = NULL;
+
+ BKE_texpaint_slot_refresh_cache(scene, ma);
+ DAG_id_tag_update(&ma->id, 0);
+ WM_event_add_notifier(C, NC_MATERIAL, CTX_data_scene(C));
+ /* we need a notifier for data change since we change the displayed modifier uvs */
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ return OPERATOR_FINISHED;
+}
+
+
+void PAINT_OT_delete_texture_paint_slot(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete Texture Paint Slot";
+ ot->description = "Add a texture paint slot";
+ ot->idname = "PAINT_OT_delete_texture_paint_slot";
+
+ /* api callbacks */
+ ot->exec = texture_paint_delete_texture_paint_slot_exec;
+ ot->poll = ED_operator_region_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index b20c1756d75..5e1ac0cf8a8 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -38,7 +38,9 @@ struct bglMats;
struct Brush;
struct ImagePool;
struct ColorSpace;
+struct ColorManagedDisplay;
struct ListBase;
+struct Material;
struct Mesh;
struct MTex;
struct Object;
@@ -65,7 +67,7 @@ typedef void (*StrokeUpdateStep)(struct bContext *C, struct PaintStroke *stroke,
typedef void (*StrokeRedraw)(const struct bContext *C, struct PaintStroke *stroke, bool final);
typedef void (*StrokeDone)(const struct bContext *C, struct PaintStroke *stroke);
-struct PaintStroke *paint_stroke_new(struct bContext *C,
+struct PaintStroke *paint_stroke_new(struct bContext *C, struct wmOperator *op,
StrokeGetLocation get_location, StrokeTestStart test_start,
StrokeUpdateStep update_step, StrokeRedraw redraw,
StrokeDone done, int event_type);
@@ -82,8 +84,10 @@ struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf);
int paint_stroke_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int paint_stroke_exec(struct bContext *C, struct wmOperator *op);
void paint_stroke_cancel(struct bContext *C, struct wmOperator *op);
+bool paint_stroke_flipped(struct PaintStroke *stroke);
struct ViewContext *paint_stroke_view_context(struct PaintStroke *stroke);
void *paint_stroke_mode_data(struct PaintStroke *stroke);
+float paint_stroke_distance_get(struct PaintStroke *stroke);
void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data);
int paint_poll(struct bContext *C);
void paint_cursor_start(struct bContext *C, int (*poll)(struct bContext *C));
@@ -117,7 +121,7 @@ void PAINT_OT_weight_gradient(struct wmOperatorType *ot);
void PAINT_OT_vertex_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
-unsigned int vpaint_get_current_col(struct VPaint *vp);
+unsigned int vpaint_get_current_col(struct Scene *scene, struct VPaint *vp);
/* paint_vertex_proj.c */
@@ -144,32 +148,43 @@ typedef struct ImagePaintPartialRedraw {
#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS)
int image_texture_paint_poll(struct bContext *C);
-void *image_undo_find_tile(struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask);
-void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile);
+void *image_undo_find_tile(struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate);
+void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **, bool **valid, bool proj);
void image_undo_remove_masks(void);
+void image_undo_init_locks(void);
+void image_undo_end_locks(void);
+
void imapaint_image_update(struct SpaceImage *sima, struct Image *image, struct ImBuf *ibuf, short texpaint);
struct ImagePaintPartialRedraw *get_imapaintpartial(void);
void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr);
void imapaint_region_tiles(struct ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th);
int get_imapaint_zoom(struct bContext *C, float *zoomx, float *zoomy);
-void *paint_2d_new_stroke(struct bContext *, struct wmOperator *);
+void *paint_2d_new_stroke(struct bContext *, struct wmOperator *, int mode);
void paint_2d_redraw(const bContext *C, void *ps, bool final);
void paint_2d_stroke_done(void *ps);
-void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], int eraser);
+void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], const bool eraser, float pressure, float distance, float size);
+void paint_2d_bucket_fill(const struct bContext *C, const float color[3], struct Brush *br, const float mouse_init[2], void *ps);
+void paint_2d_gradient_fill (const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps);
void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const float mouse[2], int mode);
-void paint_proj_stroke(struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2]);
-void paint_proj_redraw(const bContext *C, void *pps, bool final);
+void paint_proj_stroke(const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2], const bool eraser, float pressure, float distance, float size);
+void paint_proj_redraw(const struct bContext *C, void *pps, bool final);
void paint_proj_stroke_done(void *ps);
+void paint_proj_mesh_data_ensure(bContext *C, struct Object *ob, struct wmOperator *op);
+bool proj_paint_add_slot(bContext *C, struct Material *ma, struct wmOperator *op);
+
+void paint_brush_color_get(struct Scene *scene, struct Brush *br, bool color_correction, bool invert, float distance, float pressure, float color[3], struct ColorManagedDisplay *display);
+bool paint_use_opacity_masking(struct Brush *brush);
void paint_brush_init_tex(struct Brush *brush);
void paint_brush_exit_tex(struct Brush *brush);
void PAINT_OT_grab_clone(struct wmOperatorType *ot);
void PAINT_OT_sample_color(struct wmOperatorType *ot);
+void PAINT_OT_brush_colors_flip(struct wmOperatorType *ot);
void PAINT_OT_texture_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_project_image(struct wmOperatorType *ot);
void PAINT_OT_image_from_view(struct wmOperatorType *ot);
-
-/* new texture painting */
+void PAINT_OT_add_texture_paint_slot(struct wmOperatorType *ot);
+void PAINT_OT_delete_texture_paint_slot(struct wmOperatorType *ot);
void PAINT_OT_image_paint(struct wmOperatorType *ot);
/* uv sculpting */
@@ -202,7 +217,10 @@ float paint_calc_object_space_radius(struct ViewContext *vc, const float center[
float paint_get_tex_pixel(struct MTex *mtex, float u, float v, struct ImagePool *pool, int thread);
void paint_get_tex_pixel_col(struct MTex *mtex, float u, float v, float rgba[4], struct ImagePool *pool, int thread, bool convert, struct ColorSpace *colorspace);
-void paint_sample_color(const struct bContext *C, struct ARegion *ar, int x, int y);
+void paint_sample_color(bContext *C, struct ARegion *ar, int x, int y, bool texpaint_proj, bool palette);
+
+void paint_stroke_operator_properties(struct wmOperatorType *ot);
+
void BRUSH_OT_curve_preset(struct wmOperatorType *ot);
void PAINT_OT_face_select_linked(struct wmOperatorType *ot);
@@ -213,8 +231,10 @@ void PAINT_OT_face_select_reveal(struct wmOperatorType *ot);
void PAINT_OT_vert_select_all(struct wmOperatorType *ot);
void PAINT_OT_vert_select_ungrouped(struct wmOperatorType *ot);
+
int vert_paint_poll(struct bContext *C);
int mask_paint_poll(struct bContext *C);
+int paint_curve_poll(struct bContext *C);
int facemask_paint_poll(struct bContext *C);
void flip_v3_v3(float out[3], const float in[3], const char symm);
@@ -229,7 +249,6 @@ typedef enum BrushStrokeMode {
/* paint_undo.c */
struct ListBase *undo_paint_push_get_list(int type);
void undo_paint_push_count_alloc(int type, int size);
-bool sculpt_undo_cleanup(struct bContext *C, struct ListBase *lb);
/* paint_hide.c */
@@ -258,4 +277,29 @@ typedef enum {
void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot);
void PAINT_OT_mask_lasso_gesture(struct wmOperatorType *ot);
+/* paint_curve.c */
+void PAINTCURVE_OT_new(struct wmOperatorType *ot);
+void PAINTCURVE_OT_add_point(struct wmOperatorType *ot);
+void PAINTCURVE_OT_delete_point(struct wmOperatorType *ot);
+void PAINTCURVE_OT_select(struct wmOperatorType *ot);
+void PAINTCURVE_OT_slide(struct wmOperatorType *ot);
+void PAINTCURVE_OT_draw(struct wmOperatorType *ot);
+void PAINTCURVE_OT_cursor(struct wmOperatorType *ot);
+
+/* image painting blur kernel */
+typedef struct {
+ float *wdata; /* actual kernel */
+ int side; /* kernel side */
+ int side_squared; /* data side */
+ int pixel_len; /* pixels around center that kernel is wide */
+} BlurKernel;
+
+enum BlurKernelType;
+/* can be extended to other blur kernels later */
+BlurKernel *paint_new_blur_kernel(struct Brush *br, bool proj);
+void paint_delete_blur_kernel(BlurKernel *);
+
+/* paint curve defines */
+#define PAINT_CURVE_NUM_SEGMENTS 40
+
#endif /* __PAINT_INTERN_H__ */
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index b3f81f379f3..8faa4cfaf33 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -115,7 +115,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
sculpt_undo_push_begin("Mask flood fill");
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (i = 0; i < totnode; i++) {
PBVHVertexIter vi;
@@ -236,7 +236,7 @@ int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *r
BKE_pbvh_search_gather(pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes_final, &nodes, &totnode);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (i = 0; i < totnode; i++) {
PBVHVertexIter vi;
bool any_masked = false;
@@ -385,7 +385,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
/* gather nodes inside lasso's enclosing rectangle (should greatly help with bigger meshes) */
BKE_pbvh_search_gather(pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes_final, &nodes, &totnode);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (i = 0; i < totnode; i++) {
PBVHVertexIter vi;
bool any_masked = false;
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 9021581d47f..90161fa87dd 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -149,11 +149,112 @@ static void BRUSH_OT_scale_size(wmOperatorType *ot)
RNA_def_float(ot->srna, "scalar", 1, 0, 2, "Scalar", "Factor to scale brush size by", 0, 2);
}
+/* Palette operators */
+
+static int palette_new_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Main *bmain = CTX_data_main(C);
+ Palette *palette;
+
+ palette = BKE_palette_add(bmain, "Palette");
+
+ BKE_paint_palette_set(paint, palette);
+
+ return OPERATOR_FINISHED;
+}
+
+static void PALETTE_OT_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add New Palette";
+ ot->description = "Add new palette";
+ ot->idname = "PALETTE_OT_new";
+
+ /* api callbacks */
+ ot->exec = palette_new_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int palette_poll(bContext *C)
+{
+ Paint *paint = BKE_paint_get_active_from_context(C);
+
+ if (paint && paint->palette != NULL)
+ return true;
+
+ return false;
+}
+
+static int palette_color_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *brush = paint->brush;
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
+ Palette *palette = paint->palette;
+ PaletteColor *color = BKE_palette_color_add(palette);
+
+ if (ELEM(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX)) {
+ copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush));
+ color->value = 0.0;
+ }
+ else if (mode == PAINT_WEIGHT) {
+ zero_v3(color->rgb);
+ color->value = brush->weight;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void PALETTE_OT_color_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "New Palette Color";
+ ot->description = "Add new color to active palette";
+ ot->idname = "PALETTE_OT_color_add";
+
+ /* api callbacks */
+ ot->exec = palette_color_add_exec;
+ ot->poll = palette_poll;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+static int palette_color_delete_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Palette *palette = paint->palette;
+
+ BKE_palette_color_delete(palette);
+
+ return OPERATOR_FINISHED;
+}
+
+static void PALETTE_OT_color_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete Palette Color";
+ ot->description = "Remove active color from palette";
+ ot->idname = "PALETTE_OT_color_delete";
+
+ /* api callbacks */
+ ot->exec = palette_color_delete_exec;
+ ot->poll = palette_poll;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+
static int vertex_color_set_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
- unsigned int paintcol = vpaint_get_current_col(scene->toolsettings->vpaint);
+ unsigned int paintcol = vpaint_get_current_col(scene, scene->toolsettings->vpaint);
if (ED_vpaint_fill(obact, paintcol)) {
ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
@@ -332,6 +433,7 @@ static int brush_generic_tool_set(Main *bmain, Paint *paint, const int tool,
if (brush) {
BKE_paint_brush_set(paint, brush);
BKE_paint_invalidate_overlay_all();
+
WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);
return OPERATOR_FINISHED;
}
@@ -928,8 +1030,37 @@ static void ed_keymap_stencil(wmKeyMap *keymap)
/**************************** registration **********************************/
+void ED_operatormacros_paint(void)
+{
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("PAINTCURVE_OT_add_point_slide", "Add Curve Point and Slide",
+ "Add new curve point and slide it", OPTYPE_UNDO);
+ ot->description = "Add new curve point and slide it";
+ WM_operatortype_macro_define(ot, "PAINTCURVE_OT_add_point");
+ otmacro = WM_operatortype_macro_define(ot, "PAINTCURVE_OT_slide");
+ RNA_boolean_set(otmacro->ptr, "align", true);
+ RNA_boolean_set(otmacro->ptr, "select", false);
+}
+
+
void ED_operatortypes_paint(void)
{
+ /* palette */
+ WM_operatortype_append(PALETTE_OT_new);
+ WM_operatortype_append(PALETTE_OT_color_add);
+ WM_operatortype_append(PALETTE_OT_color_delete);
+
+ /* paint curve */
+ WM_operatortype_append(PAINTCURVE_OT_new);
+ WM_operatortype_append(PAINTCURVE_OT_add_point);
+ WM_operatortype_append(PAINTCURVE_OT_delete_point);
+ WM_operatortype_append(PAINTCURVE_OT_select);
+ WM_operatortype_append(PAINTCURVE_OT_slide);
+ WM_operatortype_append(PAINTCURVE_OT_draw);
+ WM_operatortype_append(PAINTCURVE_OT_cursor);
+
/* brush */
WM_operatortype_append(BRUSH_OT_add);
WM_operatortype_append(BRUSH_OT_scale_size);
@@ -950,6 +1081,9 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_grab_clone);
WM_operatortype_append(PAINT_OT_project_image);
WM_operatortype_append(PAINT_OT_image_from_view);
+ WM_operatortype_append(PAINT_OT_brush_colors_flip);
+ WM_operatortype_append(PAINT_OT_add_texture_paint_slot);
+ WM_operatortype_append(PAINT_OT_delete_texture_paint_slot);
/* weight */
WM_operatortype_append(PAINT_OT_weight_paint_toggle);
@@ -1119,12 +1253,44 @@ static void paint_partial_visibility_keys(wmKeyMap *keymap)
RNA_enum_set(kmi->ptr, "area", PARTIALVIS_ALL);
}
+
+static void paint_keymap_curve(wmKeyMap *keymap)
+{
+ wmKeyMapItem *kmi;
+
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_add_point_slide", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "PAINTCURVE_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_slide", ACTIONMOUSE, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "PAINTCURVE_OT_slide", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "align", true);
+ kmi = WM_keymap_add_item(keymap, "PAINTCURVE_OT_select", AKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "toggle", true);
+
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_cursor", ACTIONMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_delete_point", XKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_draw", RETKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_draw", PADENTER, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", GKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
+ WM_keymap_add_item(keymap, "TRANSFORM_OT_rotate", RKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "TRANSFORM_OT_resize", SKEY, KM_PRESS, 0, 0);
+}
+
void ED_keymap_paint(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
int i;
+ keymap = WM_keymap_find(keyconf, "Paint Curve", 0, 0);
+ keymap->poll = paint_curve_poll;
+
+ paint_keymap_curve(keymap);
+
/* Sculpt mode */
keymap = WM_keymap_find(keyconf, "Sculpt", 0, 0);
keymap->poll = sculpt_mode_poll;
@@ -1191,7 +1357,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "create_missing", 1);
/* */
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.sculpt.brush.stroke_method");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SKEY, KM_PRESS, KM_SHIFT, 0);
@@ -1225,7 +1391,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.texture_angle_source_random");
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.stroke_method");
/* Weight Paint mode */
@@ -1250,7 +1416,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
ed_keymap_stencil(keymap);
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.stroke_method");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* face mask toggle */
@@ -1283,6 +1449,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "mode", BRUSH_STROKE_NORMAL);
RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "mode", BRUSH_STROKE_INVERT);
+ WM_keymap_add_item(keymap, "PAINT_OT_brush_colors_flip", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PAINT_OT_grab_clone", RIGHTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PAINT_OT_sample_color", SKEY, KM_PRESS, 0, 0);
@@ -1301,7 +1468,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.texture_angle_source_random");
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.stroke_method");
/* face-mask mode */
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index e87f8ca6827..8f189b49aa6 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -36,16 +36,19 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_rand.h"
+#include "BLI_listbase.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
+#include "DNA_curve_types.h"
#include "RNA_access.h"
#include "BKE_context.h"
#include "BKE_paint.h"
#include "BKE_brush.h"
+#include "BKE_curve.h"
#include "BKE_colortools.h"
#include "BKE_image.h"
@@ -72,7 +75,7 @@ typedef struct PaintSample {
typedef struct PaintStroke {
void *mode_data;
- void *smooth_stroke_cursor;
+ void *stroke_cursor;
wmTimer *timer;
/* Cached values */
@@ -81,6 +84,9 @@ typedef struct PaintStroke {
Brush *brush;
UnifiedPaintSettings *ups;
+ /* used for lines and curves */
+ ListBase line;
+
/* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
* to smooth the stroke */
PaintSample samples[PAINT_MAX_INPUT_SAMPLES];
@@ -88,6 +94,8 @@ typedef struct PaintStroke {
int cur_sample;
float last_mouse_position[2];
+ /* space distance covered so far */
+ float stroke_distance;
/* Set whether any stroke step has yet occurred
* e.g. in sculpt mode, stroke doesn't start until cursor
@@ -104,7 +112,7 @@ typedef struct PaintStroke {
float cached_size_pressure;
/* last pressure will store last pressure value for use in interpolation for space strokes */
float last_pressure;
-
+ int stroke_mode;
float zoom_2d;
int pen_flip;
@@ -116,18 +124,17 @@ typedef struct PaintStroke {
StrokeDone done;
} PaintStroke;
-/*** Cursor ***/
-static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata)
+/*** Cursors ***/
+static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata)
{
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
PaintStroke *stroke = customdata;
- if (stroke && brush && (brush->flag & BRUSH_SMOOTH_STROKE)) {
- glColor4ubv(paint->paint_cursor_col);
+ if (stroke && brush) {
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
-
+ glColor4ubv(paint->paint_cursor_col);
sdrawline(x, y, (int)stroke->last_mouse_position[0],
(int)stroke->last_mouse_position[1]);
glDisable(GL_BLEND);
@@ -135,32 +142,39 @@ static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata
}
}
-/* if this is a tablet event, return tablet pressure and set *pen_flip
- * to 1 if the eraser tool is being used, 0 otherwise */
-static float event_tablet_data(const wmEvent *event, int *pen_flip)
+static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
{
- int erasor = 0;
- float pressure = 1;
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ PaintStroke *stroke = customdata;
- if (event->tablet_data) {
- wmTabletData *wmtab = event->tablet_data;
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
- erasor = (wmtab->Active == EVT_TABLET_ERASER);
- pressure = (wmtab->Active != EVT_TABLET_NONE) ? wmtab->Pressure : 1;
- }
+ glEnable(GL_LINE_STIPPLE);
+ glLineStipple(3, 0xAAAA);
+
+ glColor4ub(0, 0, 0, paint->paint_cursor_col[3]);
+ glLineWidth(3.0);
+ sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
+ x, y);
+
+ glColor4ub(255, 255, 255, paint->paint_cursor_col[3]);
+ glLineWidth(1.0);
+ sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
+ x, y);
- if (pen_flip)
- (*pen_flip) = erasor;
+ glDisable(GL_LINE_STIPPLE);
- return pressure;
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
}
static bool paint_tool_require_location(Brush *brush, PaintMode mode)
{
switch (mode) {
case PAINT_SCULPT:
- if (ELEM4(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB))
+ if (ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB))
{
return false;
}
@@ -175,13 +189,18 @@ static bool paint_tool_require_location(Brush *brush, PaintMode mode)
}
/* Initialize the stroke cache variants from operator properties */
-static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
- struct PaintStroke *stroke,
- const float mouse[2], float pressure)
+static bool paint_brush_update(bContext *C,
+ Brush *brush,
+ PaintMode mode,
+ struct PaintStroke *stroke,
+ const float mouse_init[2],
+ float mouse[2], float pressure,
+ float location[3])
{
Scene *scene = CTX_data_scene(C);
- UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
-
+ UnifiedPaintSettings *ups = stroke->ups;
+ bool location_sampled = false;
+ bool location_success = false;
/* XXX: Use pressure value from first brush step for brushes which don't
* support strokes (grab, thumb). They depends on initial state and
* brush coord/pressure/etc.
@@ -194,6 +213,9 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
copy_v2_v2(ups->mask_tex_mouse, mouse);
stroke->cached_size_pressure = pressure;
+ ups->do_linear_conversion = false;
+ ups->colorspace = NULL;
+
/* check here if color sampling the main brush should do color conversion. This is done here
* to avoid locking up to get the image buffer during sampling */
if (brush->mtex.tex && brush->mtex.tex->type == TEX_IMAGE && brush->mtex.tex->ima) {
@@ -242,14 +264,14 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
else {
copy_v2_v2(ups->tex_mouse, mouse);
}
- }
- /* take care of mask texture, if any */
- if (brush->mask_mtex.tex) {
- if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
- BKE_brush_randomize_texture_coordinates(ups, true);
- else {
- copy_v2_v2(ups->mask_tex_mouse, mouse);
+ /* take care of mask texture, if any */
+ if (brush->mask_mtex.tex) {
+ if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
+ BKE_brush_randomize_texture_coordinates(ups, true);
+ else {
+ copy_v2_v2(ups->mask_tex_mouse, mouse);
+ }
}
}
@@ -266,14 +288,14 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
ups->brush_rotation = atan2(dx, dy) + M_PI;
if (brush->flag & BRUSH_EDGE_TO_EDGE) {
- float out[3];
-
halfway[0] = dx * 0.5f + stroke->initial_mouse[0];
halfway[1] = dy * 0.5f + stroke->initial_mouse[1];
if (stroke->get_location) {
- if (stroke->get_location(C, out, halfway)) {
+ if (stroke->get_location(C, location, halfway)) {
hit = true;
+ location_sampled = true;
+ location_success = true;
}
else if (!paint_tool_require_location(brush, mode)) {
hit = true;
@@ -286,30 +308,69 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
if (hit) {
copy_v2_v2(ups->anchored_initial_mouse, halfway);
copy_v2_v2(ups->tex_mouse, halfway);
+ copy_v2_v2(ups->mask_tex_mouse, halfway);
+ copy_v2_v2(mouse, halfway);
ups->anchored_size /= 2.0f;
ups->pixel_radius /= 2.0f;
+ stroke->stroke_distance = ups->pixel_radius;
}
- else
+ else {
copy_v2_v2(ups->anchored_initial_mouse, stroke->initial_mouse);
-
+ copy_v2_v2(mouse, stroke->initial_mouse);
+ stroke->stroke_distance = ups->pixel_radius;
+ }
+ ups->pixel_radius /= stroke->zoom_2d;
ups->draw_anchored = true;
}
else if (brush->flag & BRUSH_RAKE) {
- paint_calculate_rake_rotation(ups, mouse);
+ /* here we are using the initial mouse coordinate because we do not want the rake
+ * result to depend on jittering */
+ if (!stroke->brush_init)
+ copy_v2_v2(ups->last_rake, mouse_init);
+ else
+ paint_calculate_rake_rotation(ups, mouse_init);
+ }
+
+ if (!location_sampled) {
+ if (stroke->get_location) {
+ if (stroke->get_location(C, location, mouse))
+ location_success = true;
+ else if (!paint_tool_require_location(brush, mode))
+ location_success = true;
+ }
+ else {
+ zero_v3(location);
+ location_success = true;
+ }
}
+
+ return location_success;
}
+static bool paint_stroke_use_jitter(PaintMode mode, Brush *brush, bool invert)
+{
+ bool use_jitter = (brush->flag & BRUSH_ABSOLUTE_JITTER) ?
+ (brush->jitter_absolute != 0) : (brush->jitter != 0);
+
+ /* jitter-ed brush gives weird and unpredictable result for this
+ * kinds of stroke, so manually disable jitter usage (sergey) */
+ use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0;
+ use_jitter &= (!ELEM(mode, PAINT_TEXTURE_2D, PAINT_TEXTURE_PROJECTIVE) ||
+ !(invert && brush->imagepaint_tool == PAINT_TOOL_CLONE));
+
+
+ return use_jitter;
+}
/* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */
static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float mouse_in[2], float pressure)
{
Scene *scene = CTX_data_scene(C);
- wmWindow *window = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
Paint *paint = BKE_paint_get_active_from_context(C);
PaintMode mode = BKE_paintmode_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
PaintStroke *stroke = op->customdata;
+ UnifiedPaintSettings *ups = stroke->ups;
float mouse_out[2];
PointerRNA itemptr;
float location[3];
@@ -335,9 +396,7 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
copy_v2_v2(stroke->last_mouse_position, mouse_in);
stroke->last_pressure = pressure;
- paint_brush_update(C, brush, mode, stroke, mouse_in, pressure);
-
- {
+ if (paint_stroke_use_jitter(mode, brush, stroke->stroke_mode == BRUSH_STROKE_INVERT)) {
float delta[2];
float factor = stroke->zoom_2d;
@@ -355,23 +414,17 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
add_v2_v2v2(mouse_out, mouse_in, delta);
}
}
+ else {
+ copy_v2_v2(mouse_out, mouse_in);
+ }
- /* TODO: can remove the if statement once all modes have this */
- if (stroke->get_location) {
- if (!stroke->get_location(C, location, mouse_out)) {
- if (paint_tool_require_location(brush, mode)) {
- if (ar && (paint->flags & PAINT_SHOW_BRUSH))
- WM_paint_cursor_tag_redraw(window, ar);
- return;
- }
- }
+ if (!paint_brush_update(C, brush, mode, stroke, mouse_in, mouse_out, pressure, location)) {
+ return;
}
- else
- zero_v3(location);
/* Add to stroke */
RNA_collection_add(op->ptr, "stroke", &itemptr);
-
+ RNA_float_set(&itemptr, "size", ups->pixel_radius);
RNA_float_set_array(&itemptr, "location", location);
RNA_float_set_array(&itemptr, "mouse", mouse_out);
RNA_boolean_set(&itemptr, "pen_flip", stroke->pen_flip);
@@ -382,20 +435,12 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
/* don't record this for now, it takes up a lot of memory when doing long
* strokes with small brush size, and operators have register disabled */
RNA_collection_clear(op->ptr, "stroke");
-
- /* always redraw region if brush is shown */
- if (ar && (paint->flags & PAINT_SHOW_BRUSH))
- WM_paint_cursor_tag_redraw(window, ar);
}
/* Returns zero if no sculpt changes should be made, non-zero otherwise */
static int paint_smooth_stroke(PaintStroke *stroke, float output[2], float *outpressure,
const PaintSample *sample, PaintMode mode)
{
- output[0] = sample->mouse[0];
- output[1] = sample->mouse[1];
- *outpressure = sample->pressure;
-
if (paint_supports_smooth_stroke(stroke->brush, mode)) {
float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d;
float u = stroke->brush->smooth_stroke_factor, v = 1.0f - u;
@@ -411,6 +456,11 @@ static int paint_smooth_stroke(PaintStroke *stroke, float output[2], float *outp
output[1] = sample->mouse[1] * v + stroke->last_mouse_position[1] * u;
*outpressure = sample->pressure * v + stroke->last_pressure * u;
}
+ else {
+ output[0] = sample->mouse[0];
+ output[1] = sample->mouse[1];
+ *outpressure = sample->pressure;
+ }
return 1;
}
@@ -433,6 +483,55 @@ static float paint_space_stroke_spacing(const Scene *scene, PaintStroke *stroke,
return max_ff(1.0, size_clamp * spacing / 50.0f);
}
+
+
+static float paint_stroke_overlapped_curve(Brush *br, float x, float spacing)
+{
+ int i;
+ const int n = 100 / spacing;
+ const float h = spacing / 50.0f;
+ const float x0 = x - 1;
+
+ float sum;
+
+ sum = 0;
+ for (i = 0; i < n; i++) {
+ float xx;
+
+ xx = fabs(x0 + i * h);
+
+ if (xx < 1.0f)
+ sum += BKE_brush_curve_strength(br, xx, 1);
+ }
+
+ return sum;
+}
+
+static float paint_stroke_integrate_overlap(Brush *br, float factor)
+{
+ int i;
+ int m;
+ float g;
+ float max;
+
+ float spacing = br->spacing * factor;
+
+ if (!(br->flag & BRUSH_SPACE_ATTEN && (br->spacing < 100)))
+ return 1.0;
+
+ m = 10;
+ g = 1.0f / m;
+ max = 0;
+ for (i = 0; i < m; i++) {
+ float overlap = paint_stroke_overlapped_curve(br, i * g, spacing);
+
+ if (overlap > max)
+ max = overlap;
+ }
+
+ return 1.0f / max;
+}
+
static float paint_space_stroke_spacing_variable(const Scene *scene, PaintStroke *stroke, float pressure, float dpressure, float length)
{
if (BKE_brush_use_size_pressure(scene, stroke->brush)) {
@@ -464,40 +563,42 @@ static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mou
{
const Scene *scene = CTX_data_scene(C);
PaintStroke *stroke = op->customdata;
- PaintMode mode = BKE_paintmode_get_active_from_context(C);
+ UnifiedPaintSettings *ups = stroke->ups;
int cnt = 0;
- if (paint_space_stroke_enabled(stroke->brush, mode)) {
- float pressure, dpressure;
- float mouse[2], dmouse[2];
- float length;
+ float pressure, dpressure;
+ float mouse[2], dmouse[2];
+ float length;
+ float no_pressure_spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
- sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
+ sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
- pressure = stroke->last_pressure;
- dpressure = final_pressure - stroke->last_pressure;
+ pressure = stroke->last_pressure;
+ dpressure = final_pressure - stroke->last_pressure;
- length = normalize_v2(dmouse);
+ length = normalize_v2(dmouse);
- while (length > 0.0f) {
- float spacing = paint_space_stroke_spacing_variable(scene, stroke, pressure, dpressure, length);
-
- if (length >= spacing) {
- mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
- mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
- pressure = stroke->last_pressure + (spacing / length) * dpressure;
+ while (length > 0.0f) {
+ float spacing = paint_space_stroke_spacing_variable(scene, stroke, pressure, dpressure, length);
- paint_brush_stroke_add_step(C, op, mouse, pressure);
+ if (length >= spacing) {
+ mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
+ mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
+ pressure = stroke->last_pressure + (spacing / length) * dpressure;
- length -= spacing;
- pressure = stroke->last_pressure;
- dpressure = final_pressure - stroke->last_pressure;
+ ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, spacing / no_pressure_spacing);
- cnt++;
- }
- else {
- break;
- }
+ stroke->stroke_distance += spacing / stroke->zoom_2d;
+ paint_brush_stroke_add_step(C, op, mouse, pressure);
+
+ length -= spacing;
+ pressure = stroke->last_pressure;
+ dpressure = final_pressure - stroke->last_pressure;
+
+ cnt++;
+ }
+ else {
+ break;
}
}
@@ -507,6 +608,7 @@ static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mou
/**** Public API ****/
PaintStroke *paint_stroke_new(bContext *C,
+ wmOperator *op,
StrokeGetLocation get_location,
StrokeTestStart test_start,
StrokeUpdateStep update_step,
@@ -517,6 +619,7 @@ PaintStroke *paint_stroke_new(bContext *C,
ToolSettings *toolsettings = CTX_data_tool_settings(C);
UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
Brush *br = stroke->brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
+ float zoomx, zoomy;
view3d_set_viewcontext(C, &stroke->vc);
if (stroke->vc.v3d)
@@ -529,6 +632,19 @@ PaintStroke *paint_stroke_new(bContext *C,
stroke->done = done;
stroke->event_type = event_type; /* for modal, return event */
stroke->ups = ups;
+ stroke->stroke_mode = RNA_enum_get(op->ptr, "mode");
+
+ get_imapaint_zoom(C, &zoomx, &zoomy);
+ stroke->zoom_2d = max_ff(zoomx, zoomy);
+
+ if ((br->flag & BRUSH_CURVE) &&
+ RNA_struct_property_is_set(op->ptr, "mode"))
+ {
+ RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL);
+ }
+ /* initialize here */
+ ups->overlap_factor = 1.0;
+ ups->stroke_active = true;
/* initialize here to avoid initialization conflict with threaded strokes */
curvemapping_initialize(br->curve);
@@ -541,8 +657,7 @@ PaintStroke *paint_stroke_new(bContext *C,
void paint_stroke_data_free(struct wmOperator *op)
{
BKE_paint_set_overlay_override(0);
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ MEM_SAFE_FREE(op->customdata);
}
static void stroke_done(struct bContext *C, struct wmOperator *op)
@@ -572,8 +687,10 @@ static void stroke_done(struct bContext *C, struct wmOperator *op)
stroke->timer);
}
- if (stroke->smooth_stroke_cursor)
- WM_paint_cursor_end(CTX_wm_manager(C), stroke->smooth_stroke_cursor);
+ if (stroke->stroke_cursor)
+ WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor);
+
+ BLI_freelistN(&stroke->line);
paint_stroke_data_free(op);
}
@@ -586,7 +703,7 @@ bool paint_space_stroke_enabled(Brush *br, PaintMode mode)
static bool sculpt_is_grab_tool(Brush *br)
{
- return ELEM4(br->sculpt_tool,
+ return ELEM(br->sculpt_tool,
SCULPT_TOOL_GRAB,
SCULPT_TOOL_THUMB,
SCULPT_TOOL_ROTATE,
@@ -604,6 +721,16 @@ bool paint_supports_dynamic_size(Brush *br, PaintMode mode)
if (sculpt_is_grab_tool(br))
return false;
break;
+
+ case PAINT_TEXTURE_2D: /* fall through */
+ case PAINT_TEXTURE_PROJECTIVE:
+ if ((br->imagepaint_tool == PAINT_TOOL_FILL) &&
+ (br->flag & BRUSH_USE_GRADIENT))
+ {
+ return false;
+ }
+ break;
+
default:
break;
}
@@ -613,8 +740,7 @@ bool paint_supports_dynamic_size(Brush *br, PaintMode mode)
bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
{
if (!(br->flag & BRUSH_SMOOTH_STROKE) ||
- (br->flag & BRUSH_ANCHORED) ||
- (br->flag & BRUSH_DRAG_DOT))
+ (br->flag & (BRUSH_ANCHORED | BRUSH_DRAG_DOT | BRUSH_LINE)))
{
return false;
}
@@ -633,7 +759,7 @@ bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
bool paint_supports_texture(PaintMode mode)
{
/* ommit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */
- return ELEM4(mode, PAINT_SCULPT, PAINT_VERTEX, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D);
+ return ELEM(mode, PAINT_SCULPT, PAINT_VERTEX, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D);
}
/* return true if the brush size can change during paint (normally used for pressure) */
@@ -721,28 +847,141 @@ static void paint_stroke_sample_average(const PaintStroke *stroke,
/*printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);*/
}
+/**
+ * Slightly different version of spacing for line/curve strokes,
+ * makes sure the dabs stay on the line path.
+ */
+static void paint_line_strokes_spacing(
+ bContext *C, wmOperator *op, PaintStroke *stroke, float spacing, float *length_residue,
+ const float old_pos[2], const float new_pos[2])
+{
+ UnifiedPaintSettings *ups = stroke->ups;
+
+ float mouse[2], dmouse[2];
+ float length;
+
+ sub_v2_v2v2(dmouse, new_pos, old_pos);
+ copy_v2_v2(stroke->last_mouse_position, old_pos);
+
+ length = normalize_v2(dmouse);
+
+ BLI_assert(length >= 0.0f);
+
+ if (length == 0.0f)
+ return;
+
+ while (length > 0.0f) {
+ float spacing_final = spacing - *length_residue;
+ length += *length_residue;
+ *length_residue = 0.0;
+
+ if (length >= spacing) {
+ mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final;
+ mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing_final;
+
+ ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, 1.0);
+
+ stroke->stroke_distance += spacing / stroke->zoom_2d;
+ paint_brush_stroke_add_step(C, op, mouse, 1.0);
+
+ length -= spacing;
+ spacing_final = spacing;
+ }
+ else {
+ break;
+ }
+ }
+
+ *length_residue = length;
+}
+
+
+static void paint_stroke_line_end(bContext *C, wmOperator *op, PaintStroke *stroke, float mouse[2])
+{
+ Brush *br = stroke->brush;
+ if (stroke->stroke_started && (br->flag & BRUSH_LINE)) {
+ stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
+
+ paint_brush_stroke_add_step(C, op, stroke->last_mouse_position, 1.0);
+ paint_space_stroke(C, op, mouse, 1.0);
+ }
+}
+
+static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *stroke)
+{
+ Brush *br = stroke->brush;
+ if (br->flag & BRUSH_CURVE) {
+ const Scene *scene = CTX_data_scene(C);
+ const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
+ PaintCurve *pc = br->paint_curve;
+ PaintCurvePoint *pcp;
+ float length_residue = 0.0f;
+ int i;
+
+ if (!pc)
+ return true;
+
+ pcp = pc->points;
+ stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
+
+ for (i = 0; i < pc->tot_points - 1; i++, pcp++) {
+ int j;
+ float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
+ PaintCurvePoint *pcp_next = pcp + 1;
+
+ for (j = 0; j < 2; j++)
+ BKE_curve_forward_diff_bezier(
+ pcp->bez.vec[1][j],
+ pcp->bez.vec[2][j],
+ pcp_next->bez.vec[0][j],
+ pcp_next->bez.vec[1][j],
+ data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
+
+
+ for (j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) {
+ if (!stroke->stroke_started) {
+ stroke->last_pressure = 1.0;
+ copy_v2_v2(stroke->last_mouse_position, data + 2 * j);
+ stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position);
+
+ if (stroke->stroke_started) {
+ paint_brush_stroke_add_step(C, op, data + 2 * j, 1.0);
+ paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
+ }
+ }
+ else {
+ paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
+ }
+ }
+ }
+
+ stroke_done(C, op);
+ return true;
+ }
+
+ return false;
+}
+
+
int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Paint *p = BKE_paint_get_active_from_context(C);
PaintMode mode = BKE_paintmode_get_active_from_context(C);
PaintStroke *stroke = op->customdata;
+ Brush *br = stroke->brush;
PaintSample sample_average;
float mouse[2];
bool first_dab = false;
bool first_modal = false;
- float zoomx, zoomy;
bool redraw = false;
float pressure;
- /* see if tablet affects event */
- pressure = event_tablet_data(event, &stroke->pen_flip);
+ /* see if tablet affects event. Line, anchored and drag dot strokes do not support pressure */
+ pressure = (br->flag & (BRUSH_LINE | BRUSH_ANCHORED | BRUSH_DRAG_DOT)) ? 1.0f : WM_event_tablet_data(event, &stroke->pen_flip, NULL);
paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
paint_stroke_sample_average(stroke, &sample_average);
- get_imapaint_zoom(C, &zoomx, &zoomy);
- stroke->zoom_2d = max_ff(zoomx, zoomy);
-
/* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously!
* this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it
* since the 2D deltas are zero -- code in this file needs to be updated to use the
@@ -752,8 +991,12 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* one time initialization */
if (!stroke->stroke_init) {
- stroke->smooth_stroke_cursor =
- WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_smooth_stroke, stroke);
+ if (paint_stroke_curve_end(C, op, stroke))
+ return OPERATOR_FINISHED;
+
+ if (paint_supports_smooth_stroke(br, mode))
+ stroke->stroke_cursor =
+ WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_smooth_cursor, stroke);
stroke->stroke_init = true;
first_modal = true;
@@ -767,9 +1010,14 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */
if (stroke->stroke_started) {
- if (stroke->brush->flag & BRUSH_AIRBRUSH)
+ if (br->flag & BRUSH_AIRBRUSH)
stroke->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, stroke->brush->rate);
+ if (br->flag & BRUSH_LINE) {
+ stroke->stroke_cursor =
+ WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_line_cursor, stroke);
+ }
+
first_dab = true;
}
}
@@ -785,20 +1033,42 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- if (event->type == stroke->event_type && event->val == KM_RELEASE && !first_modal) {
+ if (event->type == stroke->event_type && !first_modal) {
+ if (event->val == KM_RELEASE) {
+ paint_stroke_line_end (C, op, stroke, sample_average.mouse);
+ stroke_done(C, op);
+ return OPERATOR_FINISHED;
+ }
+ }
+ else if (ELEM(event->type, RETKEY, SPACEKEY)) {
+ paint_stroke_line_end(C, op, stroke, sample_average.mouse);
stroke_done(C, op);
return OPERATOR_FINISHED;
}
- else if (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) ||
- (event->type == TIMER && (event->customdata == stroke->timer)) )
+ else if ((br->flag & BRUSH_LINE) && stroke->stroke_started &&
+ (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))))
+ {
+ if (br->flag & BRUSH_RAKE) {
+ copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
+ paint_calculate_rake_rotation(stroke->ups, sample_average.mouse);
+ }
+ }
+ else if (first_modal ||
+ /* regular dabs */
+ (!(br->flag & (BRUSH_AIRBRUSH)) && (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))) ||
+ /* airbrush */
+ ((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER && event->customdata == stroke->timer))
{
if (paint_smooth_stroke(stroke, mouse, &pressure, &sample_average, mode)) {
if (stroke->stroke_started) {
- if (paint_space_stroke_enabled(stroke->brush, mode)) {
+ if (paint_space_stroke_enabled(br, mode)) {
if (paint_space_stroke(C, op, mouse, pressure))
redraw = true;
}
else {
+ float dmouse[2];
+ sub_v2_v2v2(dmouse, mouse, stroke->last_mouse_position);
+ stroke->stroke_distance += len_v2(dmouse);
paint_brush_stroke_add_step(C, op, mouse, pressure);
redraw = true;
}
@@ -809,19 +1079,27 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* we want the stroke to have the first daub at the start location
* instead of waiting till we have moved the space distance */
if (first_dab &&
- paint_space_stroke_enabled(stroke->brush, mode) &&
- !(stroke->brush->flag & BRUSH_ANCHORED) &&
- !(stroke->brush->flag & BRUSH_SMOOTH_STROKE))
+ paint_space_stroke_enabled(br, mode) &&
+ !(br->flag & BRUSH_SMOOTH_STROKE))
{
- paint_brush_stroke_add_step(C, op, mouse, pressure);
+ stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
+ paint_brush_stroke_add_step(C, op, sample_average.mouse, sample_average.pressure);
redraw = true;
}
/* do updates for redraw. if event is inbetween mousemove there are more
* coming, so postpone potentially slow redraw updates until all are done */
- if (event->type != INBETWEEN_MOUSEMOVE)
+ if (event->type != INBETWEEN_MOUSEMOVE) {
+ wmWindow *window = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ /* At the very least, invalidate the cursor */
+ if (ar && (p->flags & PAINT_SHOW_BRUSH))
+ WM_paint_cursor_tag_redraw(window, ar);
+
if (redraw && stroke->redraw)
stroke->redraw(C, stroke, false);
+ }
return OPERATOR_RUNNING_MODAL;
}
@@ -863,6 +1141,16 @@ void *paint_stroke_mode_data(struct PaintStroke *stroke)
return stroke->mode_data;
}
+bool paint_stroke_flipped(struct PaintStroke *stroke)
+{
+ return stroke->pen_flip;
+}
+
+float paint_stroke_distance_get(struct PaintStroke *stroke)
+{
+ return stroke->stroke_distance;
+}
+
void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data)
{
stroke->mode_data = mode_data;
@@ -876,6 +1164,6 @@ int paint_poll(bContext *C)
ARegion *ar = CTX_wm_region(C);
return p && ob && BKE_paint_brush(p) &&
- (sa && sa->spacetype == SPACE_VIEW3D) &&
+ (sa && ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) &&
(ar && ar->regiontype == RGN_TYPE_WINDOW);
}
diff --git a/source/blender/editors/sculpt_paint/paint_undo.c b/source/blender/editors/sculpt_paint/paint_undo.c
index c5c747dbab4..20e3155c01d 100644
--- a/source/blender/editors/sculpt_paint/paint_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_undo.c
@@ -51,19 +51,17 @@ typedef struct UndoElem {
UndoRestoreCb restore;
UndoFreeCb free;
+ UndoCleanupCb cleanup;
} UndoElem;
-typedef bool (*UndoCleanupCb)(struct bContext *C, ListBase *lb);
-
typedef struct UndoStack {
int type;
ListBase elems;
UndoElem *current;
- UndoCleanupCb cleanup;
} UndoStack;
-static UndoStack ImageUndoStack = {UNDO_PAINT_IMAGE, {NULL, NULL}, NULL, NULL};
-static UndoStack MeshUndoStack = {UNDO_PAINT_MESH, {NULL, NULL}, NULL, sculpt_undo_cleanup};
+static UndoStack ImageUndoStack = {UNDO_PAINT_IMAGE, {NULL, NULL}, NULL};
+static UndoStack MeshUndoStack = {UNDO_PAINT_MESH, {NULL, NULL}, NULL};
/* Generic */
@@ -81,7 +79,7 @@ static void undo_elem_free(UndoStack *UNUSED(stack), UndoElem *uel)
}
}
-static void undo_stack_push_begin(UndoStack *stack, const char *name, UndoRestoreCb restore, UndoFreeCb free)
+static void undo_stack_push_begin(UndoStack *stack, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup)
{
UndoElem *uel;
int nr;
@@ -101,6 +99,7 @@ static void undo_stack_push_begin(UndoStack *stack, const char *name, UndoRestor
stack->current = uel = MEM_callocN(sizeof(UndoElem), "undo file");
uel->restore = restore;
uel->free = free;
+ uel->cleanup = cleanup;
BLI_addtail(&stack->elems, uel);
/* name can be a dynamic string */
@@ -179,25 +178,24 @@ static void undo_stack_cleanup(UndoStack *stack, bContext *C)
UndoElem *uel = stack->elems.first;
bool stack_reset = false;
- if (stack->cleanup) {
- while (uel) {
- if (stack->cleanup(C, &uel->elems)) {
- UndoElem *uel_tmp = uel->next;
- if (stack->current == uel) {
- stack->current = NULL;
- stack_reset = true;
- }
- undo_elem_free(stack, uel);
- BLI_freelinkN(&stack->elems, uel);
- uel = uel_tmp;
+ while (uel) {
+ if (uel->cleanup && uel->cleanup(C, &uel->elems)) {
+ UndoElem *uel_tmp = uel->next;
+ if (stack->current == uel) {
+ stack->current = NULL;
+ stack_reset = true;
}
- else
- uel = uel->next;
- }
- if (stack_reset) {
- stack->current = stack->elems.last;
+ undo_elem_free(stack, uel);
+ BLI_freelinkN(&stack->elems, uel);
+ uel = uel_tmp;
}
+ else
+ uel = uel->next;
+ }
+ if (stack_reset) {
+ stack->current = stack->elems.last;
}
+
}
static int undo_stack_step(bContext *C, UndoStack *stack, int step, const char *name)
@@ -255,23 +253,25 @@ static void undo_stack_free(UndoStack *stack)
/* Exported Functions */
-void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free)
+void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup)
{
if (type == UNDO_PAINT_IMAGE)
- undo_stack_push_begin(&ImageUndoStack, name, restore, free);
+ undo_stack_push_begin(&ImageUndoStack, name, restore, free, cleanup);
else if (type == UNDO_PAINT_MESH)
- undo_stack_push_begin(&MeshUndoStack, name, restore, free);
+ undo_stack_push_begin(&MeshUndoStack, name, restore, free, cleanup);
}
ListBase *undo_paint_push_get_list(int type)
{
if (type == UNDO_PAINT_IMAGE) {
- if (ImageUndoStack.current)
+ if (ImageUndoStack.current) {
return &ImageUndoStack.current->elems;
+ }
}
else if (type == UNDO_PAINT_MESH) {
- if (MeshUndoStack.current)
+ if (MeshUndoStack.current) {
return &MeshUndoStack.current->elems;
+ }
}
return NULL;
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 25308f6595e..f34d0ff3f7b 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -35,23 +35,28 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "DNA_material_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "BLI_math.h"
+#include "BLI_math_color.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_rect.h"
#include "BLF_translation.h"
+#include "BKE_scene.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_material.h"
#include "BKE_image.h"
#include "BKE_paint.h"
#include "BKE_report.h"
+#include "BKE_image.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -67,6 +72,10 @@
#include "ED_view3d.h"
#include "ED_screen.h"
+#include "ED_uvedit.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
#include "BLI_sys_types.h"
#include "ED_mesh.h" /* for face mask functions */
@@ -205,6 +214,192 @@ void paint_get_tex_pixel_col(MTex *mtex, float u, float v, float rgba[4], struct
CLAMP(rgba[3], 0.0f, 1.0f);
}
+void paint_stroke_operator_properties(wmOperatorType *ot)
+{
+ static EnumPropertyItem stroke_mode_items[] = {
+ {BRUSH_STROKE_NORMAL, "NORMAL", 0, "Normal", "Apply brush normally"},
+ {BRUSH_STROKE_INVERT, "INVERT", 0, "Invert", "Invert action of brush for duration of stroke"},
+ {BRUSH_STROKE_SMOOTH, "SMOOTH", 0, "Smooth", "Switch brush to smooth mode for duration of stroke"},
+ {0}
+ };
+
+ RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+
+ RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL,
+ "Stroke Mode",
+ "Action taken when a paint stroke is made");
+
+}
+
+/* 3D Paint */
+
+static void imapaint_project(float matrix[4][4], const float co[3], float pco[4])
+{
+ copy_v3_v3(pco, co);
+ pco[3] = 1.0f;
+
+ mul_m4_v4(matrix, pco);
+}
+
+static void imapaint_tri_weights(float matrix[4][4], GLint view[4],
+ const float v1[3], const float v2[3], const float v3[3],
+ const float co[2], float w[3])
+{
+ float pv1[4], pv2[4], pv3[4], h[3], divw;
+ float wmat[3][3], invwmat[3][3];
+
+ /* compute barycentric coordinates */
+
+ /* project the verts */
+ imapaint_project(matrix, v1, pv1);
+ imapaint_project(matrix, v2, pv2);
+ imapaint_project(matrix, v3, pv3);
+
+ /* do inverse view mapping, see gluProject man page */
+ h[0] = (co[0] - view[0]) * 2.0f / view[2] - 1.0f;
+ h[1] = (co[1] - view[1]) * 2.0f / view[3] - 1.0f;
+ h[2] = 1.0f;
+
+ /* solve for (w1,w2,w3)/perspdiv in:
+ * h * perspdiv = Project * Model * (w1 * v1 + w2 * v2 + w3 * v3) */
+
+ wmat[0][0] = pv1[0]; wmat[1][0] = pv2[0]; wmat[2][0] = pv3[0];
+ wmat[0][1] = pv1[1]; wmat[1][1] = pv2[1]; wmat[2][1] = pv3[1];
+ wmat[0][2] = pv1[3]; wmat[1][2] = pv2[3]; wmat[2][2] = pv3[3];
+
+ invert_m3_m3(invwmat, wmat);
+ mul_m3_v3(invwmat, h);
+
+ copy_v3_v3(w, h);
+
+ /* w is still divided by perspdiv, make it sum to one */
+ divw = w[0] + w[1] + w[2];
+ if (divw != 0.0f) {
+ mul_v3_fl(w, 1.0f / divw);
+ }
+}
+
+/* compute uv coordinates of mouse in face */
+static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2])
+{
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ MTFace *tf_base, *tf;
+ Material *ma;
+ TexPaintSlot *slot;
+ int numfaces = dm->getNumTessFaces(dm), a, findex;
+ float p[2], w[3], absw, minabsw;
+ MFace mf;
+ MVert mv[4];
+ float matrix[4][4], proj[4][4];
+ GLint view[4];
+
+ /* compute barycentric coordinates */
+
+ /* double lookup */
+ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+ if (index_mf_to_mpoly == NULL) {
+ index_mp_to_orig = NULL;
+ }
+
+ /* get the needed opengl matrices */
+ glGetIntegerv(GL_VIEWPORT, view);
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)matrix);
+ glGetFloatv(GL_PROJECTION_MATRIX, (float *)proj);
+ view[0] = view[1] = 0;
+ mul_m4_m4m4(matrix, matrix, ob->obmat);
+ mul_m4_m4m4(matrix, proj, matrix);
+
+ minabsw = 1e10;
+ uv[0] = uv[1] = 0.0;
+
+ /* test all faces in the derivedmesh with the original index of the picked face */
+ for (a = 0; a < numfaces; a++) {
+ findex = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
+
+ if (findex == faceindex) {
+ dm->getTessFace(dm, a, &mf);
+
+ ma = dm->mat[mf.mat_nr];
+ slot = &ma->texpaintslot[ma->paint_active_slot];
+
+ dm->getVert(dm, mf.v1, &mv[0]);
+ dm->getVert(dm, mf.v2, &mv[1]);
+ dm->getVert(dm, mf.v3, &mv[2]);
+ if (mf.v4)
+ dm->getVert(dm, mf.v4, &mv[3]);
+
+ if (!(slot && slot->uvname && (tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, slot->uvname))))
+ tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+
+ tf = &tf_base[a];
+
+ p[0] = xy[0];
+ p[1] = xy[1];
+
+ if (mf.v4) {
+ /* the triangle with the largest absolute values is the one
+ * with the most negative weights */
+ imapaint_tri_weights(matrix, view, mv[0].co, mv[1].co, mv[3].co, p, w);
+ absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
+ if (absw < minabsw) {
+ uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[3][0] * w[2];
+ uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[3][1] * w[2];
+ minabsw = absw;
+ }
+
+ imapaint_tri_weights(matrix, view, mv[1].co, mv[2].co, mv[3].co, p, w);
+ absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
+ if (absw < minabsw) {
+ uv[0] = tf->uv[1][0] * w[0] + tf->uv[2][0] * w[1] + tf->uv[3][0] * w[2];
+ uv[1] = tf->uv[1][1] * w[0] + tf->uv[2][1] * w[1] + tf->uv[3][1] * w[2];
+ minabsw = absw;
+ }
+ }
+ else {
+ imapaint_tri_weights(matrix, view, mv[0].co, mv[1].co, mv[2].co, p, w);
+ absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
+ if (absw < minabsw) {
+ uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[2][0] * w[2];
+ uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[2][1] * w[2];
+ minabsw = absw;
+ }
+ }
+ }
+ }
+
+ dm->release(dm);
+}
+
+/* returns 0 if not found, otherwise 1 */
+static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *r_index, unsigned int totface)
+{
+ if (totface == 0)
+ return 0;
+
+ /* sample only on the exact position */
+ *r_index = view3d_sample_backbuf(vc, mval[0], mval[1]);
+
+ if ((*r_index) == 0 || (*r_index) > (unsigned int)totface) {
+ return 0;
+ }
+
+ (*r_index)--;
+
+ return 1;
+}
+
+
+static Image *imapaint_face_image(DerivedMesh *dm, int face_index)
+{
+ Image *ima;
+ MFace *mf = dm->getTessFaceArray(dm) + face_index;
+ Material *ma = dm->mat[mf->mat_nr];
+ ima = ma->texpaintslot[ma->paint_active_slot].ima;
+
+ return ima;
+}
+
/* Uses symm to selectively flip any axis of a coordinate. */
void flip_v3_v3(float out[3], const float in[3], const char symm)
{
@@ -223,25 +418,132 @@ void flip_v3_v3(float out[3], const float in[3], const char symm)
}
/* used for both 3d view and image window */
-void paint_sample_color(const bContext *C, ARegion *ar, int x, int y) /* frontbuf */
+void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_proj, bool use_palette)
{
+ Scene *scene = CTX_data_scene(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Palette *palette = BKE_paint_palette(paint);
+ PaletteColor *color;
Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
unsigned int col;
- const char *cp;
+ const unsigned char *cp;
CLAMP(x, 0, ar->winx);
CLAMP(y, 0, ar->winy);
- glReadBuffer(GL_FRONT);
- glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
- glReadBuffer(GL_BACK);
+ if (use_palette) {
+ if (!palette) {
+ palette = BKE_palette_add(CTX_data_main(C), "Palette");
+ BKE_paint_palette_set(paint, palette);
+ }
- cp = (char *)&col;
+ color = BKE_palette_color_add(palette);
+ }
+
+
+ if (CTX_wm_view3d(C) && texpaint_proj) {
+ /* first try getting a colour directly from the mesh faces if possible */
+ Object *ob = OBACT;
+ bool sample_success = false;
+ ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+ bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
+
+ if (ob) {
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+
+ ViewContext vc;
+ const int mval[2] = {x, y};
+ unsigned int faceindex;
+ unsigned int totface = dm->getNumTessFaces(dm);
+ MTFace *dm_mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
+
+ DM_update_materials(dm, ob);
+
+ if (dm_mtface) {
+ view3d_set_viewcontext(C, &vc);
+
+ view3d_operator_needs_opengl(C);
+
+ if (imapaint_pick_face(&vc, mval, &faceindex, totface)) {
+ Image *image;
+
+ if (use_material)
+ image = imapaint_face_image(dm, faceindex);
+ else
+ image = imapaint->canvas;
+
+ if (image) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
+ if (ibuf && ibuf->rect) {
+ float uv[2];
+ float u, v;
+ imapaint_pick_uv(scene, ob, faceindex, mval, uv);
+ sample_success = true;
+
+ u = fmodf(uv[0], 1.0f);
+ v = fmodf(uv[1], 1.0f);
+
+ if (u < 0.0f) u += 1.0f;
+ if (v < 0.0f) v += 1.0f;
+
+ u = u * ibuf->x - 0.5f;
+ v = v * ibuf->y - 0.5f;
+
+ if (ibuf->rect_float) {
+ float rgba_f[4];
+ bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
+ straight_to_premul_v4(rgba_f);
+ if (use_palette) {
+ linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
+ }
+ else {
+ linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
+ BKE_brush_color_set(scene, br, rgba_f);
+ }
+ }
+ else {
+ unsigned char rgba[4];
+ bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
+ if (use_palette) {
+ rgb_uchar_to_float(color->rgb, rgba);
+ }
+ else {
+ float rgba_f[3];
+ rgb_uchar_to_float(rgba_f, rgba);
+ BKE_brush_color_set(scene, br, rgba_f);
+ }
+ }
+ }
+
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
+ }
+ }
+ dm->release(dm);
+ }
+
+ if (!sample_success) {
+ glReadBuffer(GL_FRONT);
+ glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ glReadBuffer(GL_BACK);
+ }
+ else
+ return;
+ }
+ else {
+ glReadBuffer(GL_FRONT);
+ glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ glReadBuffer(GL_BACK);
+ }
+ cp = (unsigned char *)&col;
- if (br) {
- br->rgb[0] = cp[0] / 255.0f;
- br->rgb[1] = cp[1] / 255.0f;
- br->rgb[2] = cp[2] / 255.0f;
+ if (use_palette) {
+ rgb_uchar_to_float(color->rgb, cp);
+ }
+ else {
+ float rgba_f[3];
+ rgb_uchar_to_float(rgba_f, cp);
+ BKE_brush_color_set(scene, br, rgba_f);
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 969c5a09a82..509a7f31f5b 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -33,6 +33,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_bitmap.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -75,7 +76,6 @@
#include "paint_intern.h" /* own include */
-
/* check if we can do partial updates and have them draw realtime
* (without rebuilding the 'derivedFinal') */
static bool vertex_paint_use_fast_update_check(Object *ob)
@@ -197,11 +197,11 @@ static int *get_indexarray(Mesh *me)
return MEM_mallocN(sizeof(int) * (me->totpoly + 1), "vertexpaint");
}
-unsigned int vpaint_get_current_col(VPaint *vp)
+unsigned int vpaint_get_current_col(Scene *scene, VPaint *vp)
{
Brush *brush = BKE_paint_brush(&vp->paint);
unsigned char col[4];
- rgb_float_to_uchar(col, brush->rgb);
+ rgb_float_to_uchar(col, BKE_brush_color_get(scene, brush));
col[3] = 255; /* alpha isn't used, could even be removed to speedup paint a little */
return *(unsigned int *)col;
}
@@ -2547,14 +2547,17 @@ static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int retval;
- op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start,
+ op->customdata = paint_stroke_new(C, op, NULL, wpaint_stroke_test_start,
wpaint_stroke_update_step, NULL,
wpaint_stroke_done, event->type);
+ if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ paint_stroke_data_free(op);
+ return OPERATOR_FINISHED;
+ }
/* add modal handler */
WM_event_add_modal_handler(C, op);
- retval = op->type->modal(C, op, event);
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
@@ -2563,7 +2566,7 @@ static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int wpaint_exec(bContext *C, wmOperator *op)
{
- op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start,
+ op->customdata = paint_stroke_new(C, op, NULL, wpaint_stroke_test_start,
wpaint_stroke_update_step, NULL,
wpaint_stroke_done, 0);
@@ -2595,8 +2598,8 @@ void PAINT_OT_weight_paint(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+
+ paint_stroke_operator_properties(ot);
}
static int weight_paint_set_exec(bContext *C, wmOperator *op)
@@ -2778,7 +2781,8 @@ static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me)
static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float UNUSED(mouse[2]))
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
struct PaintStroke *stroke = op->customdata;
VPaint *vp = ts->vpaint;
Brush *brush = BKE_paint_brush(&vp->paint);
@@ -2810,7 +2814,7 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
vpd->vp_handle = ED_vpaint_proj_handle_create(vpd->vc.scene, ob, &vpd->vertexcosnos);
vpd->indexar = get_indexarray(me);
- vpd->paintcol = vpaint_get_current_col(vp);
+ vpd->paintcol = vpaint_get_current_col(scene, vp);
vpd->is_texbrush = !(brush->vertexpaint_tool == PAINT_BLEND_BLUR) &&
brush->mtex.tex;
@@ -3062,14 +3066,18 @@ static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int retval;
- op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start,
+ op->customdata = paint_stroke_new(C, op, NULL, vpaint_stroke_test_start,
vpaint_stroke_update_step, NULL,
vpaint_stroke_done, event->type);
+ if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ paint_stroke_data_free(op);
+ return OPERATOR_FINISHED;
+ }
+
/* add modal handler */
WM_event_add_modal_handler(C, op);
- retval = op->type->modal(C, op, event);
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
@@ -3078,7 +3086,7 @@ static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int vpaint_exec(bContext *C, wmOperator *op)
{
- op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start,
+ op->customdata = paint_stroke_new(C, op, NULL, vpaint_stroke_test_start,
vpaint_stroke_update_step, NULL,
vpaint_stroke_done, 0);
@@ -3110,7 +3118,7 @@ void PAINT_OT_vertex_paint(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
- RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+ paint_stroke_operator_properties(ot);
}
/* ********************** weight from bones operator ******************* */
@@ -3184,6 +3192,8 @@ typedef struct DMGradient_userData {
int def_nr;
short is_init;
DMGradient_vertStore *vert_cache;
+ /* only for init */
+ BLI_bitmap *vert_visit;
/* options */
short use_select;
@@ -3191,19 +3201,81 @@ typedef struct DMGradient_userData {
float weightpaint;
} DMGradient_userData;
-static void gradientVert__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+static void gradientVert_update(DMGradient_userData *grad_data, int index)
{
- DMGradient_userData *grad_data = userData;
Mesh *me = grad_data->me;
+ DMGradient_vertStore *vs = &grad_data->vert_cache[index];
+ float alpha;
+
+ if (grad_data->type == WPAINT_GRADIENT_TYPE_LINEAR) {
+ alpha = line_point_factor_v2(vs->sco, grad_data->sco_start, grad_data->sco_end);
+ }
+ else {
+ BLI_assert(grad_data->type == WPAINT_GRADIENT_TYPE_RADIAL);
+ alpha = len_v2v2(grad_data->sco_start, vs->sco) * grad_data->sco_line_div;
+ }
+ /* no need to clamp 'alpha' yet */
- if (grad_data->use_select == false || (me->mvert[index].flag & SELECT)) {
+ /* adjust weight */
+ alpha = BKE_brush_curve_strength_clamp(grad_data->brush, alpha, 1.0f);
+
+ if (alpha != 0.0f) {
+ MDeformVert *dv = &me->dvert[index];
+ MDeformWeight *dw = defvert_verify_index(dv, grad_data->def_nr);
+ // dw->weight = alpha; // testing
+ int tool = grad_data->brush->vertexpaint_tool;
+ float testw;
+
+ /* init if we just added */
+ testw = wpaint_blend_tool(tool, vs->weight_orig, grad_data->weightpaint, alpha * grad_data->brush->alpha);
+ CLAMP(testw, 0.0f, 1.0f);
+ dw->weight = testw;
+ }
+ else {
+ MDeformVert *dv = &me->dvert[index];
+ if (vs->flag & VGRAD_STORE_DW_EXIST) {
+ /* normally we NULL check, but in this case we know it exists */
+ MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
+ dw->weight = vs->weight_orig;
+ }
+ else {
+ /* wasn't originally existing, remove */
+ MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
+ if (dw) {
+ defvert_remove_group(dv, dw);
+ }
+ }
+ }
+}
+
+static void gradientVertUpdate__mapFunc(
+ void *userData, int index, const float UNUSED(co[3]),
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+ DMGradient_userData *grad_data = userData;
+ Mesh *me = grad_data->me;
+ if ((grad_data->use_select == false) || (me->mvert[index].flag & SELECT)) {
DMGradient_vertStore *vs = &grad_data->vert_cache[index];
+ if (vs->sco[0] != FLT_MAX) {
+ gradientVert_update(grad_data, index);
+ }
+ }
+}
- /* run first pass only, could be split into its own mapFunc
+static void gradientVertInit__mapFunc(
+ void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+ DMGradient_userData *grad_data = userData;
+ Mesh *me = grad_data->me;
+
+ if ((grad_data->use_select == false) || (me->mvert[index].flag & SELECT)) {
+ /* run first pass only,
* the screen coords of the verts need to be cached because
* updating the mesh may move them about (entering feedback loop) */
- if (grad_data->is_init) {
+
+ if (BLI_BITMAP_TEST(grad_data->vert_visit, index) == 0) {
+ DMGradient_vertStore *vs = &grad_data->vert_cache[index];
if (ED_view3d_project_float_object(grad_data->ar,
co, vs->sco,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
@@ -3220,55 +3292,14 @@ static void gradientVert__mapFunc(void *userData, int index, const float co[3],
vs->weight_orig = 0.0f;
vs->flag = VGRAD_STORE_NOP;
}
- }
- else {
- /* no go */
- copy_v2_fl(vs->sco, FLT_MAX);
- }
- }
- /* end init */
- if (vs->sco[0] != FLT_MAX) {
- float alpha;
+ BLI_BITMAP_ENABLE(grad_data->vert_visit, index);
- if (grad_data->type == WPAINT_GRADIENT_TYPE_LINEAR) {
- alpha = line_point_factor_v2(vs->sco, grad_data->sco_start, grad_data->sco_end);
+ gradientVert_update(grad_data, index);
}
else {
- BLI_assert(grad_data->type == WPAINT_GRADIENT_TYPE_RADIAL);
- alpha = len_v2v2(grad_data->sco_start, vs->sco) * grad_data->sco_line_div;
- }
- /* no need to clamp 'alpha' yet */
-
- /* adjust weight */
- alpha = BKE_brush_curve_strength_clamp(grad_data->brush, alpha, 1.0f);
-
- if (alpha != 0.0f) {
- MDeformVert *dv = &me->dvert[index];
- MDeformWeight *dw = defvert_verify_index(dv, grad_data->def_nr);
- // dw->weight = alpha; // testing
- int tool = grad_data->brush->vertexpaint_tool;
- float testw;
-
- /* init if we just added */
- testw = wpaint_blend_tool(tool, vs->weight_orig, grad_data->weightpaint, alpha * grad_data->brush->alpha);
- CLAMP(testw, 0.0f, 1.0f);
- dw->weight = testw;
- }
- else {
- MDeformVert *dv = &me->dvert[index];
- if (vs->flag & VGRAD_STORE_DW_EXIST) {
- /* normally we NULL check, but in this case we know it exists */
- MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
- dw->weight = vs->weight_orig;
- }
- else {
- /* wasn't originally existing, remove */
- MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
- if (dw) {
- defvert_remove_group(dv, dw);
- }
- }
+ /* no go */
+ copy_v2_fl(vs->sco, FLT_MAX);
}
}
}
@@ -3364,6 +3395,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
data.def_nr = ob->actdef - 1;
data.use_select = (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL));
data.vert_cache = vert_cache;
+ data.vert_visit = NULL;
data.type = RNA_enum_get(op->ptr, "type");
{
@@ -3379,7 +3411,17 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
ED_view3d_init_mats_rv3d(ob, ar->regiondata);
- dm->foreachMappedVert(dm, gradientVert__mapFunc, &data, DM_FOREACH_NOP);
+ if (data.is_init) {
+ data.vert_visit = BLI_BITMAP_NEW(me->totvert, __func__);
+
+ dm->foreachMappedVert(dm, gradientVertInit__mapFunc, &data, DM_FOREACH_NOP);
+
+ MEM_freeN(data.vert_visit);
+ data.vert_visit = NULL;
+ }
+ else {
+ dm->foreachMappedVert(dm, gradientVertUpdate__mapFunc, &data, DM_FOREACH_NOP);
+ }
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 12223effcf5..33d0510c08a 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -37,6 +37,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_dial.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_threads.h"
@@ -238,12 +239,8 @@ typedef struct StrokeCache {
float anchored_location[3];
float vertex_rotation; /* amount to rotate the vertices when using rotate brush */
- float previous_vertex_rotation; /* previous rotation, used to detect if we rotate more than
- * PI radians */
- short num_vertex_turns; /* records number of full 2*PI turns */
- float initial_mouse_dir[2]; /* used to calculate initial angle */
- bool init_dir_set; /* detect if we have initialized the initial mouse direction */
-
+ Dial *dial;
+
char saved_active_brush_name[MAX_ID_NAME];
char saved_mask_brush_tool;
int saved_smooth_size; /* smooth tool copies the size of the current tool */
@@ -359,19 +356,19 @@ static int sculpt_stroke_dynamic_topology(const SculptSession *ss,
!(brush->flag & BRUSH_ANCHORED) &&
!(brush->flag & BRUSH_DRAG_DOT) &&
- (!ELEM6(brush->sculpt_tool,
- /* These brushes, as currently coded, cannot
- * support dynamic topology */
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_LAYER,
+ (!ELEM(brush->sculpt_tool,
+ /* These brushes, as currently coded, cannot
+ * support dynamic topology */
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_LAYER,
- /* These brushes could handle dynamic topology,
- * but user feedback indicates it's better not
- * to */
- SCULPT_TOOL_SMOOTH,
- SCULPT_TOOL_MASK)));
+ /* These brushes could handle dynamic topology,
+ * but user feedback indicates it's better not
+ * to */
+ SCULPT_TOOL_SMOOTH,
+ SCULPT_TOOL_MASK)));
}
/*** paint mesh ***/
@@ -396,7 +393,7 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
* entries might be inserted by sculpt_undo_push_node() into the
* GHash used internally by BM_log_original_vert_co() by a
* different thread. [#33787] */
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP && !ss->bm)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && !ss->bm && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
SculptUndoNode *unode;
SculptUndoType type = (brush->sculpt_tool == SCULPT_TOOL_MASK ?
@@ -663,47 +660,6 @@ static bool sculpt_brush_test_cyl(SculptBrushTest *test, float co[3], float loca
/* ===== Sculpting =====
*
*/
-
-static float overlapped_curve(Brush *br, float x)
-{
- int i;
- const int n = 100 / br->spacing;
- const float h = br->spacing / 50.0f;
- const float x0 = x - 1;
-
- float sum;
-
- sum = 0;
- for (i = 0; i < n; i++) {
- float xx;
-
- xx = fabsf(x0 + i * h);
-
- if (xx < 1.0f)
- sum += BKE_brush_curve_strength(br, xx, 1);
- }
-
- return sum;
-}
-
-static float integrate_overlap(Brush *br)
-{
- int i;
- int m = 10;
- float g = 1.0f / m;
- float max;
-
- max = 0;
- for (i = 0; i < m; i++) {
- float overlap = overlapped_curve(br, i * g);
-
- if (overlap > max)
- max = overlap;
- }
-
- return max;
-}
-
static void flip_v3(float v[3], const char symm)
{
flip_v3_v3(v, v, symm);
@@ -776,7 +732,7 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
/* Return modified brush strength. Includes the direction of the brush, positive
* values pull vertices, negative values push. Uses tablet pressure and a
* special multiplier found experimentally to scale the strength factor. */
-static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather)
+static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather, UnifiedPaintSettings *ups)
{
const Scene *scene = cache->vc->scene;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -788,13 +744,10 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather)
float pressure = BKE_brush_use_alpha_pressure(scene, brush) ? cache->pressure : 1;
float pen_flip = cache->pen_flip ? -1 : 1;
float invert = cache->invert ? -1 : 1;
- float accum = integrate_overlap(brush);
+ float overlap = ups->overlap_factor;
/* spacing is integer percentage of radius, divide by 50 to get
* normalized diameter */
- float overlap = (brush->flag & BRUSH_SPACE_ATTEN &&
- brush->flag & BRUSH_SPACE &&
- !(brush->flag & BRUSH_ANCHORED) &&
- (brush->spacing < 100)) ? 1.0f / accum : 1;
+
float flip = dir * invert * pen_flip;
switch (brush->sculpt_tool) {
@@ -1040,7 +993,7 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
zero_v3(an);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1236,14 +1189,14 @@ static int brush_needs_sculpt_normal(const Brush *brush)
SCULPT_TOOL_SNAKE_HOOK) &&
(brush->normal_weight > 0)) ||
- ELEM7(brush->sculpt_tool,
- SCULPT_TOOL_BLOB,
- SCULPT_TOOL_CREASE,
- SCULPT_TOOL_DRAW,
- SCULPT_TOOL_LAYER,
- SCULPT_TOOL_NUDGE,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB) ||
+ ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_BLOB,
+ SCULPT_TOOL_CREASE,
+ SCULPT_TOOL_DRAW,
+ SCULPT_TOOL_LAYER,
+ SCULPT_TOOL_NUDGE,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB) ||
(brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA));
}
@@ -1646,7 +1599,7 @@ static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode,
for (iteration = 0; iteration <= count; ++iteration) {
float strength = (iteration != count) ? 1.0f : last;
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
switch (type) {
case PBVH_GRIDS:
@@ -1682,7 +1635,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
int n;
/* threaded loop over nodes */
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1735,7 +1688,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
mul_v3_fl(offset, bstrength);
/* threaded loop over nodes */
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1790,7 +1743,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
if (brush->sculpt_tool == SCULPT_TOOL_BLOB) flippedbstrength *= -1.0f;
/* threaded loop over nodes */
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1833,7 +1786,7 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
float bstrength = ss->cache->bstrength;
int n;
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1880,7 +1833,7 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
add_v3_v3(grab_delta, ss->cache->sculpt_normal_symm);
}
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1928,7 +1881,7 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
cross_v3_v3v3(tmp, ss->cache->sculpt_normal_symm, grab_delta);
cross_v3_v3v3(cono, tmp, ss->cache->sculpt_normal_symm);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1976,7 +1929,7 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
add_v3_v3(grab_delta, ss->cache->sculpt_normal_symm);
}
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2016,7 +1969,7 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
cross_v3_v3v3(tmp, ss->cache->sculpt_normal_symm, grab_delta);
cross_v3_v3v3(cono, tmp, ss->cache->sculpt_normal_symm);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2059,7 +2012,7 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
static const int flip[8] = { 1, -1, -1, 1, -1, 1, 1, -1 };
float angle = ss->cache->vertex_rotation * flip[ss->cache->mirror_symmetry_pass];
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2112,7 +2065,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
mul_v3_v3v3(offset, ss->cache->scale, ss->cache->sculpt_normal_symm);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2175,7 +2128,7 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
float bstrength = ss->cache->bstrength;
int n;
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2220,7 +2173,7 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
zero_v3(fc);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2327,7 +2280,7 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
/* for flatten center */
zero_v3(fc);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2579,7 +2532,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
mul_v3_fl(temp, displace);
add_v3_v3(fc, temp);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2651,7 +2604,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
/* add_v3_v3v3(p, ss->cache->location, an); */
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2752,7 +2705,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
mul_m4_m4m4(tmat, mat, scale);
invert_m4_m4(mat, tmat);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2816,7 +2769,7 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
mul_v3_fl(temp, displace);
add_v3_v3(fc, temp);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2880,7 +2833,7 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
mul_v3_fl(temp, displace);
add_v3_v3(fc, temp);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2934,7 +2887,7 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl
mul_v3_fl(offset, bstrength);
/* threaded loop over nodes */
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -3030,11 +2983,11 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
radius = ss->cache->radius * 1.25f;
data.radius_squared = radius * radius;
- data.original = ELEM4(brush->sculpt_tool,
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_LAYER) ? true : ss->cache->original;
+ data.original = ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_LAYER) ? true : ss->cache->original;
BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
@@ -3092,18 +3045,18 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
data.ss = ss;
data.sd = sd;
data.radius_squared = ss->cache->radius_squared;
- data.original = ELEM4(brush->sculpt_tool,
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_LAYER) ? true : ss->cache->original;
+ data.original = ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_LAYER) ? true : ss->cache->original;
BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
/* Only act if some verts are inside the brush area */
if (totnode) {
float location[3];
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
sculpt_undo_push_node(ob, nodes[n],
brush->sculpt_tool == SCULPT_TOOL_MASK ?
@@ -3233,10 +3186,10 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
ss->cache->supports_gravity)
{
/* these brushes start from original coordinates */
- const bool use_orco = ELEM3(brush->sculpt_tool, SCULPT_TOOL_GRAB,
- SCULPT_TOOL_ROTATE, SCULPT_TOOL_THUMB);
+ const bool use_orco = ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE, SCULPT_TOOL_THUMB);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
PBVHProxyNode *proxies;
@@ -3329,7 +3282,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob)
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
@@ -3377,7 +3330,7 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm,
/* XXX This reduces the length of the grab delta if it approaches the line of symmetry
* XXX However, a different approach appears to be needed */
#if 0
- if (sd->flags & SCULPT_SYMMETRY_FEATHER) {
+ if (sd->paint.symmetry_flags & SCULPT_SYMMETRY_FEATHER) {
float frac = 1.0f / max_overlap_count(sd);
float reduce = (feather - frac) / (1 - frac);
@@ -3437,7 +3390,7 @@ static void sculpt_fix_noise_tear(Sculpt *sd, Object *ob)
}
static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob,
- BrushActionFunc action)
+ BrushActionFunc action, UnifiedPaintSettings *ups)
{
Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
@@ -3447,7 +3400,7 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob,
float feather = calc_symmetry_feather(sd, ss->cache);
- cache->bstrength = brush_strength(sd, cache, feather);
+ cache->bstrength = brush_strength(sd, cache, feather, ups);
cache->symmetry = symm;
/* symm is a bit combination of XYZ - 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
@@ -3571,6 +3524,8 @@ static void sculpt_cache_free(StrokeCache *cache)
{
if (cache->face_norms)
MEM_freeN(cache->face_norms);
+ if (cache->dial)
+ MEM_freeN(cache->dial);
MEM_freeN(cache);
}
@@ -3733,8 +3688,8 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
/* not very nice, but with current events system implementation
* we can't handle brush appearance inversion hotkey separately (sergey) */
- if (cache->invert) brush->flag |= BRUSH_INVERTED;
- else brush->flag &= ~BRUSH_INVERTED;
+ if (cache->invert) ups->draw_inverted = true;
+ else ups->draw_inverted = false;
/* Alt-Smooth */
if (cache->alt_smooth) {
@@ -3780,7 +3735,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
mul_m3_v3(mat, viewDir);
normalize_v3_v3(cache->true_view_normal, viewDir);
- cache->supports_gravity = (!ELEM3(brush->sculpt_tool, SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SIMPLIFY) &&
+ cache->supports_gravity = (!ELEM(brush->sculpt_tool, SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SIMPLIFY) &&
(sd->gravity_factor > 0.0f));
/* get gravity vector in world space */
if (cache->supports_gravity) {
@@ -3838,10 +3793,10 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
cache->original = 1;
}
- if (ELEM9(brush->sculpt_tool,
- SCULPT_TOOL_DRAW, SCULPT_TOOL_CREASE, SCULPT_TOOL_BLOB,
- SCULPT_TOOL_LAYER, SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY,
- SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_ROTATE, SCULPT_TOOL_FLATTEN))
+ if (ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_DRAW, SCULPT_TOOL_CREASE, SCULPT_TOOL_BLOB,
+ SCULPT_TOOL_LAYER, SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY,
+ SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_ROTATE, SCULPT_TOOL_FLATTEN))
{
if (!(brush->flag & BRUSH_ACCUMULATE)) {
cache->original = 1;
@@ -3850,11 +3805,12 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
cache->first_time = 1;
- cache->vertex_rotation = 0;
- cache->num_vertex_turns = 0;
- cache->previous_vertex_rotation = 0;
- cache->init_dir_set = false;
-
+#define PIXEL_INPUT_THRESHHOLD 5
+ if (brush->sculpt_tool == SCULPT_TOOL_ROTATE)
+ cache->dial = BLI_dial_initialize(cache->initial_mouse, PIXEL_INPUT_THRESHHOLD);
+
+#undef PIXEL_INPUT_THRESHHOLD
+
sculpt_omp_start(sd, ss);
}
@@ -3868,10 +3824,10 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
};
int tool = brush->sculpt_tool;
- if (ELEM5(tool,
- SCULPT_TOOL_GRAB, SCULPT_TOOL_NUDGE,
- SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_SNAKE_HOOK,
- SCULPT_TOOL_THUMB))
+ if (ELEM(tool,
+ SCULPT_TOOL_GRAB, SCULPT_TOOL_NUDGE,
+ SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_SNAKE_HOOK,
+ SCULPT_TOOL_THUMB))
{
float grab_location[3], imat[4][4], delta[3], loc[3];
@@ -3992,16 +3948,9 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob,
cache->radius_squared = cache->radius * cache->radius;
if (brush->flag & BRUSH_ANCHORED) {
+ /* true location has been calculated as part of the stroke system already here */
if (brush->flag & BRUSH_EDGE_TO_EDGE) {
- float halfway[2];
- float out[3];
- halfway[0] = 0.5f * (cache->mouse[0] + cache->initial_mouse[0]);
- halfway[1] = 0.5f * (cache->mouse[1] + cache->initial_mouse[1]);
-
- if (sculpt_stroke_get_location(C, out, halfway)) {
- copy_v3_v3(cache->anchored_location, out);
- copy_v3_v3(cache->true_location, cache->anchored_location);
- }
+ RNA_float_get_array(ptr, "location", cache->true_location);
}
cache->radius = paint_calc_object_space_radius(cache->vc,
@@ -4015,48 +3964,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob,
sculpt_update_brush_delta(ups, ob, brush);
if (brush->sculpt_tool == SCULPT_TOOL_ROTATE) {
-#define PIXEL_INPUT_THRESHHOLD 5
-
- const float dx = cache->mouse[0] - cache->initial_mouse[0];
- const float dy = cache->mouse[1] - cache->initial_mouse[1];
-
- /* only update when we have enough precision, by having the mouse adequately away from center
- * may be better to convert to radial representation but square works for small values too*/
- if (fabsf(dx) > PIXEL_INPUT_THRESHHOLD && fabsf(dy) > PIXEL_INPUT_THRESHHOLD) {
- float mouse_angle;
- float dir[2] = {dx, dy};
- float cosval, sinval;
- normalize_v2(dir);
-
- if (!cache->init_dir_set) {
- copy_v2_v2(cache->initial_mouse_dir, dir);
- cache->init_dir_set = true;
- }
-
- /* calculate mouse angle between initial and final mouse position */
- cosval = dot_v2v2(dir, cache->initial_mouse_dir);
- sinval = cross_v2v2(dir, cache->initial_mouse_dir);
-
- /* clamp to avoid nans in acos */
- CLAMP(cosval, -1.0f, 1.0f);
- mouse_angle = (sinval > 0) ? acosf(cosval) : -acosf(cosval);
-
- /* change of sign, we passed the 180 degree threshold. This means we need to add a turn.
- * to distinguish between transition from 0 to -1 and -PI to +PI, use comparison with PI/2 */
- if ((mouse_angle * cache->previous_vertex_rotation < 0.0f) &&
- (fabsf(cache->previous_vertex_rotation) > (float)M_PI_2))
- {
- if (cache->previous_vertex_rotation < 0)
- cache->num_vertex_turns--;
- else
- cache->num_vertex_turns++;
- }
- cache->previous_vertex_rotation = mouse_angle;
-
- cache->vertex_rotation = -(mouse_angle + 2.0f * (float)M_PI * cache->num_vertex_turns) * cache->bstrength;
-
-#undef PIXEL_INPUT_THRESHHOLD
- }
+ cache->vertex_rotation = -BLI_dial_angle(cache->dial, cache->mouse) * cache->bstrength;
ups->draw_anchored = true;
copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse);
@@ -4393,10 +4301,10 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st
}
if (sculpt_stroke_dynamic_topology(ss, brush)) {
- do_symmetrical_brush_actions(sd, ob, sculpt_topology_update);
+ do_symmetrical_brush_actions(sd, ob, sculpt_topology_update, ups);
}
- do_symmetrical_brush_actions(sd, ob, do_brush_action);
+ do_symmetrical_brush_actions(sd, ob, do_brush_action, ups);
sculpt_combine_proxies(sd, ob);
@@ -4446,8 +4354,9 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
/* Finished */
if (ss->cache) {
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
Brush *brush = BKE_paint_brush(&sd->paint);
- brush->flag &= ~BRUSH_INVERTED;
+ ups->draw_inverted = false;
sculpt_stroke_modifiers_check(C, ob);
@@ -4506,7 +4415,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
if (!sculpt_brush_stroke_init(C, op))
return OPERATOR_CANCELLED;
- stroke = paint_stroke_new(C, sculpt_stroke_get_location,
+ stroke = paint_stroke_new(C, op, sculpt_stroke_get_location,
sculpt_stroke_test_start,
sculpt_stroke_update_step, NULL,
sculpt_stroke_done, event->type);
@@ -4521,10 +4430,13 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_PASS_THROUGH;
}
+ if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ paint_stroke_data_free(op);
+ return OPERATOR_FINISHED;
+ }
/* add modal handler */
WM_event_add_modal_handler(C, op);
- retval = op->type->modal(C, op, event);
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
@@ -4536,7 +4448,7 @@ static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
if (!sculpt_brush_stroke_init(C, op))
return OPERATOR_CANCELLED;
- op->customdata = paint_stroke_new(C, sculpt_stroke_get_location, sculpt_stroke_test_start,
+ op->customdata = paint_stroke_new(C, op, sculpt_stroke_get_location, sculpt_stroke_test_start,
sculpt_stroke_update_step, NULL, sculpt_stroke_done, 0);
/* frees op->customdata */
@@ -4567,13 +4479,6 @@ static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
static void SCULPT_OT_brush_stroke(wmOperatorType *ot)
{
- static EnumPropertyItem stroke_mode_items[] = {
- {BRUSH_STROKE_NORMAL, "NORMAL", 0, "Normal", "Apply brush normally"},
- {BRUSH_STROKE_INVERT, "INVERT", 0, "Invert", "Invert action of brush for duration of stroke"},
- {BRUSH_STROKE_SMOOTH, "SMOOTH", 0, "Smooth", "Switch brush to smooth mode for duration of stroke"},
- {0}
- };
-
/* identifiers */
ot->name = "Sculpt";
ot->idname = "SCULPT_OT_brush_stroke";
@@ -4591,15 +4496,11 @@ static void SCULPT_OT_brush_stroke(wmOperatorType *ot)
/* properties */
- RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
-
- RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL,
- "Sculpt Stroke Mode",
- "Action taken when a sculpt stroke is made");
+ paint_stroke_operator_properties(ot);
RNA_def_boolean(ot->srna, "ignore_background_click", 0,
"Ignore Background Click",
- "Clicks on the background do not start the stroke");
+ "Clicks on the background do not start the stroke");
}
/**** Reset the copy of the mesh that is being sculpted on (currently just for the layer brush) ****/
@@ -4856,7 +4757,7 @@ static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, co
bool modifiers = false;
for (i = 0; i < CD_NUMTYPES; i++) {
- if (!ELEM7(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX) &&
+ if (!ELEM(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX) &&
(CustomData_has_layer(&me->vdata, i) ||
CustomData_has_layer(&me->edata, i) ||
CustomData_has_layer(&me->fdata, i)))
@@ -5062,11 +4963,11 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
ts->sculpt->paint.flags |= PAINT_SHOW_BRUSH;
/* Make sure at least dyntopo subdivision is enabled */
- ts->sculpt->flags |= SCULPT_DYNTOPO_SUBDIVIDE;
+ ts->sculpt->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE;
}
if (!ts->sculpt->detail_size) {
- ts->sculpt->detail_size = 30;
+ ts->sculpt->detail_size = 12;
}
if (ts->sculpt->constant_detail == 0.0f)
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index cd79f525d82..a61f571fdf6 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -130,4 +130,11 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]);
void sculpt_update_object_bounding_box(struct Object *ob);
+/* Setting zero so we can catch bugs in OpenMP/sculpt. */
+#ifdef DEBUG
+# define SCULPT_OMP_LIMIT 0
+#else
+# define SCULPT_OMP_LIMIT 4
+#endif
+
#endif
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 0d49049c78e..91f80a4fc40 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -291,7 +291,7 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_redraw(nodes[i]);
}
@@ -543,7 +543,7 @@ static void sculpt_undo_free(ListBase *lb)
}
}
-bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
+static bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
{
Object *ob = CTX_data_active_object(C);
SculptUndoNode *unode;
@@ -551,10 +551,8 @@ bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
unode = lb->first;
if (unode && strcmp(unode->idname, ob->id.name) != 0) {
- for (unode = lb->first; unode; unode = unode->next) {
- if (unode->bm_entry)
- BM_log_cleanup_entry(unode->bm_entry);
- }
+ if (unode->bm_entry)
+ BM_log_cleanup_entry(unode->bm_entry);
return true;
}
@@ -881,7 +879,7 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
void sculpt_undo_push_begin(const char *name)
{
ED_undo_paint_push_begin(UNDO_PAINT_MESH, name,
- sculpt_undo_restore, sculpt_undo_free);
+ sculpt_undo_restore, sculpt_undo_free, sculpt_undo_cleanup);
}
void sculpt_undo_push_end(void)
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index 797a881ce79..292d6236bab 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -239,12 +239,14 @@ void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings
BKE_paint_init(&settings->uvsculpt->paint, PAINT_CURSOR_SCULPT);
- WM_paint_cursor_activate(wm, uv_sculpt_brush_poll,
- brush_drawcursor_uvsculpt, NULL);
+ settings->uvsculpt->paint.paint_cursor = WM_paint_cursor_activate(wm, uv_sculpt_brush_poll,
+ brush_drawcursor_uvsculpt, NULL);
}
else {
- if (settings->uvsculpt)
- settings->uvsculpt->paint.flags &= ~PAINT_SHOW_BRUSH;
+ if (settings->uvsculpt) {
+ WM_paint_cursor_end(wm, settings->uvsculpt->paint.paint_cursor);
+ settings->uvsculpt->paint.paint_cursor = NULL;
+ }
}
}
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index b2e55085579..335949e8495 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -219,7 +219,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
sel = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
- if (ELEM3(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
+ if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
switch (ale->type) {
case ANIMTYPE_SUMMARY:
{
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index cf18cffefb6..ddfca98a119 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -1086,8 +1086,9 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
View2D *v2d = &ac->ar->v2d;
bDopeSheet *ads = NULL;
int channel_index;
- short found = 0;
- float selx = 0.0f;
+ bool found = false;
+ float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */
+ float selx = 0.0f; /* frame of keyframe under mouse */
float x, y;
rctf rectf;
@@ -1179,7 +1180,8 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
* requiring to map each frame once again...
*/
selx = BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
- found = 1;
+ frame = ak->cfra;
+ found = true;
break;
}
else if (ak->cfra < rectf.xmin)
@@ -1258,8 +1260,11 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
if (found) {
/* apply selection to keyframes */
if (column) {
- /* select all keyframes in the same frame as the one we hit on the active channel */
- actkeys_mselect_column(ac, select_mode, selx);
+ /* select all keyframes in the same frame as the one we hit on the active channel
+ * [T41077]: "frame" not "selx" here (i.e. no NLA corrections yet) as the code here
+ * does that itself again as it needs to work on multiple datablocks
+ */
+ actkeys_mselect_column(ac, select_mode, frame);
}
else if (same_channel) {
/* select all keyframes in the active channel */
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 7a74a58c69d..c8431d58bf5 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -61,6 +61,7 @@
#include "ED_space_api.h"
#include "ED_sound.h"
#include "ED_uvedit.h"
+#include "ED_view3d.h"
#include "ED_mball.h"
#include "ED_logic.h"
#include "ED_clip.h"
@@ -130,8 +131,17 @@ void ED_spacetypes_init(void)
type->operatortypes();
}
- /* Macros's must go last since they reference other operators
- * maybe we'll need to have them go after python operators too? */
+ /* register internal render callbacks */
+ ED_render_internal_init();
+}
+
+void ED_spacemacros_init(void)
+{
+ const ListBase *spacetypes;
+ SpaceType *type;
+
+ /* Macros's must go last since they reference other operators.
+ * We need to have them go after python operators too */
ED_operatormacros_armature();
ED_operatormacros_mesh();
ED_operatormacros_metaball();
@@ -144,6 +154,7 @@ void ED_spacetypes_init(void)
ED_operatormacros_curve();
ED_operatormacros_mask();
ED_operatormacros_sequencer();
+ ED_operatormacros_paint();
/* register dropboxes (can use macros) */
spacetypes = BKE_spacetypes_list();
@@ -151,9 +162,6 @@ void ED_spacetypes_init(void)
if (type->dropboxes)
type->dropboxes();
}
-
- /* register internal render callbacks */
- ED_render_internal_init();
}
/* called in wm.c */
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 5fcceb25e4e..524a42ba388 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -55,6 +55,7 @@
#include "BKE_particle.h"
#include "BKE_screen.h"
#include "BKE_texture.h"
+#include "BKE_linestyle.h"
#include "RNA_access.h"
@@ -153,7 +154,7 @@ static int buttons_context_path_linestyle(ButsContextPath *path)
/* if we have a scene, use the lineset's linestyle */
else if (buttons_context_path_scene(path)) {
scene = path->ptr[path->len - 1].data;
- linestyle = CTX_data_linestyle_from_scene(scene);
+ linestyle = BKE_linestyle_active_from_scene(scene);
if (linestyle) {
RNA_id_pointer_create(&linestyle->id, &path->ptr[path->len]);
path->len++;
@@ -199,7 +200,7 @@ static int buttons_context_path_data(ButsContextPath *path, int type)
/* if we already have a data, we're done */
if (RNA_struct_is_a(ptr->type, &RNA_Mesh) && (type == -1 || type == OB_MESH)) return 1;
- else if (RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM3(type, OB_CURVE, OB_SURF, OB_FONT))) return 1;
+ else if (RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM(type, OB_CURVE, OB_SURF, OB_FONT))) return 1;
else if (RNA_struct_is_a(ptr->type, &RNA_Armature) && (type == -1 || type == OB_ARMATURE)) return 1;
else if (RNA_struct_is_a(ptr->type, &RNA_MetaBall) && (type == -1 || type == OB_MBALL)) return 1;
else if (RNA_struct_is_a(ptr->type, &RNA_Lattice) && (type == -1 || type == OB_LATTICE)) return 1;
@@ -229,7 +230,7 @@ static int buttons_context_path_modifier(ButsContextPath *path)
if (buttons_context_path_object(path)) {
ob = path->ptr[path->len - 1].data;
- if (ob && ELEM5(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE))
+ if (ob && ELEM(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE))
return 1;
}
@@ -637,7 +638,7 @@ static int buttons_shading_context(const bContext *C, int mainb)
{
Object *ob = CTX_data_active_object(C);
- if (ELEM3(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE))
+ if (ELEM(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE))
return 1;
if (mainb == BCONTEXT_DATA && ob && ELEM(ob->type, OB_LAMP, OB_CAMERA))
return 1;
@@ -1119,7 +1120,7 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);
if (name) {
- if (!ELEM3(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene)
+ if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene)
uiItemLDrag(row, ptr, "", icon); /* save some space */
else
uiItemLDrag(row, ptr, name, icon);
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 0aa3e47df4b..020d477fc39 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -53,8 +53,8 @@
#include "DNA_world_types.h"
#include "DNA_linestyle_types.h"
-
#include "BKE_context.h"
+#include "BKE_linestyle.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_node.h"
@@ -352,7 +352,7 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext *
ob = (scene->basact) ? scene->basact->object : NULL;
wrld = scene->world;
brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
- linestyle = CTX_data_linestyle_from_scene(scene);
+ linestyle = BKE_linestyle_active_from_scene(scene);
}
if (ob && ob->type == OB_LAMP && !la)
@@ -370,7 +370,7 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext *
if (wrld && !limited_mode)
buttons_texture_users_find_nodetree(users, &wrld->id, wrld->nodetree, "World");
if (linestyle && !limited_mode)
- buttons_texture_users_find_nodetree(users, &linestyle->id, linestyle->nodetree, "LineStyle");
+ buttons_texture_users_find_nodetree(users, &linestyle->id, linestyle->nodetree, "Line Style");
if (ob) {
ParticleSystem *psys = psys_get_current(ob);
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 1c3bad9757d..8c6bf67c9a8 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -358,7 +358,7 @@ static void buttons_area_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *
case NC_ANIMATION:
switch (wmn->data) {
case ND_KEYFRAME:
- if (ELEM3(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
+ if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
ED_area_tag_redraw(sa);
break;
}
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 9c31b909a95..cf7032cbe2d 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -1592,21 +1592,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
}
}
- if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
- MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);
-
- if (track) {
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
-
- offsx = marker->pos[0];
- offsy = marker->pos[1];
-
- gpd = track->gpd;
- }
-
- }
- else {
+ if (sc->gpencil_src != SC_GPENCIL_SRC_TRACK) {
gpd = clip->gpd;
}
@@ -1725,7 +1711,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
smat[1][1] = 1.0f / height;
invert_m4_m4(ismat, smat);
- mul_serie_m4(sc->unistabmat, smat, sc->stabmat, ismat, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(sc->unistabmat, smat, sc->stabmat, ismat);
}
}
else if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
@@ -1775,13 +1761,15 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d)
return;
if (onlyv2d) {
- /* if manual calibration is used then grease pencil data is already
- * drawn in draw_distortion */
- if ((sc->flag & SC_MANUAL_CALIBRATION) == 0) {
+ bool is_track_source = sc->gpencil_src == SC_GPENCIL_SRC_TRACK;
+ /* if manual calibration is used then grease pencil data
+ * associated with the clip is already drawn in draw_distortion
+ */
+ if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || is_track_source) {
glPushMatrix();
glMultMatrixf(sc->unistabmat);
- if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
+ if (is_track_source) {
MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);
if (track) {
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index 95f59e79c08..d1e2c770ade 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -104,7 +104,7 @@ typedef struct {
int coord; /* coordinate index of found entuty (0 = X-axis, 1 = Y-axis) */
bool has_prev; /* if there's valid coordinate of previous point of curve segment */
- float min_dist, /* minimal distance between mouse and currently found entuty */
+ float min_dist_sq, /* minimal distance between mouse and currently found entity */
mouse_co[2], /* mouse coordinate */
prev_co[2], /* coordinate of previeous point of segment */
min_co[2]; /* coordinate of entity with minimal distance */
@@ -121,11 +121,11 @@ static void find_nearest_tracking_segment_cb(void *userdata, MovieTrackingTrack
float co[2] = {scene_framenr, val};
if (data->has_prev) {
- float d = dist_to_line_segment_v2(data->mouse_co, data->prev_co, co);
+ float dist_sq = dist_squared_to_line_segment_v2(data->mouse_co, data->prev_co, co);
- if (data->track == NULL || d < data->min_dist) {
+ if (data->track == NULL || dist_sq < data->min_dist_sq) {
data->track = track;
- data->min_dist = d;
+ data->min_dist_sq = dist_sq;
data->coord = coord;
copy_v2_v2(data->min_co, co);
}
@@ -146,15 +146,15 @@ static void find_nearest_tracking_knot_cb(void *userdata, MovieTrackingTrack *tr
MovieTrackingMarker *marker, int coord, int scene_framenr, float val)
{
MouseSelectUserData *data = userdata;
- float dx = scene_framenr - data->mouse_co[0], dy = val - data->mouse_co[1];
- float d = dx * dx + dy * dy;
+ float mdiff[2] = {scene_framenr - data->mouse_co[0], val - data->mouse_co[1]};
+ float dist_sq = len_squared_v2(mdiff);
- if (data->marker == NULL || d < data->min_dist) {
+ if (data->marker == NULL || dist_sq < data->min_dist_sq) {
float co[2] = {scene_framenr, val};
data->track = track;
data->marker = marker;
- data->min_dist = d;
+ data->min_dist_sq = dist_sq;
data->coord = coord;
copy_v2_v2(data->min_co, co);
}
@@ -164,7 +164,7 @@ static void find_nearest_tracking_knot_cb(void *userdata, MovieTrackingTrack *tr
static void mouse_select_init_data(MouseSelectUserData *userdata, const float co[2])
{
memset(userdata, 0, sizeof(MouseSelectUserData));
- userdata->min_dist = FLT_MAX;
+ userdata->min_dist_sq = FLT_MAX;
copy_v2_v2(userdata->mouse_co, co);
}
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index c0434def3d5..87efaa615ee 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -591,6 +591,8 @@ static void view_zoom_cancel(bContext *C, wmOperator *op)
void CLIP_OT_view_zoom(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "View Zoom";
ot->idname = "CLIP_OT_view_zoom";
@@ -607,8 +609,9 @@ void CLIP_OT_view_zoom(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
/* properties */
- RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX,
- "Factor", "Zoom factor, values higher than 1.0 zoom in, lower values zoom out", -FLT_MAX, FLT_MAX);
+ prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor",
+ "Zoom factor, values higher than 1.0 zoom in, lower values zoom out", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/********************** view zoom in/out operator *********************/
@@ -641,6 +644,8 @@ static int view_zoom_in_invoke(bContext *C, wmOperator *op, const wmEvent *event
void CLIP_OT_view_zoom_in(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "View Zoom In";
ot->idname = "CLIP_OT_view_zoom_in";
@@ -652,8 +657,9 @@ void CLIP_OT_view_zoom_in(wmOperatorType *ot)
ot->poll = ED_space_clip_view_clip_poll;
/* properties */
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location",
- "Cursor location in screen coordinates", -10.0f, 10.0f);
+ prop = RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location",
+ "Cursor location in screen coordinates", -10.0f, 10.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
static int view_zoom_out_exec(bContext *C, wmOperator *op)
@@ -684,6 +690,8 @@ static int view_zoom_out_invoke(bContext *C, wmOperator *op, const wmEvent *even
void CLIP_OT_view_zoom_out(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "View Zoom Out";
ot->idname = "CLIP_OT_view_zoom_out";
@@ -695,8 +703,9 @@ void CLIP_OT_view_zoom_out(wmOperatorType *ot)
ot->poll = ED_space_clip_view_clip_poll;
/* properties */
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location",
- "Cursor location in normalized (0.0-1.0) coordinates", -10.0f, 10.0f);
+ prop = RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location",
+ "Cursor location in normalized (0.0-1.0) coordinates", -10.0f, 10.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/********************** view zoom ratio operator *********************/
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index d3be25050c8..a6fbb0c399d 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -846,7 +846,7 @@ static int clip_context(const bContext *C, const char *member, bContextDataResul
static int clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_PATH)
- if (ELEM4(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */
+ if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */
return true;
return false;
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index ce14471f608..abbffcd8546 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -2277,7 +2277,7 @@ static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingOb
copy_v3_v3(lmat[3], obmat[3]);
invert_m4_m4(ilmat, lmat);
- mul_serie_m4(mat, lmat, mat, ilmat, obmat, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, lmat, mat, ilmat, obmat);
}
else {
mul_m4_m4m4(mat, obmat, mat);
@@ -2996,7 +2996,7 @@ void CLIP_OT_detect_features(wmOperatorType *ot)
/* properties */
RNA_def_enum(ot->srna, "placement", placement_items, 0, "Placement", "Placement for detected features");
RNA_def_int(ot->srna, "margin", 16, 0, INT_MAX, "Margin", "Only features further than margin pixels from the image edges are considered", 0, 300);
- RNA_def_float(ot->srna, "threshold", 1.0f, 0.0001f, FLT_MAX, "Threshold", "Threshold level to consider feature good enough for tracking", 0.0001f, FLT_MAX);
+ RNA_def_float(ot->srna, "threshold", 0.5f, 0.0001f, FLT_MAX, "Threshold", "Threshold level to consider feature good enough for tracking", 0.0001f, FLT_MAX);
RNA_def_int(ot->srna, "min_distance", 120, 0, INT_MAX, "Distance", "Minimal distance accepted between two features", 0, 300);
}
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 29846246a9b..f6f11316a04 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -414,11 +414,12 @@ static void draw_background(FileLayout *layout, View2D *v2d)
int i;
int sy;
+ UI_ThemeColorShade(TH_BACK, -7);
+
/* alternating flat shade background */
for (i = 0; (i <= layout->rows); i += 2) {
sy = (int)v2d->cur.ymax - i * (layout->tile_h + 2 * layout->tile_border_y) - layout->tile_border_y;
- UI_ThemeColorShade(TH_BACK, -7);
glRectf(v2d->cur.xmin, (float)sy, v2d->cur.xmax, (float)(sy + layout->tile_h + 2 * layout->tile_border_y));
}
@@ -426,18 +427,36 @@ static void draw_background(FileLayout *layout, View2D *v2d)
static void draw_dividers(FileLayout *layout, View2D *v2d)
{
+ const int step = (layout->tile_w + 2 * layout->tile_border_x);
+ int v1[2], v2[2];
int sx;
+ unsigned char col_hi[3], col_lo[3];
+
+ UI_GetThemeColorShade3ubv(TH_BACK, 30, col_hi);
+ UI_GetThemeColorShade3ubv(TH_BACK, -30, col_lo);
+
+ v1[1] = v2d->cur.ymax - layout->tile_border_y;
+ v2[1] = v2d->cur.ymin;
+
+ glBegin(GL_LINES);
/* vertical column dividers */
sx = (int)v2d->tot.xmin;
while (sx < v2d->cur.xmax) {
- sx += (layout->tile_w + 2 * layout->tile_border_x);
-
- UI_ThemeColorShade(TH_BACK, 30);
- sdrawline(sx + 1, (short)(v2d->cur.ymax - layout->tile_border_y), sx + 1, (short)v2d->cur.ymin);
- UI_ThemeColorShade(TH_BACK, -30);
- sdrawline(sx, (short)(v2d->cur.ymax - layout->tile_border_y), sx, (short)v2d->cur.ymin);
+ sx += step;
+
+ glColor3ubv(col_lo);
+ v1[0] = v2[0] = sx;
+ glVertex2iv(v1);
+ glVertex2iv(v2);
+
+ glColor3ubv(col_hi);
+ v1[0] = v2[0] = sx + 1;
+ glVertex2iv(v1);
+ glVertex2iv(v2);
}
+
+ glEnd();
}
void file_draw_list(const bContext *C, ARegion *ar)
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 1d3013bd8b4..27d6fabba4e 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -1277,8 +1277,9 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
const char *lastdir = folderlist_peeklastdir(sfile->folders_prev);
/* if not, ask to create it and enter if confirmed */
+ wmOperatorType *ot = WM_operatortype_find("FILE_OT_directory_new", false);
PointerRNA ptr;
- WM_operator_properties_create(&ptr, "FILE_OT_directory_new");
+ WM_operator_properties_create_ptr(&ptr, ot);
RNA_string_set(&ptr, "directory", sfile->params->dir);
RNA_boolean_set(&ptr, "open", true);
@@ -1286,7 +1287,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
- WM_operator_name_call(C, "FILE_OT_directory_new", WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
WM_operator_properties_free(&ptr);
}
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index 69789569912..8fad17e1210 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -57,12 +57,13 @@
static void file_panel_cb(bContext *C, void *arg_entry, void *UNUSED(arg_v))
{
+ wmOperatorType *ot = WM_operatortype_find("FILE_OT_select_bookmark", false);
PointerRNA ptr;
const char *entry = (char *)arg_entry;
- WM_operator_properties_create(&ptr, "FILE_OT_select_bookmark");
+ WM_operator_properties_create_ptr(&ptr, ot);
RNA_string_set(&ptr, "dir", entry);
- WM_operator_name_call(C, "FILE_OT_select_bookmark", WM_OP_INVOKE_REGION_WIN, &ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_REGION_WIN, &ptr);
WM_operator_properties_free(&ptr);
}
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 81ab276ccc0..afe3f29e9bc 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -281,14 +281,28 @@ int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *ar)
{
int numfiles;
+ /* Values in pixels.
+ *
+ * - *_item: size of each (row|col), (including padding)
+ * - *_view: (x|y) size of the view.
+ * - *_over: extra pixels, to take into account, when the fit isnt exact
+ * (needed since you may see the end of the previous column and the beginning of the next).
+ *
+ * Could be more clever and take scrolling into account,
+ * but for now don't bother.
+ */
if (layout->flag & FILE_LAYOUT_HOR) {
- int width = (int)(BLI_rctf_size_x(&ar->v2d.cur) - 2 * layout->tile_border_x);
- numfiles = (int)((float)width / (float)layout->tile_w + 0.5f);
+ const int x_item = layout->tile_w + (2 * layout->tile_border_x);
+ const int x_view = (int)(BLI_rctf_size_x(&ar->v2d.cur));
+ const int x_over = x_item - (x_view % x_item);
+ numfiles = (int)((float)(x_view + x_over) / (float)(x_item));
return numfiles * layout->rows;
}
else {
- int height = (int)(BLI_rctf_size_y(&ar->v2d.cur) - 2 * layout->tile_border_y);
- numfiles = (int)((float)height / (float)layout->tile_h + 0.5f);
+ const int y_item = layout->tile_h + (2 * layout->tile_border_y);
+ const int y_view = (int)(BLI_rctf_size_y(&ar->v2d.cur));
+ const int y_over = y_item - (y_view % y_item);
+ numfiles = (int)((float)(y_view + y_over) / (float)(y_item));
return numfiles * layout->columns;
}
}
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 3a493c0338c..d5be04cff20 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -422,7 +422,7 @@ static void file_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, 0, 0);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
- kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_ALT, 0);
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "fill", true);
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index d1738f3dada..b59030d3c12 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -560,7 +560,7 @@ static void graph_panel_driverVar__rotDiff(uiLayout *layout, ID *id, DriverVar *
uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiTemplateAnyID(col, &dtar_ptr, "id", "id_type", IFACE_("Bone 1:"));
- if (dtar->id && ob1->pose) {
+ if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) {
PointerRNA tar_ptr;
RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr);
@@ -571,7 +571,7 @@ static void graph_panel_driverVar__rotDiff(uiLayout *layout, ID *id, DriverVar *
uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiTemplateAnyID(col, &dtar2_ptr, "id", "id_type", IFACE_("Bone 2:"));
- if (dtar2->id && ob2->pose) {
+ if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) {
PointerRNA tar_ptr;
RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr);
@@ -598,7 +598,7 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiTemplateAnyID(col, &dtar_ptr, "id", "id_type", IFACE_("Ob/Bone 1:"));
- if (dtar->id && ob1->pose) {
+ if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) {
PointerRNA tar_ptr;
RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr);
@@ -612,7 +612,7 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiTemplateAnyID(col, &dtar2_ptr, "id", "id_type", IFACE_("Ob/Bone 2:"));
- if (dtar2->id && ob2->pose) {
+ if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) {
PointerRNA tar_ptr;
RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr);
@@ -639,7 +639,7 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar
uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiTemplateAnyID(col, &dtar_ptr, "id", "id_type", IFACE_("Ob/Bone:"));
- if (dtar->id && ob->pose) {
+ if (dtar->id && GS(dtar->id->name) == ID_OB && ob->pose) {
PointerRNA tar_ptr;
RNA_pointer_create(dtar->id, &RNA_Pose, ob->pose, &tar_ptr);
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 1f1aac8c456..c8298927f7d 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -1707,7 +1707,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
*/
if (strstr(fcu->rna_path, "rotation_euler") == NULL)
continue;
- else if (ELEM3(fcu->array_index, 0, 1, 2) == 0) {
+ else if (ELEM(fcu->array_index, 0, 1, 2) == 0) {
BKE_reportf(op->reports, RPT_WARNING,
"Euler Rotation F-Curve has invalid index (ID='%s', Path='%s', Index=%d)",
(ale->id) ? ale->id->name : TIP_("<No ID>"), fcu->rna_path, fcu->array_index);
@@ -1750,7 +1750,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
/* sanity check: ensure that there are enough F-Curves to work on in this group */
/* TODO: also enforce assumption that there be a full set of keyframes at each position by ensuring that totvert counts are same? */
- if (ELEM3(NULL, euf->fcurves[0], euf->fcurves[1], euf->fcurves[2])) {
+ if (ELEM(NULL, euf->fcurves[0], euf->fcurves[1], euf->fcurves[2])) {
/* report which components are missing */
BKE_reportf(op->reports, RPT_WARNING,
"Missing %s%s%s component(s) of euler rotation for ID='%s' and RNA-Path='%s'",
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index fbfa9358a22..62b6b59df29 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -167,6 +167,7 @@ static int graphview_cursor_modal(bContext *C, wmOperator *op, const wmEvent *ev
case LEFTMOUSE:
case RIGHTMOUSE:
+ case MIDDLEMOUSE:
/* we check for either mouse-button to end, as checking for ACTIONMOUSE (which is used to init
* the modal op) doesn't work for some reason
*/
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 3675282654f..7e90008d8d2 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -843,14 +843,14 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
uiItemR(sub, imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE);
/* only display depth setting if multiple depths can be used */
- if ((ELEM7(depth_ok,
- R_IMF_CHAN_DEPTH_1,
- R_IMF_CHAN_DEPTH_8,
- R_IMF_CHAN_DEPTH_10,
- R_IMF_CHAN_DEPTH_12,
- R_IMF_CHAN_DEPTH_16,
- R_IMF_CHAN_DEPTH_24,
- R_IMF_CHAN_DEPTH_32)) == 0)
+ if ((ELEM(depth_ok,
+ R_IMF_CHAN_DEPTH_1,
+ R_IMF_CHAN_DEPTH_8,
+ R_IMF_CHAN_DEPTH_10,
+ R_IMF_CHAN_DEPTH_12,
+ R_IMF_CHAN_DEPTH_16,
+ R_IMF_CHAN_DEPTH_24,
+ R_IMF_CHAN_DEPTH_32)) == 0)
{
row = uiLayoutRow(col, false);
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index a2f7d9e7d6c..24b1c54dd9f 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -28,6 +28,7 @@
* \ingroup spimage
*/
+#include "DNA_brush_types.h"
#include "DNA_mask_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -297,44 +298,51 @@ bool ED_space_image_show_render(SpaceImage *sima)
bool ED_space_image_show_paint(SpaceImage *sima)
{
if (ED_space_image_show_render(sima))
- return 0;
+ return false;
return (sima->mode == SI_MODE_PAINT);
}
+bool ED_space_image_show_texpaint(SpaceImage *sima, Object *ob)
+{
+ return (ob && ob->type == OB_MESH &&
+ ob->mode == OB_MODE_TEXTURE_PAINT &&
+ !(sima->flag & SI_NO_DRAW_TEXPAINT));
+}
+
bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
{
if (sima && (ED_space_image_show_render(sima) || ED_space_image_show_paint(sima)))
- return 0;
+ return false;
if (obedit && obedit->type == OB_MESH) {
struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
- int ret;
+ bool ret;
ret = EDBM_mtexpoly_check(em);
return ret;
}
- return 0;
+ return false;
}
bool ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit)
{
if (ED_space_image_show_render(sima))
- return 0;
+ return false;
if (ED_space_image_show_paint(sima))
if (obedit && obedit->type == OB_MESH) {
struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
- int ret;
+ bool ret;
ret = EDBM_mtexpoly_check(em);
- return ret;
+ return ret && !(sima->flag & SI_NO_DRAW_TEXPAINT);
}
- return 0;
+ return false;
}
/* matches clip function */
@@ -361,6 +369,21 @@ int ED_space_image_maskedit_poll(bContext *C)
return false;
}
+bool ED_space_image_paint_curve(const bContext *C)
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+
+ if (sima && sima->mode == SI_MODE_PAINT) {
+ Brush *br = CTX_data_tool_settings(C)->imapaint.paint.brush;
+
+ if (br && (br->flag & BRUSH_CURVE))
+ return true;
+ }
+
+ return false;
+}
+
+
int ED_space_image_maskedit_mask_poll(bContext *C)
{
if (ED_space_image_maskedit_poll(C)) {
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index 8e556378803..74a0a18b0c8 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -71,6 +71,7 @@ void IMAGE_OT_view_ndof(struct wmOperatorType *ot);
void IMAGE_OT_new(struct wmOperatorType *ot);
void IMAGE_OT_open(struct wmOperatorType *ot);
+void IMAGE_OT_unlink(struct wmOperatorType *ot);
void IMAGE_OT_match_movie_length(struct wmOperatorType *ot);
void IMAGE_OT_replace(struct wmOperatorType *ot);
void IMAGE_OT_reload(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 7c021cf6645..c87e547b6ea 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -48,6 +48,7 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_global.h"
@@ -564,6 +565,8 @@ static void image_view_zoom_cancel(bContext *C, wmOperator *op)
void IMAGE_OT_view_zoom(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "View Zoom";
ot->idname = "IMAGE_OT_view_zoom";
@@ -580,8 +583,9 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_LOCK_BYPASS;
/* properties */
- RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX,
- "Factor", "Zoom factor, values higher than 1.0 zoom in, lower values zoom out", -FLT_MAX, FLT_MAX);
+ prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor",
+ "Zoom factor, values higher than 1.0 zoom in, lower values zoom out", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/********************** NDOF operator *********************/
@@ -799,6 +803,8 @@ static int image_view_zoom_in_invoke(bContext *C, wmOperator *op, const wmEvent
void IMAGE_OT_view_zoom_in(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "View Zoom In";
ot->idname = "IMAGE_OT_view_zoom_in";
@@ -813,7 +819,9 @@ void IMAGE_OT_view_zoom_in(wmOperatorType *ot)
ot->flag = OPTYPE_LOCK_BYPASS;
/* properties */
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in screen coordinates", -10.0f, 10.0f);
+ prop = RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
+ "Location", "Cursor location in screen coordinates", -10.0f, 10.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
static int image_view_zoom_out_exec(bContext *C, wmOperator *op)
@@ -844,6 +852,8 @@ static int image_view_zoom_out_invoke(bContext *C, wmOperator *op, const wmEvent
void IMAGE_OT_view_zoom_out(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "View Zoom Out";
ot->idname = "IMAGE_OT_view_zoom_out";
@@ -858,7 +868,9 @@ void IMAGE_OT_view_zoom_out(wmOperatorType *ot)
ot->flag = OPTYPE_LOCK_BYPASS;
/* properties */
- RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in screen coordinates", -10.0f, 10.0f);
+ prop = RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
+ "Location", "Cursor location in screen coordinates", -10.0f, 10.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/********************** view zoom ratio operator *********************/
@@ -1382,7 +1394,7 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
/* sanitize all settings */
/* unlikely but just in case */
- if (ELEM3(simopts->im_format.planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB, R_IMF_PLANES_RGBA) == 0) {
+ if (ELEM(simopts->im_format.planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB, R_IMF_PLANES_RGBA) == 0) {
simopts->im_format.planes = R_IMF_PLANES_RGBA;
}
@@ -1484,9 +1496,12 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
}
else {
/* TODO, better solution, if a 24bit image is painted onto it may contain alpha */
- if (ibuf->userflags & IB_BITMAPDIRTY) { /* it has been painted onto */
+ if ((simopts->im_format.planes == R_IMF_PLANES_RGBA) &&
+ /* it has been painted onto */
+ (ibuf->userflags & IB_BITMAPDIRTY))
+ {
/* checks each pixel, not ideal */
- ibuf->planes = BKE_imbuf_alpha_test(ibuf) ? 32 : 24;
+ ibuf->planes = BKE_imbuf_alpha_test(ibuf) ? R_IMF_PLANES_RGBA : R_IMF_PLANES_RGB;
}
}
@@ -1866,6 +1881,7 @@ static int image_reload_exec(bContext *C, wmOperator *UNUSED(op))
// XXX other users?
BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_RELOAD);
+ DAG_id_tag_update(&ima->id, 0);
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
@@ -1921,7 +1937,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
gen_type = RNA_enum_get(op->ptr, "generated_type");
RNA_float_get_array(op->ptr, "color", color);
alpha = RNA_boolean_get(op->ptr, "alpha");
-
+
if (!alpha)
color[3] = 1.0f;
@@ -2001,6 +2017,9 @@ void IMAGE_OT_new(wmOperatorType *ot)
RNA_def_enum(ot->srna, "generated_type", image_generated_type_items, IMA_GENTYPE_BLANK,
"Generated Type", "Fill the image with a grid for UV map testing");
RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
+ prop = RNA_def_boolean(ot->srna, "texstencil", 0, "Stencil", "Set Image as stencil");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
}
#undef IMA_DEF_NAME
@@ -2035,7 +2054,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
if (support_undo) {
ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free);
+ ED_image_undo_restore, ED_image_undo_free, NULL);
/* not strictly needed, because we only imapaint_dirty_region to invalidate all tiles
* but better do this right in case someone copies this for a tool that uses partial redraw better */
ED_imapaint_clear_partial_redraw();
@@ -2459,11 +2478,12 @@ static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event
int point = RNA_enum_get(op->ptr, "point");
if (point == 1) {
- curvemapping_set_black_white(curve_mapping, NULL, info->colfp);
+ curvemapping_set_black_white(curve_mapping, NULL, info->linearcol);
}
else if (point == 0) {
- curvemapping_set_black_white(curve_mapping, info->colfp, NULL);
+ curvemapping_set_black_white(curve_mapping, info->linearcol, NULL);
}
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
}
}
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 0fb93ad27ee..375a0ddeac3 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -349,7 +349,7 @@ static void image_keymap(struct wmKeyConfig *keyconf)
static int image_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_PATH)
- if (ELEM3(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */
+ if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */
return 1;
return 0;
}
@@ -633,6 +633,12 @@ static void image_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
/* image paint polls for mode */
+ keymap = WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+
+ keymap = WM_keymap_find(wm->defaultconf, "Paint Curve", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
keymap = WM_keymap_find(wm->defaultconf, "Image Paint", 0, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -657,6 +663,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
Object *obact = CTX_data_active_object(C);
Object *obedit = CTX_data_edit_object(C);
Mask *mask = NULL;
+ bool curve = false;
Scene *scene = CTX_data_scene(C);
View2D *v2d = &ar->v2d;
//View2DScrollers *scrollers;
@@ -702,6 +709,9 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
else if (sima->mode == SI_MODE_MASK) {
mask = ED_space_image_get_mask(sima);
}
+ else if (ED_space_image_paint_curve(C)) {
+ curve = true;
+ }
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
@@ -753,6 +763,11 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
draw_image_cursor(ar, sima->cursor);
UI_view2d_view_restore(C);
}
+ else if (curve) {
+ UI_view2d_view_ortho(v2d);
+ draw_image_cursor(ar, sima->cursor);
+ UI_view2d_view_restore(C);
+ }
draw_image_cache(C, ar);
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 8664ebf30b7..a0dfb285a1c 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -57,6 +57,7 @@
#include "ED_armature.h"
#define MAX_INFO_LEN 512
+#define MAX_INFO_NUM_LEN 16
typedef struct SceneStats {
int totvert, totvertsel;
@@ -65,11 +66,22 @@ typedef struct SceneStats {
int totbone, totbonesel;
int totobj, totobjsel;
int totlamp, totlampsel;
- int tottri, totmesh;
+ int tottri;
char infostr[MAX_INFO_LEN];
} SceneStats;
+typedef struct SceneStatsFmt {
+ /* Totals */
+ char totvert[MAX_INFO_NUM_LEN], totvertsel[MAX_INFO_NUM_LEN];
+ char totface[MAX_INFO_NUM_LEN], totfacesel[MAX_INFO_NUM_LEN];
+ char totedge[MAX_INFO_NUM_LEN], totedgesel[MAX_INFO_NUM_LEN];
+ char totbone[MAX_INFO_NUM_LEN], totbonesel[MAX_INFO_NUM_LEN];
+ char totobj[MAX_INFO_NUM_LEN], totobjsel[MAX_INFO_NUM_LEN];
+ char totlamp[MAX_INFO_NUM_LEN], totlampsel[MAX_INFO_NUM_LEN];
+ char tottri[MAX_INFO_NUM_LEN];
+} SceneStatsFmt;
+
static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
{
switch (ob->type) {
@@ -79,8 +91,6 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
DerivedMesh *dm = ob->derivedFinal;
int totvert, totedge, totface, totloop;
- stats->totmesh += totob;
-
if (dm) {
totvert = dm->getNumVerts(dm);
totedge = dm->getNumEdges(dm);
@@ -367,6 +377,7 @@ static void stats_string(Scene *scene)
{
#define MAX_INFO_MEM_LEN 64
SceneStats *stats = scene->stats;
+ SceneStatsFmt stats_fmt;
Object *ob = (scene->basact) ? scene->basact->object : NULL;
uintptr_t mem_in_use, mmap_in_use;
char memstr[MAX_INFO_MEM_LEN];
@@ -376,6 +387,34 @@ static void stats_string(Scene *scene)
mem_in_use = MEM_get_memory_in_use();
mmap_in_use = MEM_get_mapped_memory_in_use();
+
+ /* Generate formatted numbers */
+#define SCENE_STATS_FMT_INT(_id) \
+ BLI_str_format_int_grouped(stats_fmt._id, stats->_id)
+
+ SCENE_STATS_FMT_INT(totvert);
+ SCENE_STATS_FMT_INT(totvertsel);
+
+ SCENE_STATS_FMT_INT(totedge);
+ SCENE_STATS_FMT_INT(totedgesel);
+
+ SCENE_STATS_FMT_INT(totface);
+ SCENE_STATS_FMT_INT(totfacesel);
+
+ SCENE_STATS_FMT_INT(totbone);
+ SCENE_STATS_FMT_INT(totbonesel);
+
+ SCENE_STATS_FMT_INT(totobj);
+ SCENE_STATS_FMT_INT(totobjsel);
+
+ SCENE_STATS_FMT_INT(totlamp);
+ SCENE_STATS_FMT_INT(totlampsel);
+
+ SCENE_STATS_FMT_INT(tottri);
+
+#undef SCENE_STATS_FMT_INT
+
+
/* get memory statistics */
s = memstr;
ofs += BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" | Mem:%.2fM"),
@@ -394,32 +433,36 @@ static void stats_string(Scene *scene)
if (scene->obedit->type == OB_MESH) {
ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
- IFACE_("Verts:%d/%d | Edges:%d/%d | Faces:%d/%d | Tris:%d"),
- stats->totvertsel, stats->totvert, stats->totedgesel, stats->totedge,
- stats->totfacesel, stats->totface, stats->tottri);
+ IFACE_("Verts:%s/%s | Edges:%s/%s | Faces:%s/%s | Tris:%s"),
+ stats_fmt.totvertsel, stats_fmt.totvert, stats_fmt.totedgesel, stats_fmt.totedge,
+ stats_fmt.totfacesel, stats_fmt.totface, stats_fmt.tottri);
}
else if (scene->obedit->type == OB_ARMATURE) {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%d/%d | Bones:%d/%d"), stats->totvertsel,
- stats->totvert, stats->totbonesel, stats->totbone);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s/%s | Bones:%s/%s"), stats_fmt.totvertsel,
+ stats_fmt.totvert, stats_fmt.totbonesel, stats_fmt.totbone);
}
else {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%d/%d"), stats->totvertsel, stats->totvert);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s/%s"), stats_fmt.totvertsel,
+ stats_fmt.totvert);
}
ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs);
}
else if (ob && (ob->mode & OB_MODE_POSE)) {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%d/%d %s"),
- stats->totbonesel, stats->totbone, memstr);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%s/%s %s"),
+ stats_fmt.totbonesel, stats_fmt.totbone, memstr);
}
else if (stats_is_object_dynamic_topology_sculpt(ob)) {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%d | Tris:%d"), stats->totvert, stats->tottri);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s"), stats_fmt.totvert,
+ stats_fmt.tottri);
}
else {
ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
- IFACE_("Verts:%d | Faces:%d | Tris:%d | Objects:%d/%d | Lamps:%d/%d%s"), stats->totvert,
- stats->totface, stats->tottri, stats->totobjsel, stats->totobj, stats->totlampsel,
- stats->totlamp, memstr);
+ IFACE_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s | Lamps:%s/%s%s"),
+ stats_fmt.totvert, stats_fmt.totface,
+ stats_fmt.tottri, stats_fmt.totobjsel,
+ stats_fmt.totobj, stats_fmt.totlampsel,
+ stats_fmt.totlamp, memstr);
}
if (ob)
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index 40ab4dcecca..4cbfce0f6e9 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -289,7 +289,7 @@ int textview_draw(TextViewContext *tvc, const int draw, int mval[2], void **mous
cdc.lheight = tvc->lheight;
cdc.lofs = -BLF_descender(mono);
/* note, scroll bar must be already subtracted () */
- cdc.console_width = (tvc->winx - (CONSOLE_DRAW_MARGIN * 2) ) / cdc.cwidth;
+ cdc.console_width = (tvc->winx - (CONSOLE_DRAW_MARGIN * 2)) / cdc.cwidth;
/* avoid divide by zero on small windows */
if (cdc.console_width < 1)
cdc.console_width = 1;
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index b52d6265800..dd152022762 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -1144,15 +1144,30 @@ static void draw_sensor_message(uiLayout *layout, PointerRNA *ptr)
uiItemR(layout, ptr, "subject", 0, NULL, ICON_NONE);
}
-static void draw_sensor_mouse(uiLayout *layout, PointerRNA *ptr)
+static void draw_sensor_mouse(uiLayout *layout, PointerRNA *ptr, bContext *C)
{
- uiLayout *split;
+ uiLayout *split, *split2;
+ PointerRNA main_ptr;
split = uiLayoutSplit(layout, 0.8f, false);
uiItemR(split, ptr, "mouse_event", 0, NULL, ICON_NONE);
- if (RNA_enum_get(ptr, "mouse_event") == BL_SENS_MOUSE_MOUSEOVER_ANY)
+ if (RNA_enum_get(ptr, "mouse_event") == BL_SENS_MOUSE_MOUSEOVER_ANY) {
uiItemR(split, ptr, "use_pulse", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
+
+ split = uiLayoutSplit(layout, 0.3f, false);
+ uiItemR(split, ptr, "use_material", 0, "", ICON_NONE);
+
+ split2 = uiLayoutSplit(split, 0.7f, false);
+ if (RNA_enum_get(ptr, "use_material") == SENS_RAY_PROPERTY) {
+ uiItemR(split2, ptr, "property", 0, "", ICON_NONE);
+ }
+ else {
+ RNA_main_pointer_create(CTX_data_main(C), &main_ptr);
+ uiItemPointerR(split2, ptr, "material", &main_ptr, "materials", "", ICON_MATERIAL_DATA);
+ }
+ uiItemR(split2, ptr, "use_x_ray", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
+ }
}
static void draw_sensor_near(uiLayout *layout, PointerRNA *ptr)
@@ -1273,7 +1288,7 @@ static void draw_brick_sensor(uiLayout *layout, PointerRNA *ptr, bContext *C)
draw_sensor_message(box, ptr);
break;
case SENS_MOUSE:
- draw_sensor_mouse(box, ptr);
+ draw_sensor_mouse(box, ptr, C);
break;
case SENS_NEAR:
draw_sensor_near(box, ptr);
@@ -1720,6 +1735,12 @@ static void draw_actuator_edit_object(uiLayout *layout, PointerRNA *ptr)
sub = uiLayoutSplit(split, 0.7f, false);
uiItemR(sub, ptr, "time", 0, NULL, ICON_NONE);
uiItemR(sub, ptr, "use_3d_tracking", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
+
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, ptr, "up_axis", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, ptr, "track_axis", 0, NULL, ICON_NONE);
break;
case ACT_EDOB_DYNAMICS:
if (ob->type != OB_MESH) {
@@ -1811,7 +1832,7 @@ static void draw_actuator_motion(uiLayout *layout, PointerRNA *ptr)
uiItemR(row, ptr, "offset_rotation", 0, NULL, ICON_NONE);
uiItemR(split, ptr, "use_local_rotation", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
- if (ELEM3(physics_type, OB_BODY_TYPE_DYNAMIC, OB_BODY_TYPE_RIGID, OB_BODY_TYPE_SOFT)) {
+ if (ELEM(physics_type, OB_BODY_TYPE_DYNAMIC, OB_BODY_TYPE_RIGID, OB_BODY_TYPE_SOFT)) {
uiItemL(layout, IFACE_("Dynamic Object Settings:"), ICON_NONE);
split = uiLayoutSplit(layout, 0.9, false);
row = uiLayoutRow(split, false);
@@ -1933,6 +1954,7 @@ static void draw_actuator_property(uiLayout *layout, PointerRNA *ptr)
switch (RNA_enum_get(ptr, "mode")) {
case ACT_PROP_TOGGLE:
+ case ACT_PROP_LEVEL:
break;
case ACT_PROP_ADD:
uiItemR(layout, ptr, "value", 0, NULL, ICON_NONE);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 73f95870329..86f9bc5d768 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -885,6 +885,11 @@ static void node_shader_buts_uvmap(uiLayout *layout, bContext *C, PointerRNA *pt
}
}
+static void node_shader_buts_uvalongstroke(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "use_tips", 0, NULL, 0);
+}
+
static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
uiItemR(layout, ptr, "space", 0, "", 0);
@@ -937,30 +942,23 @@ static void node_shader_buts_anisotropic(uiLayout *layout, bContext *UNUSED(C),
static void node_shader_buts_subsurface(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- /* SSS does not work on GPU yet */
+ /* SSS only enabled in Experimental Kernel */
PointerRNA scene = CTX_data_pointer_get(C, "scene");
if (scene.data) {
PointerRNA cscene = RNA_pointer_get(&scene, "cycles");
- if (cscene.data && (RNA_enum_get(&cscene, "device") == 1 && U.compute_device_type != 0))
- uiItemL(layout, IFACE_("SSS not supported on GPU"), ICON_ERROR);
+ if (cscene.data &&
+ ((U.compute_device_type != USER_COMPUTE_DEVICE_NONE) &&
+ (RNA_enum_get(&cscene, "device") == 1) &&
+ (RNA_enum_get(&cscene, "feature_set") == 0)))
+ {
+ uiItemL(layout, IFACE_("Only enabled in experimental GPU kernel"), ICON_ERROR);
+ }
}
uiItemR(layout, ptr, "falloff", 0, "", ICON_NONE);
}
-static void node_shader_buts_volume(uiLayout *layout, bContext *C, PointerRNA *UNUSED(ptr))
-{
- /* Volume does not work on GPU yet */
- PointerRNA scene = CTX_data_pointer_get(C, "scene");
- if (scene.data) {
- PointerRNA cscene = RNA_pointer_get(&scene, "cycles");
-
- if (cscene.data && (RNA_enum_get(&cscene, "device") == 1 && U.compute_device_type != 0))
- uiItemL(layout, IFACE_("Volumes not supported on GPU"), ICON_ERROR);
- }
-}
-
static void node_shader_buts_toon(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "component", 0, "", ICON_NONE);
@@ -1000,6 +998,16 @@ static void node_shader_buts_script_ex(uiLayout *layout, bContext *C, PointerRNA
#endif
}
+static void node_buts_output_linestyle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiLayout *row, *col;
+
+ col = uiLayoutColumn(layout, false);
+ row = uiLayoutRow(col, true);
+ uiItemR(row, ptr, "blend_type", 0, "", ICON_NONE);
+ uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE);
+}
+
/* only once called */
static void node_shader_set_butfunc(bNodeType *ntype)
{
@@ -1107,12 +1115,6 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_SUBSURFACE_SCATTERING:
ntype->draw_buttons = node_shader_buts_subsurface;
break;
- case SH_NODE_VOLUME_SCATTER:
- ntype->draw_buttons = node_shader_buts_volume;
- break;
- case SH_NODE_VOLUME_ABSORPTION:
- ntype->draw_buttons = node_shader_buts_volume;
- break;
case SH_NODE_BSDF_TOON:
ntype->draw_buttons = node_shader_buts_toon;
break;
@@ -1126,6 +1128,12 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_UVMAP:
ntype->draw_buttons = node_shader_buts_uvmap;
break;
+ case SH_NODE_UVALONGSTROKE:
+ ntype->draw_buttons = node_shader_buts_uvalongstroke;
+ break;
+ case SH_NODE_OUTPUT_LINESTYLE:
+ ntype->draw_buttons = node_buts_output_linestyle;
+ break;
}
}
@@ -2307,6 +2315,12 @@ static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout), bContext *UNU
{
}
+static void node_composit_buts_sunbeams(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "source", UI_ITEM_R_EXPAND, "", ICON_NONE);
+ uiItemR(layout, ptr, "ray_length", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+}
+
/* only once called */
static void node_composit_set_butfunc(bNodeType *ntype)
{
@@ -2531,6 +2545,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_CORNERPIN:
ntype->draw_buttons = node_composit_buts_cornerpin;
break;
+ case CMP_NODE_SUNBEAMS:
+ ntype->draw_buttons = node_composit_buts_sunbeams;
+ break;
}
}
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 2dea441c03d..52c1cefbfed 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -138,6 +138,10 @@ void ED_node_tag_update_id(ID *id)
DAG_id_tag_update(id, 0);
WM_main_add_notifier(NC_TEXTURE | ND_NODES, id);
}
+ else if (id == &ntree->id) {
+ /* node groups */
+ DAG_id_tag_update(id, 0);
+ }
}
void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree)
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 1c41ce9d86d..ca13d87d632 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -640,11 +640,11 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
/* tree specific activate calls */
if (ntree->type == NTREE_SHADER) {
/* when we select a material, active texture is cleared, for buttons */
- if (node->id && ELEM3(GS(node->id->name), ID_MA, ID_LA, ID_WO))
+ if (node->id && ELEM(GS(node->id->name), ID_MA, ID_LA, ID_WO))
nodeClearActiveID(ntree, ID_TE);
- if (ELEM4(node->type, SH_NODE_OUTPUT, SH_NODE_OUTPUT_MATERIAL,
- SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LAMP))
+ if (ELEM(node->type, SH_NODE_OUTPUT, SH_NODE_OUTPUT_MATERIAL,
+ SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LAMP, SH_NODE_OUTPUT_LINESTYLE))
{
bNode *tnode;
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 39aba921f72..96cc7fb4407 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -200,7 +200,7 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
* - ngroup (i.e. the source NodeTree) is left unscathed
* - temp copy. don't change ID usercount
*/
- wgroup = ntreeCopyTree_ex(ngroup, false);
+ wgroup = ntreeCopyTree_ex(ngroup, G.main, false);
/* Add the nodes into the ntree */
for (node = wgroup->nodes.first; node; node = nextnode) {
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index ddfbe3bebf2..9eaee60bfce 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -501,6 +501,12 @@ static void node_area_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn)
}
}
break;
+
+ case NC_LINESTYLE:
+ if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_LINESTYLE) {
+ ED_area_tag_refresh(sa);
+ }
+ break;
}
}
@@ -740,6 +746,7 @@ static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegi
case NC_TEXTURE:
case NC_WORLD:
case NC_NODE:
+ case NC_LINESTYLE:
ED_region_tag_redraw(ar);
break;
case NC_OBJECT:
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 5d6f4b9896c..0db7a90e313 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -638,7 +638,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
layflag++; /* is lay_xor */
- if (ELEM8(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT,
+ if (ELEM(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT,
SCE_PASS_INDIRECT, SCE_PASS_EMIT, SCE_PASS_ENVIRONMENT))
{
bt = uiDefIconButBitI(block, TOG, passflag, 0, (*layflag & passflag) ? ICON_DOT : ICON_BLANK1,
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 17e1e032bbf..ef621407abd 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -215,15 +215,15 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, ReportList *reports)
{
/* can't rename rna datablocks entries or listbases */
- if (ELEM4(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE)) {
+ if (ELEM(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE)) {
/* do nothing */;
}
- else if (ELEM10(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE,
- TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_R_PASS))
+ else if (ELEM(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE,
+ TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_R_PASS))
{
BKE_report(reports, RPT_WARNING, "Cannot edit builtin name");
}
- else if (ELEM3(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
+ else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
BKE_report(reports, RPT_WARNING, "Cannot edit sequence name");
}
else if (tselem->id->lib) {
@@ -1654,7 +1654,7 @@ static int outliner_parenting_poll(bContext *C)
SpaceOops *soops = CTX_wm_space_outliner(C);
if (soops) {
- return ELEM4(soops->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_GROUPS);
+ return ELEM(soops->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_GROUPS);
}
return false;
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index d7521edd57a..6f5bf712d55 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -948,7 +948,7 @@ static bool do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, Sp
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
- else if (ELEM5(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
+ else if (ELEM(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
}
else { // rest of types
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index d1e9b3d34b7..d09ed1a100e 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -1339,7 +1339,7 @@ static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, S
else if (datalevel == TSE_DRIVER_BASE) {
/* do nothing... no special ops needed yet */
}
- else if (ELEM3(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS)) {
+ else if (ELEM(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS)) {
/*WM_operator_name_call(C, "OUTLINER_OT_renderdata_operation", WM_OP_INVOKE_REGION_WIN, NULL)*/
}
else {
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 520cd9a544d..5801dd126e3 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -821,7 +821,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
TreeStoreElem *tselem;
ID *id = idv;
- if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
id = ((PointerRNA *)idv)->id.data;
if (!id) id = ((PointerRNA *)idv)->data;
}
@@ -847,10 +847,10 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
te->parent = parent;
te->index = index; // for data arays
- if (ELEM3(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
+ if (ELEM(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
/* pass */
}
- else if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
/* pass */
}
else if (type == TSE_ANIM_DATA) {
@@ -985,7 +985,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
te->directdata = seq;
te->name = seq->strip->stripdata->name;
}
- else if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
PointerRNA pptr, propptr, *ptr = (PointerRNA *)idv;
PropertyRNA *prop, *iterprop;
PropertyType proptype;
@@ -1062,7 +1062,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (tot)
te->flag |= TE_LAZY_CLOSED;
}
- else if (ELEM3(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
+ else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
tot = RNA_property_array_length(ptr, prop);
if (TSELEM_OPEN(tselem, soops)) {
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 41c5b00b381..504d9628d98 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -143,7 +143,7 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- if (!ELEM4(soops->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_GROUPS)) {
+ if (!ELEM(soops->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_GROUPS)) {
return false;
}
@@ -156,7 +156,7 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
switch (te->idcode) {
case ID_SCE:
- return (ELEM3(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS));
+ return (ELEM(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS));
case ID_OB:
return (ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE));
/* Other codes to ignore? */
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 0ab14a15b58..0dff2242b28 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -142,19 +142,21 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[
case SEQ_TYPE_GLOW:
case SEQ_TYPE_MULTICAM:
case SEQ_TYPE_ADJUSTMENT:
+ case SEQ_TYPE_GAUSSIAN_BLUR:
UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
/* slightly offset hue to distinguish different effects */
- if (seq->type == SEQ_TYPE_ADD) rgb_byte_set_hue_float_offset(col, 0.04);
- else if (seq->type == SEQ_TYPE_SUB) rgb_byte_set_hue_float_offset(col, 0.08);
- else if (seq->type == SEQ_TYPE_MUL) rgb_byte_set_hue_float_offset(col, 0.12);
- else if (seq->type == SEQ_TYPE_ALPHAOVER) rgb_byte_set_hue_float_offset(col, 0.16);
- else if (seq->type == SEQ_TYPE_ALPHAUNDER) rgb_byte_set_hue_float_offset(col, 0.20);
- else if (seq->type == SEQ_TYPE_OVERDROP) rgb_byte_set_hue_float_offset(col, 0.24);
- else if (seq->type == SEQ_TYPE_GLOW) rgb_byte_set_hue_float_offset(col, 0.28);
- else if (seq->type == SEQ_TYPE_TRANSFORM) rgb_byte_set_hue_float_offset(col, 0.36);
- else if (seq->type == SEQ_TYPE_MULTICAM) rgb_byte_set_hue_float_offset(col, 0.32);
- else if (seq->type == SEQ_TYPE_ADJUSTMENT) rgb_byte_set_hue_float_offset(col, 0.40);
+ if (seq->type == SEQ_TYPE_ADD) rgb_byte_set_hue_float_offset(col, 0.04);
+ else if (seq->type == SEQ_TYPE_SUB) rgb_byte_set_hue_float_offset(col, 0.08);
+ else if (seq->type == SEQ_TYPE_MUL) rgb_byte_set_hue_float_offset(col, 0.12);
+ else if (seq->type == SEQ_TYPE_ALPHAOVER) rgb_byte_set_hue_float_offset(col, 0.16);
+ else if (seq->type == SEQ_TYPE_ALPHAUNDER) rgb_byte_set_hue_float_offset(col, 0.20);
+ else if (seq->type == SEQ_TYPE_OVERDROP) rgb_byte_set_hue_float_offset(col, 0.24);
+ else if (seq->type == SEQ_TYPE_GLOW) rgb_byte_set_hue_float_offset(col, 0.28);
+ else if (seq->type == SEQ_TYPE_TRANSFORM) rgb_byte_set_hue_float_offset(col, 0.36);
+ else if (seq->type == SEQ_TYPE_MULTICAM) rgb_byte_set_hue_float_offset(col, 0.32);
+ else if (seq->type == SEQ_TYPE_ADJUSTMENT) rgb_byte_set_hue_float_offset(col, 0.40);
+ else if (seq->type == SEQ_TYPE_GAUSSIAN_BLUR) rgb_byte_set_hue_float_offset(col, 0.42);
break;
case SEQ_TYPE_COLOR:
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 3c17b2986ff..9c43d22ae2f 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -86,6 +86,7 @@ EnumPropertyItem sequencer_prop_effect_types[] = {
{SEQ_TYPE_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
{SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
+ {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1918,9 +1919,12 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
strip_new = seq_new->strip;
strip_new->us = 1;
- /* new stripdata */
- se_new = strip_new->stripdata;
+ /* new stripdata (only one element now!) */
+ /* Note this assume all elements (images) have the same dimension, since we only copy the name here. */
+ se_new = MEM_reallocN(strip_new->stripdata, sizeof(*se_new));
BLI_strncpy(se_new->name, se->name, sizeof(se_new->name));
+ strip_new->stripdata = se_new;
+
BKE_sequence_calc(scene, seq_new);
if (step > 1) {
@@ -2055,8 +2059,8 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
Sequence *seq, *seqm, *next, *last_seq = BKE_sequencer_active_get(scene);
int channel_max = 1;
- if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
- BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
+ if (BKE_sequence_base_isolated_sel_check(ed->seqbasep, false) == false) {
+ BKE_report(op->reports, RPT_ERROR, "Please select more than one or all related strips");
return OPERATOR_CANCELLED;
}
@@ -2763,7 +2767,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
BKE_sequencer_free_clipboard();
- if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
+ if (BKE_sequence_base_isolated_sel_check(ed->seqbasep, true) == false) {
BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 60fc300da1f..df266b0f546 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -165,6 +165,13 @@ enum {
SEQ_UNSELECTED
};
+enum {
+ SEQ_SELECT_LR_NONE = 0,
+ SEQ_SELECT_LR_MOUSE,
+ SEQ_SELECT_LR_LEFT,
+ SEQ_SELECT_LR_RIGHT
+};
+
/* defines used internally */
#define SCE_MARKERS 0 // XXX - dummy
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index e69a02aa3df..c5e47c3aa3e 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -237,12 +237,12 @@ void sequencer_keymap(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
RNA_boolean_set(kmi->ptr, "linked_handle", false);
- RNA_boolean_set(kmi->ptr, "left_right", false);
+ RNA_enum_set(kmi->ptr, "left_right", SEQ_SELECT_LR_NONE);
RNA_boolean_set(kmi->ptr, "linked_time", false);
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "linked_handle", false);
- RNA_boolean_set(kmi->ptr, "left_right", false);
+ RNA_enum_set(kmi->ptr, "left_right", SEQ_SELECT_LR_NONE);
RNA_boolean_set(kmi->ptr, "linked_time", false);
@@ -275,27 +275,27 @@ void sequencer_keymap(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
RNA_boolean_set(kmi->ptr, "linked_handle", true);
- RNA_boolean_set(kmi->ptr, "left_right", false);
+ RNA_enum_set(kmi->ptr, "left_right", SEQ_SELECT_LR_NONE);
RNA_boolean_set(kmi->ptr, "linked_time", false);
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "linked_handle", true);
- RNA_boolean_set(kmi->ptr, "left_right", false);
+ RNA_enum_set(kmi->ptr, "left_right", SEQ_SELECT_LR_NONE);
RNA_boolean_set(kmi->ptr, "linked_time", false);
/* match action editor */
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
RNA_boolean_set(kmi->ptr, "linked_handle", false);
- RNA_boolean_set(kmi->ptr, "left_right", true); /* grr, these conflict - only use left_right if not over an active seq */
+ RNA_enum_set(kmi->ptr, "left_right", SEQ_SELECT_LR_MOUSE); /* grr, these conflict - only use left_right if not over an active seq */
RNA_boolean_set(kmi->ptr, "linked_time", true);
/* adjusted since 2.4 */
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "linked_handle", false);
- RNA_boolean_set(kmi->ptr, "left_right", false);
+ RNA_enum_set(kmi->ptr, "left_right", SEQ_SELECT_LR_NONE);
RNA_boolean_set(kmi->ptr, "linked_time", true);
WM_keymap_add_item(keymap, "SEQUENCER_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 9826ef10902..83a0de62329 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -314,7 +314,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
const bool extend = RNA_boolean_get(op->ptr, "extend");
const bool linked_handle = RNA_boolean_get(op->ptr, "linked_handle");
const bool linked_time = RNA_boolean_get(op->ptr, "linked_time");
- bool left_right = RNA_boolean_get(op->ptr, "left_right");
+ int left_right = RNA_enum_get(op->ptr, "left_right");
Sequence *seq, *neighbor, *act_orig;
int hand, sel_side;
@@ -328,8 +328,8 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
seq = find_nearest_seq(scene, v2d, &hand, event->mval);
// XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip
- if (seq && linked_time && left_right)
- left_right = false;
+ if (seq && linked_time && (left_right == SEQ_SELECT_LR_MOUSE))
+ left_right = SEQ_SELECT_LR_NONE;
if (marker) {
@@ -348,12 +348,24 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
}
- else if (left_right) {
+ else if (left_right != SEQ_SELECT_LR_NONE) {
/* use different logic for this */
float x;
ED_sequencer_deselect_all(scene);
- x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
-
+
+ switch (left_right) {
+ case SEQ_SELECT_LR_MOUSE:
+ x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
+ break;
+
+ case SEQ_SELECT_LR_LEFT:
+ x = CFRA - 1;
+ break;
+ case SEQ_SELECT_LR_RIGHT:
+ x = CFRA + 1;
+ break;
+ }
+
SEQP_BEGIN (ed, seq)
{
if (x < CFRA) {
@@ -522,6 +534,14 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
void SEQUENCER_OT_select(wmOperatorType *ot)
{
+ static EnumPropertyItem sequencer_select_left_right_types[] = {
+ {SEQ_SELECT_LR_NONE, "NONE", 0, "None", "Don't do left-right selection"},
+ {SEQ_SELECT_LR_MOUSE, "MOUSE", 0, "Mouse", "Use mouse position for selction"},
+ {SEQ_SELECT_LR_LEFT, "LEFT", 0, "Left", "Select left"},
+ {SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Select Right"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
/* identifiers */
ot->name = "Activate/Select";
ot->idname = "SEQUENCER_OT_select";
@@ -538,7 +558,7 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
RNA_def_boolean(ot->srna, "linked_handle", 0, "Linked Handle", "Select handles next to the active strip");
/* for animation this is an enum but atm having an enum isn't useful for us */
- RNA_def_boolean(ot->srna, "left_right", 0, "Left/Right", "Select based on the current frame side the cursor is on");
+ RNA_def_enum(ot->srna, "left_right", sequencer_select_left_right_types, 0, "Left/Right", "Select based on the current frame side the cursor is on");
RNA_def_boolean(ot->srna, "linked_time", 0, "Linked Time", "Select other strips at the same time");
}
@@ -912,7 +932,7 @@ static EnumPropertyItem sequencer_prop_select_grouped_types[] = {
#define SEQ_IS_EFFECT(_seq) ((_seq->type & SEQ_TYPE_EFFECT) != 0)
-#define SEQ_USE_DATA(_seq) (ELEM3(_seq->type, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) || SEQ_HAS_PATH(_seq))
+#define SEQ_USE_DATA(_seq) (ELEM(_seq->type, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) || SEQ_HAS_PATH(_seq))
static bool select_grouped_type(Editing *ed, Sequence *actseq)
{
@@ -1035,7 +1055,7 @@ static bool select_grouped_effect(Editing *ed, Sequence *actseq)
SEQP_BEGIN (ed, seq)
{
- if (ELEM3(actseq, seq->seq1, seq->seq2, seq->seq3)) {
+ if (ELEM(actseq, seq->seq1, seq->seq2, seq->seq3)) {
effects[seq->type] = true;
}
}
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index a94b73802b2..c0cfaed7867 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -279,24 +279,40 @@ static void sequencer_refresh(const bContext *C, ScrArea *sa)
}
break;
case SEQ_VIEW_SEQUENCE_PREVIEW:
- if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) {
- ar_main->flag &= ~RGN_FLAG_HIDDEN;
- ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = true;
- }
- if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) {
- ar_preview->flag &= ~RGN_FLAG_HIDDEN;
- ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
- ar_preview->v2d.cur = ar_preview->v2d.tot;
- view_changed = true;
- }
- if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
- ar_main->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- if (ar_preview && ar_preview->alignment != RGN_ALIGN_TOP) {
- ar_preview->alignment = RGN_ALIGN_TOP;
- view_changed = true;
+ if (ar_main && ar_preview) {
+ /* Get available height (without DPI correction). */
+ const float height = (sa->winy - ED_area_headersize()) / UI_DPI_FAC;
+
+ /* We reuse hidden area's size, allows to find same layout as before if we just switch
+ * between one 'full window' view and the combined one. This gets lost if we switch to both
+ * 'full window' views before, though... Better than nothing. */
+ if (ar_main->flag & RGN_FLAG_HIDDEN) {
+ ar_main->flag &= ~RGN_FLAG_HIDDEN;
+ ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
+ ar_preview->sizey = (int)(height - ar_main->sizey);
+ view_changed = true;
+ }
+ if (ar_preview->flag & RGN_FLAG_HIDDEN) {
+ ar_preview->flag &= ~RGN_FLAG_HIDDEN;
+ ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
+ ar_preview->v2d.cur = ar_preview->v2d.tot;
+ ar_main->sizey = (int)(height - ar_preview->sizey);
+ view_changed = true;
+ }
+ if (ar_main->alignment != RGN_ALIGN_NONE) {
+ ar_main->alignment = RGN_ALIGN_NONE;
+ view_changed = true;
+ }
+ if (ar_preview->alignment != RGN_ALIGN_TOP) {
+ ar_preview->alignment = RGN_ALIGN_TOP;
+ view_changed = true;
+ }
+ /* Final check that both preview and main height are reasonable! */
+ if (ar_preview->sizey < 10 || ar_main->sizey < 10 || ar_preview->sizey + ar_main->sizey > height) {
+ ar_preview->sizey = (int)(height * 0.4f + 0.5f);
+ ar_main->sizey = (int)(height - ar_preview->sizey);
+ view_changed = true;
+ }
}
break;
}
@@ -339,40 +355,6 @@ static void sequencer_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn
}
}
-/* *********************** sequencer (main) region ************************ */
-/* add handlers, stuff you only do once or on area/region changes */
-static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar)
-{
- wmKeyMap *keymap;
- ListBase *lb;
-
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
-
-// keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0);
-// WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
-
- keymap = WM_keymap_find(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
-
- /* own keymap */
- keymap = WM_keymap_find(wm->defaultconf, "Sequencer", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
-
- /* add drop boxes */
- lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
-
- WM_event_add_dropbox_handler(&ar->handlers, lb);
-
-}
-
-static void sequencer_main_area_draw(const bContext *C, ARegion *ar)
-{
-// ScrArea *sa = CTX_wm_area(C);
-
- /* NLE - strip editing timeline interface */
- draw_timeline_seq(C, ar);
-}
-
/* ************* dropboxes ************* */
static int image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
@@ -396,7 +378,7 @@ static int movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
int hand;
if (drag->type == WM_DRAG_PATH)
- if (ELEM3(drag->icon, 0, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */
+ if (ELEM(drag->icon, 0, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */
if (find_nearest_seq(scene, &ar->v2d, &hand, event->mval) == NULL)
return 1;
return 0;
@@ -439,7 +421,7 @@ static void sequencer_drop_copy(wmDrag *drag, wmDropBox *drop)
static void sequencer_dropboxes(void)
{
ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
-
+
WM_dropbox_add(lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy);
WM_dropbox_add(lb, "SEQUENCER_OT_movie_strip_add", movie_drop_poll, sequencer_drop_copy);
WM_dropbox_add(lb, "SEQUENCER_OT_sound_strip_add", sound_drop_poll, sequencer_drop_copy);
@@ -469,16 +451,37 @@ static int sequencer_context(const bContext *C, const char *member, bContextData
return false;
}
-
+/* *********************** sequencer (main) region ************************ */
/* add handlers, stuff you only do once or on area/region changes */
-static void sequencer_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar)
{
- ED_region_header_init(ar);
+ wmKeyMap *keymap;
+ ListBase *lb;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+
+#if 0
+ keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+#endif
+
+ keymap = WM_keymap_find(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+
+ /* own keymap */
+ keymap = WM_keymap_find(wm->defaultconf, "Sequencer", SPACE_SEQ, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+
+ /* add drop boxes */
+ lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
+
+ WM_event_add_dropbox_handler(&ar->handlers, lb);
}
-static void sequencer_header_area_draw(const bContext *C, ARegion *ar)
+static void sequencer_main_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ /* NLE - strip editing timeline interface */
+ draw_timeline_seq(C, ar);
}
static void sequencer_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
@@ -512,15 +515,29 @@ static void sequencer_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
}
}
+/* *********************** header region ************************ */
+/* add handlers, stuff you only do once or on area/region changes */
+static void sequencer_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+{
+ ED_region_header_init(ar);
+}
+
+static void sequencer_header_area_draw(const bContext *C, ARegion *ar)
+{
+ ED_region_header(C, ar);
+}
+
/* *********************** preview region ************************ */
static void sequencer_preview_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
-
-// keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0);
-// WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+
+#if 0
+ keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+#endif
keymap = WM_keymap_find(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -593,7 +610,6 @@ static void sequencer_preview_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED
break;
}
break;
-
case NC_MASK:
if (wmn->action == NA_EDITED) {
ED_region_tag_redraw(ar);
@@ -654,10 +670,10 @@ void ED_spacetype_sequencer(void)
{
SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype sequencer");
ARegionType *art;
-
+
st->spaceid = SPACE_SEQ;
strncpy(st->name, "Sequencer", BKE_ST_MAXNAME);
-
+
st->new = sequencer_new;
st->free = sequencer_free;
st->init = sequencer_init;
@@ -682,13 +698,12 @@ void ED_spacetype_sequencer(void)
/* preview */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
art->regionid = RGN_TYPE_PREVIEW;
- art->prefsizey = 240; // XXX
art->init = sequencer_preview_area_init;
art->draw = sequencer_preview_area_draw;
art->listener = sequencer_preview_area_listener;
art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
BLI_addhead(&st->regiontypes, art);
-
+
/* regions: listview/buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
art->regionid = RGN_TYPE_UI;
@@ -698,7 +713,7 @@ void ED_spacetype_sequencer(void)
art->init = sequencer_buttons_area_init;
art->draw = sequencer_buttons_area_draw;
BLI_addhead(&st->regiontypes, art);
-
+
sequencer_buttons_register(art);
/* regions: header */
@@ -706,13 +721,13 @@ void ED_spacetype_sequencer(void)
art->regionid = RGN_TYPE_HEADER;
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
-
+
art->init = sequencer_header_area_init;
art->draw = sequencer_header_area_draw;
art->listener = sequencer_main_area_listener;
-
+
BLI_addhead(&st->regiontypes, art);
-
+
BKE_spacetype_register(st);
/* set the sequencer callback when not in background mode */
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index fbca9bcc04f..1e710b88cad 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -462,10 +462,13 @@ static void text_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
static int text_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
- if (drag->type == WM_DRAG_PATH)
- if (ELEM(drag->icon, ICON_FILE_SCRIPT, ICON_FILE_BLANK)) /* rule might not work? */
- return 1;
- return 0;
+ if (drag->type == WM_DRAG_PATH) {
+ /* rule might not work? */
+ if (ELEM(drag->icon, ICON_FILE_SCRIPT, ICON_FILE_TEXT, ICON_FILE_BLANK)) {
+ return true;
+ }
+ }
+ return false;
}
static void text_drop_copy(wmDrag *drag, wmDropBox *drop)
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index c91c51ee5a9..480696760d4 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -397,7 +397,8 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
/* skip hidden part of line */
if (skip) {
skip--;
- fstart = fpos; mstart = mend;
+ fstart = fpos = end;
+ mstart = mend;
mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
end = (wrap += max - padding);
continue;
@@ -1459,7 +1460,7 @@ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa)
ARegion *ar = NULL;
int i, x, winx = 0;
- if (ELEM3(NULL, st, st->text, st->text->curl)) return;
+ if (ELEM(NULL, st, st->text, st->text->curl)) return;
text = st->text;
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index fcd6fb3c179..2e3d8d056e8 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -1825,11 +1825,17 @@ static int text_move_cursor(bContext *C, int type, bool select)
switch (type) {
case LINE_BEGIN:
+ if (!select) {
+ txt_sel_clear(text);
+ }
if (st && st->wordwrap && ar) txt_wrap_move_bol(st, ar, select);
else txt_move_bol(text, select);
break;
case LINE_END:
+ if (!select) {
+ txt_sel_clear(text);
+ }
if (st && st->wordwrap && ar) txt_wrap_move_eol(st, ar, select);
else txt_move_eol(text, select);
break;
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index 245cdadc7a2..dfa373f111f 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -67,6 +67,7 @@
#include "view3d_intern.h"
+#include "GPU_select.h"
/* *************** Armature Drawing - Coloring API ***************************** */
@@ -93,7 +94,7 @@ static void set_pchan_colorset(Object *ob, bPoseChannel *pchan)
short color_index = 0;
/* sanity check */
- if (ELEM4(NULL, ob, arm, pose, pchan)) {
+ if (ELEM(NULL, ob, arm, pose, pchan)) {
bcolor = NULL;
return;
}
@@ -466,10 +467,10 @@ static const unsigned int bone_octahedral_solid_tris[8][3] = {
/* aligned with bone_octahedral_solid_tris */
static const float bone_octahedral_solid_normals[8][3] = {
- { 0.70710683f, -0.70710683f, 0.00000000f},
- {-0.00000000f, -0.70710683f, -0.70710683f},
- {-0.70710683f, -0.70710683f, 0.00000000f},
- { 0.00000000f, -0.70710683f, 0.70710683f},
+ { M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
+ {-0.00000000f, -M_SQRT1_2, -M_SQRT1_2},
+ {-M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
+ { 0.00000000f, -M_SQRT1_2, M_SQRT1_2},
{ 0.99388373f, 0.11043154f, -0.00000000f},
{ 0.00000000f, 0.11043154f, -0.99388373f},
{-0.99388373f, 0.11043154f, 0.00000000f},
@@ -551,7 +552,7 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag,
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
if (id != -1)
- glLoadName(id | BONESEL_ROOT);
+ GPU_select_load_id(id | BONESEL_ROOT);
if (dt <= OB_WIRE) {
if (armflag & ARM_EDITMODE) {
@@ -574,7 +575,7 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag,
/* Draw tip point */
if (id != -1)
- glLoadName(id | BONESEL_TIP);
+ GPU_select_load_id(id | BONESEL_TIP);
if (dt <= OB_WIRE) {
if (armflag & ARM_EDITMODE) {
@@ -787,7 +788,7 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
if (id != -1)
- glLoadName(id | BONESEL_ROOT);
+ GPU_select_load_id(id | BONESEL_ROOT);
drawcircball(GL_LINE_LOOP, headvec, head, imat);
}
@@ -799,7 +800,7 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
}
if (id != -1)
- glLoadName(id | BONESEL_TIP);
+ GPU_select_load_id(id | BONESEL_TIP);
drawcircball(GL_LINE_LOOP, tailvec, tail, imat);
@@ -830,7 +831,7 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
cross_v3_v3v3(norvect, vec, imat[2]);
if (id != -1)
- glLoadName(id | BONESEL_BONE);
+ GPU_select_load_id(id | BONESEL_BONE);
glBegin(GL_LINES);
@@ -907,7 +908,7 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
if (id != -1)
- glLoadName(id | BONESEL_ROOT);
+ GPU_select_load_id(id | BONESEL_ROOT);
gluSphere(qobj, head, 16, 10);
}
@@ -918,7 +919,7 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
}
if (id != -1)
- glLoadName(id | BONESEL_TIP);
+ GPU_select_load_id(id | BONESEL_TIP);
glTranslatef(0.0f, 0.0f, length);
gluSphere(qobj, tail, 16, 10);
@@ -939,7 +940,7 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
if (length > (head + tail)) {
if (id != -1)
- glLoadName(id | BONESEL_BONE);
+ GPU_select_load_id(id | BONESEL_BONE);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -1.0f);
@@ -1009,7 +1010,7 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
if (G.f & G_PICKSEL) { /* no bitmap in selection mode, crashes 3d cards... */
- glLoadName(id | BONESEL_ROOT);
+ GPU_select_load_id(id | BONESEL_ROOT);
glBegin(GL_POINTS);
glVertex3f(0.0f, 0.0f, 0.0f);
glEnd();
@@ -1021,7 +1022,7 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned
}
if (id != -1)
- glLoadName((GLuint) id | BONESEL_BONE);
+ GPU_select_load_id((GLuint) id | BONESEL_BONE);
glBegin(GL_LINES);
glVertex3f(0.0f, 0.0f, 0.0f);
@@ -1031,7 +1032,7 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned
/* tip */
if (G.f & G_PICKSEL) {
/* no bitmap in selection mode, crashes 3d cards... */
- glLoadName(id | BONESEL_TIP);
+ GPU_select_load_id(id | BONESEL_TIP);
glBegin(GL_POINTS);
glVertex3f(0.0f, 1.0f, 0.0f);
glEnd();
@@ -1043,7 +1044,7 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned
/* further we send no names */
if (id != -1)
- glLoadName(id & 0xFFFF); /* object tag, for bordersel optim */
+ GPU_select_load_id(id & 0xFFFF); /* object tag, for bordersel optim */
if (armflag & ARM_POSEMODE)
set_pchan_glColor(PCHAN_COLOR_LINEBONE, boneflag, constflag);
@@ -1161,7 +1162,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
}
if (id != -1) {
- glLoadName((GLuint) id | BONESEL_BONE);
+ GPU_select_load_id((GLuint) id | BONESEL_BONE);
}
/* set up solid drawing */
@@ -1266,13 +1267,13 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons
/* this chunk not in object mode */
if (armflag & (ARM_EDITMODE | ARM_POSEMODE)) {
if (id != -1)
- glLoadName((GLuint) id | BONESEL_BONE);
+ GPU_select_load_id((GLuint) id | BONESEL_BONE);
draw_wire_bone_segments(pchan, bbones, length, segments);
/* further we send no names */
if (id != -1)
- glLoadName(id & 0xFFFF); /* object tag, for bordersel optim */
+ GPU_select_load_id(id & 0xFFFF); /* object tag, for bordersel optim */
}
/* colors for modes */
@@ -1315,7 +1316,7 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag
/* now draw the bone itself */
if (id != -1) {
- glLoadName((GLuint) id | BONESEL_BONE);
+ GPU_select_load_id((GLuint) id | BONESEL_BONE);
}
/* wire? */
@@ -1370,7 +1371,7 @@ static void draw_custom_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, Obje
}
if (id != -1) {
- glLoadName((GLuint) id | BONESEL_BONE);
+ GPU_select_load_id((GLuint) id | BONESEL_BONE);
}
draw_object_instance(scene, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE);
@@ -1812,12 +1813,12 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
index += 0x10000; /* pose bones count in higher 2 bytes only */
}
- /* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet,
+ /* very very confusing... but in object mode, solid draw, we cannot do GPU_select_load_id yet,
* stick bones and/or wire custom-shapes are drawn in next loop
*/
- if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && (draw_wire == false)) {
+ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && (draw_wire == false) && index != -1) {
/* object tag, for bordersel optim */
- glLoadName(index & 0xFFFF);
+ GPU_select_load_id(index & 0xFFFF);
index = -1;
}
}
@@ -1881,9 +1882,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
index += 0x10000; /* pose bones count in higher 2 bytes only */
}
/* stick or wire bones have not been drawn yet so don't clear object selection in this case */
- if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && draw_wire) {
+ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && draw_wire && index != -1) {
/* object tag, for bordersel optim */
- glLoadName(index & 0xFFFF);
+ GPU_select_load_id(index & 0xFFFF);
index = -1;
}
}
@@ -1926,7 +1927,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
*/
if ((do_dashed & 2) && ((bone->flag & BONE_CONNECTED) == 0)) {
if (arm->flag & ARM_POSEMODE) {
- glLoadName(index & 0xFFFF); /* object tag, for bordersel optim */
+ GPU_select_load_id(index & 0xFFFF); /* object tag, for bordersel optim */
UI_ThemeColor(TH_WIRE);
}
setlinestyle(3);
@@ -1946,7 +1947,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (constflag & PCHAN_HAS_TARGET) glColor3ub(200, 120, 0);
else glColor3ub(200, 200, 50); /* add theme! */
- glLoadName(index & 0xFFFF);
+ GPU_select_load_id(index & 0xFFFF);
pchan_draw_IK_root_lines(pchan, !(do_dashed & 2));
}
}
@@ -1954,7 +1955,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (bone->flag & BONE_SELECTED) {
glColor3ub(150, 200, 50); /* add theme! */
- glLoadName(index & 0xFFFF);
+ GPU_select_load_id(index & 0xFFFF);
pchan_draw_IK_root_lines(pchan, !(do_dashed & 2));
}
}
@@ -2020,7 +2021,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* draw DoFs */
if (arm->flag & ARM_POSEMODE) {
- if (((base->flag & OB_FROMDUPLI) == 0)) {
+ if (((base->flag & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) {
draw_pose_dofs(ob);
}
}
@@ -2174,7 +2175,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
/* if wire over solid, set offset */
index = -1;
- glLoadName(-1);
+ GPU_select_load_id(-1);
if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
if (G.f & G_PICKSEL)
index = 0;
@@ -2223,7 +2224,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
/* offset to parent */
if (eBone->parent) {
UI_ThemeColor(TH_WIRE_EDIT);
- glLoadName(-1); /* -1 here is OK! */
+ GPU_select_load_id(-1); /* -1 here is OK! */
setlinestyle(3);
glBegin(GL_LINES);
@@ -2240,7 +2241,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
/* restore */
if (index != -1) {
- glLoadName(-1);
+ GPU_select_load_id(-1);
}
if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index 75d0f86de57..1d54cb0cff9 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -211,12 +211,16 @@ static Material *give_current_material_or_def(Object *ob, int matnr)
static struct TextureDrawState {
Object *ob;
+ Image *stencil; /* texture painting stencil */
+ Image *canvas; /* texture painting canvas, for image mode */
bool use_game_mat;
int is_lit, is_tex;
int color_profile;
bool use_backface_culling;
unsigned char obcol[4];
-} Gtexdraw = {NULL, false, 0, 0, 0, false, {0, 0, 0, 0}};
+ bool is_texpaint;
+ bool texpaint_material; /* use material slots for texture painting */
+} Gtexdraw = {NULL, NULL, NULL, false, 0, 0, 0, false, {0, 0, 0, 0}, false, false};
static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw)
{
@@ -228,13 +232,15 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
static int c_lit;
static int c_has_texface;
- Object *litob = NULL; /* to get mode to turn off mipmap in painting mode */
int backculled = 1;
int alphablend = GPU_BLEND_SOLID;
int textured = 0;
int lit = 0;
int has_texface = texface != NULL;
bool need_set_tpage = false;
+ bool texpaint = ((gtexdraw.ob->mode & OB_MODE_TEXTURE_PAINT) != 0);
+
+ Image *ima = NULL;
if (ma != NULL) {
if (ma->mode & MA_TRANSP) {
@@ -247,10 +253,10 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
memset(&c_texface, 0, sizeof(MTFace));
c_badtex = false;
c_has_texface = -1;
+ c_ma = NULL;
}
else {
textured = gtexdraw.is_tex;
- litob = gtexdraw.ob;
}
/* convert number of lights into boolean */
@@ -265,14 +271,19 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
}
}
- if (texface) {
+ if (texface && !texpaint) {
textured = textured && (texface->tpage);
/* no material, render alpha if texture has depth=32 */
if (!ma && BKE_image_has_alpha(texface->tpage))
alphablend = GPU_BLEND_ALPHA;
}
-
+ else if (texpaint && ma) {
+ if (gtexdraw.texpaint_material)
+ ima = ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
+ else
+ ima = gtexdraw.canvas;
+ }
else
textured = 0;
@@ -286,11 +297,43 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
/* need to re-set tpage if textured flag changed or existsment of texface changed.. */
need_set_tpage = textured != c_textured || has_texface != c_has_texface;
/* ..or if settings inside texface were changed (if texface was used) */
- need_set_tpage |= texface && memcmp(&c_texface, texface, sizeof(c_texface));
+ need_set_tpage |= (texpaint && c_ma != ma) || (texface && memcmp(&c_texface, texface, sizeof(c_texface)));
if (need_set_tpage) {
if (textured) {
- c_badtex = !GPU_set_tpage(texface, !(litob->mode & OB_MODE_TEXTURE_PAINT), alphablend);
+ if (texpaint) {
+ c_badtex = false;
+ if (GPU_verify_image(ima, NULL, 0, 1, 0, false)) {
+ glEnable(GL_TEXTURE_2D);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
+
+ glActiveTexture(GL_TEXTURE1);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, ima->bindcode);
+ glActiveTexture(GL_TEXTURE0);
+ }
+ else {
+ glActiveTexture(GL_TEXTURE1);
+ glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glActiveTexture(GL_TEXTURE0);
+
+ c_badtex = true;
+ GPU_clear_tpage(true);
+ glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ }
+ }
+ else {
+ c_badtex = !GPU_set_tpage(texface, !texpaint, alphablend);
+ }
}
else {
GPU_set_tpage(NULL, 0, 0);
@@ -324,6 +367,7 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
glDisable(GL_COLOR_MATERIAL);
}
c_lit = lit;
+ c_ma = ma;
}
return c_badtex;
@@ -334,6 +378,7 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
unsigned char obcol[4];
bool is_tex, solidtex;
Mesh *me = ob->data;
+ ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
/* XXX scene->obedit warning */
@@ -363,8 +408,52 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
else is_tex = false;
Gtexdraw.ob = ob;
+ Gtexdraw.stencil = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? imapaint->stencil : NULL;
+ Gtexdraw.is_texpaint = (ob->mode == OB_MODE_TEXTURE_PAINT);
+ Gtexdraw.texpaint_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
+ Gtexdraw.canvas = (Gtexdraw.texpaint_material) ? NULL : imapaint->canvas;
Gtexdraw.is_tex = is_tex;
+ /* naughty multitexturing hacks to quickly support stencil + shading + alpha blending
+ * in new texpaint code. The better solution here would be to support GLSL */
+ if (Gtexdraw.is_texpaint) {
+ glActiveTexture(GL_TEXTURE1);
+ glEnable(GL_TEXTURE_2D);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
+
+ /* load the stencil texture here */
+ if (Gtexdraw.stencil != NULL) {
+ glActiveTexture(GL_TEXTURE2);
+ if (GPU_verify_image(Gtexdraw.stencil, NULL, false, false, false, false)) {
+ float col[4] = {imapaint->stencil_col[0], imapaint->stencil_col[1], imapaint->stencil_col[2], 1.0f};
+ glEnable(GL_TEXTURE_2D);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
+ glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, col);
+ if ((imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) == 0) {
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_ONE_MINUS_SRC_COLOR);
+ }
+ else {
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
+ }
+ }
+ }
+ glActiveTexture(GL_TEXTURE0);
+ }
+
Gtexdraw.color_profile = BKE_scene_check_color_management_enabled(scene);
Gtexdraw.use_game_mat = (RE_engines_find(scene->r.engine)->flag & RE_GAME) != 0;
Gtexdraw.use_backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0;
@@ -378,8 +467,31 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
static void draw_textured_end(void)
{
- /* switch off textures */
- GPU_set_tpage(NULL, 0, 0);
+ if (Gtexdraw.ob->mode & OB_MODE_TEXTURE_PAINT) {
+ glActiveTexture(GL_TEXTURE1);
+ glDisable(GL_TEXTURE_2D);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ if (Gtexdraw.stencil != NULL) {
+ glActiveTexture(GL_TEXTURE2);
+ glDisable(GL_TEXTURE_2D);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+ glActiveTexture(GL_TEXTURE0);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ /* manual reset, since we don't use tpage */
+ glBindTexture(GL_TEXTURE_2D, 0);
+ /* force switch off textures */
+ GPU_clear_tpage(true);
+ }
+ else {
+ /* switch off textures */
+ GPU_set_tpage(NULL, 0, 0);
+ }
glShadeModel(GL_FLAT);
glDisable(GL_CULL_FACE);
@@ -455,7 +567,7 @@ static DMDrawOption draw_tface__set_draw(MTFace *tface, const bool UNUSED(has_mc
if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0;
- if (tface)
+ if (tface || Gtexdraw.is_texpaint)
set_draw_settings_cached(0, tface, ma, Gtexdraw);
/* always use color from mcol, as set in update_tface_color_layer */
@@ -769,7 +881,8 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
Object *ob, DerivedMesh *dm, const int draw_flags)
{
Mesh *me = ob->data;
-
+ DMDrawFlag uvflag = DM_DRAW_USE_ACTIVE_UV;
+
/* correct for negative scale */
if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
else glFrontFace(GL_CCW);
@@ -779,6 +892,10 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ uvflag = DM_DRAW_USE_TEXPAINT_UV;
+ }
+
if (ob->mode & OB_MODE_EDIT) {
drawEMTFMapped_userData data;
@@ -788,7 +905,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
data.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
data.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
- dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data);
+ dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data, 0);
}
else if (draw_flags & DRAW_FACE_SELECT) {
if (ob->mode & OB_MODE_WEIGHT_PAINT)
@@ -800,15 +917,15 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
userData.me = me;
- dm->drawMappedFacesTex(dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, compareDrawOptions, &userData);
+ dm->drawMappedFacesTex(dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, compareDrawOptions, &userData, uvflag);
}
}
else {
if (GPU_buffer_legacy(dm)) {
if (draw_flags & DRAW_MODIFIERS_PREVIEW)
- dm->drawFacesTex(dm, draw_mcol__set_draw_legacy, NULL, NULL);
+ dm->drawFacesTex(dm, draw_mcol__set_draw_legacy, NULL, NULL, uvflag);
else
- dm->drawFacesTex(dm, draw_tface__set_draw_legacy, NULL, NULL);
+ dm->drawFacesTex(dm, draw_tface__set_draw_legacy, NULL, NULL, uvflag);
}
else {
drawTFace_userData userData;
@@ -819,7 +936,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
userData.me = NULL;
- dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData);
+ dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData, uvflag);
}
}
@@ -866,7 +983,7 @@ static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
int texture_set = 0;
/* draw image texture if we find one */
- if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node)) {
+ if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node, NULL)) {
/* get openl texture */
int mipmap = 1;
int bindcode = (ima) ? GPU_verify_image(ima, iuser, 0, 0, mipmap, false) : 0;
@@ -951,7 +1068,8 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
/* if not cycles, or preview-modifiers, or drawing matcaps */
if ((draw_flags & DRAW_MODIFIERS_PREVIEW) ||
(v3d->flag2 & V3D_SHOW_SOLID_MATCAP) ||
- (BKE_scene_use_new_shading_nodes(scene) == false))
+ (BKE_scene_use_new_shading_nodes(scene) == false) ||
+ ((ob->mode & OB_MODE_TEXTURE_PAINT) && ELEM(v3d->drawtype, OB_TEXTURE, OB_SOLID)))
{
draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags);
return;
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index e51ce652b53..5694f388780 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -86,6 +86,7 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
+#include "GPU_select.h"
#include "ED_mesh.h"
#include "ED_particle.h"
@@ -109,7 +110,7 @@
*
* Ideally we don't want to evaluate objects from drawing,
* but it'll require some major sequencer re-design. So
- * for now just fallback to legacy behaior with calling
+ * for now just fallback to legacy behavior with calling
* display ist creating from draw().
*/
#define SEQUENCER_DAG_WORKAROUND
@@ -301,7 +302,7 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
if (BKE_scene_use_new_shading_nodes(scene))
return false;
- return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
+ return ((scene->gm.matmode == GAME_MAT_GLSL) || (v3d->drawtype == OB_MATERIAL)) && (dt > OB_SOLID);
}
static bool check_alpha_pass(Base *base)
@@ -1585,7 +1586,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
continue;
if (dflag & DRAW_PICKING)
- glLoadName(base->selcol + (tracknr << 16));
+ GPU_select_load_id(base->selcol + (tracknr << 16));
glPushMatrix();
glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
@@ -1736,7 +1737,7 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d,
}
if (dflag & DRAW_PICKING)
- glLoadName(base->selcol);
+ GPU_select_load_id(base->selcol);
}
/* flag similar to draw_object() */
@@ -3609,7 +3610,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
draw_dm_vert_normals(em, scene, ob, cageDM);
}
if (me->drawflag & ME_DRAW_LNORMALS) {
- UI_ThemeColor(TH_VNORMAL);
+ UI_ThemeColor(TH_LNORMAL);
draw_dm_loop_normals(em, scene, ob, cageDM);
}
@@ -4867,7 +4868,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
normalize_v3(imat[1]);
}
- if (ELEM3(draw_as, PART_DRAW_DOT, PART_DRAW_CROSS, PART_DRAW_LINE) &&
+ if (ELEM(draw_as, PART_DRAW_DOT, PART_DRAW_CROSS, PART_DRAW_LINE) &&
(part->draw_col > PART_DRAW_COL_MAT))
{
create_cdata = 1;
@@ -5879,7 +5880,7 @@ static void editnurb_draw_active_nurbs(Nurb *nu)
glLineWidth(1);
}
-static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
+static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
{
Nurb *nu;
BPoint *bp, *bp1;
@@ -5995,8 +5996,9 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
}
}
-static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb,
- const char dt, const short dflag, const unsigned char ob_wire_col[4])
+static void draw_editnurb(
+ Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb,
+ const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
ToolSettings *ts = scene->toolsettings;
Object *ob = base->object;
@@ -6014,6 +6016,11 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ /* for shadows only show solid faces */
+ if (v3d->flag2 & V3D_RENDER_SHADOW) {
+ return;
+ }
+
if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
/* first non-selected and active handles */
@@ -6026,8 +6033,8 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
}
index++;
}
- draw_editnurb(ob, nurb, 0);
- draw_editnurb(ob, nurb, 1);
+ draw_editnurb_splines(ob, nurb, false);
+ draw_editnurb_splines(ob, nurb, true);
/* selected handles */
for (nu = nurb; nu; nu = nu->next) {
if (nu->type == CU_BEZIER && (cu->drawflag & CU_HIDE_HANDLES) == 0)
@@ -6037,11 +6044,11 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
+ glColor3ubv(wire_col);
+
/* direction vectors for 3d curve paths
* when at its lowest, don't render normals */
if ((cu->flag & CU_3D) && (ts->normalsize > 0.0015f) && (cu->drawflag & CU_HIDE_NORMALS) == 0) {
-
- UI_ThemeColor(TH_WIRE_EDIT);
for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
BevPoint *bevp = bl->bevpoints;
int nr = bl->nr;
@@ -6478,7 +6485,7 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
if (G.f & G_PICKSEL) {
ml->selcol1 = code;
- glLoadName(code++);
+ GPU_select_load_id(code++);
}
}
drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat);
@@ -6492,7 +6499,7 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
if (G.f & G_PICKSEL) {
ml->selcol2 = code;
- glLoadName(code++);
+ GPU_select_load_id(code++);
}
drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad * atanf(ml->s) / (float)M_PI_2, imat);
}
@@ -6698,28 +6705,6 @@ static void draw_box(float vec[8][3])
glEnd();
}
-/* uses boundbox, function used by Ketsji */
-#if 0
-static void get_local_bounds(Object *ob, float center[3], float size[3])
-{
- BoundBox *bb = BKE_object_boundbox_get(ob);
-
- if (bb == NULL) {
- zero_v3(center);
- copy_v3_v3(size, ob->size);
- }
- else {
- size[0] = 0.5 * fabsf(bb->vec[0][0] - bb->vec[4][0]);
- size[1] = 0.5 * fabsf(bb->vec[0][1] - bb->vec[2][1]);
- size[2] = 0.5 * fabsf(bb->vec[0][2] - bb->vec[1][2]);
-
- center[0] = (bb->vec[0][0] + bb->vec[4][0]) / 2.0;
- center[1] = (bb->vec[0][1] + bb->vec[2][1]) / 2.0;
- center[2] = (bb->vec[0][2] + bb->vec[1][2]) / 2.0;
- }
-}
-#endif
-
static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin)
{
float size[3], cent[3];
@@ -6727,17 +6712,13 @@ static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin)
gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
- size[0] = 0.5f * fabsf(bb->vec[0][0] - bb->vec[4][0]);
- size[1] = 0.5f * fabsf(bb->vec[0][1] - bb->vec[2][1]);
- size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]);
+ BKE_boundbox_calc_size_aabb(bb, size);
if (around_origin) {
zero_v3(cent);
}
else {
- cent[0] = 0.5f * (bb->vec[0][0] + bb->vec[4][0]);
- cent[1] = 0.5f * (bb->vec[0][1] + bb->vec[2][1]);
- cent[2] = 0.5f * (bb->vec[0][2] + bb->vec[1][2]);
+ BKE_boundbox_calc_center_aabb(bb, cent);
}
glPushMatrix();
@@ -6781,7 +6762,7 @@ static void draw_bounding_volume(Object *ob, char type)
if (ob->type == OB_MESH) {
bb = BKE_mesh_boundbox_get(ob);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
bb = BKE_curve_boundbox_get(ob);
}
else if (ob->type == OB_MBALL) {
@@ -6806,9 +6787,7 @@ static void draw_bounding_volume(Object *ob, char type)
if (type == OB_BOUND_BOX) {
float vec[8][3], size[3];
- size[0] = 0.5f * fabsf(bb->vec[0][0] - bb->vec[4][0]);
- size[1] = 0.5f * fabsf(bb->vec[0][1] - bb->vec[2][1]);
- size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]);
+ BKE_boundbox_calc_size_aabb(bb, size);
vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0];
vec[4][0] = vec[5][0] = vec[6][0] = vec[7][0] = +size[0];
@@ -6838,7 +6817,7 @@ static void drawtexspace(Object *ob)
if (ob->type == OB_MESH) {
BKE_mesh_texspace_get(ob->data, loc, NULL, size);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
BKE_curve_texspace_get(ob->data, loc, NULL, size);
}
else if (ob->type == OB_MBALL) {
@@ -6876,7 +6855,7 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
glDepthMask(0);
- if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+ if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
DerivedMesh *dm = ob->derivedFinal;
bool has_faces = false;
@@ -6920,7 +6899,7 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const unsigned char ob_wire_col[4])
{
- if (ELEM4(ob->type, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL)) {
+ if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL)) {
if (scene->obedit == ob) {
UI_ThemeColor(TH_WIRE_EDIT);
@@ -6932,7 +6911,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const
ED_view3d_polygon_offset(rv3d, 1.0);
glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
- if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+ if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
if (ob->derivedFinal) {
@@ -7123,9 +7102,7 @@ static void draw_rigidbody_shape(Object *ob)
switch (ob->rigidbody_object->shape) {
case RB_SHAPE_BOX:
- size[0] = 0.5f * fabsf(bb->vec[0][0] - bb->vec[4][0]);
- size[1] = 0.5f * fabsf(bb->vec[0][1] - bb->vec[2][1]);
- size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]);
+ BKE_boundbox_calc_size_aabb(bb, size);
vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0];
vec[4][0] = vec[5][0] = vec[6][0] = vec[7][0] = +size[0];
@@ -7170,23 +7147,23 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
const bool is_obact = (ob == OBACT);
const bool render_override = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0;
const bool is_picking = (G.f & G_PICKSEL) != 0;
- bool skip_object = false;
+ const bool has_particles = (ob->particlesystem.first != NULL);
bool particle_skip_object = false; /* Draw particles but not their emitter object. */
if (ob != scene->obedit) {
if (ob->restrictflag & OB_RESTRICT_VIEW)
- skip_object = true;
+ return;
if (render_override) {
if (ob->restrictflag & OB_RESTRICT_RENDER)
- skip_object = true;
+ return;
- if (ob->transflag & OB_DUPLI)
- skip_object = true; /* note: can be reset by particle "draw emitter" below */
+ if (!has_particles && (ob->transflag & (OB_DUPLI & ~OB_DUPLIFRAMES)))
+ return;
}
}
- if (ob->particlesystem.first) {
+ if (has_particles) {
/* XXX particles are not safe for simultaneous threaded render */
if (G.is_rendering) {
return;
@@ -7199,7 +7176,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
for (psys = ob->particlesystem.first; psys; psys = psys->next) {
/* Once we have found a psys which renders its emitter object, we are done. */
if (psys->part->draw & PART_DRAW_EMITTER) {
- skip_object = false;
particle_skip_object = false;
break;
}
@@ -7207,9 +7183,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
}
- if (skip_object)
- return;
-
/* xray delay? */
if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
/* don't do xray in particle mode, need the z-buffer */
@@ -7354,7 +7327,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (cu->editnurb) {
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- drawnurb(scene, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col);
+ draw_editnurb(scene, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col);
}
else if (dt == OB_BOUNDBOX) {
if ((render_override && (v3d->drawtype >= OB_WIRE)) == 0) {
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 7a4634bf01a..8b76ec3a56d 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -43,7 +43,9 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_icons.h"
+#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_scene.h"
@@ -285,7 +287,7 @@ static void view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
}
}
-void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
+void ED_view3d_shade_update(Main *bmain, Scene *scene, View3D *v3d, ScrArea *sa)
{
wmWindowManager *wm = bmain->wm.first;
@@ -297,6 +299,10 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
view3d_stop_render_preview(wm, ar);
}
}
+ else if (scene->obedit != NULL && scene->obedit->type == OB_MESH) {
+ /* Tag mesh to load edit data. */
+ DAG_id_tag_update(scene->obedit->data, 0);
+ }
}
/* ******************** default callbacks for view3d space ***************** */
@@ -389,7 +395,16 @@ static SpaceLink *view3d_new(const bContext *C)
static void view3d_free(SpaceLink *sl)
{
View3D *vd = (View3D *) sl;
+ BGpic *bgpic;
+ for (bgpic = vd->bgpicbase.first; bgpic; bgpic = bgpic->next) {
+ if (bgpic->source == V3D_BGPIC_IMAGE) {
+ id_us_min((ID *)bgpic->ima);
+ }
+ else if (bgpic->source == V3D_BGPIC_MOVIE) {
+ id_us_min((ID *)bgpic->clip);
+ }
+ }
BLI_freelistN(&vd->bgpicbase);
if (vd->localvd) MEM_freeN(vd->localvd);
@@ -416,6 +431,7 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
{
View3D *v3do = (View3D *)sl;
View3D *v3dn = MEM_dupallocN(sl);
+ BGpic *bgpic;
/* clear or remove stuff from old */
@@ -433,8 +449,16 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
/* copy or clear inside new stuff */
v3dn->defmaterial = NULL;
-
+
BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase);
+ for (bgpic = v3dn->bgpicbase.first; bgpic; bgpic = bgpic->next) {
+ if (bgpic->source == V3D_BGPIC_IMAGE) {
+ id_us_plus((ID *)bgpic->ima);
+ }
+ else if (bgpic->source == V3D_BGPIC_MOVIE) {
+ id_us_plus((ID *)bgpic->clip);
+ }
+ }
v3dn->properties_storage = NULL;
@@ -464,6 +488,12 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
keymap = WM_keymap_find(wm->defaultconf, "Object Mode", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_find(wm->defaultconf, "Paint Curve", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
+ keymap = WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
keymap = WM_keymap_find(wm->defaultconf, "Image Paint", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
@@ -654,7 +684,7 @@ static void view3d_dropboxes(void)
WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_mesh_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
- WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
+ WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
}
@@ -760,7 +790,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
break;
case ND_NLA:
case ND_KEYFRAME:
- if (ELEM3(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
+ if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
ED_region_tag_redraw(ar);
break;
case ND_ANIMCHAN:
@@ -841,14 +871,18 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
switch (wmn->data) {
case ND_SHADING:
case ND_NODES:
+ {
+ Object *ob = OBACT;
if ((v3d->drawtype == OB_MATERIAL) ||
+ (ob && (ob->mode == OB_MODE_TEXTURE_PAINT)) ||
(v3d->drawtype == OB_TEXTURE &&
- (scene->gm.matmode == GAME_MAT_GLSL ||
- BKE_scene_use_new_shading_nodes(scene))))
+ (scene->gm.matmode == GAME_MAT_GLSL ||
+ BKE_scene_use_new_shading_nodes(scene))))
{
ED_region_tag_redraw(ar);
}
break;
+ }
case ND_SHADING_DRAW:
case ND_SHADING_LINKS:
ED_region_tag_redraw(ar);
@@ -886,7 +920,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
ED_region_tag_redraw(ar);
break;
case NC_MOVIECLIP:
- if (wmn->data == ND_DISPLAY)
+ if (wmn->data == ND_DISPLAY || wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
break;
case NC_SPACE:
@@ -1011,7 +1045,7 @@ static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
break;
case ND_NLA:
case ND_KEYFRAME:
- if (ELEM3(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
+ if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
ED_region_tag_redraw(ar);
break;
}
@@ -1080,6 +1114,11 @@ static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
if (wmn->data == ND_DATA || wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
break;
+ case NC_IMAGE:
+ /* Update for the image layers in texture paint. */
+ if (wmn->action == NA_EDITED)
+ ED_region_tag_redraw(ar);
+ break;
}
}
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index e96db2b220f..ee0f3da18b4 100644
--- a/source/blender/editors/space_view3d/view3d_camera_control.c
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -31,9 +31,9 @@
*
* Typical view-control usage:
*
- * - aquire a view-control (#ED_view3d_control_aquire).
+ * - acquire a view-control (#ED_view3d_control_acquire).
* - modify ``rv3d->ofs``, ``rv3d->viewquat``.
- * - update the view data (#ED_view3d_control_aquire) - within a loop which draws the viewport.
+ * - update the view data (#ED_view3d_control_acquire) - within a loop which draws the viewport.
* - finish and release the view-control (#ED_view3d_control_release),
* either keeping the current view or restoring the initial view.
*
@@ -138,7 +138,7 @@ Object *ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl)
* Creates a #View3DControl handle and sets up
* the view for first-person style navigation.
*/
-struct View3DCameraControl *ED_view3d_cameracontrol_aquire(
+struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
Scene *scene, View3D *v3d, RegionView3D *rv3d,
const bool use_parent_root)
{
@@ -282,7 +282,7 @@ void ED_view3d_cameracontrol_update(
* Release view control.
*
* \param restore Sets the view state to the values that were set
- * before #ED_view3d_control_aquire was called.
+ * before #ED_view3d_control_acquire was called.
*/
void ED_view3d_cameracontrol_release(
View3DCameraControl *vctrl,
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 03808a82041..be3aaa13818 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -878,7 +878,7 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
}
}
}
- else if (ELEM3(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
+ else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
Key *key = NULL;
KeyBlock *kb = NULL;
@@ -1283,6 +1283,12 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
{
/* do nothing */
}
+ /* texture paint mode sampling */
+ else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) &&
+ (v3d->drawtype > OB_WIRE))
+ {
+ /* do nothing */
+ }
else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
v3d->drawtype > OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT))
{
@@ -1976,6 +1982,7 @@ static void draw_dupli_objects_color(
DupliApplyData *apply_data;
if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
+ if ((base->object->restrictflag & OB_RESTRICT_RENDER) && (v3d->flag2 & V3D_RENDER_OVERRIDE)) return;
if (dflag & DRAW_CONSTCOLOR) {
BLI_assert(color == TH_UNDEFINED);
@@ -2503,7 +2510,7 @@ CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d)
mask |= CD_MASK_ORCO;
}
else {
- if (scene->gm.matmode == GAME_MAT_GLSL)
+ if (scene->gm.matmode == GAME_MAT_GLSL || v3d->drawtype == OB_MATERIAL)
mask |= CD_MASK_ORCO;
}
}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index e3260dba485..db675b09896 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -78,6 +78,7 @@
#include "ED_view3d.h"
#include "ED_sculpt.h"
+#include "UI_resources.h"
#include "PIL_time.h" /* smoothview */
@@ -307,12 +308,12 @@ static void view3d_boxview_clip(ScrArea *sa)
}
for (val = 0; val < 8; val++) {
- if (ELEM4(val, 0, 3, 4, 7))
+ if (ELEM(val, 0, 3, 4, 7))
bb->vec[val][0] = -x1 - ofs[0];
else
bb->vec[val][0] = x1 - ofs[0];
- if (ELEM4(val, 0, 1, 4, 5))
+ if (ELEM(val, 0, 1, 4, 5))
bb->vec[val][1] = -y1 - ofs[1];
else
bb->vec[val][1] = y1 - ofs[1];
@@ -465,11 +466,13 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
* properties are always being edited, weak */
viewlock = rv3d->viewlock;
- if ((viewlock & RV3D_LOCKED) == 0)
+ if ((viewlock & RV3D_LOCKED) == 0) {
+ do_clip = (viewlock & RV3D_BOXCLIP) != 0;
viewlock = 0;
- else if ((viewlock & RV3D_BOXVIEW) == 0) {
- viewlock &= ~RV3D_BOXCLIP;
+ }
+ else if ((viewlock & RV3D_BOXVIEW) == 0 && (viewlock & RV3D_BOXCLIP) != 0) {
do_clip = true;
+ viewlock &= ~RV3D_BOXCLIP;
}
for (; ar; ar = ar->prev) {
@@ -648,6 +651,39 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
is_set = true;
}
+ else if (ob == NULL || ob->mode == OB_MODE_OBJECT) {
+ /* object mode use boundbox centers */
+ View3D *v3d = CTX_wm_view3d(C);
+ Base *base;
+ unsigned int tot = 0;
+ float select_center[3];
+
+ zero_v3(select_center);
+ for (base = FIRSTBASE; base; base = base->next) {
+ if (TESTBASE(v3d, base)) {
+ /* use the boundbox if we can */
+ Object *ob = base->object;
+
+ if (ob->bb && !(ob->bb->flag & BOUNDBOX_DIRTY)) {
+ float cent[3];
+
+ BKE_boundbox_calc_center_aabb(ob->bb, cent);
+
+ mul_m4_v3(ob->obmat, cent);
+ add_v3_v3(select_center, cent);
+ }
+ else {
+ add_v3_v3(select_center, ob->obmat[3]);
+ }
+ tot++;
+ }
+ }
+ if (tot) {
+ mul_v3_fl(select_center, 1.0f / (float)tot);
+ copy_v3_v3(lastofs, select_center);
+ is_set = true;
+ }
+ }
else {
/* If there's no selection, lastofs is unmodified and last value since static */
is_set = calculateTransformCenter(C, V3D_CENTROID, lastofs, NULL);
@@ -1136,7 +1172,7 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
*
* shared with NDOF.
*/
-static void view3d_ensure_persp(struct View3D *v3d, ARegion *ar)
+static bool view3d_ensure_persp(struct View3D *v3d, ARegion *ar)
{
RegionView3D *rv3d = ar->regiondata;
const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0;
@@ -1144,7 +1180,7 @@ static void view3d_ensure_persp(struct View3D *v3d, ARegion *ar)
BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
if (ED_view3d_camera_lock_check(v3d, rv3d))
- return;
+ return false;
if (rv3d->persp != RV3D_PERSP) {
if (rv3d->persp == RV3D_CAMOB) {
@@ -1155,7 +1191,10 @@ static void view3d_ensure_persp(struct View3D *v3d, ARegion *ar)
else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
rv3d->persp = RV3D_PERSP;
}
+ return true;
}
+
+ return false;
}
static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -1174,8 +1213,14 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
/* switch from camera view when: */
- view3d_ensure_persp(vod->v3d, vod->ar);
-
+ 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
+ * are properly updated.
+ */
+ ED_region_tag_redraw(vod->ar);
+ }
+
if (event->type == MOUSEPAN) {
/* Rotate direction we keep always same */
if (U.uiflag2 & USER_TRACKPAD_NATURAL)
@@ -2070,9 +2115,12 @@ static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzo
{
float zfac = 1.0;
bool use_cam_zoom;
+ float dist_range[2];
use_cam_zoom = (vod->rv3d->persp == RV3D_CAMOB) && !(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d));
+ ED_view3d_dist_range_get(vod->v3d, dist_range);
+
if (use_cam_zoom) {
float delta;
delta = (xy[0] - vod->origx + xy[1] - vod->origy) / 10.0f;
@@ -2139,16 +2187,19 @@ static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzo
}
if (!use_cam_zoom) {
- if (zfac != 1.0f && zfac * vod->rv3d->dist > 0.001f * vod->grid &&
- zfac * vod->rv3d->dist < 10.0f * vod->far)
- {
- view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy);
+ if (zfac != 1.0f) {
+ const float zfac_min = dist_range[0] / vod->rv3d->dist;
+ const float zfac_max = dist_range[1] / vod->rv3d->dist;
+ CLAMP(zfac, zfac_min, zfac_max);
+
+ if (zfac != 1.0f) {
+ view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy);
+ }
}
}
/* these limits were in old code too */
- if (vod->rv3d->dist < 0.001f * vod->grid) vod->rv3d->dist = 0.001f * vod->grid;
- if (vod->rv3d->dist > 10.0f * vod->far) vod->rv3d->dist = 10.0f * vod->far;
+ CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]);
if (vod->rv3d->viewlock & RV3D_BOXVIEW)
view3d_boxview_sync(vod->sa, vod->ar);
@@ -2212,6 +2263,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
ScrArea *sa;
ARegion *ar;
bool use_cam_zoom;
+ float dist_range[2];
const int delta = RNA_int_get(op->ptr, "delta");
int mx, my;
@@ -2235,13 +2287,15 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
use_cam_zoom = (rv3d->persp == RV3D_CAMOB) && !(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d));
+ ED_view3d_dist_range_get(v3d, dist_range);
+
if (delta < 0) {
/* this min and max is also in viewmove() */
if (use_cam_zoom) {
rv3d->camzoom -= 10.0f;
if (rv3d->camzoom < RV3D_CAMZOOM_MIN) rv3d->camzoom = RV3D_CAMZOOM_MIN;
}
- else if (rv3d->dist < 10.0f * v3d->far) {
+ else if (rv3d->dist < dist_range[1]) {
view_zoom_mouseloc(ar, 1.2f, mx, my);
}
}
@@ -2250,7 +2304,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
rv3d->camzoom += 10.0f;
if (rv3d->camzoom > RV3D_CAMZOOM_MAX) rv3d->camzoom = RV3D_CAMZOOM_MAX;
}
- else if (rv3d->dist > 0.001f * v3d->grid) {
+ else if (rv3d->dist > dist_range[0]) {
view_zoom_mouseloc(ar, 0.83333f, mx, my);
}
}
@@ -2363,6 +2417,8 @@ static void viewzoom_cancel(bContext *C, wmOperator *op)
void VIEW3D_OT_zoom(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Zoom View";
ot->description = "Zoom in/out in the view";
@@ -2379,8 +2435,10 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX);
- RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT_MAX);
+ prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
@@ -3243,6 +3301,8 @@ static int render_border_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_render_border(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Set Render Border";
ot->description = "Set the boundaries of the border render and enable border render";
@@ -3262,7 +3322,8 @@ void VIEW3D_OT_render_border(wmOperatorType *ot)
/* rna */
WM_operator_properties_border(ot);
- RNA_def_boolean(ot->srna, "camera_only", 0, "Camera Only", "Set render border for camera view and final render only");
+ prop = RNA_def_boolean(ot->srna, "camera_only", 0, "Camera Only", "Set render border for camera view and final render only");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* ********************* Clear render border operator ****************** */
@@ -3326,7 +3387,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
/* Zooms in on a border drawn by the user */
rcti rect;
float dvec[3], vb[2], xscale, yscale;
- float dist_range_min;
+ float dist_range[2];
/* SMOOTHVIEW */
float new_dist;
@@ -3346,6 +3407,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
/* check if zooming in/out view */
gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
+ ED_view3d_dist_range_get(v3d, dist_range);
+
/* Get Z Depths, needed for perspective, nice for ortho */
bgl_get_mats(&mats);
ED_view3d_draw_depth(scene, ar, v3d, true);
@@ -3394,8 +3457,9 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
new_ofs[2] = -p[2];
new_dist = len_v3(dvec);
- dist_range_min = v3d->near * 1.5f;
+ /* ignore dist_range min */
+ dist_range[0] = v3d->near * 1.5f;
}
else { /* othographic */
/* find the current window width and height */
@@ -3437,9 +3501,6 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
xscale = (BLI_rcti_size_x(&rect) / vb[0]);
yscale = (BLI_rcti_size_y(&rect) / vb[1]);
new_dist *= max_ff(xscale, yscale);
-
- /* zoom in as required, or as far as we can go */
- dist_range_min = 0.001f * v3d->grid;
}
if (gesture_mode == GESTURE_MODAL_OUT) {
@@ -3449,9 +3510,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
}
/* clamp after because we may have been zooming out */
- if (new_dist < dist_range_min) {
- new_dist = dist_range_min;
- }
+ CLAMP(new_dist, dist_range[0], dist_range[1]);
ED_view3d_smooth_view(C, v3d, ar, NULL, NULL,
new_ofs, NULL, &new_dist, NULL,
@@ -3545,13 +3604,13 @@ void VIEW3D_OT_zoom_camera_1_to_1(wmOperatorType *ot)
/* ********************* Changing view operator ****************** */
static EnumPropertyItem prop_view_items[] = {
+ {RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View From the Left"},
+ {RV3D_VIEW_RIGHT, "RIGHT", ICON_TRIA_RIGHT, "Right", "View From the Right"},
+ {RV3D_VIEW_BOTTOM, "BOTTOM", ICON_TRIA_DOWN, "Bottom", "View From the Bottom"},
+ {RV3D_VIEW_TOP, "TOP", ICON_TRIA_UP, "Top", "View From the Top"},
{RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View From the Front"},
{RV3D_VIEW_BACK, "BACK", 0, "Back", "View From the Back"},
- {RV3D_VIEW_LEFT, "LEFT", 0, "Left", "View From the Left"},
- {RV3D_VIEW_RIGHT, "RIGHT", 0, "Right", "View From the Right"},
- {RV3D_VIEW_TOP, "TOP", 0, "Top", "View From the Top"},
- {RV3D_VIEW_BOTTOM, "BOTTOM", 0, "Bottom", "View From the Bottom"},
- {RV3D_VIEW_CAMERA, "CAMERA", 0, "Camera", "View From the Active Camera"},
+ {RV3D_VIEW_CAMERA, "CAMERA", ICON_CAMERA_DATA, "Camera", "View From the Active Camera"},
{0, NULL, 0, NULL, NULL}
};
@@ -4435,7 +4494,7 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
}
}
-static void view3d_cursor3d_update(bContext *C, const int *mval)
+void ED_view3d_cursor3d_update(bContext *C, const int mval[2])
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -4449,32 +4508,11 @@ static void view3d_cursor3d_update(bContext *C, const int *mval)
WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
}
-static int view3d_cursor3d_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- view3d_cursor3d_update(C, event->mval);
- op->customdata = SET_INT_IN_POINTER(event->type);
- WM_event_add_modal_handler(C, op);
+ ED_view3d_cursor3d_update(C, event->mval);
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int view3d_cursor3d_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- int event_type = GET_INT_FROM_POINTER(op->customdata);
-
- if (event->type == event_type) {
- return OPERATOR_FINISHED;
- }
-
- switch (event->type) {
- case MOUSEMOVE:
- view3d_cursor3d_update(C, event->mval);
- break;
- case LEFTMOUSE:
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_FINISHED;
}
void VIEW3D_OT_cursor3d(wmOperatorType *ot)
@@ -4487,7 +4525,6 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
/* api callbacks */
ot->invoke = view3d_cursor3d_invoke;
- ot->modal = view3d_cursor3d_modal;
ot->poll = ED_operator_view3d_active;
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index 6afe0ef896f..da77c4f75f7 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -385,7 +385,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
fly->zlock = FLY_AXISLOCK_STATE_IDLE;
}
- fly->v3d_camera_control = ED_view3d_cameracontrol_aquire(
+ fly->v3d_camera_control = ED_view3d_cameracontrol_acquire(
fly->scene, fly->v3d, fly->rv3d,
(U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index e3d0e87066b..a88724a1cdd 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -32,6 +32,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "DNA_brush_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -45,6 +46,7 @@
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
+#include "BKE_paint.h"
#include "BKE_screen.h"
#include "BKE_editmesh.h"
@@ -308,7 +310,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
/* mode */
if (ob) {
modeselect = ob->mode;
- is_paint = ELEM4(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT);
+ is_paint = ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT);
}
else {
modeselect = OB_MODE_OBJECT;
@@ -336,8 +338,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
if (obedit == NULL && is_paint) {
-
- if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (ob->mode & OB_MODE_ALL_PAINT) {
/* Only for Weight Paint. makes no sense in other paint modes. */
row = uiLayoutRow(layout, true);
uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 169bc494e1b..84ac4f7d02d 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -233,7 +233,7 @@ void VIEW3D_OT_properties(struct wmOperatorType *ot);
void view3d_buttons_register(struct ARegionType *art);
/* view3d_camera_control.c */
-struct View3DCameraControl *ED_view3d_cameracontrol_aquire(
+struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
Scene *scene, View3D *v3d, RegionView3D *rv3d,
const bool use_parent_root);
void ED_view3d_cameracontrol_update(
@@ -285,7 +285,7 @@ void draw_smoke_heat(struct SmokeDomainSettings *domain, struct Object *ob);
/* workaround for trivial but noticeable camera bug caused by imprecision
* between view border calculation in 2D/3D space, workaround for bug [#28037].
- * without this deifne we get the old behavior which is to try and align them
+ * without this define we get the old behavior which is to try and align them
* both which _mostly_ works fine, but when the camera moves beyond ~1000 in
* any direction it starts to fail */
#define VIEW3D_CAMERA_BORDER_HACK
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index c1e42c97c4d..75c1d9dcd22 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -277,7 +277,7 @@ eV3DProjStatus ED_view3d_project_float_object(const ARegion *ar, const float co[
* *************************************************** */
/**
- * Caculate a depth value from \a co, use with #ED_view3d_win_to_delta
+ * Calculate a depth value from \a co, use with #ED_view3d_win_to_delta
*/
float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3], bool *r_flip)
{
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 32f063d6154..46ea52054c5 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1147,11 +1147,12 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
}
{
+ wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_select_menu", false);
PointerRNA ptr;
- WM_operator_properties_create(&ptr, "VIEW3D_OT_select_menu");
+ WM_operator_properties_create_ptr(&ptr, ot);
RNA_boolean_set(&ptr, "toggle", toggle);
- WM_operator_name_call(C, "VIEW3D_OT_select_menu", WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
WM_operator_properties_free(&ptr);
}
@@ -1193,15 +1194,32 @@ static short selectbuffer_ret_hits_5(unsigned int *buffer, const short hits15, c
/* we want a select buffer with bones, if there are... */
/* so check three selection levels and compare */
-static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buffer, const int mval[2])
+static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buffer, const int mval[2], bool *p_do_nearest, bool enumerate)
{
rcti rect;
int offs;
short hits15, hits9 = 0, hits5 = 0;
bool has_bones15 = false, has_bones9 = false, has_bones5 = false;
-
+ static int last_mval[2] = {-100, -100};
+ bool do_nearest = false;
+ View3D *v3d = vc->v3d;
+
+ /* define if we use solid nearest select or not */
+ if (v3d->drawtype > OB_WIRE) {
+ do_nearest = true;
+ if (len_manhattan_v2v2_int(mval, last_mval) < 3) {
+ do_nearest = false;
+ }
+ }
+ copy_v2_v2_int(last_mval, mval);
+
+ if (p_do_nearest)
+ *p_do_nearest = do_nearest;
+
+ do_nearest = do_nearest && !enumerate;
+
BLI_rcti_init(&rect, mval[0] - 14, mval[0] + 14, mval[1] - 14, mval[1] + 14);
- hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
+ hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, do_nearest);
if (hits15 == 1) {
return selectbuffer_ret_hits_15(buffer, hits15);
}
@@ -1210,7 +1228,7 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff
offs = 4 * hits15;
BLI_rcti_init(&rect, mval[0] - 9, mval[0] + 9, mval[1] - 9, mval[1] + 9);
- hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect);
+ hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, do_nearest);
if (hits9 == 1) {
return selectbuffer_ret_hits_9(buffer, hits15, hits9);
}
@@ -1219,7 +1237,7 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff
offs += 4 * hits9;
BLI_rcti_init(&rect, mval[0] - 5, mval[0] + 5, mval[1] - 5, mval[1] + 5);
- hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect);
+ hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, do_nearest);
if (hits5 == 1) {
return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
}
@@ -1241,25 +1259,13 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff
}
/* returns basact */
-static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits, const int mval[2],
- Base *startbase, bool has_bones)
+static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits,
+ Base *startbase, bool has_bones, bool do_nearest)
{
Scene *scene = vc->scene;
View3D *v3d = vc->v3d;
Base *base, *basact = NULL;
- static int lastmval[2] = {-100, -100};
int a;
- bool do_nearest = false;
-
- /* define if we use solid nearest select or not */
- if (v3d->drawtype > OB_WIRE) {
- do_nearest = true;
- if (ABS(mval[0] - lastmval[0]) < 3 && ABS(mval[1] - lastmval[1]) < 3) {
- if (!has_bones) /* hrms, if theres bones we always do nearest */
- do_nearest = false;
- }
- }
- lastmval[0] = mval[0]; lastmval[1] = mval[1];
if (do_nearest) {
unsigned int min = 0xFFFFFFFF;
@@ -1342,16 +1348,17 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
Base *basact = NULL;
unsigned int buffer[4 * MAXPICKBUF];
int hits;
+ bool do_nearest;
/* setup view context for argument to callbacks */
view3d_operator_needs_opengl(C);
view3d_set_viewcontext(C, &vc);
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval);
+ hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, &do_nearest, false);
if (hits > 0) {
const bool has_bones = selectbuffer_has_bones(buffer, hits);
- basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, vc.scene->base.first, has_bones);
+ basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.scene->base.first, has_bones, do_nearest);
}
return basact;
@@ -1438,10 +1445,11 @@ static bool mouse_select(bContext *C, const int mval[2],
}
else {
unsigned int buffer[4 * MAXPICKBUF];
+ bool do_nearest;
/* if objects have posemode set, the bones are in the same selection buffer */
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval);
+ hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, &do_nearest, enumerate);
if (hits > 0) {
/* note: bundles are handling in the same way as bones */
@@ -1452,7 +1460,7 @@ static bool mouse_select(bContext *C, const int mval[2],
basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle);
}
else {
- basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, startbase, has_bones);
+ basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest);
}
if (has_bones && basact) {
@@ -1510,7 +1518,7 @@ static bool mouse_select(bContext *C, const int mval[2],
if (!changed) {
/* fallback to regular object selection if no new bundles were selected,
* allows to select object parented to reconstruction object */
- basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, startbase, 0);
+ basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, 0, do_nearest);
}
}
}
@@ -1872,7 +1880,7 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
unsigned int buffer[4 * MAXPICKBUF];
short hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect);
+ hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, false);
if (extend == false && select)
BKE_mball_deselect_all(mb);
@@ -1906,7 +1914,7 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
unsigned int buffer[4 * MAXPICKBUF];
short hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect);
+ hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, false);
/* clear flag we use to detect point was affected */
for (ebone = arm->edbo->first; ebone; ebone = ebone->next)
@@ -2000,7 +2008,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
vbuffer = MEM_mallocN(4 * (totobj + MAXPICKBUF) * sizeof(unsigned int), "selection buffer");
- hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKBUF), rect);
+ hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKBUF), rect, false);
/*
* LOGIC NOTES (theeth):
* The buffer and ListBase have the same relative order, which makes the selection
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 716f4b10fae..7d3f7ce282e 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -56,6 +56,7 @@
#include "BIF_glutil.h"
#include "GPU_draw.h"
+#include "GPU_select.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -273,7 +274,7 @@ void ED_view3d_smooth_view_ex(
rv3d->rflag |= RV3D_NAVIGATING;
/* not essential but in some cases the caller will tag the area for redraw,
- * and in that case we can get a ficker of the 'org' user view but we want to see 'src' */
+ * and in that case we can get a flicker of the 'org' user view but we want to see 'src' */
view3d_smooth_view_state_restore(&sms.src, v3d, rv3d);
/* keep track of running timer! */
@@ -723,6 +724,13 @@ void ED_view3d_depth_tag_update(RegionView3D *rv3d)
rv3d->depths->damaged = true;
}
+void ED_view3d_dist_range_get(struct View3D *v3d,
+ float r_dist_range[2])
+{
+ r_dist_range[0] = v3d->grid * 0.001f;
+ r_dist_range[1] = v3d->far * 10.0f;
+}
+
/* copies logic of get_view3d_viewplane(), keep in sync */
bool ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *r_clipsta, float *r_clipend,
const bool use_ortho_factor)
@@ -955,6 +963,78 @@ void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d)
}
}
+static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar, bool use_obedit_skip)
+{
+ short code = 1;
+ char dt;
+ short dtx;
+
+ if (vc->obedit && vc->obedit->type == OB_MBALL) {
+ draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR);
+ }
+ else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) {
+ /* if not drawing sketch, draw bones */
+ if (!BDR_drawSketchNames(vc)) {
+ draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR);
+ }
+ }
+ else {
+ Base *base;
+
+ v3d->xray = true; /* otherwise it postpones drawing */
+ for (base = scene->base.first; base; base = base->next) {
+ if (base->lay & v3d->lay) {
+
+ if ((base->object->restrictflag & OB_RESTRICT_SELECT) ||
+ (use_obedit_skip && (scene->obedit->data == base->object->data)))
+ {
+ base->selcol = 0;
+ }
+ else {
+ base->selcol = code;
+
+ if (GPU_select_load_id(code)) {
+ draw_object(scene, ar, v3d, base, DRAW_PICKING | DRAW_CONSTCOLOR);
+
+ /* we draw duplicators for selection too */
+ if ((base->object->transflag & OB_DUPLI)) {
+ ListBase *lb;
+ DupliObject *dob;
+ Base tbase;
+
+ tbase.flag = OB_FROMDUPLI;
+ lb = object_duplilist(G.main->eval_ctx, scene, base->object);
+
+ for (dob = lb->first; dob; dob = dob->next) {
+ float omat[4][4];
+
+ tbase.object = dob->ob;
+ copy_m4_m4(omat, dob->ob->obmat);
+ copy_m4_m4(dob->ob->obmat, dob->mat);
+
+ /* extra service: draw the duplicator in drawtype of parent */
+ /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
+ dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
+ dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx;
+
+ draw_object(scene, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR);
+
+ tbase.object->dt = dt;
+ tbase.object->dtx = dtx;
+
+ copy_m4_m4(dob->ob->obmat, omat);
+ }
+ free_object_duplilist(lb);
+ }
+ }
+ code++;
+ }
+ }
+ }
+ v3d->xray = false; /* restore */
+ }
+}
+
/**
* \warning be sure to account for a negative return value
* This is an error, "Too many objects in select buffer"
@@ -962,17 +1042,16 @@ void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d)
*
* \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection.
*/
-short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input)
+short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, bool do_nearest)
{
Scene *scene = vc->scene;
View3D *v3d = vc->v3d;
ARegion *ar = vc->ar;
- rctf rect;
- short code, hits;
- char dt;
- short dtx;
+ rctf rect, selrect;
+ short hits;
const bool use_obedit_skip = (scene->obedit != NULL) && (vc->obedit == NULL);
-
+ const bool do_passes = do_nearest && GPU_select_query_check_active();
+
G.f |= G_PICKSEL;
/* case not a border select */
@@ -985,6 +1064,8 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
else {
BLI_rctf_rcti_copy(&rect, input);
}
+
+ selrect = rect;
view3d_winmatrix_set(ar, v3d, &rect);
mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat);
@@ -997,78 +1078,24 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
if (vc->rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_set(vc->rv3d);
- glSelectBuffer(bufsize, (GLuint *)buffer);
- glRenderMode(GL_SELECT);
- glInitNames(); /* these two calls whatfor? It doesnt work otherwise */
- glPushName(-1);
- code = 1;
+ if (do_passes)
+ GPU_select_begin(buffer, bufsize, &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
+ else
+ GPU_select_begin(buffer, bufsize, &selrect, GPU_SELECT_ALL, 0);
+
+ view3d_select_loop(vc, scene, v3d, ar, use_obedit_skip);
+
+ hits = GPU_select_end();
- if (vc->obedit && vc->obedit->type == OB_MBALL) {
- draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR);
- }
- else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) {
- /* if not drawing sketch, draw bones */
- if (!BDR_drawSketchNames(vc)) {
- draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR);
- }
- }
- else {
- Base *base;
-
- v3d->xray = true; /* otherwise it postpones drawing */
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & v3d->lay) {
-
- if ((base->object->restrictflag & OB_RESTRICT_SELECT) ||
- (use_obedit_skip && (scene->obedit->data == base->object->data)))
- {
- base->selcol = 0;
- }
- else {
- base->selcol = code;
- glLoadName(code);
- draw_object(scene, ar, v3d, base, DRAW_PICKING | DRAW_CONSTCOLOR);
-
- /* we draw duplicators for selection too */
- if ((base->object->transflag & OB_DUPLI)) {
- ListBase *lb;
- DupliObject *dob;
- Base tbase;
-
- tbase.flag = OB_FROMDUPLI;
- lb = object_duplilist(G.main->eval_ctx, scene, base->object);
-
- for (dob = lb->first; dob; dob = dob->next) {
- float omat[4][4];
-
- tbase.object = dob->ob;
- copy_m4_m4(omat, dob->ob->obmat);
- copy_m4_m4(dob->ob->obmat, dob->mat);
-
- /* extra service: draw the duplicator in drawtype of parent */
- /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
- dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
- dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx;
-
- draw_object(scene, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR);
-
- tbase.object->dt = dt;
- tbase.object->dtx = dtx;
-
- copy_m4_m4(dob->ob->obmat, omat);
- }
- free_object_duplilist(lb);
- }
- code++;
- }
- }
- }
- v3d->xray = false; /* restore */
+ /* second pass, to get the closest object to camera */
+ if (do_passes) {
+ GPU_select_begin(buffer, bufsize, &selrect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+
+ view3d_select_loop(vc, scene, v3d, ar, use_obedit_skip);
+
+ GPU_select_end();
}
-
- glPopName(); /* see above (pushname) */
- hits = glRenderMode(GL_RENDER);
-
+
G.f &= ~G_PICKSEL;
view3d_winmatrix_set(ar, v3d, NULL);
mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat);
@@ -1285,7 +1312,7 @@ static bool view3d_localview_init(
return ok;
}
-static void restore_localviewdata(wmWindowManager *wm, wmWindow *win, Main *bmain, ScrArea *sa, const int smooth_viewtx)
+static void restore_localviewdata(wmWindowManager *wm, wmWindow *win, Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx)
{
const bool free = true;
ARegion *ar;
@@ -1335,7 +1362,7 @@ static void restore_localviewdata(wmWindowManager *wm, wmWindow *win, Main *bmai
}
}
- ED_view3d_shade_update(bmain, v3d, sa);
+ ED_view3d_shade_update(bmain, scene, v3d, sa);
}
}
}
@@ -1352,7 +1379,7 @@ static bool view3d_localview_exit(
locallay = v3d->lay & 0xFF000000;
- restore_localviewdata(wm, win, bmain, sa, smooth_viewtx);
+ restore_localviewdata(wm, win, bmain, scene, sa, smooth_viewtx);
/* for when in other window the layers have changed */
if (v3d->scenelock) v3d->lay = scene->lay;
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 1c3e223f3ed..7bdf39d6768 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -60,10 +60,8 @@
#include "view3d_intern.h" /* own include */
-#define EARTH_GRAVITY 9.80668f /* m/s2 */
-
/* prototypes */
-static float getVelocityZeroTime(float velocity);
+static float getVelocityZeroTime(const float gravity, const float velocity);
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
enum {
@@ -280,7 +278,8 @@ typedef struct WalkInfo {
bool is_reversed;
/* gravity system */
- eWalkGravityState gravity;
+ eWalkGravityState gravity_state;
+ float gravity;
/* height to use in walk mode */
float view_height;
@@ -360,11 +359,11 @@ static void walk_navigation_mode_set(bContext *C, WalkInfo *walk, eWalkMethod mo
{
if (mode == WALK_MODE_FREE) {
walk->navigation_mode = WALK_MODE_FREE;
- walk->gravity = WALK_GRAVITY_STATE_OFF;
+ walk->gravity_state = WALK_GRAVITY_STATE_OFF;
}
else { /* WALK_MODE_GRAVITY */
walk->navigation_mode = WALK_MODE_GRAVITY;
- walk->gravity = WALK_GRAVITY_STATE_START;
+ walk->gravity_state = WALK_GRAVITY_STATE_START;
}
walk_update_header(C, walk);
@@ -510,7 +509,14 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->speed = U.walk_navigation.walk_speed;
walk->speed_factor = U.walk_navigation.walk_speed_factor;
- walk->gravity = WALK_GRAVITY_STATE_OFF;
+ walk->gravity_state = WALK_GRAVITY_STATE_OFF;
+
+ if ((walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)) {
+ walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]);
+ }
+ else {
+ walk->gravity = 9.80668f; /* m/s2 */
+ }
walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0);
@@ -532,7 +538,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->rv3d->rflag |= RV3D_NAVIGATING;
- walk->v3d_camera_control = ED_view3d_cameracontrol_aquire(
+ walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
walk->scene, walk->v3d, walk->rv3d,
(U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
@@ -755,10 +761,10 @@ static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const
#define JUMP_SPEED_MIN 1.0f
#define JUMP_TIME_MAX 0.2f /* s */
-#define JUMP_SPEED_MAX sqrtf(2.0f * EARTH_GRAVITY * walk->jump_height)
+#define JUMP_SPEED_MAX sqrtf(2.0f * walk->gravity * walk->jump_height)
case WALK_MODAL_JUMP_STOP:
- if (walk->gravity == WALK_GRAVITY_STATE_JUMP) {
+ if (walk->gravity_state == WALK_GRAVITY_STATE_JUMP) {
float t;
/* delta time */
@@ -769,21 +775,21 @@ static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const
walk->speed_jump = JUMP_SPEED_MIN + t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX;
/* when jumping, duration is how long it takes before we start going down */
- walk->teleport.duration = getVelocityZeroTime(walk->speed_jump);
+ walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump);
/* no more increase of jump speed */
- walk->gravity = WALK_GRAVITY_STATE_ON;
+ walk->gravity_state = WALK_GRAVITY_STATE_ON;
}
break;
case WALK_MODAL_JUMP:
if ((walk->navigation_mode == WALK_MODE_GRAVITY) &&
- (walk->gravity == WALK_GRAVITY_STATE_OFF) &&
+ (walk->gravity_state == WALK_GRAVITY_STATE_OFF) &&
(walk->teleport.state == WALK_TELEPORT_STATE_OFF))
{
/* no need to check for ground,
* walk->gravity wouldn't be off
* if we were over a hole */
- walk->gravity = WALK_GRAVITY_STATE_JUMP;
+ walk->gravity_state = WALK_GRAVITY_STATE_JUMP;
walk->speed_jump = JUMP_SPEED_MAX;
walk->teleport.initial_time = PIL_check_seconds_timer();
@@ -793,7 +799,7 @@ static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const
copy_v2_v2(walk->teleport.direction, walk->dvec_prev);
/* when jumping, duration is how long it takes before we start going down */
- walk->teleport.duration = getVelocityZeroTime(walk->speed_jump);
+ walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump);
}
break;
@@ -853,14 +859,14 @@ static void walkMoveCamera(bContext *C, WalkInfo *walk,
ED_view3d_cameracontrol_update(walk->v3d_camera_control, true, C, do_rotate, do_translate);
}
-static float getFreeFallDistance(const float time)
+static float getFreeFallDistance(const float gravity, const float time)
{
- return EARTH_GRAVITY * (time * time) * 0.5f;
+ return gravity * (time * time) * 0.5f;
}
-static float getVelocityZeroTime(float velocity)
+static float getVelocityZeroTime(const float gravity, const float velocity)
{
- return velocity / EARTH_GRAVITY;
+ return velocity / gravity;
}
static int walkApply(bContext *C, WalkInfo *walk)
@@ -910,7 +916,7 @@ static int walkApply(bContext *C, WalkInfo *walk)
if ((walk->active_directions) ||
moffset[0] || moffset[1] ||
walk->teleport.state == WALK_TELEPORT_STATE_ON ||
- walk->gravity != WALK_GRAVITY_STATE_OFF)
+ walk->gravity_state != WALK_GRAVITY_STATE_OFF)
{
float dvec_tmp[3];
@@ -1000,7 +1006,7 @@ static int walkApply(bContext *C, WalkInfo *walk)
/* WASD - 'move' translation code */
if ((walk->active_directions) &&
- (walk->gravity == WALK_GRAVITY_STATE_OFF))
+ (walk->gravity_state == WALK_GRAVITY_STATE_OFF))
{
short direction;
@@ -1076,7 +1082,7 @@ static int walkApply(bContext *C, WalkInfo *walk)
/* stick to the floor */
if (walk->navigation_mode == WALK_MODE_GRAVITY &&
- ELEM(walk->gravity,
+ ELEM(walk->gravity_state,
WALK_GRAVITY_STATE_OFF,
WALK_GRAVITY_STATE_START))
{
@@ -1101,13 +1107,13 @@ static int walkApply(bContext *C, WalkInfo *walk)
dvec[2] -= difference;
/* in case we switched from FREE to GRAVITY too close to the ground */
- if (walk->gravity == WALK_GRAVITY_STATE_START)
- walk->gravity = WALK_GRAVITY_STATE_OFF;
+ if (walk->gravity_state == WALK_GRAVITY_STATE_START)
+ walk->gravity_state = WALK_GRAVITY_STATE_OFF;
}
else {
/* hijack the teleport variables */
walk->teleport.initial_time = PIL_check_seconds_timer();
- walk->gravity = WALK_GRAVITY_STATE_ON;
+ walk->gravity_state = WALK_GRAVITY_STATE_ON;
walk->teleport.duration = 0.0f;
copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
@@ -1117,7 +1123,7 @@ static int walkApply(bContext *C, WalkInfo *walk)
}
/* Falling or jumping) */
- if (ELEM(walk->gravity, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) {
+ if (ELEM(walk->gravity_state, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) {
float t;
float z_cur, z_new;
bool ret;
@@ -1130,7 +1136,7 @@ static int walkApply(bContext *C, WalkInfo *walk)
copy_v2_v2(dvec, walk->teleport.direction);
z_cur = walk->rv3d->viewinv[3][2];
- z_new = walk->teleport.origin[2] - getFreeFallDistance(t) * walk->grid;
+ z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid;
/* jump */
z_new += t * walk->speed_jump * walk->grid;
@@ -1148,7 +1154,7 @@ static int walkApply(bContext *C, WalkInfo *walk)
if (difference > 0.0f) {
/* quit falling, lands at "view_height" from the floor */
dvec[2] -= difference;
- walk->gravity = WALK_GRAVITY_STATE_OFF;
+ walk->gravity_state = WALK_GRAVITY_STATE_OFF;
walk->speed_jump = 0.0f;
}
else {
@@ -1334,5 +1340,3 @@ void VIEW3D_OT_walk(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING;
}
-
-#undef EARTH_GRAVITY
diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript
index f3c8c13647a..4f47062e3a3 100644
--- a/source/blender/editors/transform/SConscript
+++ b/source/blender/editors/transform/SConscript
@@ -40,6 +40,7 @@ incs = [
'../../ikplugin',
'../../makesdna',
'../../makesrna',
+ '../../gpu',
'../../windowmanager',
]
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 42cc6b14fd5..9092dbd52dd 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -86,6 +86,9 @@
#include "transform.h"
+/* Disabling, since when you type you know what you are doing, and being able to set it to zero is handy. */
+// #define USE_NUM_NO_ZERO
+
#define MAX_INFO_LEN 256
static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg);
@@ -190,9 +193,9 @@ static bool transdata_check_local_center(TransInfo *t, short around)
{
return ((around == V3D_LOCAL) && (
(t->flag & (T_OBJECT | T_POSE)) ||
- (t->obedit && ELEM4(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)) ||
+ (t->obedit && ELEM(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)) ||
(t->spacetype == SPACE_IPO) ||
- (t->options & (CTX_MOVIECLIP | CTX_MASK)))
+ (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE)))
);
}
@@ -263,17 +266,27 @@ static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy)
void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
{
if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
- const float mval_f[2] = {(float)dx, (float)dy};
- ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac);
+ if (t->options & CTX_PAINT_CURVE) {
+ r_vec[0] = dx;
+ r_vec[1] = dy;
+ }
+ else { const float mval_f[2] = {(float)dx, (float)dy};
+ ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac);
+ }
}
else if (t->spacetype == SPACE_IMAGE) {
float aspx, aspy;
if (t->options & CTX_MASK) {
-
convertViewVec2D_mask(t->view, r_vec, dx, dy);
ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ r_vec[0] = dx;
+ r_vec[1] = dy;
+
+ aspx = aspy = 1.0;
+ }
else {
convertViewVec2D(t->view, r_vec, dx, dy);
ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
@@ -351,6 +364,10 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
adr[0] = v[0];
adr[1] = v[1];
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ adr[0] = vec[0];
+ adr[1] = vec[1];
+ }
else {
float aspx, aspy, v[2];
@@ -452,7 +469,11 @@ void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV
switch (t->spacetype) {
case SPACE_VIEW3D:
{
- if (t->ar->regiontype == RGN_TYPE_WINDOW) {
+ if (t->options & CTX_PAINT_CURVE) {
+ adr[0] = vec[0];
+ adr[1] = vec[1];
+ }
+ else if (t->ar->regiontype == RGN_TYPE_WINDOW) {
/* allow points behind the view [#33643] */
if (ED_view3d_project_float_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) {
/* XXX, 2.64 and prior did this, weak! */
@@ -480,7 +501,7 @@ void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
void applyAspectRatio(TransInfo *t, float vec[2])
{
- if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
+ if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION) && !(t->options & CTX_PAINT_CURVE)) {
SpaceImage *sima = t->sa->spacedata.first;
float aspx, aspy;
@@ -557,17 +578,23 @@ void removeAspectRatio(TransInfo *t, float vec[2])
static void viewRedrawForce(const bContext *C, TransInfo *t)
{
if (t->spacetype == SPACE_VIEW3D) {
- /* Do we need more refined tags? */
- if (t->flag & T_POSE)
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- else
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ if (t->options & CTX_PAINT_CURVE) {
+ wmWindow *window = CTX_wm_window(C);
+ WM_paint_cursor_tag_redraw(window, t->ar);
+ }
+ else {
+ /* Do we need more refined tags? */
+ if (t->flag & T_POSE)
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ else
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- /* for realtime animation record - send notifiers recognised by animation editors */
- // XXX: is this notifier a lame duck?
- if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
-
+ /* for realtime animation record - send notifiers recognised by animation editors */
+ // XXX: is this notifier a lame duck?
+ if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
+
+ }
}
else if (t->spacetype == SPACE_ACTION) {
//SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
@@ -593,6 +620,10 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ wmWindow *window = CTX_wm_window(C);
+ WM_paint_cursor_tag_redraw(window, t->ar);
+ }
else {
// XXX how to deal with lock?
SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
@@ -646,7 +677,7 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
allqueue(REDRAWIMAGE, 0);
allqueue(REDRAWVIEW3D, 0);
}
- else if (ELEM3(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_IPO)) {
+ else if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_IPO)) {
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWNLA, 0);
@@ -969,7 +1000,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case TFM_MODAL_TRANSLATE:
/* only switch when... */
- if (ELEM5(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
resetTransModal(t);
resetTransRestrictions(t);
restoreTransObjects(t);
@@ -1025,7 +1056,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
case TFM_MODAL_ROTATE:
/* only switch when... */
if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) {
- if (ELEM6(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
resetTransModal(t);
resetTransRestrictions(t);
@@ -1045,7 +1076,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case TFM_MODAL_RESIZE:
/* only switch when... */
- if (ELEM5(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
/* Scale isn't normally very useful after extrude along normals, see T39756 */
if ((t->con.mode & CON_APPLY) && (t->con.orientation == V3D_MANIP_NORMAL)) {
@@ -1308,7 +1339,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case GKEY:
/* only switch when... */
- if (ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
resetTransModal(t);
resetTransRestrictions(t);
restoreTransObjects(t);
@@ -1320,7 +1351,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case SKEY:
/* only switch when... */
- if (ELEM3(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL) ) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL)) {
resetTransModal(t);
resetTransRestrictions(t);
restoreTransObjects(t);
@@ -1333,7 +1364,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
case RKEY:
/* only switch when... */
if (!(t->options & CTX_TEXTURE)) {
- if (ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) {
resetTransModal(t);
resetTransRestrictions(t);
@@ -1807,23 +1838,25 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar)
BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
- xco = rect.xmax - (int)printable_size[0] - 10;
- yco = rect.ymax - (int)printable_size[1] - 10;
+ xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
+ yco = (rect.ymax - U.widget_unit);
/* warning text (to clarify meaning of overlays)
* - original color was red to match the icon, but that clashes badly with a less nasty border
*/
UI_ThemeColorShade(TH_TEXT_HI, -50);
#ifdef WITH_INTERNATIONAL
- BLF_draw_default(xco, ar->winy - 17, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
#else
- BLF_draw_default_ascii(xco, ar->winy - 17, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
#endif
/* autokey recording icon... */
glEnable(GL_BLEND);
- xco -= (ICON_DEFAULT_WIDTH + 2);
+ xco -= U.widget_unit;
+ yco -= (int)printable_size[1] / 2;
+
UI_icon_draw(xco, yco, ICON_REC);
glDisable(GL_BLEND);
@@ -2064,7 +2097,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
* moded are available from manipulator and doing such check could
* lead to keymap conflicts for other modes (see #31584)
*/
- if (ELEM3(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) {
+ if (ELEM(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) {
wmKeyMapItem *kmi;
for (kmi = t->keymap->items.first; kmi; kmi = kmi->next) {
@@ -2840,7 +2873,7 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN * 2];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bend Angle: %s Radius: %s Alt, Clamp %s"),
&c[0], &c[NUM_STR_REP_LEN],
@@ -3008,7 +3041,7 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shear: %s %s"), c, t->proptext);
}
@@ -3084,9 +3117,11 @@ static void initResize(TransInfo *t)
t->num.flag |= NUM_AFFECT_ALL;
if (!t->obedit) {
t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
t->num.val_flag[1] |= NUM_NO_ZERO;
t->num.val_flag[2] |= NUM_NO_ZERO;
+#endif
}
t->idx_max = 2;
@@ -3107,7 +3142,7 @@ static void headerResize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
char tvec[NUM_STR_REP_LEN * 3];
size_t ofs = 0;
if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
}
else {
BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
@@ -3376,9 +3411,11 @@ static void initSkinResize(TransInfo *t)
t->num.flag |= NUM_AFFECT_ALL;
if (!t->obedit) {
t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
t->num.val_flag[1] |= NUM_NO_ZERO;
t->num.val_flag[2] |= NUM_NO_ZERO;
+#endif
}
t->idx_max = 2;
@@ -3519,7 +3556,7 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("To Sphere: %s %s"), c, t->proptext);
}
@@ -3591,8 +3628,15 @@ static void initRotation(TransInfo *t)
if (t->flag & T_2D_EDIT)
t->flag |= T_NO_CONSTRAINT;
- negate_v3_v3(t->axis, t->viewinv[2]);
- normalize_v3(t->axis);
+ if (t->options & CTX_PAINT_CURVE) {
+ t->axis[0] = 0.0;
+ t->axis[1] = 0.0;
+ t->axis[2] = -1.0;
+ }
+ else {
+ negate_v3_v3(t->axis, t->viewinv[2]);
+ normalize_v3(t->axis);
+ }
copy_v3_v3(t->axis_orig, t->axis);
}
@@ -3626,7 +3670,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
if (td->flag & TD_USEQUAT) {
- mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(fmat, td->smtx, mat, td->mtx);
mat3_to_quat(quat, fmat); // Actual transform
if (td->ext->quat) {
@@ -3696,7 +3740,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't rotate objects itself */
/* euler or quaternion/axis-angle? */
if (td->ext->rotOrder == ROT_MODE_QUAT) {
- mul_serie_m3(fmat, td->ext->r_mtx, mat, td->ext->r_smtx, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx);
mat3_to_quat(quat, fmat); /* Actual transform */
@@ -3711,7 +3755,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
- mul_serie_m3(fmat, td->ext->r_mtx, mat, td->ext->r_smtx, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx);
mat3_to_quat(quat, fmat); /* Actual transform */
mul_qt_qtqt(tquat, quat, iquat);
@@ -3768,7 +3812,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) {
/* can be called for texture space translate for example, then opt out */
if (td->ext->quat) {
- mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(fmat, td->smtx, mat, td->mtx);
mat3_to_quat(quat, fmat); // Actual transform
mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
@@ -3782,7 +3826,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
- mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(fmat, td->smtx, mat, td->mtx);
mat3_to_quat(quat, fmat); // Actual transform
mul_qt_qtqt(tquat, quat, iquat);
@@ -3876,7 +3920,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext);
}
@@ -3980,7 +4024,7 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN * 2];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Trackball: %s %s %s"),
&c[0], &c[NUM_STR_REP_LEN], t->proptext);
@@ -4082,7 +4126,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char str[MAX_INFO_LEN]
float dist;
if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
dist = len_v3(t->num.val);
}
else {
@@ -4330,7 +4374,7 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Shrink/Fatten:"), MAX_INFO_LEN - ofs);
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, " %s", c);
}
else {
@@ -4425,7 +4469,7 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Tilt: %s° %s"), &c[0], t->proptext);
@@ -4479,7 +4523,9 @@ static void initCurveShrinkFatten(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE;
t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
+#endif
t->flag |= T_NO_CONSTRAINT;
}
@@ -4501,7 +4547,7 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %s"), c);
}
else {
@@ -4554,7 +4600,9 @@ static void initMaskShrinkFatten(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE;
t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
+#endif
t->flag |= T_NO_CONSTRAINT;
}
@@ -4577,7 +4625,7 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Feather Shrink/Fatten: %s"), c);
}
else {
@@ -4670,7 +4718,7 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext);
}
@@ -4763,7 +4811,7 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
if (weight >= 0.0f)
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: +%s %s"), c, t->proptext);
@@ -4841,7 +4889,7 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
if (crease >= 0.0f)
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: +%s %s"), c, t->proptext);
@@ -4911,7 +4959,7 @@ static void headerBoneSize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
}
else {
BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
@@ -5048,7 +5096,7 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Envelope: %s"), c);
}
else {
@@ -6222,7 +6270,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
if (is_proportional) {
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s"),
@@ -6744,7 +6792,7 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Vert Slide: "), MAX_INFO_LEN - ofs);
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
ofs += BLI_strncpy_rlen(str + ofs, &c[0], MAX_INFO_LEN - ofs);
}
else {
@@ -6811,7 +6859,7 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Roll: %s"), &c[0]);
}
@@ -6885,7 +6933,7 @@ static void applyBakeTime(TransInfo *t, const int mval[2])
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), c, &t->scene->unit);
if (time >= 0.0f)
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: +%s %s"), c, t->proptext);
@@ -7096,7 +7144,7 @@ static void headerSeqSlide(TransInfo *t, float val[2], char str[MAX_INFO_LEN])
size_t ofs = 0;
if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
}
else {
BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]);
@@ -7322,7 +7370,7 @@ static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN])
/* if numeric input is active, use results from that, otherwise apply snapping to result */
if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
}
else {
const Scene *scene = t->scene;
@@ -7486,7 +7534,7 @@ static void headerTimeSlide(TransInfo *t, float sval, char str[MAX_INFO_LEN])
char tvec[NUM_STR_REP_LEN * 3];
if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
}
else {
float minx = *((float *)(t->customData));
@@ -7634,7 +7682,7 @@ static void headerTimeScale(TransInfo *t, char str[MAX_INFO_LEN])
char tvec[NUM_STR_REP_LEN * 3];
if (hasNumInput(&t->num))
- outputNumInput(&(t->num), tvec, t->scene->unit.scale_length);
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
else
BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values[0]);
@@ -7704,7 +7752,7 @@ bool checkUseAxisMatrix(TransInfo *t)
{
/* currently only checks for editmode */
if (t->flag & T_EDIT) {
- if ((t->around == V3D_LOCAL) && (ELEM4(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) {
+ if ((t->around == V3D_LOCAL) && (ELEM(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) {
/* not all editmode supports axis-matrix */
return true;
}
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 0bccf177128..012f9185d8b 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -130,15 +130,15 @@ typedef struct TransDataExtension {
// float drotAxis[3]; /* Initial object drotAxis, TODO: not yet implemented */
float dquat[4]; /* Initial object dquat */
float dscale[3]; /* Initial object dscale */
- float *rot; /* Rotation of the data to transform (Faculative) */
+ float *rot; /* Rotation of the data to transform */
float irot[3]; /* Initial rotation */
- float *quat; /* Rotation quaternion of the data to transform (Faculative) */
+ float *quat; /* Rotation quaternion of the data to transform */
float iquat[4]; /* Initial rotation quaternion */
- float *rotAngle; /* Rotation angle of the data to transform (Faculative) */
+ float *rotAngle; /* Rotation angle of the data to transform */
float irotAngle; /* Initial rotation angle */
- float *rotAxis; /* Rotation axis of the data to transform (Faculative) */
+ float *rotAxis; /* Rotation axis of the data to transform */
float irotAxis[4]; /* Initial rotation axis */
- float *size; /* Size of the data to transform (Faculative) */
+ float *size; /* Size of the data to transform */
float isize[3]; /* Initial size */
float obmat[4][4]; /* Object matrix */
float l_smtx[3][3]; /* use instead of td->smtx, It is the same but without the 'bone->bone_mat', see TD_PBONE_LOCAL_MTX_C */
@@ -532,6 +532,7 @@ void flushTransNodes(TransInfo *t);
void flushTransSeq(TransInfo *t);
void flushTransTracking(TransInfo *t);
void flushTransMasking(TransInfo *t);
+void flushTransPaintCurve(TransInfo *t);
void restoreBones(TransInfo *t);
/*********************** exported from transform_manipulator.c ********** */
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 79f266df607..d8f17315c01 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -663,7 +663,7 @@ void drawConstraint(TransInfo *t)
{
TransCon *tc = &(t->con);
- if (!ELEM3(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE))
+ if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE))
return;
if (!(tc->mode & CON_APPLY))
return;
@@ -756,6 +756,9 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
/* untested - mask aspect is TODO */
ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ aspx = aspy = 1.0;
+ }
else {
ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 9dfd3e568e5..aa215613841 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -33,6 +33,7 @@
#include <math.h>
#include "DNA_anim_types.h"
+#include "DNA_brush_types.h"
#include "DNA_armature_types.h"
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
@@ -80,6 +81,7 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_particle.h"
+#include "BKE_paint.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
@@ -124,8 +126,8 @@
static void transform_around_single_fallback(TransInfo *t)
{
if ((t->total == 1) &&
- (ELEM3(t->around, V3D_CENTER, V3D_CENTROID, V3D_ACTIVE)) &&
- (ELEM3(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL)))
+ (ELEM(t->around, V3D_CENTER, V3D_CENTROID, V3D_ACTIVE)) &&
+ (ELEM(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL)))
{
t->around = V3D_LOCAL;
}
@@ -282,7 +284,7 @@ static void createTransTexspace(TransInfo *t)
}
id = ob->data;
- if (id == NULL || !ELEM3(GS(id->name), ID_ME, ID_CU, ID_MB)) {
+ if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) {
BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform");
t->total = 0;
return;
@@ -584,12 +586,12 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr
if (constraints_list_needinv(t, &pchan->constraints)) {
copy_m3_m4(tmat, pchan->constinv);
invert_m3_m3(cmat, tmat);
- mul_serie_m3(td->mtx, pmat, omat, cmat, NULL, NULL, NULL, NULL, NULL);
- mul_serie_m3(td->ext->r_mtx, rpmat, omat, cmat, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(td->mtx, cmat, omat, pmat);
+ mul_m3_series(td->ext->r_mtx, cmat, omat, rpmat);
}
else {
- mul_serie_m3(td->mtx, pmat, omat, NULL, NULL, NULL, NULL, NULL, NULL);
- mul_serie_m3(td->ext->r_mtx, rpmat, omat, NULL, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(td->mtx, omat, pmat);
+ mul_m3_series(td->ext->r_mtx, omat, rpmat);
}
invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx);
}
@@ -1279,7 +1281,7 @@ static void createTransArmatureVerts(TransInfo *t)
}
}
- if (mirror && total_mirrored) {
+ if (mirror) {
/* trick to terminate iteration */
bid[total_mirrored].bone = NULL;
}
@@ -2368,8 +2370,7 @@ static void createTransEditVerts(TransInfo *t)
quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]);
if (defmats)
- mul_serie_m3(mat, mtx, qmat, defmats[a],
- NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(mat, defmats[a], qmat, mtx);
else
mul_m3_m3m3(mat, mtx, qmat);
}
@@ -3707,7 +3708,7 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *
static bool graph_edit_is_translation_mode(TransInfo *t)
{
- return ELEM4(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE);
+ return ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE);
}
static bool graph_edit_use_local_center(TransInfo *t)
@@ -4767,12 +4768,12 @@ static bool constraints_list_needinv(TransInfo *t, ListBase *list)
if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) {
/* (affirmative) returns for specific constraints here... */
/* constraints that require this regardless */
- if (ELEM5(con->type,
- CONSTRAINT_TYPE_CHILDOF,
- CONSTRAINT_TYPE_FOLLOWPATH,
- CONSTRAINT_TYPE_CLAMPTO,
- CONSTRAINT_TYPE_OBJECTSOLVER,
- CONSTRAINT_TYPE_FOLLOWTRACK))
+ if (ELEM(con->type,
+ CONSTRAINT_TYPE_CHILDOF,
+ CONSTRAINT_TYPE_FOLLOWPATH,
+ CONSTRAINT_TYPE_CLAMPTO,
+ CONSTRAINT_TYPE_OBJECTSOLVER,
+ CONSTRAINT_TYPE_FOLLOWTRACK))
{
return true;
}
@@ -5848,6 +5849,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ /* pass */
+ }
else if ((t->scene->basact) &&
(ob = t->scene->basact->object) &&
(ob->mode & OB_MODE_PARTICLE_EDIT) &&
@@ -7027,6 +7031,173 @@ void flushTransMasking(TransInfo *t)
}
}
+typedef struct TransDataPaintCurve {
+ PaintCurvePoint *pcp; /* initial curve point */
+ char id;
+} TransDataPaintCurve;
+
+
+#define PC_IS_ANY_SEL(pc) (((pc)->bez.f1 | (pc)->bez.f2 | (pc)->bez.f3) & SELECT)
+
+static void PaintCurveConvertHandle(PaintCurvePoint *pcp, int id, TransData2D *td2d, TransDataPaintCurve *tdpc, TransData *td)
+{
+ BezTriple *bezt = &pcp->bez;
+ copy_v2_v2(td2d->loc, bezt->vec[id]);
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = bezt->vec[id];
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, bezt->vec[1]);
+ copy_v3_v3(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+
+ tdpc->id = id;
+ tdpc->pcp = pcp;
+}
+
+static void PaintCurvePointToTransData(PaintCurvePoint *pcp, TransData *td, TransData2D *td2d, TransDataPaintCurve *tdpc)
+{
+ BezTriple *bezt = &pcp->bez;
+
+ if (pcp->bez.f2 == SELECT) {
+ int i;
+ for (i = 0; i < 3; i++) {
+ copy_v2_v2(td2d->loc, bezt->vec[i]);
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = bezt->vec[i];
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, bezt->vec[1]);
+ copy_v3_v3(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+
+ tdpc->id = i;
+ tdpc->pcp = pcp;
+
+ td++;
+ td2d++;
+ tdpc++;
+ }
+ }
+ else {
+ if (bezt->f3 & SELECT) {
+ PaintCurveConvertHandle(pcp, 2, td2d, tdpc, td);
+ td2d++;
+ tdpc++;
+ td++;
+ }
+
+ if (bezt->f1 & SELECT) {
+ PaintCurveConvertHandle(pcp, 0, td2d, tdpc, td);
+ }
+ }
+}
+
+static void createTransPaintCurveVerts(bContext *C, TransInfo *t)
+{
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ PaintCurve *pc;
+ PaintCurvePoint *pcp;
+ Brush *br;
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ TransDataPaintCurve *tdpc = NULL;
+ int i;
+ int total = 0;
+
+ t->total = 0;
+
+ if (!paint || !paint->brush || !paint->brush->paint_curve)
+ return;
+
+ br = paint->brush;
+ pc = br->paint_curve;
+
+ for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
+ if (PC_IS_ANY_SEL(pcp)) {
+ if (pcp->bez.f2 & SELECT) {
+ total += 3;
+ continue;
+ }
+ else {
+ if (pcp->bez.f1 & SELECT)
+ total++;
+ if (pcp->bez.f3 & SELECT)
+ total++;
+ }
+ }
+ }
+
+ if (!total)
+ return;
+
+ t->total = total;
+ td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransData2D");
+ td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransData");
+ tdpc = t->customData = MEM_callocN(t->total * sizeof(TransDataPaintCurve), "TransDataPaintCurve");
+ t->flag |= T_FREE_CUSTOMDATA;
+
+ for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
+ if (PC_IS_ANY_SEL(pcp)) {
+ PaintCurvePointToTransData (pcp, td, td2d, tdpc);
+
+ if (pcp->bez.f2 & SELECT) {
+ td += 3;
+ td2d += 3;
+ tdpc += 3;
+ }
+ else {
+ if (pcp->bez.f1 & SELECT) {
+ td++;
+ td2d++;
+ tdpc++;
+ }
+ if (pcp->bez.f3 & SELECT) {
+ td++;
+ td2d++;
+ tdpc++;
+ }
+ }
+ }
+ }
+}
+
+
+void flushTransPaintCurve(TransInfo *t)
+{
+ int i;
+ TransData2D *td2d = t->data2d;
+ TransDataPaintCurve *tdpc = (TransDataPaintCurve *)t->customData;
+
+ for (i = 0; i < t->total; i++, tdpc++, td2d++) {
+ PaintCurvePoint *pcp = tdpc->pcp;
+ copy_v2_v2(pcp->bez.vec[tdpc->id], td2d->loc);
+ }
+}
+
+
void createTransData(bContext *C, TransInfo *t)
{
Scene *scene = t->scene;
@@ -7059,6 +7230,10 @@ void createTransData(bContext *C, TransInfo *t)
sort_trans_data_dist(t);
}
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN))
+ createTransPaintCurveVerts(C, t);
+ }
else if (t->obedit) {
createTransUVs(C, t);
if (t->data && (t->flag & T_PROP_EDIT)) {
@@ -7165,7 +7340,7 @@ void createTransData(bContext *C, TransInfo *t)
// XXX active-layer checking isn't done as that should probably be checked through context instead
createTransPose(t, ob);
}
- else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
+ else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) {
/* important that ob_armature can be set even when its not selected [#23412]
* lines below just check is also visible */
Object *ob_armature = modifiers_isDeformedByArmature(ob);
@@ -7190,12 +7365,11 @@ void createTransData(bContext *C, TransInfo *t)
sort_trans_data_dist(t);
}
}
- else if (ob && (ob->mode & (OB_MODE_ALL_PAINT))) {
- /* sculpt mode and project paint have own undo stack
- * transform ops redo clears sculpt/project undo stack.
- *
- * Could use 'OB_MODE_ALL_PAINT' since there are key conflicts,
- * transform + paint isn't well supported. */
+ else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
+ if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ createTransPaintCurveVerts(C, t);
+ }
}
else {
createTransObject(C, t);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 15d1bb75d89..24dc6f6e74b 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -38,6 +38,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
+#include "DNA_brush_types.h"
#include "DNA_lattice_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
@@ -74,6 +75,7 @@
#include "BKE_lattice.h"
#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_paint.h"
#include "BKE_sequencer.h"
#include "BKE_editmesh.h"
#include "BKE_tracking.h"
@@ -98,6 +100,7 @@
#include "WM_api.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "transform.h"
@@ -262,7 +265,7 @@ static void animrecord_check_state(Scene *scene, ID *id, wmTimer *animtimer)
ScreenAnimData *sad = (animtimer) ? animtimer->customdata : NULL;
/* sanity checks */
- if (ELEM3(NULL, scene, id, sad))
+ if (ELEM(NULL, scene, id, sad))
return;
/* check if we need a new strip if:
@@ -653,6 +656,9 @@ static void recalcData_image(TransInfo *t)
if (t->options & CTX_MASK) {
recalcData_mask_common(t);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ flushTransPaintCurve(t);
+ }
else if (t->obedit && t->obedit->type == OB_MESH) {
SpaceImage *sima = t->sa->spacedata.first;
@@ -817,7 +823,7 @@ static void recalcData_objects(TransInfo *t)
}
}
- if (!ELEM3(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONESIZE)) {
+ if (!ELEM(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONESIZE)) {
/* fix roll */
for (i = 0; i < t->total; i++, td++) {
if (td->extra) {
@@ -965,6 +971,9 @@ void recalcData(TransInfo *t)
else if (t->options & CTX_EDGE) {
recalcData_objects(t);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ flushTransPaintCurve(t);
+ }
else if (t->spacetype == SPACE_IMAGE) {
recalcData_image(t);
}
@@ -1073,6 +1082,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
ARegion *ar = CTX_wm_region(C);
ScrArea *sa = CTX_wm_area(C);
Object *obedit = CTX_data_edit_object(C);
+ Object *ob = CTX_data_active_object(C);
PropertyRNA *prop;
t->scene = sce;
@@ -1193,11 +1203,18 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
/* exceptional case */
if (t->around == V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
- if (ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
t->options |= CTX_NO_PET;
}
}
+ if (ob && ob->mode & OB_MODE_ALL_PAINT) {
+ Paint *p = BKE_paint_get_active_from_context(C);
+ if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
+ t->options |= CTX_PAINT_CURVE;
+ }
+ }
+
/* initialize UV transform from */
if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) {
if (RNA_property_is_set(op->ptr, prop)) {
@@ -1226,9 +1243,13 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
else if (sima->mode == SI_MODE_MASK) {
t->options |= CTX_MASK;
}
- else {
- /* image not in uv edit, nor in mask mode, can happen for some tools */
+ else if (sima->mode == SI_MODE_PAINT) {
+ Paint *p = &sce->toolsettings->imapaint.paint;
+ if (p->brush && (p->brush->flag & BRUSH_CURVE)) {
+ t->options |= CTX_PAINT_CURVE;
+ }
}
+ /* image not in uv edit, nor in mask mode, can happen for some tools */
}
else if (t->spacetype == SPACE_NODE) {
// XXX for now, get View2D from the active region
@@ -1409,7 +1430,7 @@ void postTrans(bContext *C, TransInfo *t)
}
if (t->spacetype == SPACE_IMAGE) {
- if (t->options & CTX_MASK) {
+ if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
/* pass */
}
else {
@@ -1539,6 +1560,13 @@ void calculateCenterCursor(TransInfo *t, float r_center[3])
invert_m3_m3(imat, mat);
mul_m3_v3(imat, r_center);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ if (ED_view3d_project_float_global(t->ar, cursor, r_center, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
+ r_center[0] = t->ar->winx / 2.0f;
+ r_center[1] = t->ar->winy / 2.0f;
+ }
+ r_center[2] = 0.0f;
+ }
}
void calculateCenterCursor2D(TransInfo *t, float r_center[2])
@@ -1586,6 +1614,12 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2])
r_center[0] = co[0] * aspx;
r_center[1] = co[1] * aspy;
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ if (t->spacetype == SPACE_IMAGE) {
+ r_center[0] = UI_view2d_view_to_region_x(&t->ar->v2d, cursor[0]);
+ r_center[1] = UI_view2d_view_to_region_y(&t->ar->v2d, cursor[1]);
+ }
+ }
else {
r_center[0] = cursor[0] * aspx;
r_center[1] = cursor[1] * aspy;
@@ -1720,6 +1754,14 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
}
}
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ Paint *p = BKE_paint_get_active(t->scene);
+ Brush *br = p->brush;
+ PaintCurve *pc = br->paint_curve;
+ copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
+ r_center[2] = 0.0f;
+ ok = true;
+ }
else {
/* object mode */
Scene *scene = t->scene;
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 36d91c1c630..6441071056f 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -72,6 +72,8 @@
/* local module include */
#include "transform.h"
+#include "GPU_select.h"
+
/* return codes for select, and drawing flags */
#define MAN_TRANS_X (1 << 0)
@@ -858,8 +860,8 @@ static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int co
/* axes */
if (flagx) {
if (is_picksel) {
- if (flagx & MAN_SCALE_X) glLoadName(MAN_SCALE_X);
- else if (flagx & MAN_TRANS_X) glLoadName(MAN_TRANS_X);
+ if (flagx & MAN_SCALE_X) GPU_select_load_id(MAN_SCALE_X);
+ else if (flagx & MAN_TRANS_X) GPU_select_load_id(MAN_TRANS_X);
}
else {
manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0]));
@@ -873,8 +875,8 @@ static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int co
case 1:
if (flagy) {
if (is_picksel) {
- if (flagy & MAN_SCALE_Y) glLoadName(MAN_SCALE_Y);
- else if (flagy & MAN_TRANS_Y) glLoadName(MAN_TRANS_Y);
+ if (flagy & MAN_SCALE_Y) GPU_select_load_id(MAN_SCALE_Y);
+ else if (flagy & MAN_TRANS_Y) GPU_select_load_id(MAN_TRANS_Y);
}
else {
manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1]));
@@ -888,8 +890,8 @@ static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int co
case 2:
if (flagz) {
if (is_picksel) {
- if (flagz & MAN_SCALE_Z) glLoadName(MAN_SCALE_Z);
- else if (flagz & MAN_TRANS_Z) glLoadName(MAN_TRANS_Z);
+ if (flagz & MAN_SCALE_Z) GPU_select_load_id(MAN_SCALE_Z);
+ else if (flagz & MAN_TRANS_Z) GPU_select_load_id(MAN_TRANS_Z);
}
else {
manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2]));
@@ -975,7 +977,7 @@ static void draw_manipulator_rotate(
/* Screen aligned trackball rot circle */
if (drawflags & MAN_ROT_T) {
- if (is_picksel) glLoadName(MAN_ROT_T);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_T);
else UI_ThemeColor(TH_TRANSFORM);
drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f * size, unitmat);
@@ -983,7 +985,7 @@ static void draw_manipulator_rotate(
/* Screen aligned view rot circle */
if (drawflags & MAN_ROT_V) {
- if (is_picksel) glLoadName(MAN_ROT_V);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_V);
else UI_ThemeColor(TH_TRANSFORM);
drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f * size, unitmat);
@@ -1062,7 +1064,7 @@ static void draw_manipulator_rotate(
/* Z circle */
if (drawflags & MAN_ROT_Z) {
preOrthoFront(ortho, matt, 2);
- if (is_picksel) glLoadName(MAN_ROT_Z);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
else manipulator_setcolor(v3d, 'Z', colcode, 255);
drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
postOrtho(ortho);
@@ -1070,7 +1072,7 @@ static void draw_manipulator_rotate(
/* X circle */
if (drawflags & MAN_ROT_X) {
preOrthoFront(ortho, matt, 0);
- if (is_picksel) glLoadName(MAN_ROT_X);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_X);
else manipulator_setcolor(v3d, 'X', colcode, 255);
glRotatef(90.0, 0.0, 1.0, 0.0);
drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
@@ -1080,7 +1082,7 @@ static void draw_manipulator_rotate(
/* Y circle */
if (drawflags & MAN_ROT_Y) {
preOrthoFront(ortho, matt, 1);
- if (is_picksel) glLoadName(MAN_ROT_Y);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
else manipulator_setcolor(v3d, 'Y', colcode, 255);
glRotatef(-90.0, 1.0, 0.0, 0.0);
drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
@@ -1097,7 +1099,7 @@ static void draw_manipulator_rotate(
/* Z circle */
if (drawflags & MAN_ROT_Z) {
preOrthoFront(ortho, rv3d->twmat, 2);
- if (is_picksel) glLoadName(MAN_ROT_Z);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
else manipulator_setcolor(v3d, 'Z', colcode, 255);
partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48);
postOrtho(ortho);
@@ -1105,7 +1107,7 @@ static void draw_manipulator_rotate(
/* X circle */
if (drawflags & MAN_ROT_X) {
preOrthoFront(ortho, rv3d->twmat, 0);
- if (is_picksel) glLoadName(MAN_ROT_X);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_X);
else manipulator_setcolor(v3d, 'X', colcode, 255);
glRotatef(90.0, 0.0, 1.0, 0.0);
partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48);
@@ -1115,7 +1117,7 @@ static void draw_manipulator_rotate(
/* Y circle */
if (drawflags & MAN_ROT_Y) {
preOrthoFront(ortho, rv3d->twmat, 1);
- if (is_picksel) glLoadName(MAN_ROT_Y);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
else manipulator_setcolor(v3d, 'Y', colcode, 255);
glRotatef(-90.0, 1.0, 0.0, 0.0);
partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48);
@@ -1132,7 +1134,7 @@ static void draw_manipulator_rotate(
if (drawflags & MAN_ROT_Z) {
preOrthoFront(ortho, rv3d->twmat, 2);
glPushMatrix();
- if (is_picksel) glLoadName(MAN_ROT_Z);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
else manipulator_setcolor(v3d, 'Z', colcode, 255);
partial_doughnut(0.7f * cusize, 1.0f, 31, 33, 8, 64);
@@ -1145,7 +1147,7 @@ static void draw_manipulator_rotate(
if (drawflags & MAN_ROT_Y) {
preOrthoFront(ortho, rv3d->twmat, 1);
glPushMatrix();
- if (is_picksel) glLoadName(MAN_ROT_Y);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
else manipulator_setcolor(v3d, 'Y', colcode, 255);
glRotatef(90.0, 1.0, 0.0, 0.0);
@@ -1160,7 +1162,7 @@ static void draw_manipulator_rotate(
if (drawflags & MAN_ROT_X) {
preOrthoFront(ortho, rv3d->twmat, 0);
glPushMatrix();
- if (is_picksel) glLoadName(MAN_ROT_X);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_X);
else manipulator_setcolor(v3d, 'X', colcode, 255);
glRotatef(-90.0, 0.0, 1.0, 0.0);
@@ -1263,7 +1265,7 @@ static void draw_manipulator_scale(
int shift = 0; // XXX
/* center circle, do not add to selection when shift is pressed (planar constraint) */
- if (is_picksel && shift == 0) glLoadName(MAN_SCALE_C);
+ if (is_picksel && shift == 0) GPU_select_load_id(MAN_SCALE_C);
else manipulator_setcolor(v3d, 'C', colcode, 255);
glPushMatrix();
@@ -1304,7 +1306,7 @@ static void draw_manipulator_scale(
case 0: /* X cube */
if (drawflags & MAN_SCALE_X) {
glTranslatef(dz, 0.0, 0.0);
- if (is_picksel) glLoadName(MAN_SCALE_X);
+ if (is_picksel) GPU_select_load_id(MAN_SCALE_X);
else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0]));
drawsolidcube(cusize);
glTranslatef(-dz, 0.0, 0.0);
@@ -1313,7 +1315,7 @@ static void draw_manipulator_scale(
case 1: /* Y cube */
if (drawflags & MAN_SCALE_Y) {
glTranslatef(0.0, dz, 0.0);
- if (is_picksel) glLoadName(MAN_SCALE_Y);
+ if (is_picksel) GPU_select_load_id(MAN_SCALE_Y);
else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1]));
drawsolidcube(cusize);
glTranslatef(0.0, -dz, 0.0);
@@ -1322,7 +1324,7 @@ static void draw_manipulator_scale(
case 2: /* Z cube */
if (drawflags & MAN_SCALE_Z) {
glTranslatef(0.0, 0.0, dz);
- if (is_picksel) glLoadName(MAN_SCALE_Z);
+ if (is_picksel) GPU_select_load_id(MAN_SCALE_Z);
else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2]));
drawsolidcube(cusize);
glTranslatef(0.0, 0.0, -dz);
@@ -1337,7 +1339,7 @@ static void draw_manipulator_scale(
if (shift) {
glTranslatef(0.0, -dz, 0.0);
- glLoadName(MAN_SCALE_C);
+ GPU_select_load_id(MAN_SCALE_C);
glBegin(GL_POINTS);
glVertex3f(0.0, 0.0, 0.0);
glEnd();
@@ -1399,7 +1401,7 @@ static void draw_manipulator_translate(
glDisable(GL_DEPTH_TEST);
/* center circle, do not add to selection when shift is pressed (planar constraint) */
- if (is_picksel && shift == 0) glLoadName(MAN_TRANS_C);
+ if (is_picksel && shift == 0) GPU_select_load_id(MAN_TRANS_C);
else manipulator_setcolor(v3d, 'C', colcode, 255);
glPushMatrix();
@@ -1412,7 +1414,7 @@ static void draw_manipulator_translate(
glMultMatrixf(rv3d->twmat);
/* axis */
- glLoadName(-1);
+ GPU_select_load_id(-1);
// translate drawn as last, only axis when no combo with scale, or for ghosting
if ((combo & V3D_MANIP_SCALE) == 0 || colcode == MAN_GHOST) {
@@ -1435,7 +1437,7 @@ static void draw_manipulator_translate(
case 0: /* Z Cone */
if (drawflags & MAN_TRANS_Z) {
glTranslatef(0.0, 0.0, dz);
- if (is_picksel) glLoadName(MAN_TRANS_Z);
+ if (is_picksel) GPU_select_load_id(MAN_TRANS_Z);
else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2]));
draw_cone(qobj, cylen, cywid);
glTranslatef(0.0, 0.0, -dz);
@@ -1444,7 +1446,7 @@ static void draw_manipulator_translate(
case 1: /* X Cone */
if (drawflags & MAN_TRANS_X) {
glTranslatef(dz, 0.0, 0.0);
- if (is_picksel) glLoadName(MAN_TRANS_X);
+ if (is_picksel) GPU_select_load_id(MAN_TRANS_X);
else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0]));
glRotatef(90.0, 0.0, 1.0, 0.0);
draw_cone(qobj, cylen, cywid);
@@ -1455,7 +1457,7 @@ static void draw_manipulator_translate(
case 2: /* Y Cone */
if (drawflags & MAN_TRANS_Y) {
glTranslatef(0.0, dz, 0.0);
- if (is_picksel) glLoadName(MAN_TRANS_Y);
+ if (is_picksel) GPU_select_load_id(MAN_TRANS_Y);
else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1]));
glRotatef(-90.0, 1.0, 0.0, 0.0);
draw_cone(qobj, cylen, cywid);
@@ -1503,7 +1505,7 @@ static void draw_manipulator_rotate_cyl(
unit_m4(unitmat);
- if (is_picksel) glLoadName(MAN_ROT_V);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_V);
UI_ThemeColor(TH_TRANSFORM);
drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f * size, unitmat);
@@ -1556,7 +1558,7 @@ static void draw_manipulator_rotate_cyl(
case 0: /* X cylinder */
if (drawflags & MAN_ROT_X) {
glTranslatef(1.0, 0.0, 0.0);
- if (is_picksel) glLoadName(MAN_ROT_X);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_X);
glRotatef(90.0, 0.0, 1.0, 0.0);
manipulator_setcolor(v3d, 'X', colcode, 255);
draw_cylinder(qobj, cylen, cywid);
@@ -1567,7 +1569,7 @@ static void draw_manipulator_rotate_cyl(
case 1: /* Y cylinder */
if (drawflags & MAN_ROT_Y) {
glTranslatef(0.0, 1.0, 0.0);
- if (is_picksel) glLoadName(MAN_ROT_Y);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
glRotatef(-90.0, 1.0, 0.0, 0.0);
manipulator_setcolor(v3d, 'Y', colcode, 255);
draw_cylinder(qobj, cylen, cywid);
@@ -1578,7 +1580,7 @@ static void draw_manipulator_rotate_cyl(
case 2: /* Z cylinder */
if (drawflags & MAN_ROT_Z) {
glTranslatef(0.0, 0.0, 1.0);
- if (is_picksel) glLoadName(MAN_ROT_Z);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
manipulator_setcolor(v3d, 'Z', colcode, 255);
draw_cylinder(qobj, cylen, cywid);
glTranslatef(0.0, 0.0, -1.0);
@@ -1689,10 +1691,11 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
{
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
- rctf rect;
+ rctf rect, selrect;
GLuint buffer[64]; // max 4 items per select, so large enuf
short hits;
const bool is_picksel = true;
+ const bool do_passes = GPU_select_query_check_active();
/* XXX check a bit later on this... (ton) */
extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, rctf *rect);
@@ -1707,13 +1710,15 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
rect.ymin = mval[1] - hotspot;
rect.ymax = mval[1] + hotspot;
+ selrect = rect;
+
view3d_winmatrix_set(ar, v3d, &rect);
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
- glSelectBuffer(64, buffer);
- glRenderMode(GL_SELECT);
- glInitNames(); /* these two calls whatfor? It doesn't work otherwise */
- glPushName(-2);
+ if (do_passes)
+ GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
+ else
+ GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_ALL, 0);
/* do the drawing */
if (v3d->twtype & V3D_MANIP_ROTATE) {
@@ -1725,8 +1730,23 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
if (v3d->twtype & V3D_MANIP_TRANSLATE)
draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
- glPopName();
- hits = glRenderMode(GL_RENDER);
+ hits = GPU_select_end();
+
+ if (do_passes) {
+ GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+
+ /* do the drawing */
+ if (v3d->twtype & V3D_MANIP_ROTATE) {
+ if (G.debug_value == 3) draw_manipulator_rotate_cyl(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
+ else draw_manipulator_rotate(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, false, is_picksel);
+ }
+ if (v3d->twtype & V3D_MANIP_SCALE)
+ draw_manipulator_scale(v3d, rv3d, MAN_SCALE_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
+ if (v3d->twtype & V3D_MANIP_TRANSLATE)
+ draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
+
+ GPU_select_end();
+ }
view3d_winmatrix_set(ar, v3d, NULL);
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 7bdbbf7289d..81e065ee33a 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -26,6 +26,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -49,6 +50,8 @@
#include "UI_resources.h"
#include "ED_screen.h"
+/* for USE_LOOPSLIDE_HACK only */
+#include "ED_mesh.h"
#include "transform.h"
@@ -881,6 +884,27 @@ static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot)
Transform_Properties(ot, P_SNAP);
}
+static int edge_bevelweight_exec(bContext *C, wmOperator *op)
+{
+ Mesh *me = (Mesh *)CTX_data_edit_object(C)->data;
+
+ /* auto-enable bevel edge weight drawing, then chain to common transform code */
+ me->drawflag |= ME_DRAWBWEIGHTS;
+
+ return transform_exec(C, op);
+}
+
+static int edge_bevelweight_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Mesh *me = (Mesh *)CTX_data_edit_object(C)->data;
+
+ /* auto-enable bevel edge weight drawing, then chain to common transform code */
+ me->drawflag |= ME_DRAWBWEIGHTS;
+
+ return transform_invoke(C, op, event);
+}
+
+
static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot)
{
/* identifiers */
@@ -890,8 +914,8 @@ static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
/* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
+ ot->invoke = edge_bevelweight_invoke;
+ ot->exec = edge_bevelweight_exec;
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_editmesh;
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index ba90926df3b..69d135b8550 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -756,7 +756,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
if (flag) {
float tvec[3];
if ((v3d->around == V3D_LOCAL) ||
- ELEM3(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3))
+ ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3))
{
BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
add_v3_v3(normal, tvec);
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 451837fd311..abef2c9fc30 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -117,8 +117,8 @@ int BIF_snappingSupported(Object *obedit)
{
int status = 0;
- if (obedit == NULL || ELEM5(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) /* only support object mesh, armature, curves */
- {
+ /* only support object mesh, armature, curves */
+ if (obedit == NULL || ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) {
status = 1;
}
@@ -337,6 +337,46 @@ void applyProject(TransInfo *t)
mul_m3_v3(td->smtx, tvec);
add_v3_v3(td->loc, tvec);
+
+ if (t->tsnap.align && (t->flag & T_OBJECT)) {
+ /* handle alignment as well */
+ const float *original_normal;
+ float axis[3];
+ float mat[3][3];
+ float angle;
+ float totmat[3][3], smat[3][3];
+ float eul[3], fmat[3][3], quat[4];
+ float obmat[3][3];
+
+ /* In pose mode, we want to align normals with Y axis of bones... */
+ original_normal = td->axismtx[2];
+
+ cross_v3_v3v3(axis, original_normal, no);
+ angle = saacos(dot_v3v3(original_normal, no));
+
+ axis_angle_to_quat(quat, axis, angle);
+
+ quat_to_mat3(mat, quat);
+
+ mul_m3_m3m3(totmat, mat, td->mtx);
+ mul_m3_m3m3(smat, td->smtx, totmat);
+
+ /* calculate the total rotatation in eulers */
+ add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* we have to correct for delta rot */
+ eulO_to_mat3(obmat, eul, td->ext->rotOrder);
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
+
+ /* correct back for delta rot */
+ sub_v3_v3v3(eul, eul, td->ext->drot);
+
+ /* and apply */
+ copy_v3_v3(td->ext->rot, eul);
+
+ /* TODO support constraints for rotation too? see ElementRotation */
+ }
}
}
@@ -505,7 +545,7 @@ static void initSnappingMode(TransInfo *t)
/* Edit mode */
if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- (obedit != NULL && ELEM5(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) ) // Temporary limited to edit mode meshes, armature, curves, mballs
+ (obedit != NULL && ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) ) // Temporary limited to edit mode meshes, armature, curves, mballs
{
/* Exclude editmesh if using proportional edit */
if ((obedit->type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
@@ -588,7 +628,7 @@ void initSnapping(TransInfo *t, wmOperator *op)
}
/* use scene defaults only when transform is modal */
else if (t->flag & T_MODAL) {
- if (ELEM3(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) {
+ if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) {
if (ts->snap_flag & SCE_SNAP) {
t->modifiers |= MOD_SNAP;
}
@@ -658,7 +698,8 @@ static void setSnappingCallback(TransInfo *t)
void addSnapPoint(TransInfo *t)
{
- if (t->tsnap.status & POINT_INIT) {
+ /* Currently only 3D viewport works for snapping points. */
+ if (t->tsnap.status & POINT_INIT && t->spacetype == SPACE_VIEW3D) {
TransSnapPoint *p = MEM_callocN(sizeof(TransSnapPoint), "SnapPoint");
t->tsnap.selectedPoint = p;
@@ -1492,6 +1533,8 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
const float mval[2], float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth, bool do_bb)
{
bool retval = false;
+ const bool do_ray_start_correction = (snap_mode == SCE_SNAP_MODE_FACE && ar &&
+ !((RegionView3D *)ar->regiondata)->is_persp);
int totvert = dm->getNumVerts(dm);
if (totvert > 0) {
@@ -1518,6 +1561,28 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
return retval;
}
}
+ else if (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.
+ */
+ BVHTreeFromMesh treeData;
+ BVHTreeNearest nearest;
+ len_diff = 0.0f; /* In case BVHTree would fail for some reason... */
+
+ treeData.em_evil = em;
+ bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 2, 6);
+ if (treeData.tree != NULL) {
+ 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) {
+ len_diff = sqrtf(nearest.dist_sq);
+ }
+ }
+ free_bvhtree_from_mesh(&treeData);
+ }
switch (snap_mode) {
case SCE_SNAP_MODE_FACE:
@@ -1529,7 +1594,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
* 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 (ar && !((RegionView3D *)ar->regiondata)->is_persp) {
+ if (do_ray_start_correction) {
float ray_org_local[3];
copy_v3_v3(ray_org_local, ray_origin);
@@ -2383,6 +2448,9 @@ static void applyGridIncrement(TransInfo *t, float *val, int max_index, float fa
if (t->options & CTX_MASK) {
ED_space_image_get_aspect(t->sa->spacedata.first, asp, asp + 1);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ asp[0] = asp[1] = 1.0;
+ }
else {
ED_space_image_get_uv_aspect(t->sa->spacedata.first, asp, asp + 1);
}
diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c
index 3bd927e5b25..104b628c25a 100644
--- a/source/blender/editors/util/ed_transverts.c
+++ b/source/blender/editors/util/ed_transverts.c
@@ -192,7 +192,7 @@ static void set_mapped_co(void *vuserdata, int index, const float co[3],
bool ED_transverts_check_obedit(Object *obedit)
{
- return (ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL));
+ return (ELEM(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL));
}
void ED_transverts_create_from_obedit(TransVertStore *tvs, Object *obedit, const int mode)
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 47fbfbe3eba..56b12fcdcda 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -86,7 +86,7 @@ void ED_editors_init(bContext *C)
/* This is called during initialization, so we don't want to store any reports */
ReportList *reports = CTX_wm_reports(C);
- int reports_flag_prev = reports->flag &= ~RPT_STORE;
+ int reports_flag_prev = reports->flag & ~RPT_STORE;
SWAP(int, reports->flag, reports_flag_prev);
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index a618ab8419b..a154f12a786 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -33,6 +33,7 @@
#include "BLI_string_cursor_utf8.h"
#include "BKE_context.h"
+#include "BKE_scene.h"
#include "BKE_unit.h"
#include "DNA_scene_types.h"
@@ -87,7 +88,7 @@ void initNumInput(NumInput *n)
}
/* str must be NUM_STR_REP_LEN * (idx_max + 1) length. */
-void outputNumInput(NumInput *n, char *str, const float scale_length)
+void outputNumInput(NumInput *n, char *str, UnitSettings *unit_settings)
{
short j;
const int ln = NUM_STR_REP_LEN;
@@ -98,7 +99,7 @@ void outputNumInput(NumInput *n, char *str, const float scale_length)
const short i = (n->flag & NUM_AFFECT_ALL && n->idx != j && !(n->val_flag[j] & NUM_EDITED)) ? 0 : j;
/* Use scale_length if needed! */
- const float fac = ELEM3(n->unit_type[j], B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME) ? scale_length : 1.0f;
+ const float fac = (float)BKE_scene_unit_scale(unit_settings, n->unit_type[j], 1.0);
if (n->val_flag[i] & NUM_EDITED) {
/* Get the best precision, allows us to draw '10.0001' as '10' instead! */
@@ -189,15 +190,15 @@ bool applyNumInput(NumInput *n, float *vec)
if (n->val_flag[i] & NUM_NO_NEGATIVE && val < 0.0f) {
val = 0.0f;
}
- if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) {
- val = 0.0001f;
- }
if (n->val_flag[i] & NUM_NO_FRACTION && val != floorf(val)) {
val = floorf(val + 0.5f);
if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) {
val = 1.0f;
}
}
+ else if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) {
+ val = 0.0001f;
+ }
}
vec[j] = val;
}
@@ -442,6 +443,13 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
}
}
+ /* Up to this point, if we have a ctrl modifier, skip.
+ * This allows to still access most of modals' shortcuts even in numinput mode.
+ */
+ if (!updated && event->ctrl) {
+ return false;
+ }
+
if ((!utf8_buf || !utf8_buf[0]) && ascii[0]) {
/* Fallback to ascii. */
utf8_buf = ascii;
@@ -471,26 +479,24 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
#ifdef WITH_PYTHON
Scene *sce = CTX_data_scene(C);
double val;
- float fac = 1.0f;
char str_unit_convert[NUM_STR_REP_LEN * 6]; /* Should be more than enough! */
const char *default_unit = NULL;
+ /* Use scale_length if needed! */
+ const float fac = (float)BKE_scene_unit_scale(&sce->unit, n->unit_type[idx], 1.0);
+
/* Make radian default unit when needed. */
if (n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION)
default_unit = "r";
- /* Use scale_length if needed! */
- if (ELEM3(n->unit_type[idx], B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME))
- fac /= sce->unit.scale_length;
-
BLI_strncpy(str_unit_convert, n->str, sizeof(str_unit_convert));
- bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), default_unit, 1.0,
+ bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), default_unit, fac,
n->unit_sys, n->unit_type[idx]);
/* Note: with angles, we always get values as radians here... */
if (BPY_button_exec(C, str_unit_convert, &val, false) != -1) {
- n->val[idx] = (float)val * fac;
+ n->val[idx] = (float)val;
n->val_flag[idx] &= ~NUM_INVALID;
}
else {
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index e2f25a2a8ae..8d46d9ac7cf 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <string.h>
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -48,6 +49,8 @@
#include "BKE_DerivedMesh.h"
#include "BKE_editmesh.h"
+#include "BKE_material.h"
+
#include "BKE_scene.h"
#include "BIF_gl.h"
@@ -403,20 +406,28 @@ static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage)
int a;
BLI_bitmap *mat_test_array;
bool ok = false;
+ int totcol = 0;
if (me->mloopuv == NULL) {
return;
}
- if (ob->totcol == 0) {
+ if (curimage && ob->totcol == 0) {
return;
}
- mat_test_array = BLI_BITMAP_NEW_ALLOCA(ob->totcol);
+ totcol = max_ii(ob->totcol, 1);
+ mat_test_array = BLI_BITMAP_NEW_ALLOCA(totcol);
- for (a = 0; a < ob->totcol; a++) {
+ for (a = 0; a < totcol; a++) {
Image *image;
- ED_object_get_active_image(ob, a + 1, &image, NULL, NULL);
+
+ /* if no materials, assume a default material with no image */
+ if (ob->totcol)
+ ED_object_get_active_image(ob, a + 1, &image, NULL, NULL, NULL);
+ else
+ image = NULL;
+
if (image == curimage) {
BLI_BITMAP_ENABLE(mat_test_array, a);
ok = true;
@@ -429,7 +440,7 @@ static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage)
for (a = me->totpoly; a != 0; a--, mpoly++) {
const int mat_nr = mpoly->mat_nr;
- if ((mat_nr >= ob->totcol) ||
+ if ((mat_nr >= totcol) ||
(BLI_BITMAP_TEST(mat_test_array, mat_nr)) == 0)
{
continue;
@@ -471,13 +482,39 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
{
const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
Image *curimage = ED_space_image(sima);
+ Mesh *me = ob->data;
+ Material *ma;
if (sima->flag & SI_DRAW_OTHER) {
draw_uvs_other(scene, ob, curimage, new_shading_nodes);
}
UI_ThemeColor(TH_UV_SHADOW);
- draw_uvs_other_mesh(ob, curimage, new_shading_nodes);
+
+ ma = give_current_material(ob, ob->actcol);
+
+ if (me->mtpoly) {
+ MPoly *mpoly = me->mpoly;
+ MLoopUV *mloopuv, *mloopuv_base;
+ int a, b;
+ if (!(ma && ma->texpaintslot && ma->texpaintslot[ma->paint_active_slot].uvname &&
+ (mloopuv = CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, ma->texpaintslot[ma->paint_active_slot].uvname))))
+ {
+ mloopuv = me->mloopuv;
+ }
+
+ mloopuv_base = mloopuv;
+
+ for (a = me->totpoly; a > 0; a--, mpoly++) {
+ glBegin(GL_LINE_LOOP);
+
+ mloopuv = mloopuv_base + mpoly->loopstart;
+ for (b = 0; b < mpoly->totloop; b++, mloopuv++) {
+ glVertex2fv(mloopuv->uv);
+ }
+ glEnd();
+ }
+ }
}
#ifdef USE_EDBM_LOOPTRIS
@@ -540,7 +577,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
if (new_shading_nodes) {
if (efa_act) {
- ED_object_get_active_image(obedit, efa_act->mat_nr + 1, &curimage, NULL, NULL);
+ ED_object_get_active_image(obedit, efa_act->mat_nr + 1, &curimage, NULL, NULL, NULL);
}
else {
curimage = ima;
@@ -911,7 +948,7 @@ void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedi
ToolSettings *toolsettings = scene->toolsettings;
int show_uvedit, show_uvshadow, show_texpaint_uvshadow;
- show_texpaint_uvshadow = (obact && obact->type == OB_MESH && obact->mode == OB_MODE_TEXTURE_PAINT);
+ show_texpaint_uvshadow = ED_space_image_show_texpaint(sima, obact);
show_uvedit = ED_space_image_show_uvedit(sima, obedit);
show_uvshadow = ED_space_image_show_uvshadow(sima, obedit);
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 6cf34d9f93f..4b341547370 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -137,21 +137,24 @@ static bool is_image_texture_node(bNode *node)
}
bool ED_object_get_active_image(Object *ob, int mat_nr,
- Image **r_ima, ImageUser **r_iuser, bNode **r_node)
+ Image **r_ima, ImageUser **r_iuser, bNode **r_node, bNodeTree **r_ntree)
{
Material *ma = give_current_material(ob, mat_nr);
- bNode *node = (ma && ma->use_nodes) ? nodeGetActiveTexture(ma->nodetree) : NULL;
+ bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL;
+ bNode *node = (ntree) ? nodeGetActiveTexture(ntree) : NULL;
if (node && is_image_texture_node(node)) {
if (r_ima) *r_ima = (Image *)node->id;
if (r_iuser) *r_iuser = NULL;
if (r_node) *r_node = node;
+ if (r_ntree) *r_ntree = ntree;
return true;
}
if (r_ima) *r_ima = NULL;
if (r_iuser) *r_iuser = NULL;
if (r_node) *r_node = node;
+ if (r_ntree) *r_ntree = ntree;
return false;
}
@@ -3033,7 +3036,8 @@ static void UV_OT_circle_select(wmOperatorType *ot)
/* ******************** lasso select operator **************** */
-static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short moves, const bool select)
+static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short moves,
+ const bool select, const bool extend)
{
SpaceImage *sima = CTX_wm_space_image(C);
Image *ima = CTX_data_edit_image(C);
@@ -3060,6 +3064,10 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
BLI_lasso_boundbox(&rect, mcords, moves);
+ if (!extend && select) {
+ uv_select_all_perform(scene, ima, em, SEL_DESELECT);
+ }
+
if (use_face_center) { /* Face Center Sel */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
@@ -3122,11 +3130,12 @@ static int uv_lasso_select_exec(bContext *C, wmOperator *op)
const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
if (mcords) {
- bool select;
+ bool select, extend;
bool changed;
select = !RNA_boolean_get(op->ptr, "deselect");
- changed = do_lasso_select_mesh_uv(C, mcords, mcords_tot, select);
+ extend = RNA_boolean_get(op->ptr, "extend");
+ changed = do_lasso_select_mesh_uv(C, mcords, mcords_tot, select, extend);
MEM_freeN((void *)mcords);
@@ -3827,7 +3836,8 @@ static void UV_OT_reveal(wmOperatorType *ot)
static int uv_set_2d_cursor_poll(bContext *C)
{
return ED_operator_uvedit_space_image(C) ||
- ED_space_image_maskedit_poll(C);
+ ED_space_image_maskedit_poll(C) ||
+ ED_space_image_paint_curve(C);
}
static int uv_set_2d_cursor_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 21e7bb00204..335d8e6589e 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -201,7 +201,7 @@ void uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, fl
if (efa) {
if (BKE_scene_use_new_shading_nodes(scene)) {
- ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL);
+ ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL, NULL);
}
else {
MTexPoly *tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
@@ -938,7 +938,7 @@ static void uv_map_rotation_matrix(float result[4][4], RegionView3D *rv3d, Objec
rotup[0][0] = 1.0f / radius;
/* calculate transforms*/
- mul_serie_m4(result, rotup, rotside, viewmatrix, rotobj, NULL, NULL, NULL, NULL);
+ mul_m4_series(result, rotup, rotside, viewmatrix, rotobj);
}
static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float rotmat[4][4])
diff --git a/source/blender/freestyle/FRS_freestyle.h b/source/blender/freestyle/FRS_freestyle.h
index 7be51b37f7a..fc9fc35e410 100644
--- a/source/blender/freestyle/FRS_freestyle.h
+++ b/source/blender/freestyle/FRS_freestyle.h
@@ -30,8 +30,9 @@ extern "C" {
#endif
struct Render;
+struct Material;
struct FreestyleConfig;
-struct bContext;
+struct FreestyleLineStyle;
extern struct Scene *freestyle_scene;
extern float freestyle_viewpoint[3];
@@ -57,6 +58,9 @@ void FRS_delete_active_lineset(struct FreestyleConfig *config);
void FRS_move_active_lineset_up(struct FreestyleConfig *config);
void FRS_move_active_lineset_down(struct FreestyleConfig *config);
+/* Testing */
+struct Material *FRS_create_stroke_material(struct Main *bmain, struct FreestyleLineStyle *linestyle);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
index dbbc4f77c26..57882cbce0c 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -449,7 +449,7 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
return;
// We allocate memory for the meshes to be imported
- NodeTransform *currentMesh = new NodeTransform;
+ NodeGroup *currentMesh = new NodeGroup;
NodeShape *shape = new NodeShape;
unsigned vSize = 3 * 3 * numFaces;
@@ -799,10 +799,6 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
rep->setBBox(bbox);
shape->AddRep(rep);
- Matrix44r meshMat = Matrix44r::identity();
- currentMesh->setMatrix(meshMat);
- currentMesh->Translate(0, 0, 0);
-
currentMesh->AddChild(shape);
_Scene->AddChild(currentMesh);
}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index d47f4e5d910..47b0c9b1e48 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -30,26 +30,35 @@
extern "C" {
#include "MEM_guardedalloc.h"
+#include "RNA_access.h"
+
#include "DNA_camera_types.h"
#include "DNA_listBase.h"
+#include "DNA_linestyle_types.h"
+#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
#include "BKE_customdata.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_library.h" /* free_libblock */
-#include "BKE_main.h" /* struct Main */
#include "BKE_material.h"
#include "BKE_mesh.h"
+#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_scene.h"
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "RE_pipeline.h"
+
+#include "render_types.h"
}
#include <limits.h>
@@ -133,6 +142,15 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
// Reset serial mesh ID (used for BlenderStrokeRenderer::NewMesh())
_mesh_id = 0xffffffff;
+
+ // Check if the rendering engine uses new shading nodes
+ _use_shading_nodes = BKE_scene_use_new_shading_nodes(freestyle_scene);
+
+ // Create a bNodeTree-to-Material hash table
+ if (_use_shading_nodes)
+ _nodetree_hash = BLI_ghash_ptr_new("BlenderStrokeRenderer::_nodetree_hash");
+ else
+ _nodetree_hash = NULL;
}
BlenderStrokeRenderer::~BlenderStrokeRenderer()
@@ -186,6 +204,9 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer()
lnk = lnk->next;
BKE_libblock_free(freestyle_bmain, ma);
}
+
+ if (_use_shading_nodes)
+ BLI_ghash_free(_nodetree_hash, NULL, NULL);
}
float BlenderStrokeRenderer::get_stroke_vertex_z(void) const
@@ -206,55 +227,283 @@ unsigned int BlenderStrokeRenderer::get_stroke_mesh_id(void) const
return mesh_id;
}
-void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
+Material* BlenderStrokeRenderer::GetStrokeShader(Main *bmain, bNodeTree *iNodeTree, bool do_id_user)
{
- bool has_mat = false;
- int a = 0;
-
- // Look for a good existing material
- for (Link *lnk = (Link *)freestyle_bmain->mat.first; lnk; lnk = lnk->next) {
- Material *ma = (Material*) lnk;
- bool texs_are_good = true;
- // as soon as textures differ it's not the right one
- for (int a = 0; a < MAX_MTEX; a++) {
- if (ma->mtex[a] != iStrokeRep->getMTex(a)) {
- texs_are_good = false;
+ Material *ma = BKE_material_add(bmain, "stroke_shader");
+ bNodeTree *ntree;
+ bNode *output_linestyle = NULL;
+ bNodeSocket *fromsock, *tosock;
+ PointerRNA fromptr, toptr;
+ NodeShaderAttribute *storage;
+
+ if (iNodeTree) {
+ // make a copy of linestyle->nodetree
+ ntree = ntreeCopyTree_ex(iNodeTree, bmain, do_id_user);
+
+ // find the active Output Line Style node
+ for (bNode *node = (bNode *)ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_OUTPUT_LINESTYLE && (node->flag & NODE_DO_OUTPUT)) {
+ output_linestyle = node;
break;
}
}
+ }
+ else {
+ ntree = ntreeAddTree(NULL, "stroke_shader", "ShaderNodeTree");
+ }
+ ma->nodetree = ntree;
+ ma->use_nodes = 1;
+
+ bNode *input_attr_color = nodeAddStaticNode(NULL, ntree, SH_NODE_ATTRIBUTE);
+ input_attr_color->locx = 0.0f;
+ input_attr_color->locy = -200.0f;
+ storage = (NodeShaderAttribute *)input_attr_color->storage;
+ BLI_strncpy(storage->name, "Color", sizeof(storage->name));
+
+ bNode *mix_rgb_color = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_RGB);
+ mix_rgb_color->custom1 = MA_RAMP_BLEND; // Mix
+ mix_rgb_color->locx = 200.0f;
+ mix_rgb_color->locy = -200.0f;
+ tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 0); // Fac
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr);
+ RNA_float_set(&toptr, "default_value", 0.0f);
+
+ bNode *input_attr_alpha = nodeAddStaticNode(NULL, ntree, SH_NODE_ATTRIBUTE);
+ input_attr_alpha->locx = 400.0f;
+ input_attr_alpha->locy = 300.0f;
+ storage = (NodeShaderAttribute *)input_attr_alpha->storage;
+ BLI_strncpy(storage->name, "Alpha", sizeof(storage->name));
+
+ bNode *mix_rgb_alpha = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_RGB);
+ mix_rgb_alpha->custom1 = MA_RAMP_BLEND; // Mix
+ mix_rgb_alpha->locx = 600.0f;
+ mix_rgb_alpha->locy = 300.0f;
+ tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 0); // Fac
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr);
+ RNA_float_set(&toptr, "default_value", 0.0f);
+
+ bNode *shader_emission = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION);
+ shader_emission->locx = 400.0f;
+ shader_emission->locy = -200.0f;
+
+ bNode *input_light_path = nodeAddStaticNode(NULL, ntree, SH_NODE_LIGHT_PATH);
+ input_light_path->locx = 400.0f;
+ input_light_path->locy = 100.0f;
+
+ bNode *mix_shader_color = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_SHADER);
+ mix_shader_color->locx = 600.0f;
+ mix_shader_color->locy = -100.0f;
+
+ bNode *shader_transparent = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_TRANSPARENT);
+ shader_transparent->locx = 600.0f;
+ shader_transparent->locy = 100.0f;
+
+ bNode *mix_shader_alpha = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_SHADER);
+ mix_shader_alpha->locx = 800.0f;
+ mix_shader_alpha->locy = 100.0f;
+
+ bNode *output_material = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+ output_material->locx = 1000.0f;
+ output_material->locy = 100.0f;
+
+ fromsock = (bNodeSocket *)BLI_findlink(&input_attr_color->outputs, 0); // Color
+ tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 1); // Color1
+ nodeAddLink(ntree, input_attr_color, fromsock, mix_rgb_color, tosock);
+
+ fromsock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->outputs, 0); // Color
+ tosock = (bNodeSocket *)BLI_findlink(&shader_emission->inputs, 0); // Color
+ nodeAddLink(ntree, mix_rgb_color, fromsock, shader_emission, tosock);
+
+ fromsock = (bNodeSocket *)BLI_findlink(&shader_emission->outputs, 0); // Emission
+ tosock = (bNodeSocket *)BLI_findlink(&mix_shader_color->inputs, 2); // Shader (second)
+ nodeAddLink(ntree, shader_emission, fromsock, mix_shader_color, tosock);
+
+ fromsock = (bNodeSocket *)BLI_findlink(&input_light_path->outputs, 0); // In Camera Ray
+ tosock = (bNodeSocket *)BLI_findlink(&mix_shader_color->inputs, 0); // Fac
+ nodeAddLink(ntree, input_light_path, fromsock, mix_shader_color, tosock);
+
+ fromsock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->outputs, 0); // Color
+ tosock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->inputs, 0); // Fac
+ nodeAddLink(ntree, mix_rgb_alpha, fromsock, mix_shader_alpha, tosock);
+
+ fromsock = (bNodeSocket *)BLI_findlink(&input_attr_alpha->outputs, 0); // Color
+ tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 1); // Color1
+ nodeAddLink(ntree, input_attr_alpha, fromsock, mix_rgb_alpha, tosock);
+
+ fromsock = (bNodeSocket *)BLI_findlink(&shader_transparent->outputs, 0); // BSDF
+ tosock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->inputs, 1); // Shader (first)
+ nodeAddLink(ntree, shader_transparent, fromsock, mix_shader_alpha, tosock);
+
+ fromsock = (bNodeSocket *)BLI_findlink(&mix_shader_color->outputs, 0); // Shader
+ tosock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->inputs, 2); // Shader (second)
+ nodeAddLink(ntree, mix_shader_color, fromsock, mix_shader_alpha, tosock);
+
+ fromsock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->outputs, 0); // Shader
+ tosock = (bNodeSocket *)BLI_findlink(&output_material->inputs, 0); // Surface
+ nodeAddLink(ntree, mix_shader_alpha, fromsock, output_material, tosock);
+
+ if (output_linestyle) {
+ bNodeSocket *outsock;
+ bNodeLink *link;
+
+ mix_rgb_color->custom1 = output_linestyle->custom1; // blend_type
+ mix_rgb_color->custom2 = output_linestyle->custom2; // use_clamp
+
+ outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 0); // Color
+ tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 2); // Color2
+ link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock));
+ if (link) {
+ nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_color, tosock);
+ }
+ else {
+ float color[4];
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr);
+ RNA_float_get_array(&fromptr, "default_value", color);
+ RNA_float_set_array(&toptr, "default_value", color);
+ }
- if (texs_are_good) {
- iStrokeRep->setMaterial(ma);
- has_mat = true;
- break; // if textures are good, no need to search anymore
+ outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 1); // Color Fac
+ tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 0); // Fac
+ link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock));
+ if (link) {
+ nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_color, tosock);
+ }
+ else {
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr);
+ RNA_float_set(&toptr, "default_value", RNA_float_get(&fromptr, "default_value"));
+ }
+
+ outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 2); // Alpha
+ tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 2); // Color2
+ link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock));
+ if (link) {
+ nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_alpha, tosock);
+ }
+ else {
+ float color[4];
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr);
+ color[0] = color[1] = color[2] = RNA_float_get(&fromptr, "default_value");
+ color[3] = 1.0f;
+ RNA_float_set_array(&toptr, "default_value", color);
+ }
+
+ outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 3); // Alpha Fac
+ tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 0); // Fac
+ link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock));
+ if (link) {
+ nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_alpha, tosock);
+ }
+ else {
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr);
+ RNA_float_set(&toptr, "default_value", RNA_float_get(&fromptr, "default_value"));
+ }
+
+ for (bNode *node = (bNode *)ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_UVALONGSTROKE) {
+ // UV output of the UV Along Stroke node
+ bNodeSocket *sock = (bNodeSocket *)BLI_findlink(&node->outputs, 0);
+
+ // add new UV Map node
+ bNode *input_uvmap = nodeAddStaticNode(NULL, ntree, SH_NODE_UVMAP);
+ input_uvmap->locx = node->locx - 200.0f;
+ input_uvmap->locy = node->locy;
+ NodeShaderUVMap *storage = (NodeShaderUVMap *)input_uvmap->storage;
+ if (node->custom1 & 1) { // use_tips
+ BLI_strncpy(storage->uv_map, "along_stroke_tips", sizeof(storage->uv_map));
+ }
+ else {
+ BLI_strncpy(storage->uv_map, "along_stroke", sizeof(storage->uv_map));
+ }
+ fromsock = (bNodeSocket *)BLI_findlink(&input_uvmap->outputs, 0); // UV
+
+ // replace links from the UV Along Stroke node by links from the UV Map node
+ for (bNodeLink *link = (bNodeLink *)ntree->links.first; link; link = link->next) {
+ if (link->fromnode == node && link->fromsock == sock) {
+ nodeAddLink(ntree, input_uvmap, fromsock, link->tonode, link->tosock);
+ }
+ }
+ nodeRemSocketLinks(ntree, sock);
+ }
}
}
- // If still no material, create one
- if (!has_mat) {
- Material *ma = BKE_material_add(freestyle_bmain, "stroke_material");
+ nodeSetActive(ntree, output_material);
+ ntreeUpdateTree(bmain, ntree);
- ma->mode |= MA_VERTEXCOLP;
- ma->mode |= MA_TRANSP;
- ma->mode |= MA_SHLESS;
- ma->vcol_alpha = 1;
+ return ma;
+}
- // Textures
- //for (int a = 0; a < MAX_MTEX; a++) {
- while (iStrokeRep->getMTex(a)) {
- ma->mtex[a] = (MTex *) iStrokeRep->getMTex(a);
+void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
+{
+ if (_use_shading_nodes) {
+ bNodeTree *nt = iStrokeRep->getNodeTree();
+ Material *ma = (Material *)BLI_ghash_lookup(_nodetree_hash, nt);
+ if (!ma) {
+ ma = BlenderStrokeRenderer::GetStrokeShader(freestyle_bmain, nt, false);
+ BLI_ghash_insert(_nodetree_hash, nt, ma);
+ }
+
+ if (strcmp(freestyle_scene->r.engine, "CYCLES") == 0) {
+ PointerRNA scene_ptr;
+ RNA_pointer_create(NULL, &RNA_Scene, freestyle_scene, &scene_ptr);
+ PointerRNA cycles_ptr = RNA_pointer_get(&scene_ptr, "cycles");
+ RNA_boolean_set(&cycles_ptr, "film_transparent", 1);
+ }
- // We'll generate both with tips and without tips
- // coordinates, on two different UV layers.
- if (ma->mtex[a]->texflag & MTEX_TIPS) {
- BLI_strncpy(ma->mtex[a]->uvname, "along_stroke_tips", sizeof(ma->mtex[a]->uvname));
+ iStrokeRep->setMaterial(ma);
+ }
+ else {
+ bool has_mat = false;
+ int a = 0;
+
+ // Look for a good existing material
+ for (Link *lnk = (Link *)freestyle_bmain->mat.first; lnk; lnk = lnk->next) {
+ Material *ma = (Material*)lnk;
+ bool texs_are_good = true;
+ // as soon as textures differ it's not the right one
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (ma->mtex[a] != iStrokeRep->getMTex(a)) {
+ texs_are_good = false;
+ break;
+ }
}
- else {
- BLI_strncpy(ma->mtex[a]->uvname, "along_stroke", sizeof(ma->mtex[a]->uvname));
+
+ if (texs_are_good) {
+ iStrokeRep->setMaterial(ma);
+ has_mat = true;
+ break; // if textures are good, no need to search anymore
}
- a++;
}
- iStrokeRep->setMaterial(ma);
+
+ // If still no material, create one
+ if (!has_mat) {
+ Material *ma = BKE_material_add(freestyle_bmain, "stroke_material");
+ ma->mode |= MA_VERTEXCOLP;
+ ma->mode |= MA_TRANSP;
+ ma->mode |= MA_SHLESS;
+ ma->vcol_alpha = 1;
+
+ // Textures
+ while (iStrokeRep->getMTex(a)) {
+ ma->mtex[a] = (MTex *)iStrokeRep->getMTex(a);
+
+ // We'll generate both with tips and without tips
+ // coordinates, on two different UV layers.
+ if (ma->mtex[a]->texflag & MTEX_TIPS) {
+ BLI_strncpy(ma->mtex[a]->uvname, "along_stroke_tips", sizeof(ma->mtex[a]->uvname));
+ }
+ else {
+ BLI_strncpy(ma->mtex[a]->uvname, "along_stroke", sizeof(ma->mtex[a]->uvname));
+ }
+ a++;
+ }
+
+ iStrokeRep->setMaterial(ma);
+ }
}
RenderStrokeRepBasic(iStrokeRep);
@@ -318,7 +567,7 @@ void BlenderStrokeRenderer::test_strip_visibility(Strip::vertex_container& strip
void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
{
vector<Strip*>& strips = iStrokeRep->getStrips();
- const bool hasTex = iStrokeRep->getMTex(0) != NULL;
+ const bool hasTex = iStrokeRep->hasTex();
Strip::vertex_container::iterator v[3];
StrokeVertexRep *svRep[3];
unsigned int vertex_index, edge_index, loop_index;
@@ -355,22 +604,35 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
// vertices allocation
mesh->totvert = totvert; // visible_faces + visible_segments * 2;
- mesh->mvert = (MVert *)CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
+ CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
// edges allocation
mesh->totedge = totedge; // visible_faces * 2 + visible_segments;
- mesh->medge = (MEdge *)CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
+ CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
// faces allocation
mesh->totpoly = totpoly; // visible_faces;
- mesh->mpoly = (MPoly *)CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
+ CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
// loops allocation
mesh->totloop = totloop; // visible_faces * 3;
- mesh->mloop = (MLoop *)CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
+ CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
- // colors allocation
- mesh->mloopcol = (MLoopCol *)CustomData_add_layer(&mesh->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, mesh->totloop);
+ // uv maps
+ MLoopUV *loopsuv[2] = { NULL };
+ if (hasTex) {
+ loopsuv[0] = (MLoopUV *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, "along_stroke");
+ loopsuv[1] = (MLoopUV *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, "along_stroke_tips");
+
+ CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, "along_stroke");
+ CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, "along_stroke_tips");
+ }
+
+ // colors and transparency (the latter represented by grayscale colors)
+ MLoopCol *colors = (MLoopCol *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, mesh->totloop, "Color");
+ MLoopCol *transp = (MLoopCol *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, mesh->totloop, "Alpha");
+
+ BKE_mesh_update_customdata_pointers(mesh, true);
////////////////////
// Data copy
@@ -380,28 +642,6 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
MEdge *edges = mesh->medge;
MPoly *polys = mesh->mpoly;
MLoop *loops = mesh->mloop;
- MLoopCol *colors = mesh->mloopcol;
- MLoopUV *loopsuv[2] = {NULL};
-
- if (hasTex) {
- // First UV layer
- CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, "along_stroke");
- CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, "along_stroke");
- CustomData_set_layer_active(&mesh->pdata, CD_MTEXPOLY, 0);
- CustomData_set_layer_active(&mesh->ldata, CD_MLOOPUV, 0);
- BKE_mesh_update_customdata_pointers(mesh, true);
-
- loopsuv[0] = mesh->mloopuv;
-
- // Second UV layer
- CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, "along_stroke_tips");
- CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, "along_stroke_tips");
- CustomData_set_layer_active(&mesh->pdata, CD_MTEXPOLY, 1);
- CustomData_set_layer_active(&mesh->ldata, CD_MLOOPUV, 1);
- BKE_mesh_update_customdata_pointers(mesh, true);
-
- loopsuv[1] = mesh->mloopuv;
- }
vertex_index = edge_index = loop_index = 0;
@@ -540,7 +780,7 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
}
}
- // colors
+ // colors and alpha transparency
if (is_odd) {
colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
@@ -556,7 +796,7 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
colors[2].g = (short)(255.0f * svRep[1]->color()[1]);
colors[2].b = (short)(255.0f * svRep[1]->color()[2]);
colors[2].a = (short)(255.0f * svRep[1]->alpha());
- }
+ }
else {
colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
@@ -573,7 +813,11 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
colors[2].b = (short)(255.0f * svRep[0]->color()[2]);
colors[2].a = (short)(255.0f * svRep[0]->alpha());
}
+ transp[0].r = transp[0].g = transp[0].b = colors[0].a;
+ transp[1].r = transp[1].g = transp[1].b = colors[1].a;
+ transp[2].r = transp[2].g = transp[2].b = colors[2].a;
colors += 3;
+ transp += 3;
}
} // loop over strip vertices
} // loop over strips
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
index 0025d48e77f..74e5d321df2 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
@@ -29,12 +29,14 @@
#include "../system/FreestyleConfig.h"
extern "C" {
-#include "DNA_material_types.h"
-#include "DNA_scene_types.h"
-
-#include "BKE_main.h"
-
-#include "render_types.h"
+struct GHash;
+struct Main;
+struct Material;
+struct Object;
+struct Render;
+struct Scene;
+struct bContext;
+struct bNodeTree;
}
namespace Freestyle {
@@ -53,13 +55,18 @@ public:
Render *RenderScene(Render *re, bool render);
+ static Material* GetStrokeShader(Main *bmain, bNodeTree *iNodeTree, bool do_id_user);
+
protected:
Main *freestyle_bmain;
Scene *old_scene;
Scene *freestyle_scene;
+ bContext *_context;
float _width, _height;
float _z, _z_delta;
unsigned int _mesh_id;
+ bool _use_shading_nodes;
+ struct GHash *_nodetree_hash;
float get_stroke_vertex_z(void) const;
unsigned int get_stroke_mesh_id(void) const;
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
index a1fb9fade58..21776396ebc 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
@@ -29,10 +29,10 @@
#include "../system/PythonInterpreter.h"
extern "C" {
-#include "BKE_global.h"
-#include "BKE_library.h"
-#include "BKE_text.h"
-#include "BLI_utildefines.h"
+#include "BLI_utildefines.h" // BLI_assert()
+
+struct Scene;
+struct Text;
}
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
index 9c2b5a4037f..32f49d48ee7 100644
--- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
+++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
@@ -31,6 +31,8 @@
#include "../application/AppView.h"
#include "../application/Controller.h"
+#include "BlenderStrokeRenderer.h"
+
using namespace std;
using namespace Freestyle;
@@ -41,6 +43,7 @@ extern "C" {
#include "DNA_camera_types.h"
#include "DNA_freestyle_types.h"
#include "DNA_group_types.h"
+#include "DNA_material_types.h"
#include "DNA_text_types.h"
#include "BKE_freestyle.h"
@@ -730,4 +733,14 @@ void FRS_move_active_lineset_down(FreestyleConfig *config)
}
}
+// Testing
+
+Material *FRS_create_stroke_material(Main *bmain, struct FreestyleLineStyle *linestyle)
+{
+ bNodeTree *nt = (linestyle->use_nodes) ? linestyle->nodetree : NULL;
+ Material *ma = BlenderStrokeRenderer::GetStrokeShader(bmain, nt, true);
+ ma->id.us = 0;
+ return ma;
+}
+
} // extern "C"
diff --git a/source/blender/freestyle/intern/geometry/Grid.h b/source/blender/freestyle/intern/geometry/Grid.h
index c0cab2a05db..c1d04f6b4cc 100644
--- a/source/blender/freestyle/intern/geometry/Grid.h
+++ b/source/blender/freestyle/intern/geometry/Grid.h
@@ -30,9 +30,7 @@
#include <cstring> // for memset
#include <float.h>
-#if !defined(_MSC_VER) || _MSC_VER >= 1700
#include <stdint.h> // For SET_UINT_IN_POINTER, i.e. uintptr_t.
-#endif
#include <vector>
#include "Geom.h"
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.cpp b/source/blender/freestyle/intern/python/BPy_Convert.cpp
index 78c3599b7cd..dbd836bc562 100644
--- a/source/blender/freestyle/intern/python/BPy_Convert.cpp
+++ b/source/blender/freestyle/intern/python/BPy_Convert.cpp
@@ -387,9 +387,14 @@ PyObject *BPy_IntegrationType_from_IntegrationType(IntegrationType i)
PyObject *BPy_CurvePoint_from_CurvePoint(CurvePoint& cp)
{
PyObject *py_cp = CurvePoint_Type.tp_new(&CurvePoint_Type, 0, 0);
- ((BPy_CurvePoint *) py_cp)->cp = &cp;
+ // CurvePointIterator::operator*() returns a reference of a class data
+ // member whose value is mutable upon iteration over different CurvePoints.
+ // It is likely that such a mutable reference is passed to this function,
+ // so that a new allocated CurvePoint instance is created here to avoid
+ // nasty bugs (cf. T41464).
+ ((BPy_CurvePoint *) py_cp)->cp = new CurvePoint(cp);
((BPy_CurvePoint *) py_cp)->py_if0D.if0D = ((BPy_CurvePoint *)py_cp)->cp;
- ((BPy_CurvePoint *) py_cp)->py_if0D.borrowed = true;
+ ((BPy_CurvePoint *) py_cp)->py_if0D.borrowed = false;
return py_cp;
}
diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
index 2cfd3658189..5b8d50eb5eb 100644
--- a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
+++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
@@ -60,6 +60,7 @@ extern "C" {
#include "FRS_freestyle.h"
#include "RNA_access.h"
+#include "DNA_scene_types.h"
#include "bpy_rna.h" /* pyrna_struct_CreatePyObject() */
static char Freestyle_getCurrentScene___doc__[] =
@@ -77,7 +78,7 @@ static PyObject *Freestyle_getCurrentScene(PyObject *self)
return NULL;
}
PointerRNA ptr_scene;
- RNA_pointer_create(NULL, &RNA_Scene, freestyle_scene, &ptr_scene);
+ RNA_pointer_create(&freestyle_scene->id, &RNA_Scene, freestyle_scene, &ptr_scene);
return pyrna_struct_CreatePyObject(&ptr_scene);
}
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
index 36cdb1b92ff..1ef29792d56 100644
--- a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
@@ -178,6 +178,19 @@ static int CurvePoint_second_svertex_set(BPy_CurvePoint *self, PyObject *value,
return 0;
}
+PyDoc_STRVAR(CurvePoint_fedge_doc,
+"Gets the FEdge for the two SVertices that given CurvePoints consists out of.\n"
+"A shortcut for CurvePoint.first_svertex.get_fedge(CurvePoint.second_svertex).\n"
+"\n"
+":type: :class:`FEdge`");
+
+static PyObject *CurvePoint_fedge_get(BPy_CurvePoint *self, void *UNUSED(closure))
+{
+ SVertex *A = self->cp->A();
+ Interface0D *B = (Interface0D *)self->cp->B();
+ return Any_BPy_Interface1D_from_Interface1D(*(A->getFEdge(*B)));
+}
+
PyDoc_STRVAR(CurvePoint_t2d_doc,
"The 2D interpolation parameter.\n"
"\n"
@@ -204,6 +217,8 @@ static PyGetSetDef BPy_CurvePoint_getseters[] = {
(char *)CurvePoint_first_svertex_doc, NULL},
{(char *)"second_svertex", (getter)CurvePoint_second_svertex_get, (setter)CurvePoint_second_svertex_set,
(char *)CurvePoint_second_svertex_doc, NULL},
+ {(char *)"fedge", (getter)CurvePoint_fedge_get, NULL,
+ CurvePoint_fedge_doc, NULL},
{(char *)"t2d", (getter)CurvePoint_t2d_get, (setter)CurvePoint_t2d_set, (char *)CurvePoint_t2d_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
index af9f7198748..6f47ce93ca8 100644
--- a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
@@ -268,7 +268,7 @@ void SVertex_mathutils_register_callback()
PyDoc_STRVAR(SVertex_point_3d_doc,
"The 3D coordinates of the SVertex.\n"
"\n"
-":type: mathutils.Vector");
+":type: :class:`mathutils.Vector`");
static PyObject *SVertex_point_3d_get(BPy_SVertex *self, void *UNUSED(closure))
{
@@ -291,7 +291,7 @@ static int SVertex_point_3d_set(BPy_SVertex *self, PyObject *value, void *UNUSED
PyDoc_STRVAR(SVertex_point_2d_doc,
"The projected 3D coordinates of the SVertex.\n"
"\n"
-":type: mathutils.Vector");
+":type: :class:`mathutils.Vector`");
static PyObject *SVertex_point_2d_get(BPy_SVertex *self, void *UNUSED(closure))
{
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
index faf99e90111..fca4c979bbb 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
@@ -120,19 +120,14 @@ static PyObject *Interface0DIterator_iternext(BPy_Interface0DIterator *self)
self->if0D_it->decrement();
}
else {
- if (self->if0D_it->isEnd()) {
+ if (self->if0D_it->atLast() || self->if0D_it->isEnd()) {
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
if (self->at_start)
self->at_start = false;
- else {
+ else
self->if0D_it->increment();
- if (self->if0D_it->isEnd()) {
- PyErr_SetNone(PyExc_StopIteration);
- return NULL;
- }
- }
}
Interface0D *if0D = self->if0D_it->operator->();
return Any_BPy_Interface0D_from_Interface0D(*if0D);
@@ -177,11 +172,24 @@ static PyObject *Interface0DIterator_u_get(BPy_Interface0DIterator *self, void *
return PyFloat_FromDouble(self->if0D_it->u());
}
+PyDoc_STRVAR(Interface0DIterator_at_last_doc,
+"True if the interator points to the last valid element.\n"
+"For its counterpart (pointing to the first valid element), use it.is_begin.\n"
+"\n"
+":type: bool");
+
+static PyObject *Interface0DIterator_at_last_get(BPy_Interface0DIterator *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->if0D_it->atLast());
+}
+
static PyGetSetDef BPy_Interface0DIterator_getseters[] = {
{(char *)"object", (getter)Interface0DIterator_object_get, (setter)NULL,
(char *)Interface0DIterator_object_doc, NULL},
{(char *)"t", (getter)Interface0DIterator_t_get, (setter)NULL, (char *)Interface0DIterator_t_doc, NULL},
{(char *)"u", (getter)Interface0DIterator_u_get, (setter)NULL, (char *)Interface0DIterator_u_doc, NULL},
+ {(char *)"at_last", (getter)Interface0DIterator_at_last_get, (setter)NULL,
+ (char *)Interface0DIterator_at_last_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
index 2906f20be06..18d1b37eb3b 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
@@ -102,8 +102,8 @@ static PyObject *StrokeVertexIterator_iter(BPy_StrokeVertexIterator *self)
static PyObject *StrokeVertexIterator_iternext(BPy_StrokeVertexIterator *self)
{
/* Because Freestyle iterators for which it.isEnd() holds true have no valid object
- * (referencing it.object in this case leads to a crash), we must check if it.object
- * is valid after incrementing, to prevent crashes in Python.
+ * (they point to the past-the-end element and can't be dereferenced), we have to check
+ * iterators for validity.
* Additionally, the at_start attribute is used to keep Freestyle iterator objects
* and Python for loops in sync. */
@@ -115,7 +115,10 @@ static PyObject *StrokeVertexIterator_iternext(BPy_StrokeVertexIterator *self)
self->sv_it->decrement();
}
else {
- if (self->sv_it->isEnd()) {
+ /* if sv_it.isEnd() is true, the iterator can't be incremented. if sv_it.isLast() is true,
+ * the iterator is currently pointing to the final valid argument. Incrementing it further would
+ * give a python object that can't be dereferenced. */
+ if (self->sv_it->atLast() || self->sv_it->isEnd()) {
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
@@ -123,15 +126,8 @@ static PyObject *StrokeVertexIterator_iternext(BPy_StrokeVertexIterator *self)
* and don't increment, to keep for-loops in sync */
if (self->at_start)
self->at_start = false;
- /* after incrementing, check if the iterator is at its end
- * exit the loop if it is. not doing so will result in a crash */
- else {
+ else
self->sv_it->increment();
- if (self->sv_it->isEnd()) {
- PyErr_SetNone(PyExc_StopIteration);
- return NULL;
- }
- }
}
StrokeVertex *sv = self->sv_it->operator->();
return BPy_StrokeVertex_from_StrokeVertex(*sv);
@@ -194,7 +190,7 @@ static PyObject *StrokeVertexIterator_reversed(BPy_StrokeVertexIterator *self)
}
static PyMethodDef BPy_StrokeVertexIterator_methods[] = {
- {"incremented", (PyCFunction) StrokeVertexIterator_incremented, METH_NOARGS, StrokeVertexIterator_incremented_doc},
+ {"incremented", (PyCFunction)StrokeVertexIterator_incremented, METH_NOARGS, StrokeVertexIterator_incremented_doc},
{"decremented", (PyCFunction)StrokeVertexIterator_decremented, METH_NOARGS, StrokeVertexIterator_decremented_doc},
{"reversed", (PyCFunction)StrokeVertexIterator_reversed, METH_NOARGS, StrokeVertexIterator_reversed_doc},
{NULL, NULL, 0, NULL}
@@ -239,11 +235,25 @@ static PyObject *StrokeVertexIterator_u_get(BPy_StrokeVertexIterator *self, void
return PyFloat_FromDouble(self->sv_it->u());
}
+PyDoc_STRVAR(StrokeVertexIterator_at_last_doc,
+"True if the interator points to the last valid element.\n"
+"For its counterpart (pointing to the first valid element), use it.is_begin.\n"
+"\n"
+":type: bool");
+
+static PyObject *StrokeVertexIterator_at_last_get(BPy_StrokeVertexIterator *self)
+{
+ return PyBool_from_bool(self->sv_it->atLast());
+
+}
+
static PyGetSetDef BPy_StrokeVertexIterator_getseters[] = {
{(char *)"object", (getter)StrokeVertexIterator_object_get, (setter)NULL,
(char *)StrokeVertexIterator_object_doc, NULL},
{(char *)"t", (getter)StrokeVertexIterator_t_get, (setter)NULL, (char *)StrokeVertexIterator_t_doc, NULL},
{(char *)"u", (getter)StrokeVertexIterator_u_get, (setter)NULL, (char *)StrokeVertexIterator_u_doc, NULL},
+ {(char *)"at_last", (getter)StrokeVertexIterator_at_last_get, (setter)NULL,
+ (char *)StrokeVertexIterator_at_last_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
index e4476cf9bcf..d879ac53aaa 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
@@ -116,7 +116,7 @@ PyDoc_STRVAR(orientedViewEdgeIterator_object_doc,
"value) currently pointed to by this iterator. If the boolean value is true,\n"
"the ViewEdge is incoming.\n"
"\n"
-":type: (:class:`directedViewEdge`, bool)");
+":type: (:class:`ViewEdge`, bool)");
static PyObject *orientedViewEdgeIterator_object_get(BPy_orientedViewEdgeIterator *self, void *UNUSED(closure))
{
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp
index c8b9d7098e4..379fb7e1b12 100644
--- a/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp
@@ -41,38 +41,46 @@ static char BlenderTextureShader___doc__[] =
"\n"
"[Texture shader]\n"
"\n"
-".. method:: __init__(LineStyleTextureSlot)\n"
+".. method:: __init__(texture)\n"
"\n"
" Builds a BlenderTextureShader object.\n"
"\n"
-" :arg mtex: texture slot to add to stroke shading.\n"
-" :type mtex: LineStyleTextureSlot\n"
-
+" :arg texture: A line style texture slot or a shader node tree to define\n"
+" a set of textures.\n"
+" :type texture: :class:`LineStyleTextureSlot` or :class:`ShaderNodeTree`\n"
"\n"
".. method:: shade(stroke)\n"
"\n"
-" Assigns a blender texture slot to the stroke shading\n"
-" in order to simulate marks.\n"
+" Assigns a blender texture slot to the stroke shading in order to\n"
+" simulate marks.\n"
"\n"
" :arg stroke: A Stroke object.\n"
" :type stroke: :class:`Stroke`\n";
static int BlenderTextureShader___init__(BPy_BlenderTextureShader *self, PyObject *args, PyObject *kwds)
{
- static const char *kwlist[] = {"LineStyleTextureSlot", NULL};
- PyObject *py_mtex;
+ static const char *kwlist[] = {"texture", NULL};
+ PyObject *obj;
MTex *_mtex;
+ bNodeTree *_nodetree;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &py_mtex))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &obj))
return -1;
-
- _mtex = (MTex*)PyC_RNA_AsPointer(py_mtex, "LineStyleTextureSlot");
-
+ _mtex = (MTex *)PyC_RNA_AsPointer(obj, "LineStyleTextureSlot");
if (_mtex) {
self->py_ss.ss = new StrokeShaders::BlenderTextureShader(_mtex);
+ return 0;
}
-
- return 0;
+ PyErr_Clear();
+ _nodetree = (bNodeTree *)PyC_RNA_AsPointer(obj, "ShaderNodeTree");
+ if (_nodetree) {
+ self->py_ss.ss = new StrokeShaders::BlenderTextureShader(_nodetree);
+ return 0;
+ }
+ PyErr_Format(PyExc_TypeError,
+ "expected either 'LineStyleTextureSlot' or 'ShaderNodeTree', "
+ "found '%.200s' instead", Py_TYPE(obj)->tp_name);
+ return -1;
}
/*-----------------------BPy_BlenderTextureShader type definition ------------------------------*/
diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
index e92913d097e..b7b5eb4162b 100644
--- a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
+++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
@@ -451,7 +451,13 @@ int ColorNoiseShader::shade(Stroke& stroke) const
int BlenderTextureShader::shade(Stroke& stroke) const
{
- return stroke.setMTex(_mtex);
+ if (_mtex)
+ return stroke.setMTex(_mtex);
+ if (_nodeTree) {
+ stroke.setNodeTree(_nodeTree);
+ return 0;
+ }
+ return -1;
}
int StrokeTextureStepShader::shade(Stroke& stroke) const
diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h
index 9186d164e9b..6ac22c5b2d1 100644
--- a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h
+++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h
@@ -36,7 +36,10 @@
#include "../geometry/Bezier.h"
#include "../geometry/Geom.h"
+extern "C" {
struct MTex;
+struct bNodeTree;
+}
using namespace std;
@@ -904,6 +907,7 @@ class BlenderTextureShader : public StrokeShader
{
private:
MTex *_mtex;
+ bNodeTree *_nodeTree;
public:
/*! Builds the shader.
@@ -913,6 +917,17 @@ public:
BlenderTextureShader(MTex *mtex) : StrokeShader()
{
_mtex = mtex;
+ _nodeTree = NULL;
+ }
+
+ /*! Builds the shader.
+ * \param nodetree
+ * A node tree (of new shading nodes) to define textures.
+ */
+ BlenderTextureShader(bNodeTree *nodetree) : StrokeShader()
+ {
+ _nodeTree = nodetree;
+ _mtex = NULL;
}
virtual string getName() const
diff --git a/source/blender/freestyle/intern/stroke/Stroke.cpp b/source/blender/freestyle/intern/stroke/Stroke.cpp
index c85295e72bf..863da069259 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.cpp
+++ b/source/blender/freestyle/intern/stroke/Stroke.cpp
@@ -31,6 +31,7 @@
#include "StrokeRenderer.h"
#include "BKE_global.h"
+#include "BKE_node.h"
namespace Freestyle {
@@ -397,8 +398,8 @@ Stroke::Stroke()
for (int a = 0; a < MAX_MTEX; a++) {
_mtex[a] = NULL;
}
+ _nodeTree = NULL;
_tips = false;
- _rep = NULL;
}
Stroke::Stroke(const Stroke& iBrother)
@@ -424,11 +425,8 @@ Stroke::Stroke(const Stroke& iBrother)
_mtex[a] = NULL;
}
}
+ _nodeTree = iBrother._nodeTree;
_tips = iBrother._tips;
- if (iBrother._rep)
- _rep = new StrokeRep(*(iBrother._rep));
- else
- _rep = NULL;
}
Stroke::~Stroke()
@@ -441,10 +439,6 @@ Stroke::~Stroke()
}
_ViewEdges.clear();
- if (_rep) {
- delete _rep;
- _rep = NULL;
- }
}
Stroke& Stroke::operator=(const Stroke& iBrother)
@@ -462,10 +456,6 @@ Stroke& Stroke::operator=(const Stroke& iBrother)
_id = iBrother._id;
_ViewEdges = iBrother._ViewEdges;
_sampling = iBrother._sampling;
- if (_rep)
- delete _rep;
- if (iBrother._rep)
- _rep = new StrokeRep(*(iBrother._rep));
return *this;
}
@@ -601,11 +591,6 @@ int Stroke::Resample(int iNPoints)
_Vertices = newVertices;
newVertices.clear();
- if (_rep) {
- delete _rep;
- _rep = new StrokeRep(this);
- }
-
return 0;
}
@@ -660,10 +645,6 @@ int Stroke::Resample(float iSampling)
_Vertices = newVertices;
newVertices.clear();
- if (_rep) {
- delete _rep;
- _rep = new StrokeRep(this);
- }
return 0;
}
@@ -776,16 +757,14 @@ void Stroke::ScaleThickness(float iFactor)
void Stroke::Render(const StrokeRenderer *iRenderer)
{
- if (!_rep)
- _rep = new StrokeRep(this);
- iRenderer->RenderStrokeRep(_rep);
+ StrokeRep rep(this);
+ iRenderer->RenderStrokeRep(&rep);
}
void Stroke::RenderBasic(const StrokeRenderer *iRenderer)
{
- if (!_rep)
- _rep = new StrokeRep(this);
- iRenderer->RenderStrokeRepBasic(_rep);
+ StrokeRep rep(this);
+ iRenderer->RenderStrokeRepBasic(&rep);
}
Stroke::vertex_iterator Stroke::vertices_begin(float sampling)
diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h
index abbbcc32750..86c667a38b6 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.h
+++ b/source/blender/freestyle/intern/stroke/Stroke.h
@@ -45,6 +45,8 @@
extern "C" {
#include "DNA_material_types.h"
+
+struct bNodeTree;
}
#ifndef MAX_MTEX
@@ -541,9 +543,9 @@ private:
MediumType _mediumType;
unsigned int _textureId;
MTex *_mtex[MAX_MTEX];
+ bNodeTree *_nodeTree;
bool _tips;
Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity
- StrokeRep *_rep;
public:
/*! default constructor */
@@ -653,10 +655,16 @@ public:
return _mtex[idx];
}
+ /*! Return the shader node tree to define textures. */
+ inline bNodeTree *getNodeTree()
+ {
+ return _nodeTree;
+ }
+
/*! Returns true if this Stroke has textures assigned, false otherwise. */
inline bool hasTex() const
{
- return _mtex[0] != NULL;
+ return (_mtex[0] != NULL) || _nodeTree;
}
/*! Returns true if this Stroke uses a texture with tips, false otherwise. */
@@ -767,6 +775,12 @@ public:
return -1; /* no free slots */
}
+ /*! assigns a node tree (of new shading nodes) to define textures. */
+ inline void setNodeTree(bNodeTree *iNodeTree)
+ {
+ _nodeTree = iNodeTree;
+ }
+
/*! sets the flag telling whether this stroke is using a texture with tips or not. */
inline void setTips(bool iTips)
{
diff --git a/source/blender/freestyle/intern/stroke/StrokeIterators.h b/source/blender/freestyle/intern/stroke/StrokeIterators.h
index a8ec529fbfa..1df9aa2794a 100644
--- a/source/blender/freestyle/intern/stroke/StrokeIterators.h
+++ b/source/blender/freestyle/intern/stroke/StrokeIterators.h
@@ -171,6 +171,18 @@ public:
return _it == _begin;
}
+ /*! Returns true if the pointed StrokeVertex is the final valid StrokeVertex of the Stroke. */
+ bool atLast()
+ {
+ if (_it == _end)
+ return false;
+
+ ++_it;
+ bool result = (_it == _end);
+ --_it;
+ return result;
+ }
+
/*! Returns true if the pointed StrokeVertex is after the last StrokeVertex of the Stroke. */
bool isEnd() const
{
diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.cpp b/source/blender/freestyle/intern/stroke/StrokeRep.cpp
index 3f39443c4b8..f7857107006 100644
--- a/source/blender/freestyle/intern/stroke/StrokeRep.cpp
+++ b/source/blender/freestyle/intern/stroke/StrokeRep.cpp
@@ -704,6 +704,8 @@ StrokeRep::StrokeRep()
{
_stroke = 0;
_strokeType = Stroke::OPAQUE_MEDIUM;
+ _nodeTree = NULL;
+ _hasTex = false;
_textureStep = 1.0;
for (int a = 0; a < MAX_MTEX; a++) {
_mtex[a] = NULL;
@@ -724,6 +726,8 @@ StrokeRep::StrokeRep(Stroke *iStroke)
{
_stroke = iStroke;
_strokeType = iStroke->getMediumType();
+ _nodeTree = iStroke->getNodeTree();
+ _hasTex = iStroke->hasTex();
_textureId = iStroke->getTextureId();
_textureStep = iStroke->getTextureStep();
for (int a = 0; a < MAX_MTEX; a++) {
@@ -757,6 +761,8 @@ StrokeRep::StrokeRep(const StrokeRep& iBrother)
_strokeType = iBrother._strokeType;
_textureId = iBrother._textureId;
_textureStep = iBrother._textureStep;
+ _nodeTree = iBrother._nodeTree;
+ _hasTex = iBrother._hasTex;
for (int a = 0; a < MAX_MTEX; a++) {
if (iBrother._mtex[a]) {
_mtex[a] = iBrother._mtex[a];
@@ -808,7 +814,7 @@ void StrokeRep::create()
end = true;
}
if ((!strip.empty()) && (strip.size() > 1)) {
- _strips.push_back(new Strip(strip, _stroke->hasTex(), first, end, _textureStep));
+ _strips.push_back(new Strip(strip, _hasTex, first, end, _textureStep));
strip.clear();
}
first = false;
diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.h b/source/blender/freestyle/intern/stroke/StrokeRep.h
index 61a456cdf42..ba042eb496d 100644
--- a/source/blender/freestyle/intern/stroke/StrokeRep.h
+++ b/source/blender/freestyle/intern/stroke/StrokeRep.h
@@ -37,7 +37,8 @@
#endif
extern "C" {
-#include "DNA_material_types.h"
+#include "DNA_material_types.h" // for MAX_MTEX
+struct bNodeTree;
}
namespace Freestyle {
@@ -185,7 +186,9 @@ protected:
unsigned int _textureId;
float _textureStep;
MTex *_mtex[MAX_MTEX];
+ bNodeTree *_nodeTree;
Material *_material;
+ bool _hasTex;
// float _averageTextureAlpha;
@@ -222,6 +225,16 @@ public:
return _material;
}
+ inline bNodeTree *getNodeTree() const
+ {
+ return _nodeTree;
+ }
+
+ inline bool hasTex() const
+ {
+ return _hasTex;
+ }
+
inline vector<Strip*>& getStrips()
{
return _strips;
diff --git a/source/blender/freestyle/intern/system/PointerSequence.h b/source/blender/freestyle/intern/system/PointerSequence.h
index 32c7898f840..791df90ba9d 100644
--- a/source/blender/freestyle/intern/system/PointerSequence.h
+++ b/source/blender/freestyle/intern/system/PointerSequence.h
@@ -30,7 +30,7 @@
* PointerSequence
*
* Produces a wrapped version of a sequence type (std::vector, std::deque, std::list) that will take ownership of
- * pointers tht it stores. Those pointers will be deleted in its destructor.
+ * pointers that it stores. Those pointers will be deleted in its destructor.
*
* Because the contained pointers are wholly owned by the sequence, you cannot make a copy of the sequence.
* Making a copy would result in a double free.
diff --git a/source/blender/freestyle/intern/view_map/Interface0D.h b/source/blender/freestyle/intern/view_map/Interface0D.h
index 123253bf3e1..da71d7ad949 100644
--- a/source/blender/freestyle/intern/view_map/Interface0D.h
+++ b/source/blender/freestyle/intern/view_map/Interface0D.h
@@ -302,6 +302,18 @@ public:
return _iterator->isEnd();
}
+ /*! Returns true when the iterator is pointing to the final valid element. */
+ virtual bool atLast() const
+ {
+ if (_iterator->isEnd())
+ return false;
+
+ _iterator->increment();
+ bool result = _iterator->isEnd();
+ _iterator->decrement();
+ return result;
+ }
+
/*! operator == . */
bool operator==(const Interface0DIterator& it) const
{
diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.h b/source/blender/freestyle/intern/view_map/SteerableViewMap.h
index 0cd5d222621..3a660627776 100644
--- a/source/blender/freestyle/intern/view_map/SteerableViewMap.h
+++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.h
@@ -54,7 +54,7 @@ class GrayImage;
class SteerableViewMap
{
protected:
- // for each vector the list of nbOrientations weigths corresponding to its contributions
+ // for each vector the list of nbOrientations weights corresponding to its contributions
// to the nbOrientations directional maps
map<unsigned int, double*> _mapping;
unsigned _nbOrientations;
@@ -73,7 +73,7 @@ public:
virtual void Reset();
/*! Adds a FEdge to steerable VM.
- * Returns the nbOrientations weigths corresponding to the FEdge contributions to the nbOrientations
+ * Returns the nbOrientations weights corresponding to the FEdge contributions to the nbOrientations
* directional maps.
*/
double *AddFEdge(FEdge *iFEdge);
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index f59dd44f169..7d34c4e3829 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -140,7 +140,7 @@ set(SRC
GPU_primitives.h
GPU_raster.h
GPU_safety.h
- GPU_select.h
+ GPU_select.h
GPU_sprite.h
GPU_state_latch.h
GPU_utility.h
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 55325f91c05..ee20919dde3 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -38,11 +38,11 @@
extern "C" {
#endif
-#ifdef _DEBUG
-/*#define DEBUG_VBO(X) printf(X)*/
-#define DEBUG_VBO(X)
+#ifdef DEBUG
+/* #define DEBUG_VBO(X) printf(X)*/
+# define DEBUG_VBO(X)
#else
-#define DEBUG_VBO(X)
+# define DEBUG_VBO(X)
#endif
struct BMesh;
@@ -138,6 +138,7 @@ void GPU_drawobject_free(struct DerivedMesh *dm);
void GPU_vertex_setup(struct DerivedMesh *dm);
void GPU_normal_setup(struct DerivedMesh *dm);
void GPU_uv_setup(struct DerivedMesh *dm);
+void GPU_texpaint_uv_setup(struct DerivedMesh *dm);
/* colType is the cddata MCol type to use! */
void GPU_color_setup(struct DerivedMesh *dm, int colType);
void GPU_edge_setup(struct DerivedMesh *dm); /* does not mix with other data */
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index df707685a35..a4ac8424fbc 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -98,7 +98,7 @@ int GPU_get_material_alpha_blend(void);
* - passing NULL clears the state again */
int GPU_set_tpage(struct MTFace *tface, int mipmap, int transp);
-
+void GPU_clear_tpage(bool force);
/* Lights
* - returns how many lights were enabled
* - this affects fixed functions materials and texface, not glsl */
diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h
index ddf2601800d..dcb64628f24 100644
--- a/source/blender/gpu/GPU_immediate.h
+++ b/source/blender/gpu/GPU_immediate.h
@@ -939,23 +939,12 @@ BLI_INLINE void gpuDrawElements(GLenum mode)
}
-
-
-void gpu_draw_elements_gl(void);
-
-
-
BLI_INLINE void gpuRepeatElements(void)
{
gpu_draw_elements_gl();
}
-
-void gpu_draw_range_elements_gl(void);
-
-
-
BLI_INLINE void gpuDrawRangeElements(GLenum mode)
{
GPU_IMMEDIATE->mode = mode;
diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h
index 6b81ce7b248..9fe1b413a3c 100644
--- a/source/blender/gpu/GPU_select.h
+++ b/source/blender/gpu/GPU_select.h
@@ -1,6 +1,3 @@
-#ifndef _GPU_SELECT_H_
-#define _GPU_SELECT_H_
-
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -18,12 +15,10 @@
* 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) 2013 Blender Foundation.
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
* All rights reserved.
*
- * The Original Code is: all of this file.
- *
- * Contributor(s): Jason Wilkins.
+ * Contributor(s): Antony Riakiotakis.
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -32,30 +27,37 @@
* \ingroup gpu
*/
-#include "GPU_glew.h"
-
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#ifndef __GPU_SELECT__
+#define __GPU_SELECT__
+#include "GPU_glew.h"
+#include "DNA_vec_types.h" /* rcft */
+#include "BLI_sys_types.h"
+/* flags for mode of operation */
+enum {
+ GPU_SELECT_ALL = 1,
+ GPU_SELECT_NEAREST_FIRST_PASS = 2,
+ GPU_SELECT_NEAREST_SECOND_PASS = 3,
+};
-void GPU_select_buffer(GLsizei size, GLuint* buffer); /* replaces glSelectBuffer(size, buffer) */
+/* initialize and provide buffer for results */
+void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, char mode, int oldhits);
-void GPU_select_begin (void); /* replaces glRenderMode(GL_SELECT) */
-GLsizei GPU_select_end (void); /* replaces glRenderMode(GL_RENDER) */
+/* loads a new selection id and ends previous query, if any. In second pass of selection it also returns
+ * if id has been hit on the first pass already. Thus we can skip drawing un-hit objects IMPORTANT: We rely on the order of object rendering on passes to be
+ * the same for this to work */
+bool GPU_select_load_id(unsigned int id);
-void GPU_select_clear (void); /* replaces glInitNames() */
-void GPU_select_pop (void); /* replaces glPopName() */
-void GPU_select_push (GLuint name); /* replaces glPushName(name) */
-void GPU_select_load (GLuint name); /* replaces glLoadName(name) */
+/* cleanup and flush selection results to buffer. Return number of hits and hits in buffer.
+ * if dopass is true, we will do a second pass with occlusion queries to get the closest hit */
+unsigned int GPU_select_end(void);
+/* does the GPU support occlusion queries? */
+bool GPU_select_query_check_support(void);
+/* is occlusion query supported and user activated? */
+bool GPU_select_query_check_active(void);
-#ifdef __cplusplus
-}
#endif
-#endif /* _GPU_SELECT_H_ */
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index e6bac9afdfb..6eda6d35ff3 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -55,7 +55,16 @@
#include "BLI_ghash.h"
#include "BLI_threads.h"
+
#include "bmesh.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_ccg.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_paint.h"
+#include "BKE_material.h"
+#include "BKE_pbvh.h"
#include "DNA_meshdata_types.h"
#include "DNA_userdef_types.h"
@@ -68,15 +77,18 @@
#include <string.h>
typedef enum {
- GPU_BUFFER_VERTEX_STATE = 1,
- GPU_BUFFER_NORMAL_STATE = 2,
- GPU_BUFFER_TEXCOORD_STATE = 4,
- GPU_BUFFER_COLOR_STATE = 8,
- GPU_BUFFER_ELEMENT_STATE = 16,
+ GPU_BUFFER_VERTEX_STATE = (1 << 0),
+ GPU_BUFFER_NORMAL_STATE = (1 << 1),
+ GPU_BUFFER_TEXCOORD_UNIT_0_STATE = (1 << 2),
+ GPU_BUFFER_TEXCOORD_UNIT_2_STATE = (1 << 3),
+ GPU_BUFFER_COLOR_STATE = (1 << 4),
+ GPU_BUFFER_ELEMENT_STATE = (1 << 5),
} GPUBufferState;
#define MAX_GPU_ATTRIB_DATA 32
+#define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
+
/* -1 - undefined, 0 - vertex arrays, 1 - VBOs */
static int useVBOs = -1;
static GPUBufferState GLStates = 0;
@@ -843,6 +855,61 @@ static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int *
}
}
+
+static void GPU_buffer_copy_uv_texpaint(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
+{
+ int start;
+ int i, totface;
+
+ int totmaterial = dm->totmat;
+ MTFace **mtface_base;
+ MTFace *stencil_base;
+ int stencil;
+ MFace *mf;
+
+ /* should have been checked for before, reassert */
+ BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
+ mf = dm->getTessFaceArray(dm);
+ mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
+
+ for (i = 0; i < totmaterial; i++) {
+ mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
+ }
+
+ stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
+ stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+
+ totface = dm->getNumTessFaces(dm);
+
+ for (i = 0; i < totface; i++, mf++) {
+ int mat_i = mf->mat_nr;
+ start = index[mat_orig_to_new[mat_i]];
+
+ /* v1 v2 v3 */
+ copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]);
+ copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]);
+ copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]);
+ copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]);
+ copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]);
+ copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]);
+ index[mat_orig_to_new[mat_i]] += 12;
+
+ if (mf->v4) {
+ /* v3 v4 v1 */
+ copy_v2_v2(&varray[start + 12], mtface_base[mat_i][i].uv[2]);
+ copy_v2_v2(&varray[start + 14], stencil_base[i].uv[2]);
+ copy_v2_v2(&varray[start + 16], mtface_base[mat_i][i].uv[3]);
+ copy_v2_v2(&varray[start + 18], stencil_base[i].uv[3]);
+ copy_v2_v2(&varray[start + 20], mtface_base[mat_i][i].uv[0]);
+ copy_v2_v2(&varray[start + 22], stencil_base[i].uv[0]);
+ index[mat_orig_to_new[mat_i]] += 12;
+ }
+ }
+
+ MEM_freeN(mtface_base);
+}
+
+
static void copy_mcol_uc3(unsigned char *v, unsigned char *col)
{
v[0] = col[3];
@@ -932,6 +999,7 @@ typedef enum {
GPU_BUFFER_NORMAL,
GPU_BUFFER_COLOR,
GPU_BUFFER_UV,
+ GPU_BUFFER_UV_TEXPAINT,
GPU_BUFFER_EDGE,
GPU_BUFFER_UVEDGE,
} GPUBufferType;
@@ -943,12 +1011,13 @@ typedef struct {
} GPUBufferTypeSettings;
const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
- {GPU_buffer_copy_vertex, GL_ARRAY_BUFFER, 3},
- {GPU_buffer_copy_normal, GL_ARRAY_BUFFER, 3},
- {GPU_buffer_copy_mcol, GL_ARRAY_BUFFER, 3},
- {GPU_buffer_copy_uv, GL_ARRAY_BUFFER, 2},
- {GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER, 2},
- {GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER, 4},
+ {GPU_buffer_copy_vertex, GL_ARRAY_BUFFER, 3},
+ {GPU_buffer_copy_normal, GL_ARRAY_BUFFER, 3},
+ {GPU_buffer_copy_mcol, GL_ARRAY_BUFFER, 3},
+ {GPU_buffer_copy_uv, GL_ARRAY_BUFFER, 2},
+ {GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER, 4},
+ {GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER, 2},
+ {GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER, 4},
};
/* get the GPUDrawObject buffer associated with a type */
@@ -963,6 +1032,8 @@ static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBuffer
return &gdo->colors;
case GPU_BUFFER_UV:
return &gdo->uv;
+ case GPU_BUFFER_UV_TEXPAINT:
+ return &gdo->uv;
case GPU_BUFFER_EDGE:
return &gdo->edges;
case GPU_BUFFER_UVEDGE:
@@ -984,6 +1055,8 @@ static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
return sizeof(char) * 3 * dm->drawObject->tot_triangle_point;
case GPU_BUFFER_UV:
return sizeof(float) * 2 * dm->drawObject->tot_triangle_point;
+ case GPU_BUFFER_UV_TEXPAINT:
+ return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
case GPU_BUFFER_EDGE:
return sizeof(int) * 2 * dm->drawObject->totedge;
case GPU_BUFFER_UVEDGE:
@@ -1012,7 +1085,7 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType)))
return NULL;
}
- else if (type == GPU_BUFFER_UV) {
+ else if (ELEM(type, GPU_BUFFER_UV, GPU_BUFFER_UV_TEXPAINT)) {
if (!DM_get_tessface_data_layer(dm, CD_MTFACE))
return NULL;
}
@@ -1088,9 +1161,35 @@ void GPU_uv_setup(DerivedMesh *dm)
glTexCoordPointer(2, GL_FLOAT, 0, dm->drawObject->uv->pointer);
}
- GLStates |= GPU_BUFFER_TEXCOORD_STATE;
+ GLStates |= GPU_BUFFER_TEXCOORD_UNIT_0_STATE;
+}
+
+void GPU_texpaint_uv_setup(DerivedMesh *dm)
+{
+ if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UV_TEXPAINT))
+ return;
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ if (useVBOs) {
+ gpu_glBindBuffer(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id);
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0);
+ glClientActiveTexture(GL_TEXTURE2);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), BUFFER_OFFSET(2 * sizeof(float)));
+ glClientActiveTexture(GL_TEXTURE0);
+ }
+ else {
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), dm->drawObject->uv->pointer);
+ glClientActiveTexture(GL_TEXTURE2);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)dm->drawObject->uv->pointer + 2 * sizeof(float));
+ glClientActiveTexture(GL_TEXTURE0);
+ }
+
+ GLStates |= GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_2_STATE;
}
+
void GPU_color_setup(DerivedMesh *dm, int colType)
{
if (!dm->drawObject) {
@@ -1248,8 +1347,13 @@ void GPU_buffer_unbind(void)
glDisableClientState(GL_VERTEX_ARRAY);
if (GLStates & GPU_BUFFER_NORMAL_STATE)
glDisableClientState(GL_NORMAL_ARRAY);
- if (GLStates & GPU_BUFFER_TEXCOORD_STATE)
+ if (GLStates & GPU_BUFFER_TEXCOORD_UNIT_0_STATE)
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ if (GLStates & GPU_BUFFER_TEXCOORD_UNIT_2_STATE) {
+ glClientActiveTexture(GL_TEXTURE2);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glClientActiveTexture(GL_TEXTURE0);
+ }
if (GLStates & GPU_BUFFER_COLOR_STATE)
glDisableClientState(GL_COLOR_ARRAY);
if (GLStates & GPU_BUFFER_ELEMENT_STATE) {
@@ -1258,8 +1362,8 @@ void GPU_buffer_unbind(void)
}
}
GLStates &= ~(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE |
- GPU_BUFFER_TEXCOORD_STATE | GPU_BUFFER_COLOR_STATE |
- GPU_BUFFER_ELEMENT_STATE);
+ GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_2_STATE |
+ GPU_BUFFER_COLOR_STATE | GPU_BUFFER_ELEMENT_STATE);
for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
if (attribData[i].index != -1) {
@@ -2584,11 +2688,17 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces,
}
else if (buffers->use_bmesh) {
/* due to dynamc nature of dyntopo, only get first material */
- GSetIterator gs_iter;
- BMFace *f;
- BLI_gsetIterator_init(&gs_iter, bm_faces);
- f = BLI_gsetIterator_getKey(&gs_iter);
- GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+ if (BLI_gset_size(bm_faces) > 0) {
+ GSetIterator gs_iter;
+ BMFace *f;
+
+ BLI_gsetIterator_init(&gs_iter, bm_faces);
+ f = BLI_gsetIterator_getKey(&gs_iter);
+ GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+ }
+ else {
+ return false;
+ }
}
else {
const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]];
@@ -2596,9 +2706,7 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces,
GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
}
- return diffuse_color[0] != buffers->diffuse_color[0] ||
- diffuse_color[1] != buffers->diffuse_color[1] ||
- diffuse_color[2] != buffers->diffuse_color[2];
+ return !equals_v3v3(diffuse_color, buffers->diffuse_color);
}
/* release a GPU_PBVH_Buffers id;
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 0440215c774..c9109b96424 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -105,7 +105,7 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
/* skip a variable/function name */
while (*str) {
- if (ELEM7(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
+ if (ELEM(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
break;
else {
if (token && len < max-1) {
@@ -123,7 +123,7 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
/* skip the next special characters:
* note the missing ')' */
while (*str) {
- if (ELEM6(*str, ' ', '(', ',', '\t', '\n', '\r'))
+ if (ELEM(*str, ' ', '(', ',', '\t', '\n', '\r'))
str++;
else
break;
@@ -1417,6 +1417,10 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
/* failed? */
if (!shader) {
+ if (fragmentcode)
+ MEM_freeN(fragmentcode);
+ if (vertexcode)
+ MEM_freeN(vertexcode);
memset(attribs, 0, sizeof(*attribs));
memset(builtins, 0, sizeof(*builtins));
GPU_nodes_free(nodes);
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index dd495657ea1..729146e065b 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -378,9 +378,9 @@ static void blend_func_state_init(void)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
-static void gpu_clear_tpage(void)
+void GPU_clear_tpage(bool force)
{
- if (GTS.lasttface==NULL)
+ if (GTS.lasttface==NULL && !force)
return;
GTS.lasttface= NULL;
@@ -540,12 +540,16 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
* a high precision format only if it is available */
use_high_bit_depth = true;
}
+ /* we may skip this in high precision, but if not, we need to have a valid buffer here */
+ else if (ibuf->userflags & IB_RECT_INVALID) {
+ IMB_rect_from_float(ibuf);
+ }
/* TODO unneeded when float images are correctly treated as linear always */
if (!is_data)
do_color_management = true;
- if (ibuf->rect==NULL)
+ if (ibuf->rect == NULL)
IMB_rect_from_float(ibuf);
}
@@ -876,7 +880,7 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend)
/* check if we need to clear the state */
if (tface==NULL) {
- gpu_clear_tpage();
+ GPU_clear_tpage(false);
return 0;
}
@@ -1045,21 +1049,14 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
* which is much quicker for painting */
GLint row_length, skip_pixels, skip_rows;
- glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
- glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
- glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows);
-
/* if color correction is needed, we must update the part that needs updating. */
if (ibuf->rect_float) {
- float *buffer = MEM_mallocN(w*h*sizeof(float)*4, "temp_texpaint_float_buf");
+ float *buffer = MEM_mallocN(w * h * sizeof(float) * 4, "temp_texpaint_float_buf");
bool is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA) != 0;
IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data);
-
+
if (GPU_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
MEM_freeN(buffer);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
- glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
- glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
BKE_image_release_ibuf(ima, ibuf, NULL);
return;
}
@@ -1084,15 +1081,16 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
}
if (GPU_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
- glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
- glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
BKE_image_release_ibuf(ima, ibuf, NULL);
return;
}
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
+ glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
+ glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows);
+
glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
@@ -1558,7 +1556,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
/* setting 'do_alpha_after = true' indicates this object needs to be
* drawn in a second alpha pass for improved blending */
if (do_alpha_after && !GMS.is_alpha_pass)
- if (ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT))
+ if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT))
*do_alpha_after = true;
GMS.alphablend[a]= alphablend;
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 6c4d1018272..310b46266d3 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -79,6 +79,8 @@
#include <string.h>
+#define MAX_DEFINE_LENGTH 72
+
/* Extensions support */
/* extensions used:
@@ -992,6 +994,9 @@ bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char er
gpu_glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
GG.currentfb = fb->object;
+ /* Clean glError buffer. */
+ while (glGetError() != GL_NO_ERROR) {}
+
gpu_glFramebufferTexture2D(GL_FRAMEBUFFER, attachment,
tex->target, tex->bindcode, 0);
@@ -1378,35 +1383,51 @@ static bool print_status(GLuint object, GLboolean is_program, const char* nickna
return status;
}
+static const char *gpu_shader_version(void)
+{
+ /* turn on glsl 1.30 for bicubic bump mapping and ATI clipping support */
+ if (GLEW_VERSION_3_0 &&
+ (GPU_bicubic_bump_support() || GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)))
+ {
+ return "#version 130\n";
+ }
+
+ return "";
+}
+
+
static const char *gpu_shader_standard_extensions(void)
{
/* need this extensions for high quality bump mapping */
- if (GPU_bicubic_bump_support()) {
- return "#version 130\n"
- "#extension GL_ARB_texture_query_lod: enable\n"
- "#define BUMP_BICUBIC\n";
- }
+ if (GPU_bicubic_bump_support())
+ return "#extension GL_ARB_texture_query_lod: enable\n";
return "";
}
-static const char *gpu_shader_standard_defines(void)
+static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH])
{
/* some useful defines to detect GPU type */
- if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY))
- return "#define GPU_ATI\n";
+ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+ strcat(defines, "#define GPU_ATI\n");
+ if (GLEW_VERSION_3_0)
+ strcat(defines, "#define CLIP_WORKAROUND\n");
+ }
else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY))
- return "#define GPU_NVIDIA\n";
+ strcat(defines, "#define GPU_NVIDIA\n");
else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY))
- return "#define GPU_INTEL\n";
-
- return "";
+ strcat(defines, "#define GPU_INTEL\n");
+
+ if (GPU_bicubic_bump_support())
+ strcat(defines, "#define BUMP_BICUBIC\n");
+ return;
}
GPUShader *GPU_shader_create(const char* nickname, const char *vertexcode, const char *fragcode, const char *libcode, const char *defines)
{
GLint status;
GPUShader *shader;
+ char standard_defines[MAX_DEFINE_LENGTH] = "";
#if 0
int i;
@@ -1460,12 +1481,16 @@ GPUShader *GPU_shader_create(const char* nickname, const char *vertexcode, const
return NULL;
}
+ gpu_shader_standard_defines(standard_defines);
+
if (vertexcode) {
- const char *source[4];
+ const char *source[5];
+ /* custom limit, may be too small, beware */
int num_source = 0;
+ source[num_source++] = gpu_shader_version();
source[num_source++] = gpu_shader_standard_extensions();
- source[num_source++] = gpu_shader_standard_defines();
+ source[num_source++] = standard_defines;
if (defines) source[num_source++] = defines;
if (vertexcode) source[num_source++] = vertexcode;
@@ -1482,11 +1507,12 @@ GPUShader *GPU_shader_create(const char* nickname, const char *vertexcode, const
}
if (fragcode) {
- const char *source[5];
+ const char *source[6];
int num_source = 0;
+ source[num_source++] = gpu_shader_version();
source[num_source++] = gpu_shader_standard_extensions();
- source[num_source++] = gpu_shader_standard_defines();
+ source[num_source++] = standard_defines;
if (defines) source[num_source++] = defines;
if (libcode) source[num_source++] = libcode;
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
index dbe480993cb..7f5127408aa 100644
--- a/source/blender/gpu/intern/gpu_immediate.c
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -483,7 +483,7 @@ static GLboolean end_begin(void)
GPU_IMMEDIATE->hasOverflowed = GL_TRUE;
#endif
- if (!ELEM6(
+ if (!ELEM(
GPU_IMMEDIATE->mode,
GL_NOOP,
GL_LINE_LOOP,
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 9e89f6afd24..4f8ae3ebde8 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -951,6 +951,12 @@ static void texture_rgb_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *o
case MTEX_BLEND_COLOR:
GPU_link(mat, "mtex_rgb_color", out, tex, fact, facg, in);
break;
+ case MTEX_SOFT_LIGHT:
+ GPU_link(mat, "mtex_rgb_soft", out, tex, fact, facg, in);
+ break;
+ case MTEX_LIN_LIGHT:
+ GPU_link(mat, "mtex_rgb_linear", out, tex, fact, facg, in);
+ break;
default:
GPU_link(mat, "set_rgb_zero", &in);
break;
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
index 583e378c32f..dab468e6733 100644
--- a/source/blender/gpu/intern/gpu_matrix.c
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -79,7 +79,7 @@ static GLenum ms_current_mode;
/* Check if we have a good matrix */
-#if WITH_GPU_SAFETY
+#ifdef WITH_GPU_SAFETY
static void checkmat(GLfloat *m)
{
diff --git a/source/blender/gpu/intern/gpu_raster.c b/source/blender/gpu/intern/gpu_raster.c
index 81a733a54a0..cbda490f980 100644
--- a/source/blender/gpu/intern/gpu_raster.c
+++ b/source/blender/gpu/intern/gpu_raster.c
@@ -502,7 +502,7 @@ static GLboolean end_begin(void)
GPU_IMMEDIATE->hasOverflowed = GL_TRUE;
#endif
- if (!ELEM6(
+ if (!ELEM(
GPU_IMMEDIATE->mode,
GL_NOOP,
GL_LINE_LOOP,
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 2ae5bc8a742..17fd584a340 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -15,177 +15,237 @@
* 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) 2013 Blender Foundation.
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
* All rights reserved.
*
- * The Original Code is: all of this file.
- *
- * Contributor(s): Jason Wilkins.
+ * Contributor(s): Antony Riakiotakis, Jason Wilkins.
*
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file source/blender/gpu/intern/gpu_select.c
+/** \file blender/gpu/intern/gpu_select.c
* \ingroup gpu
+ *
+ * Interface for accessing gpu-related methods for selection. The semantics will be
+ * similar to glRenderMode(GL_SELECT) since the goal is to maintain compatibility.
*/
#if WITH_GL_PROFILE_COMPAT
#define GPU_MANGLE_DEPRECATED 0 /* Allow use of deprecated OpenGL functions in this file */
#endif
-/* my interface */
-#include "intern/gpu_select_intern.h"
-
-/* my library */
-#include "GPU_safety.h"
+#include "GPU_select.h"
+#include "GPU_extensions.h"
-/* internal */
-#include "intern/gpu_matrix_intern.h"
-#include "intern/gpu_aspect_intern.h"
-
-/* external */
#include "BLI_utildefines.h"
-
-
-static bool IS_SELECT_MODE = false;
-
-
-
-void gpu_select_init(void)
-{
- IS_SELECT_MODE = false;
-}
-
-
-
-void gpu_select_exit(void)
-{
-}
-
-
-
-bool gpu_default_select_begin(const void* UNUSED(object), void* UNUSED(param))
+#include "MEM_guardedalloc.h"
+
+#include "DNA_userdef_types.h"
+
+#include <GL/glew.h>
+
+/* Ad hoc number of queries to allocate to skip doing many glGenQueries */
+#define ALLOC_QUERIES 200
+
+typedef struct GPUQueryState {
+ /* To ignore selection id calls when not initialized */
+ bool select_is_active;
+ /* Tracks whether a query has been issued so that gpu_load_id can end the previous one */
+ bool query_issued;
+ /* array holding the OpenGL query identifiers */
+ unsigned int *queries;
+ /* array holding the id corresponding to each query */
+ unsigned int *id;
+ /* number of queries in *queries and *id */
+ unsigned int num_of_queries;
+ /* index to the next query to start */
+ unsigned int active_query;
+ /* flag to cache user preference for occlusion based selection */
+ bool use_gpu_select;
+ /* cache on initialization */
+ unsigned int *buffer;
+ unsigned int bufsize;
+ /* mode of operation */
+ char mode;
+ unsigned int index;
+ int oldhits;
+} GPUQueryState;
+
+static GPUQueryState g_query_state = {0};
+
+void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, char mode, int oldhits)
{
-#if defined(WITH_GPU_PROFILE_COMPAT)
- return true; /* nothing to do, allow this pass to start */
-#else
- return false; /* not implemented, so cancel this pass before it starts if possible */
-#endif
+ g_query_state.select_is_active = true;
+ g_query_state.query_issued = false;
+ g_query_state.active_query = 0;
+ g_query_state.use_gpu_select = GPU_select_query_check_active();
+ g_query_state.num_of_queries = 0;
+ g_query_state.bufsize = bufsize;
+ g_query_state.buffer = buffer;
+ g_query_state.mode = mode;
+ g_query_state.index = 0;
+ g_query_state.oldhits = oldhits;
+
+ if (!g_query_state.use_gpu_select) {
+ glSelectBuffer( bufsize, (GLuint *)buffer);
+ glRenderMode(GL_SELECT);
+ glInitNames();
+ glPushName(-1);
+ }
+ else {
+ float viewport[4];
+
+ g_query_state.num_of_queries = ALLOC_QUERIES;
+
+ g_query_state.queries = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.queries) , "gpu selection queries");
+ g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id) , "gpu selection ids");
+ glGenQueriesARB(g_query_state.num_of_queries, g_query_state.queries);
+
+ glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT);
+ /* disable writing to the framebuffer */
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ /* In order to save some fill rate we minimize the viewport using rect.
+ * We need to get the region of the scissor so that our geometry doesn't
+ * get rejected before the depth test. Should probably cull rect against
+ * scissor for viewport but this is a rare case I think */
+ glGetFloatv(GL_SCISSOR_BOX, viewport);
+ if (!input || input->xmin == input->xmax) {
+ glViewport(viewport[0], viewport[1], 24, 24);
+ }
+ else {
+ glViewport(viewport[0], viewport[1], (int)(input->xmax - input->xmin), (int)(input->ymax - input->ymin));
+ }
+
+ /* occlusion queries operates on fragments that pass tests and since we are interested on all
+ * objects in the view frustum independently of their order, we need to disable the depth test */
+ if (mode == GPU_SELECT_ALL) {
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+ }
+ else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);
+ glDepthFunc(GL_LEQUAL);
+ }
+ else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);
+ glDepthFunc(GL_EQUAL);
+ }
+ }
}
-
-
-bool gpu_default_select_end(const void* UNUSED(object), void* UNUSED(param))
+bool GPU_select_load_id(unsigned int id)
{
- return true; /* only one pass, 'true' means 'done' */
-}
-
-
+ /* if no selection mode active, ignore */
+ if(!g_query_state.select_is_active)
+ return true;
-bool gpu_default_select_commit(const void* UNUSED(object))
-{
-#if defined(WITH_GPU_PROFILE_COMPAT)
- gpu_set_common(NULL);
- gpu_glUseProgram(0);
- gpu_commit_matrix();
+ if (!g_query_state.use_gpu_select) {
+ glLoadName(id);
+ }
+ else {
+ if (g_query_state.query_issued) {
+ glEndQueryARB(GL_SAMPLES_PASSED_ARB);
+ }
+ /* if required, allocate extra queries */
+ if (g_query_state.active_query == g_query_state.num_of_queries) {
+ g_query_state.num_of_queries += ALLOC_QUERIES;
+ g_query_state.queries = MEM_reallocN(g_query_state.queries, g_query_state.num_of_queries * sizeof(*g_query_state.queries));
+ g_query_state.id = MEM_reallocN(g_query_state.id, g_query_state.num_of_queries * sizeof(*g_query_state.id));
+ glGenQueriesARB(ALLOC_QUERIES, &g_query_state.queries[g_query_state.active_query]);
+ }
+
+ glBeginQueryARB(GL_SAMPLES_PASSED_ARB, g_query_state.queries[g_query_state.active_query]);
+ g_query_state.id[g_query_state.active_query] = id;
+ g_query_state.active_query++;
+ g_query_state.query_issued = true;
+
+ if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) {
+ if (g_query_state.buffer[g_query_state.index * 4 + 3] == id) {
+ g_query_state.index++;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
return true;
-#else
- return false; /* cancel drawing, since select mode isn't implemented */
-#endif
}
-
-
-bool gpu_is_select_mode(void)
-{
- return IS_SELECT_MODE;
-}
-
-
-
-void GPU_select_buffer(GLsizei size, GLuint* buffer)
+unsigned int GPU_select_end(void)
{
- GPU_ASSERT(!IS_SELECT_MODE);
-
- if (!IS_SELECT_MODE) {
-#if defined(WITH_GL_PROFILE_COMPAT)
- glSelectBuffer(size, buffer);
-#endif
+ unsigned int hits = 0;
+ if (!g_query_state.use_gpu_select) {
+ glPopName();
+ hits = glRenderMode(GL_RENDER);
}
-}
-
-
-
-void GPU_select_begin(void)
-{
- GPU_ASSERT(!gpu_aspect_active());
- GPU_ASSERT(!IS_SELECT_MODE);
-
- IS_SELECT_MODE = true;
-
-#if defined(WITH_GL_PROFILE_COMPAT)
- glRenderMode(GL_SELECT);
-#endif
-}
-
-
-
-GLsizei GPU_select_end(void)
-{
- GPU_ASSERT(!gpu_aspect_active());
- GPU_ASSERT(IS_SELECT_MODE);
-
- IS_SELECT_MODE = false;
-
-#if defined(WITH_GL_PROFILE_COMPAT)
- return glRenderMode(GL_RENDER);
-#else
- return 0;
-#endif
-}
-
-
-
-void GPU_select_clear(void)
-{
- if (IS_SELECT_MODE) {
-#if defined(WITH_GL_PROFILE_COMPAT)
- glInitNames();
-#endif
+ else {
+ int i;
+
+ if (g_query_state.query_issued) {
+ glEndQueryARB(GL_SAMPLES_PASSED_ARB);
+ }
+
+ for (i = 0; i < g_query_state.active_query; i++) {
+ unsigned int result;
+ glGetQueryObjectuivARB(g_query_state.queries[i], GL_QUERY_RESULT_ARB, &result);
+ if (result > 0) {
+ if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
+ if(hits < g_query_state.bufsize) {
+ g_query_state.buffer[hits * 4] = 1;
+ g_query_state.buffer[hits * 4 + 1] = 0xFFFF;
+ g_query_state.buffer[hits * 4 + 2] = 0xFFFF;
+ g_query_state.buffer[hits * 4 + 3] = g_query_state.id[i];
+
+ hits++;
+ }
+ else {
+ hits = -1;
+ break;
+ }
+ }
+ else {
+ int j;
+ /* search in buffer and make selected object first */
+ for (j = 0; j < g_query_state.oldhits; j++) {
+ if (g_query_state.buffer[j * 4 + 3] == g_query_state.id[i]) {
+ g_query_state.buffer[j * 4 + 1] = 0;
+ g_query_state.buffer[j * 4 + 2] = 0;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ glDeleteQueriesARB(g_query_state.num_of_queries, g_query_state.queries);
+ MEM_freeN(g_query_state.queries);
+ MEM_freeN(g_query_state.id);
+ glPopAttrib();
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
-}
+ g_query_state.select_is_active = false;
-
-void GPU_select_pop(void)
-{
- if (IS_SELECT_MODE) {
-#if defined(WITH_GL_PROFILE_COMPAT)
- glPopName();
-#endif
- }
+ return hits;
}
-
-void GPU_select_push(GLuint name)
+bool GPU_select_query_check_support(void)
{
- if (IS_SELECT_MODE) {
-#if defined(WITH_GL_PROFILE_COMPAT)
- glPushName(name);
-#endif
- }
+ return GLEW_ARB_occlusion_query;
}
-
-void GPU_select_load(GLuint name)
+bool GPU_select_query_check_active(void)
{
- if (IS_SELECT_MODE) {
-#if defined(WITH_GL_PROFILE_COMPAT)
- glLoadName(name);
-#endif
- }
+ return GLEW_ARB_occlusion_query &&
+ ((U.gpu_select_method == USER_SELECT_USE_OCCLUSION_QUERY) ||
+ ((U.gpu_select_method == USER_SELECT_AUTO) && GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)));
}
diff --git a/source/blender/gpu/intern/gpu_utility.c b/source/blender/gpu/intern/gpu_utility.c
index 999a44a91c1..285701af1aa 100644
--- a/source/blender/gpu/intern/gpu_utility.c
+++ b/source/blender/gpu/intern/gpu_utility.c
@@ -57,7 +57,7 @@ const char* gpuErrorString(GLenum err)
case GL_OUT_OF_MEMORY:
return "Out of Memory";
-#if GL_ARB_imagining
+#ifdef GL_ARB_imagining
case GL_TABLE_TOO_LARGE:
return "Table Too Large";
#endif
@@ -102,7 +102,7 @@ const char* gpuErrorSymbol(GLenum err)
case GL_OUT_OF_MEMORY:
return "GL_OUT_OF_MEMORY";
-#if GL_ARB_imagining
+#ifdef GL_ARB_imagining
case GL_TABLE_TOO_LARGE:
return "GL_TABLE_TOO_LARGE";
#endif
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index d5d0c7ef454..3ba36c11311 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1012,6 +1012,38 @@ void mtex_rgb_color(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 i
incol.rgb = col.rgb;
}
+void mtex_rgb_soft(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
+{
+ float facm;
+
+ fact *= facg;
+ facm = 1.0-fact;
+
+ vec3 one = vec3(1.0);
+ vec3 scr = one - (one - texcol)*(one - outcol);
+ incol = facm*outcol + fact*((one - texcol)*outcol*texcol + outcol*scr);
+}
+
+void mtex_rgb_linear(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
+{
+ fact *= facg;
+
+ if(texcol.r > 0.5)
+ incol.r = outcol.r + fact*(2.0*(texcol.r - 0.5));
+ else
+ incol.r = outcol.r + fact*(2.0*(texcol.r) - 1.0);
+
+ if(texcol.g > 0.5)
+ incol.g = outcol.g + fact*(2.0*(texcol.g - 0.5));
+ else
+ incol.g = outcol.g + fact*(2.0*(texcol.g) - 1.0);
+
+ if(texcol.b > 0.5)
+ incol.b = outcol.b + fact*(2.0*(texcol.b - 0.5));
+ else
+ incol.b = outcol.b + fact*(2.0*(texcol.b) - 1.0);
+}
+
void mtex_value_vars(inout float fact, float facg, out float facm)
{
fact *= abs(facg);
@@ -1179,7 +1211,12 @@ void mtex_mapping_size(vec3 texco, vec3 size, out vec3 outtexco)
void mtex_2d_mapping(vec3 vec, out vec3 outvec)
{
- outvec = vec3(vec.xy*0.5 + vec2(0.5, 0.5), vec.z);
+ outvec = vec3(vec.xy*0.5 + vec2(0.5), vec.z);
+}
+
+vec3 mtex_2d_mapping(vec3 vec)
+{
+ return vec3(vec.xy*0.5 + vec2(0.5), vec.z);
}
void mtex_image(vec3 texco, sampler2D ima, out float value, out vec4 color)
@@ -2257,6 +2294,11 @@ void node_attribute(vec3 attr_uv, out vec4 outcol, out vec3 outvec, out float ou
outf = (attr_uv.x + attr_uv.y + attr_uv.z)/3.0;
}
+void node_uvmap(vec3 attr_uv, out vec3 outvec)
+{
+ outvec = attr_uv;
+}
+
void node_geometry(vec3 I, vec3 N, mat4 toworld,
out vec3 position, out vec3 normal, out vec3 tangent,
out vec3 true_normal, out vec3 incoming, out vec3 parametric,
@@ -2280,14 +2322,18 @@ void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat,
out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
out vec3 camera, out vec3 window, out vec3 reflection)
{
- generated = attr_orco;
+ generated = mtex_2d_mapping(attr_orco);
normal = normalize((obinvmat*(viewinvmat*vec4(N, 0.0))).xyz);
uv = attr_uv;
object = (obinvmat*(viewinvmat*vec4(I, 1.0))).xyz;
camera = I;
- window = gl_FragCoord.xyz;
- reflection = reflect(N, I);
+ vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0);
+ window = mtex_2d_mapping(projvec.xyz/projvec.w);
+ vec3 shade_I;
+ shade_view(I, shade_I);
+ vec3 view_reflection = reflect(shade_I, normalize(N));
+ reflection = (viewinvmat*vec4(view_reflection, 0.0)).xyz;
}
/* textures */
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_vert.glsl b/source/blender/gpu/shaders/gpu_shader_simple_vert.glsl
new file mode 100644
index 00000000000..8ccd0feb5e2
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_simple_vert.glsl
@@ -0,0 +1,54 @@
+
+#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
+varying vec3 varying_normal;
+
+#ifndef USE_SOLID_LIGHTING
+varying vec3 varying_position;
+#endif
+#endif
+
+#ifdef USE_COLOR
+varying vec4 varying_vertex_color;
+#endif
+
+#ifdef USE_TEXTURE
+varying vec2 varying_texture_coord;
+#endif
+
+#ifdef CLIP_WORKAROUND
+varying float gl_ClipDistance[6];
+#endif
+
+void main()
+{
+ vec4 co = gl_ModelViewMatrix * gl_Vertex;
+
+#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
+ varying_normal = normalize(gl_NormalMatrix * gl_Normal);
+
+#ifndef USE_SOLID_LIGHTING
+ varying_position = co.xyz;
+#endif
+#endif
+
+ gl_Position = gl_ProjectionMatrix * co;
+
+#ifdef CLIP_WORKAROUND
+ int i;
+ for(i = 0; i < 6; i++)
+ gl_ClipDistance[i] = dot(co, gl_ClipPlane[i]);
+#elif !defined(GPU_ATI)
+ // Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA
+ // graphic cards, while on ATI it can cause a software fallback.
+ gl_ClipVertex = co;
+#endif
+
+#ifdef USE_COLOR
+ varying_vertex_color = gl_Color;
+#endif
+
+#ifdef USE_TEXTURE
+ varying_texture_coord = (gl_TextureMatrix[0] * gl_MultiTexCoord0).st;
+#endif
+}
+
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
index 159e531eb44..b5d8dcc0f35 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
@@ -2,6 +2,10 @@
varying vec3 varposition;
varying vec3 varnormal;
+#ifdef CLIP_WORKAROUND
+varying float gl_ClipDistance[6];
+#endif
+
void main()
{
vec4 co = gl_ModelViewMatrix * gl_Vertex;
@@ -10,9 +14,13 @@ void main()
varnormal = normalize(gl_NormalMatrix * gl_Normal);
gl_Position = gl_ProjectionMatrix * co;
-#ifndef GPU_ATI
+#ifdef CLIP_WORKAROUND
+ int i;
+ for(i = 0; i < 6; i++)
+ gl_ClipDistance[i] = dot(co, gl_ClipPlane[i]);
+#elif !defined(GPU_ATI)
// Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA
// graphic cards, while on ATI it can cause a software fallback.
- gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+ gl_ClipVertex = co;
#endif
diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c
index 80c508267f3..cd09b56b262 100644
--- a/source/blender/ikplugin/intern/iksolver_plugin.c
+++ b/source/blender/ikplugin/intern/iksolver_plugin.c
@@ -215,7 +215,7 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[3][3]) // nr =
copy_m4_m3(ikmat, ik_mat);
if (pchan->parent)
- mul_serie_m4(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat);
else
mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, ikmat);
@@ -420,7 +420,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
/* end effector in world space */
copy_m4_m4(end_pose, pchan->pose_mat);
copy_v3_v3(end_pose[3], pchan->pose_tail);
- mul_serie_m4(world_pose, goalinv, ob->obmat, end_pose, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(world_pose, goalinv, ob->obmat, end_pose);
/* blend position */
goalpos[0] = fac * goalpos[0] + mfac * world_pose[3][0];
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index dbc4100e287..5077ccec256 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -566,7 +566,7 @@ static bool target_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Fram
float chanmat[4][4];
copy_m4_m4(chanmat, pchan->pose_mat);
copy_v3_v3(chanmat[3], pchan->pose_tail);
- mul_serie_m4(restmat, target->owner->obmat, chanmat, target->eeRest, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(restmat, target->owner->obmat, chanmat, target->eeRest);
}
else {
mul_m4_m4m4(restmat, target->owner->obmat, target->eeRest);
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 090e7a66d41..ce6a7eb1c47 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -163,6 +163,22 @@ typedef enum IMB_BlendMode {
IMB_BLEND_DARKEN = 5,
IMB_BLEND_ERASE_ALPHA = 6,
IMB_BLEND_ADD_ALPHA = 7,
+ IMB_BLEND_OVERLAY = 8,
+ IMB_BLEND_HARDLIGHT = 9,
+ IMB_BLEND_COLORBURN = 10,
+ IMB_BLEND_LINEARBURN = 11,
+ IMB_BLEND_COLORDODGE = 12,
+ IMB_BLEND_SCREEN = 13,
+ IMB_BLEND_SOFTLIGHT = 14,
+ IMB_BLEND_PINLIGHT = 15,
+ IMB_BLEND_VIVIDLIGHT = 16,
+ IMB_BLEND_LINEARLIGHT = 17,
+ IMB_BLEND_DIFFERENCE = 18,
+ IMB_BLEND_EXCLUSION = 19,
+ IMB_BLEND_HUE = 20,
+ IMB_BLEND_SATURATION = 21,
+ IMB_BLEND_LUMINOSITY = 22,
+ IMB_BLEND_COLOR = 23,
IMB_BLEND_COPY = 1000,
IMB_BLEND_COPY_RGB = 1001,
@@ -179,9 +195,9 @@ void IMB_rectclip(struct ImBuf *dbuf, struct ImBuf *sbuf, int *destx,
void IMB_rectcpy(struct ImBuf *drect, struct ImBuf *srect, int destx,
int desty, int srcx, int srcy, int width, int height);
void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *obuf, struct ImBuf *sbuf,
- unsigned short *dmask, unsigned short *smask, unsigned short mask_max,
+ unsigned short *dmask, unsigned short *curvemask, unsigned short *mmask, float mask_max,
int destx, int desty, int origx, int origy, int srcx, int srcy,
- int width, int height, IMB_BlendMode mode);
+ int width, int height, IMB_BlendMode mode, bool accumulate);
/**
*
diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c
index e8cb550fc05..880df0ce5c3 100644
--- a/source/blender/imbuf/intern/cineon/cineonlib.c
+++ b/source/blender/imbuf/intern/cineon/cineonlib.c
@@ -39,10 +39,6 @@
#include "BLI_fileops.h"
#include "BLI_utildefines.h"
-#if defined(_MSC_VER) && (_MSC_VER <= 1500)
-#include "BLI_math_base.h"
-#endif
-
#include "MEM_guardedalloc.h"
/*
diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c
index 84f80faeacc..626d05b05c5 100644
--- a/source/blender/imbuf/intern/cineon/dpxlib.c
+++ b/source/blender/imbuf/intern/cineon/dpxlib.c
@@ -39,10 +39,6 @@
#include "BLI_fileops.h"
#include "BLI_utildefines.h"
-#if defined(_MSC_VER) && (_MSC_VER <= 1500)
-#include "BLI_math_base.h"
-#endif
-
#include "MEM_guardedalloc.h"
/*
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 696e34e58cb..06dd128137b 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -3044,7 +3044,7 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s
global_glsl_state.exposure = view_settings->exposure;
global_glsl_state.gamma = view_settings->gamma;
- /* We're using curve mapping's address as a acache ID,
+ /* We're using curve mapping's address as a cache ID,
* so we need to make sure re-allocation gives new address here.
* We do this by allocating new curve mapping before freeing ol one.
*/
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 9975c58bdd2..03cd5ecd646 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -720,6 +720,7 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
ibuf->channels, IB_PROFILE_SRGB, profile_from, true,
w, h, w, ibuf->x);
+ IMB_buffer_float_unpremultiply(buffer, w, h);
/* XXX: need to convert to image buffer's rect space */
IMB_buffer_byte_from_float(rect_byte, buffer,
4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0,
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 2dca3114765..ba1bda640a6 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -48,7 +48,7 @@ extern "C"
{
// The following prevents a linking error in debug mode for MSVC using the libs in CVS
-#if defined(WITH_OPENEXR) && defined(_WIN32) && defined(_DEBUG) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+#if defined(WITH_OPENEXR) && defined(_WIN32) && defined(DEBUG) && !defined(__MINGW32__)
_CRTIMP void __cdecl _invalid_parameter_noinfo(void)
{
}
@@ -896,7 +896,7 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
echan->chan_id = name[0];
layname[0] = '\0';
- if (ELEM4(name[0], 'R', 'G', 'B', 'A'))
+ if (ELEM(name[0], 'R', 'G', 'B', 'A'))
strcpy(passname, "Combined");
else if (name[0] == 'Z')
strcpy(passname, "Depth");
@@ -927,9 +927,9 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
*
* Here we do some magic to distinguish such cases.
*/
- if (ELEM3(token[1], 'X', 'Y', 'Z') ||
- ELEM3(token[1], 'R', 'G', 'B') ||
- ELEM3(token[1], 'U', 'V', 'A'))
+ if (ELEM(token[1], 'X', 'Y', 'Z') ||
+ ELEM(token[1], 'R', 'G', 'B') ||
+ ELEM(token[1], 'U', 'V', 'A'))
{
echan->chan_id = token[1];
ok = true;
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
index 6df7587ee5c..dd2406e234e 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -65,6 +65,39 @@ void IMB_blend_color_byte(unsigned char dst[4], unsigned char src1[4], unsigned
blend_color_erase_alpha_byte(dst, src1, src2); break;
case IMB_BLEND_ADD_ALPHA:
blend_color_add_alpha_byte(dst, src1, src2); break;
+ case IMB_BLEND_OVERLAY:
+ blend_color_overlay_byte(dst, src1, src2); break;
+ case IMB_BLEND_HARDLIGHT:
+ blend_color_hardlight_byte(dst, src1, src2); break;
+ case IMB_BLEND_COLORBURN:
+ blend_color_burn_byte(dst, src1, src2); break;
+ case IMB_BLEND_LINEARBURN:
+ blend_color_linearburn_byte(dst, src1, src2); break;
+ case IMB_BLEND_COLORDODGE:
+ blend_color_dodge_byte(dst, src1, src2); break;
+ case IMB_BLEND_SCREEN:
+ blend_color_screen_byte(dst, src1, src2); break;
+ case IMB_BLEND_SOFTLIGHT:
+ blend_color_softlight_byte(dst, src1, src2); break;
+ case IMB_BLEND_PINLIGHT:
+ blend_color_pinlight_byte(dst, src1, src2); break;
+ case IMB_BLEND_LINEARLIGHT:
+ blend_color_linearlight_byte(dst, src1, src2); break;
+ case IMB_BLEND_VIVIDLIGHT:
+ blend_color_vividlight_byte(dst, src1, src2); break;
+ case IMB_BLEND_DIFFERENCE:
+ blend_color_difference_byte(dst, src1, src2); break;
+ case IMB_BLEND_EXCLUSION:
+ blend_color_exclusion_byte(dst, src1, src2); break;
+ case IMB_BLEND_COLOR:
+ blend_color_color_byte(dst, src1, src2); break;
+ case IMB_BLEND_HUE:
+ blend_color_hue_byte(dst, src1, src2); break;
+ case IMB_BLEND_SATURATION:
+ blend_color_saturation_byte(dst, src1, src2); break;
+ case IMB_BLEND_LUMINOSITY:
+ blend_color_luminosity_byte(dst, src1, src2); break;
+
default:
dst[0] = src1[0];
dst[1] = src1[1];
@@ -93,6 +126,38 @@ void IMB_blend_color_float(float dst[4], float src1[4], float src2[4], IMB_Blend
blend_color_erase_alpha_float(dst, src1, src2); break;
case IMB_BLEND_ADD_ALPHA:
blend_color_add_alpha_float(dst, src1, src2); break;
+ case IMB_BLEND_OVERLAY:
+ blend_color_overlay_float(dst, src1, src2); break;
+ case IMB_BLEND_HARDLIGHT:
+ blend_color_hardlight_float(dst, src1, src2); break;
+ case IMB_BLEND_COLORBURN:
+ blend_color_burn_float(dst, src1, src2); break;
+ case IMB_BLEND_LINEARBURN:
+ blend_color_linearburn_float(dst, src1, src2); break;
+ case IMB_BLEND_COLORDODGE:
+ blend_color_dodge_float(dst, src1, src2); break;
+ case IMB_BLEND_SCREEN:
+ blend_color_screen_float(dst, src1, src2); break;
+ case IMB_BLEND_SOFTLIGHT:
+ blend_color_softlight_float(dst, src1, src2); break;
+ case IMB_BLEND_PINLIGHT:
+ blend_color_pinlight_float(dst, src1, src2); break;
+ case IMB_BLEND_LINEARLIGHT:
+ blend_color_linearlight_float(dst, src1, src2); break;
+ case IMB_BLEND_VIVIDLIGHT:
+ blend_color_vividlight_float(dst, src1, src2); break;
+ case IMB_BLEND_DIFFERENCE:
+ blend_color_difference_float(dst, src1, src2); break;
+ case IMB_BLEND_EXCLUSION:
+ blend_color_exclusion_float(dst, src1, src2); break;
+ case IMB_BLEND_COLOR:
+ blend_color_color_float(dst, src1, src2); break;
+ case IMB_BLEND_HUE:
+ blend_color_hue_float(dst, src1, src2); break;
+ case IMB_BLEND_SATURATION:
+ blend_color_saturation_float(dst, src1, src2); break;
+ case IMB_BLEND_LUMINOSITY:
+ blend_color_luminosity_float(dst, src1, src2); break;
default:
dst[0] = src1[0];
dst[1] = src1[1];
@@ -226,22 +291,23 @@ static void imb_rectclip3(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, int *destx,
void IMB_rectcpy(ImBuf *dbuf, ImBuf *sbuf, int destx,
int desty, int srcx, int srcy, int width, int height)
{
- IMB_rectblend(dbuf, dbuf, sbuf, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, width, height, IMB_BLEND_COPY);
+ IMB_rectblend(dbuf, dbuf, sbuf, NULL, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, width, height, IMB_BLEND_COPY, false);
}
typedef void (*IMB_blend_func)(unsigned char *dst, const unsigned char *src1, const unsigned char *src2);
typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2);
-void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
- unsigned short *smask, unsigned short mask_max,
+void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, unsigned short *curvemask,
+ unsigned short *texmask, float mask_max,
int destx, int desty, int origx, int origy, int srcx, int srcy, int width, int height,
- IMB_BlendMode mode)
+ 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 short *smaskrect = smask, *smr;
+ unsigned short *cmaskrect = curvemask, *cmr;
unsigned short *dmaskrect = dmask, *dmr;
+ unsigned short *texmaskrect = texmask, *tmr;
int do_float, do_char, srcskip, destskip, origskip, x;
IMB_blend_func func = NULL;
IMB_blend_func_float func_float = NULL;
@@ -277,8 +343,11 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx) * 4;
srcskip = sbuf->x;
- if (smaskrect)
- smaskrect += srcy * sbuf->x + srcx;
+ if (cmaskrect)
+ cmaskrect += srcy * sbuf->x + srcx;
+
+ if (texmaskrect)
+ texmaskrect += srcy * sbuf->x + srcx;
}
else {
srect = drect;
@@ -388,6 +457,70 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
func = blend_color_add_alpha_byte;
func_float = blend_color_add_alpha_float;
break;
+ case IMB_BLEND_OVERLAY:
+ func = blend_color_overlay_byte;
+ func_float = blend_color_overlay_float;
+ break;
+ case IMB_BLEND_HARDLIGHT:
+ func = blend_color_hardlight_byte;
+ func_float = blend_color_hardlight_float;
+ break;
+ case IMB_BLEND_COLORBURN:
+ func = blend_color_burn_byte;
+ func_float = blend_color_burn_float;
+ break;
+ case IMB_BLEND_LINEARBURN:
+ func = blend_color_linearburn_byte;
+ func_float = blend_color_linearburn_float;
+ break;
+ case IMB_BLEND_COLORDODGE:
+ func = blend_color_dodge_byte;
+ func_float = blend_color_dodge_float;
+ break;
+ case IMB_BLEND_SCREEN:
+ func = blend_color_screen_byte;
+ func_float = blend_color_screen_float;
+ break;
+ case IMB_BLEND_SOFTLIGHT:
+ func = blend_color_softlight_byte;
+ func_float = blend_color_softlight_float;
+ break;
+ case IMB_BLEND_PINLIGHT:
+ func = blend_color_pinlight_byte;
+ func_float = blend_color_pinlight_float;
+ break;
+ case IMB_BLEND_LINEARLIGHT:
+ func = blend_color_linearlight_byte;
+ func_float = blend_color_linearlight_float;
+ break;
+ case IMB_BLEND_VIVIDLIGHT:
+ func = blend_color_vividlight_byte;
+ func_float = blend_color_vividlight_float;
+ break;
+ case IMB_BLEND_DIFFERENCE:
+ func = blend_color_difference_byte;
+ func_float = blend_color_difference_float;
+ break;
+ case IMB_BLEND_EXCLUSION:
+ func = blend_color_exclusion_byte;
+ func_float = blend_color_exclusion_float;
+ break;
+ case IMB_BLEND_COLOR:
+ func = blend_color_color_byte;
+ func_float = blend_color_color_float;
+ break;
+ case IMB_BLEND_HUE:
+ func = blend_color_hue_byte;
+ func_float = blend_color_hue_float;
+ break;
+ case IMB_BLEND_SATURATION:
+ func = blend_color_saturation_byte;
+ func_float = blend_color_saturation_float;
+ break;
+ case IMB_BLEND_LUMINOSITY:
+ func = blend_color_luminosity_byte;
+ func_float = blend_color_luminosity_float;
+ break;
default:
break;
}
@@ -399,21 +532,60 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
or = orect;
sr = srect;
- if (dmaskrect && smaskrect) {
+ if (cmaskrect) {
/* mask accumulation for painting */
- dmr = dmaskrect;
- smr = smaskrect;
+ cmr = cmaskrect;
+ tmr = texmaskrect;
- for (x = width; x > 0; x--, dr++, or++, sr++, dmr++, smr++) {
- unsigned char *src = (unsigned char *)sr;
+ /* destination mask present, do max alpha masking */
+ if (dmaskrect) {
+ dmr = dmaskrect;
+ for (x = width; x > 0; x--, dr++, or++, sr++, dmr++, cmr++) {
+ unsigned char *src = (unsigned char *)sr;
+ float mask_lim = mask_max * (*cmr);
- if (src[3] && *smr) {
- unsigned short mask = *dmr + (((mask_max - *dmr) * (*smr)) / 65535);
+ if (texmaskrect)
+ mask_lim *= ((*tmr++) / 65535.0f);
- if (mask > *dmr) {
- unsigned char mask_src[4];
+ if (src[3] && mask_lim) {
+ float mask;
+
+ if (accumulate)
+ mask = *dmr + mask_lim;
+ else
+ mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
+
+ mask = min_ff(mask, 65535.0);
+
+ if (mask > *dmr) {
+ unsigned char mask_src[4];
+
+ *dmr = mask;
- *dmr = mask;
+ 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);
+ }
+ }
+ }
+ dmaskrect += origskip;
+ }
+ /* no destination mask buffer, do regular blend with masktexture if present */
+ else {
+ for (x = width; x > 0; x--, dr++, or++, sr++, cmr++) {
+ unsigned char *src = (unsigned char *)sr;
+ float mask = (float)mask_max * ((float)(*cmr));
+
+ if (texmaskrect)
+ mask *= ((float)(*tmr++) / 65535.0f);
+
+ mask = min_ff(mask, 65535.0);
+
+ if (src[3] && (mask > 0.0f)) {
+ unsigned char mask_src[4];
mask_src[0] = src[0];
mask_src[1] = src[1];
@@ -425,8 +597,9 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
}
}
- dmaskrect += origskip;
- smaskrect += srcskip;
+ cmaskrect += srcskip;
+ if (texmaskrect)
+ texmaskrect += srcskip;
}
else {
/* regular blending */
@@ -446,28 +619,65 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
orf = orectf;
srf = srectf;
- if (dmaskrect && smaskrect) {
+ if (cmaskrect) {
/* mask accumulation for painting */
- dmr = dmaskrect;
- smr = smaskrect;
+ cmr = cmaskrect;
+ tmr = texmaskrect;
+
+ /* destination mask present, do max alpha masking */
+ if (dmaskrect) {
+ dmr = dmaskrect;
+ for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, cmr++) {
+ float mask_lim = mask_max * (*cmr);
+
+ if (texmaskrect)
+ mask_lim *= ((*tmr++) / 65535.0f);
+
+ if (srf[3] && mask_lim) {
+ float mask;
+
+ if (accumulate)
+ mask = min_ff(*dmr + mask_lim, 65535.0);
+ else
+ mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
+
+ 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);
+ }
+ }
+ }
+ dmaskrect += origskip;
+ }
+ /* no destination mask buffer, do regular blend with masktexture if present */
+ else {
+ for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, cmr++) {
+ float mask = (float)mask_max * ((float)(*cmr));
+
+ if (texmaskrect)
+ mask *= ((float)(*tmr++) / 65535.0f);
- for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, smr++) {
- if (srf[3] != 0 && *smr) {
- unsigned short mask = *dmr + (((mask_max - *dmr) * (*smr)) / 65535);
+ mask = min_ff(mask, 65535.0);
- if (mask > *dmr) {
+ if (srf[3] && (mask > 0.0f)) {
float mask_srf[4];
- *dmr = mask;
- mul_v4_v4fl(mask_srf, srf, mask * (1.0f / 65535.0f));
+ mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
func_float(drf, orf, mask_srf);
}
}
}
- dmaskrect += origskip;
- smaskrect += srcskip;
+ cmaskrect += srcskip;
+ if (texmaskrect)
+ texmaskrect += srcskip;
}
else {
/* regular blending */
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index c98b39c826b..e480f06da2b 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -33,6 +33,7 @@
#include "BLI_utildefines.h"
+#include "BLI_math_base.h"
#include "BLI_math_color.h"
#include "BLI_math_interp.h"
#include "MEM_guardedalloc.h"
@@ -51,26 +52,17 @@
/************************************************************************/
-struct ImBuf *IMB_half_x(struct ImBuf *ibuf1)
+static void imb_half_x_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
{
- struct ImBuf *ibuf2;
uchar *p1, *_p1, *dest;
short a, r, g, b;
int x, y;
float af, rf, gf, bf, *p1f, *_p1f, *destf;
bool do_rect, do_float;
- if (ibuf1 == NULL) return (NULL);
- if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) return (NULL);
-
do_rect = (ibuf1->rect != NULL);
- do_float = (ibuf1->rect_float != NULL);
-
- if (ibuf1->x <= 1) return(IMB_dupImBuf(ibuf1));
+ do_float = (ibuf1->rect_float != NULL && ibuf2->rect_float != NULL);
- ibuf2 = IMB_allocImBuf((ibuf1->x) / 2, ibuf1->y, ibuf1->planes, ibuf1->flags);
- if (ibuf2 == NULL) return (NULL);
-
_p1 = (uchar *) ibuf1->rect;
dest = (uchar *) ibuf2->rect;
@@ -113,9 +105,24 @@ struct ImBuf *IMB_half_x(struct ImBuf *ibuf1)
if (do_rect) _p1 += (ibuf1->x << 2);
if (do_float) _p1f += (ibuf1->x << 2);
}
- return (ibuf2);
}
+struct ImBuf *IMB_half_x(struct ImBuf *ibuf1)
+{
+ struct ImBuf *ibuf2;
+
+ if (ibuf1 == NULL) return (NULL);
+ if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) return (NULL);
+
+ if (ibuf1->x <= 1) return(IMB_dupImBuf(ibuf1));
+
+ ibuf2 = IMB_allocImBuf((ibuf1->x) / 2, ibuf1->y, ibuf1->planes, ibuf1->flags);
+ if (ibuf2 == NULL) return (NULL);
+
+ imb_half_x_no_alloc(ibuf2, ibuf1);
+
+ return (ibuf2);
+}
struct ImBuf *IMB_double_fast_x(struct ImBuf *ibuf1)
{
@@ -170,9 +177,8 @@ struct ImBuf *IMB_double_x(struct ImBuf *ibuf1)
}
-struct ImBuf *IMB_half_y(struct ImBuf *ibuf1)
+static void imb_half_y_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
{
- struct ImBuf *ibuf2;
uchar *p1, *p2, *_p1, *dest;
short a, r, g, b;
int x, y;
@@ -181,15 +187,9 @@ struct ImBuf *IMB_half_y(struct ImBuf *ibuf1)
p1 = p2 = NULL;
p1f = p2f = NULL;
- if (ibuf1 == NULL) return (NULL);
- if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) return (NULL);
- if (ibuf1->y <= 1) return(IMB_dupImBuf(ibuf1));
do_rect = (ibuf1->rect != NULL);
- do_float = (ibuf1->rect_float != NULL);
-
- ibuf2 = IMB_allocImBuf(ibuf1->x, (ibuf1->y) / 2, ibuf1->planes, ibuf1->flags);
- if (ibuf2 == NULL) return (NULL);
+ do_float = (ibuf1->rect_float != NULL && ibuf2->rect_float != NULL);
_p1 = (uchar *) ibuf1->rect;
dest = (uchar *) ibuf2->rect;
@@ -238,6 +238,23 @@ struct ImBuf *IMB_half_y(struct ImBuf *ibuf1)
if (do_rect) _p1 += (ibuf1->x << 3);
if (do_float) _p1f += (ibuf1->x << 3);
}
+}
+
+
+struct ImBuf *IMB_half_y(struct ImBuf *ibuf1)
+{
+ struct ImBuf *ibuf2;
+
+ if (ibuf1 == NULL) return (NULL);
+ if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) return (NULL);
+
+ if (ibuf1->y <= 1) return(IMB_dupImBuf(ibuf1));
+
+ ibuf2 = IMB_allocImBuf(ibuf1->x, (ibuf1->y) / 2, ibuf1->planes, ibuf1->flags);
+ if (ibuf2 == NULL) return (NULL);
+
+ imb_half_y_no_alloc(ibuf2, ibuf1);
+
return (ibuf2);
}
@@ -303,24 +320,24 @@ MINLINE void straight_uchar_to_premul_ushort(unsigned short result[4], const uns
result[0] = color[0] * alpha;
result[1] = color[1] * alpha;
result[2] = color[2] * alpha;
- result[3] = alpha * 255;
+ result[3] = alpha * 256;
}
MINLINE void premul_ushort_to_straight_uchar(unsigned char *result, const unsigned short color[4])
{
if (color[3] <= 255) {
- result[0] = color[0] / 255;
- result[1] = color[1] / 255;
- result[2] = color[2] / 255;
- result[3] = color[3] / 255;
+ result[0] = USHORTTOUCHAR(color[0]);
+ result[1] = USHORTTOUCHAR(color[1]);
+ result[2] = USHORTTOUCHAR(color[2]);
+ result[3] = USHORTTOUCHAR(color[3]);
}
else {
- unsigned short alpha = color[3] / 255;
+ unsigned short alpha = color[3] / 256;
- result[0] = color[0] / alpha;
- result[1] = color[1] / alpha;
- result[2] = color[2] / alpha;
- result[3] = alpha;
+ result[0] = USHORTTOUCHAR(color[0] / alpha * 256);
+ result[1] = USHORTTOUCHAR(color[1] / alpha * 256);
+ result[2] = USHORTTOUCHAR(color[2] / alpha * 256);
+ result[3] = USHORTTOUCHAR(color[3]);
}
}
@@ -335,28 +352,38 @@ void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
imb_addrectImBuf(ibuf2);
}
+ if (ibuf1->x <= 1) {
+ imb_half_y_no_alloc(ibuf2, ibuf1);
+ return;
+ }
+ if (ibuf1->y <= 1) {
+ imb_half_x_no_alloc(ibuf2, ibuf1);
+ return;
+ }
+
if (do_rect) {
unsigned char *cp1, *cp2, *dest;
cp1 = (unsigned char *) ibuf1->rect;
dest = (unsigned char *) ibuf2->rect;
+
for (y = ibuf2->y; y > 0; y--) {
cp2 = cp1 + (ibuf1->x << 2);
for (x = ibuf2->x; x > 0; x--) {
unsigned short p1i[8], p2i[8], desti[4];
-
+
straight_uchar_to_premul_ushort(p1i, cp1);
straight_uchar_to_premul_ushort(p2i, cp2);
straight_uchar_to_premul_ushort(p1i + 4, cp1 + 4);
straight_uchar_to_premul_ushort(p2i + 4, cp2 + 4);
-
+
desti[0] = ((unsigned int) p1i[0] + p2i[0] + p1i[4] + p2i[4]) >> 2;
desti[1] = ((unsigned int) p1i[1] + p2i[1] + p1i[5] + p2i[5]) >> 2;
desti[2] = ((unsigned int) p1i[2] + p2i[2] + p1i[6] + p2i[6]) >> 2;
desti[3] = ((unsigned int) p1i[3] + p2i[3] + p1i[7] + p2i[7]) >> 2;
-
+
premul_ushort_to_straight_uchar(dest, desti);
-
+
cp1 += 8;
cp2 += 8;
dest += 4;
@@ -1353,7 +1380,7 @@ static ImBuf *scaleupy(struct ImBuf *ibuf, int newy)
val_g += 0.5f;
val_r = rect[3];
- nval_r = rect[skipx + 4];
+ nval_r = rect[skipx + 3];
diff_r = nval_r - val_r;
val_r += 0.5f;
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index b912c3e229a..32100aa2288 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -254,10 +254,6 @@ static int isqtime(const char *name)
#ifdef WITH_FFMPEG
-#if defined(_MSC_VER) && _MSC_VER < 1800
-#define va_copy(dst, src) ((dst) = (src))
-#endif
-
/* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */
#ifdef __GNUC__
# pragma GCC diagnostic push
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index f429360e1cf..8483e5f08f9 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -168,14 +168,10 @@ typedef struct PreviewImage {
#ifdef __BIG_ENDIAN__
/* big endian */
-# define MAKE_ID2(c, d) ( (c)<<8 | (d) )
-# define MOST_SIG_BYTE 0
-# define BBIG_ENDIAN
+# define MAKE_ID2(c, d) ((c) << 8 | (d))
#else
/* little endian */
-# define MAKE_ID2(c, d) ( (d)<<8 | (c) )
-# define MOST_SIG_BYTE 1
-# define BLITTLE_ENDIAN
+# define MAKE_ID2(c, d) ((d) << 8 | (c))
#endif
/* ID from database */
@@ -213,6 +209,8 @@ typedef struct PreviewImage {
#define ID_MC MAKE_ID2('M', 'C') /* MovieClip */
#define ID_MSK MAKE_ID2('M', 'S') /* Mask */
#define ID_LS MAKE_ID2('L', 'S') /* FreestyleLineStyle */
+#define ID_PAL MAKE_ID2('P', 'L') /* Palette */
+#define ID_PC MAKE_ID2('P', 'C') /* Paint Curve */
/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */
#define ID_SEQ MAKE_ID2('S', 'Q')
@@ -235,7 +233,7 @@ typedef struct PreviewImage {
# undef GS
#endif
// #define GS(a) (*((short *)(a)))
-#define GS(a) (CHECK_TYPE_INLINE(a, const char *), (*((short *)(a))))
+#define GS(a) (CHECK_TYPE_INLINE(a, char *), (*((short *)(a))))
#define ID_NEW(a) if ( (a) && (a)->id.newid ) (a) = (void *)(a)->id.newid
#define ID_NEW_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; }
diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h
index 5ab799a75e5..dcde9007cd8 100644
--- a/source/blender/makesdna/DNA_actuator_types.h
+++ b/source/blender/makesdna/DNA_actuator_types.h
@@ -97,6 +97,8 @@ typedef struct bEditObjectActuator {
float mass;
short localflag; /* flag for the lin & ang. vel: apply locally */
short dyn_operation;
+ short upflag, trackflag; /* flag for up axis and track axis */
+ int pad;
} bEditObjectActuator;
typedef struct bSceneActuator {
@@ -395,6 +397,7 @@ typedef struct bActuator {
#define ACT_PROP_ADD 1
#define ACT_PROP_COPY 2
#define ACT_PROP_TOGGLE 3
+#define ACT_PROP_LEVEL 4
/* constraint flag */
#define ACT_CONST_NONE 0
@@ -439,6 +442,19 @@ typedef struct bActuator {
/* editObjectActuator->flag */
#define ACT_TRACK_3D 1
+/* editObjectActuator->upflag */
+#define ACT_TRACK_UP_X 0
+#define ACT_TRACK_UP_Y 1
+#define ACT_TRACK_UP_Z 2
+
+/* editObjectActuator->trackflag */
+#define ACT_TRACK_TRAXIS_X 0
+#define ACT_TRACK_TRAXIS_Y 1
+#define ACT_TRACK_TRAXIS_Z 2
+#define ACT_TRACK_TRAXIS_NEGX 3
+#define ACT_TRACK_TRAXIS_NEGY 4
+#define ACT_TRACK_TRAXIS_NEGZ 5
+
/* editObjectActuator->flag for replace mesh actuator */
#define ACT_EDOB_REPLACE_MESH_NOGFX 2 /* use for replace mesh actuator */
#define ACT_EDOB_REPLACE_MESH_PHYS 4
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 390233a433d..3d0d6b820d7 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -793,6 +793,9 @@ typedef enum eInsertKeyFlags {
INSERTKEY_REPLACE = (1<<4), /* only replace an existing keyframe (this overrides INSERTKEY_NEEDED) */
INSERTKEY_XYZ2RGB = (1<<5), /* transform F-Curves should have XYZ->RGB color mode */
INSERTKEY_NO_USERPREF = (1 << 6), /* ignore user-prefs (needed for predictable API use) */
+ /* Allow to make a full copy of new key into existing one, if any, instead of 'reusing' existing handles.
+ * Used by copy/paste code. */
+ INSERTKEY_OVERWRITE_FULL = (1<<7),
} eInsertKeyFlags;
/* ************************************************ */
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 86fa7058f97..9fbd70419f4 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -35,6 +35,7 @@
#include "DNA_ID.h"
#include "DNA_texture_types.h" /* for MTex */
+#include "DNA_curve_types.h"
//#ifndef MAX_MTEX // XXX Not used?
//#define MAX_MTEX 18
@@ -62,6 +63,9 @@ typedef struct Brush {
struct ImBuf *icon_imbuf;
PreviewImage *preview;
+ struct ColorBand *gradient; /* color gradient */
+ struct PaintCurve *paint_curve;
+
char icon_filepath[1024]; /* 1024 = FILE_MAX */
float normal_weight;
@@ -71,6 +75,7 @@ typedef struct Brush {
float weight; /* brush weight */
int size; /* brush diameter */
int flag; /* general purpose flag */
+ int mask_pressure; /* pressure influence for mask */
float jitter; /* jitter the position of the brush */
int jitter_absolute; /* absolute jitter in pixels */
int overlay_flags;
@@ -82,10 +87,17 @@ typedef struct Brush {
float rgb[3]; /* color */
float alpha; /* opacity */
+ float secondary_rgb[3]; /* background color */
+
int sculpt_plane; /* the direction of movement for sculpt vertices */
float plane_offset; /* offset for plane brushes (clay, flatten, fill, scrape) */
+ float pad;
+ int gradient_spacing;
+ int gradient_stroke_mode; /* source for stroke color gradient application */
+ int gradient_fill_mode; /* source for fill tool color gradient application */
+
char sculpt_tool; /* active sculpt tool */
char vertexpaint_tool; /* active vertex/weight paint blend mode (poorly named) */
char imagepaint_tool; /* active image paint tool */
@@ -100,12 +112,21 @@ typedef struct Brush {
float texture_sample_bias;
+ /* overlay */
int texture_overlay_alpha;
int mask_overlay_alpha;
int cursor_overlay_alpha;
float unprojected_radius;
+ /* soften/sharpen */
+ float sharp_threshold;
+ int blur_kernel_radius;
+ int blur_mode;
+
+ /* fill tool */
+ float fill_threshold;
+
float add_col[3];
float sub_col[3];
@@ -116,6 +137,52 @@ typedef struct Brush {
float mask_stencil_dimension[2];
} Brush;
+typedef struct PaletteColor
+{
+ struct PaletteColor *next, *prev;
+ /* two values, one to store rgb, other to store values for sculpt/weight */
+ float rgb[3];
+ float value;
+} PaletteColor;
+
+typedef struct Palette
+{
+ ID id;
+
+ /* pointer to individual colours */
+ ListBase colors;
+ ListBase deleted;
+
+ int num_of_colours;
+ int active_color;
+} Palette;
+
+typedef struct PaintCurvePoint
+{
+ BezTriple bez; /* bezier handle */
+ float pressure; /* pressure on that point */
+} PaintCurvePoint;
+
+typedef struct PaintCurve
+{
+ ID id;
+ PaintCurvePoint *points; /* points of curve */
+ int tot_points;
+ int add_index; /* index where next point will be added */
+} PaintCurve;
+
+/* Brush.gradient_source */
+typedef enum BrushGradientSourceStroke {
+ BRUSH_GRADIENT_PRESSURE = 0, /* gradient from pressure */
+ BRUSH_GRADIENT_SPACING_REPEAT = 1, /* gradient from spacing */
+ BRUSH_GRADIENT_SPACING_CLAMP = 2 /* gradient from spacing */
+} BrushGradientSourceStroke;
+
+typedef enum BrushGradientSourceFill {
+ BRUSH_GRADIENT_LINEAR = 0, /* gradient from pressure */
+ BRUSH_GRADIENT_RADIAL = 1 /* gradient from spacing */
+} BrushGradientSourceFill;
+
/* Brush.flag */
typedef enum BrushFlags {
BRUSH_AIRBRUSH = (1 << 0),
@@ -124,7 +191,7 @@ typedef enum BrushFlags {
BRUSH_SIZE_PRESSURE = (1 << 3),
BRUSH_JITTER_PRESSURE = (1 << 4),
BRUSH_SPACING_PRESSURE = (1 << 5),
- // BRUSH_FIXED_TEX = (1 << 6), /* obsolete, use mtex->brush_map_mode = MTEX_MAP_MODE_TILED instead */
+ BRUSH_UNUSED = (1 << 6),
BRUSH_RAKE = (1 << 7),
BRUSH_ANCHORED = (1 << 8),
BRUSH_DIR_IN = (1 << 9),
@@ -138,7 +205,7 @@ typedef enum BrushFlags {
BRUSH_SPACE_ATTEN = (1 << 18),
BRUSH_ADAPTIVE_SPACE = (1 << 19),
BRUSH_LOCK_SIZE = (1 << 20),
-// BRUSH_TEXTURE_OVERLAY = (1 << 21), /* obsolete, use overlay_flags |= BRUSH_OVERLAY_PRIMARY instead */
+ BRUSH_USE_GRADIENT = (1 << 21),
BRUSH_EDGE_TO_EDGE = (1 << 22),
BRUSH_DRAG_DOT = (1 << 23),
BRUSH_INVERSE_SMOOTH_PRESSURE = (1 << 24),
@@ -146,13 +213,16 @@ typedef enum BrushFlags {
BRUSH_PLANE_TRIM = (1 << 26),
BRUSH_FRONTFACE = (1 << 27),
BRUSH_CUSTOM_ICON = (1 << 28),
-
- /* temporary flag which sets up automatically for correct brush
- * drawing when inverted modal operator is running */
- BRUSH_INVERTED = (1 << 29),
- BRUSH_ABSOLUTE_JITTER = (1 << 30)
+ BRUSH_LINE = (1 << 29),
+ BRUSH_ABSOLUTE_JITTER = (1 << 30),
+ BRUSH_CURVE = (1 << 31)
} BrushFlags;
+typedef enum {
+ BRUSH_MASK_PRESSURE_RAMP = (1 << 1),
+ BRUSH_MASK_PRESSURE_CUTOFF = (1 << 2)
+} BrushMaskPressureFlags;
+
/* Brush.overlay_flags */
typedef enum OverlayFlags {
BRUSH_OVERLAY_CURSOR = (1),
@@ -195,7 +265,9 @@ typedef enum BrushImagePaintTool {
PAINT_TOOL_DRAW = 0,
PAINT_TOOL_SOFTEN = 1,
PAINT_TOOL_SMEAR = 2,
- PAINT_TOOL_CLONE = 3
+ PAINT_TOOL_CLONE = 3,
+ PAINT_TOOL_FILL = 4,
+ PAINT_TOOL_MASK = 5
} BrushImagePaintTool;
/* direction that the brush displaces along */
@@ -222,6 +294,12 @@ typedef enum {
BRUSH_MASK_SMOOTH = 1
} BrushMaskTool;
+/* blur kernel types, Brush.blur_mode */
+typedef enum BlurKernelType {
+ KERNEL_GAUSSIAN,
+ KERNEL_BOX
+} BlurKernelType;
+
#define MAX_BRUSH_PIXEL_RADIUS 200
#endif
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index e35e4673684..0277956cac5 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -796,7 +796,8 @@ typedef enum ePivotConstraint_Flag {
typedef enum eFollowTrack_Flags {
FOLLOWTRACK_ACTIVECLIP = (1<<0),
- FOLLOWTRACK_USE_3D_POSITION = (1<<1)
+ FOLLOWTRACK_USE_3D_POSITION = (1<<1),
+ FOLLOWTRACK_USE_UNDISTORTION = (1<<2)
} eFollowTrack_Flags;
typedef enum eFollowTrack_FrameMethod {
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index d638d20c6a5..87496fb491f 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -72,7 +72,7 @@ typedef struct Path {
#
#
typedef struct BevPoint {
- float vec[3], alfa, radius, weight;
+ float vec[3], alfa, radius, weight, offset;
float sina, cosa; /* 2D Only */
float dir[3], tan[3], quat[4]; /* 3D Only */
short split_tag, dupe_tag;
@@ -86,6 +86,8 @@ typedef struct BevList {
int nr, dupe_nr;
int poly, hole;
int charidx;
+ int *segbevcount;
+ float *seglen;
/* over-alloc */
BevPoint bevpoints[0];
@@ -291,7 +293,7 @@ typedef struct Curve {
#define CU_PATH_RADIUS 4096 /* make use of the path radius if this is enabled (default for new curves) */
#define CU_DEFORM_FILL 8192 /* fill 2d curve after deformation */
#define CU_FILL_CAPS 16384 /* fill bevel caps */
-#define CU_MAP_TAPER 32768 /* map taper object to bevelled area */
+#define CU_MAP_TAPER 32768 /* map taper object to beveled area */
/* twist mode */
#define CU_TWIST_Z_UP 0
diff --git a/source/blender/makesdna/DNA_linestyle_types.h b/source/blender/makesdna/DNA_linestyle_types.h
index b90aaa7da8c..bac03b4efd7 100644
--- a/source/blender/makesdna/DNA_linestyle_types.h
+++ b/source/blender/makesdna/DNA_linestyle_types.h
@@ -432,7 +432,7 @@ typedef struct FreestyleLineStyle {
unsigned short split_dash2, split_gap2;
unsigned short split_dash3, split_gap3;
int sort_key, integration_type;
- float texstep;
+ float texstep;
short texact, pr_texture;
short use_nodes, pad;
unsigned short dash1, gap1, dash2, gap2, dash3, gap3;
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index 5fda38f52a1..3f94a9cfebb 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -41,6 +41,7 @@
#endif
struct MTex;
+struct Image;
struct ColorBand;
struct Group;
struct bNodeTree;
@@ -82,6 +83,13 @@ typedef struct GameSettings {
int pad1;
} GameSettings;
+typedef struct TexPaintSlot {
+ struct Image *ima; /* image to be painted on */
+ char *uvname; /* customdata index for uv layer, MAX_NAME*/
+ int index; /* index for mtex slot in material for blender internal */
+ int pad;
+} TexPaintSlot;
+
typedef struct Material {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
@@ -182,8 +190,15 @@ typedef struct Material {
float line_col[4];
short line_priority;
short vcol_alpha;
- int pad4;
+ /* texture painting */
+ short paint_active_slot;
+ short paint_clone_slot;
+ short tot_slots;
+ short pad4[3];
+
+ struct TexPaintSlot *texpaintslot; /* cached slot for painting. Make sure to recalculate before use
+ * with refresh_texpaint_image_cache */
ListBase gpumaterial; /* runtime */
} Material;
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 7c5846e5819..47782bb3ae1 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -308,6 +308,9 @@ typedef struct BevelModifierData {
short val_flags; /* used to interpret the bevel value */
short lim_flags; /* flags to tell the tool how to limit the bevel */
short e_flags; /* flags to direct how edge weights are applied to verts */
+ short mat; /* material index if >= 0, else material inherited from surrounding faces */
+ short pad;
+ int pad2;
float profile; /* controls profile shape (0->1, .5 is round) */
/* if the MOD_BEVEL_ANGLE is set, this will be how "sharp" an edge must be before it gets beveled */
float bevel_angle;
@@ -837,6 +840,7 @@ enum {
MOD_SOLIDIFY_VGROUP_INV = (1 << 3),
MOD_SOLIDIFY_RIM_MATERIAL = (1 << 4), /* deprecated, used in do_versions */
MOD_SOLIDIFY_FLIP = (1 << 5),
+ MOD_SOLIDIFY_NOSHELL = (1 << 6),
};
#if (DNA_DEPRECATED_GCC_POISON == 1)
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index b13353609c6..e0d25e763d4 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -852,6 +852,12 @@ typedef struct NodeShaderUVMap {
char uv_map[64];
} NodeShaderUVMap;
+typedef struct NodeSunBeams {
+ float source[2];
+
+ float ray_length;
+} NodeSunBeams;
+
/* script node mode */
#define NODE_SCRIPT_INTERNAL 0
#define NODE_SCRIPT_EXTERNAL 1
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 2e3cd878900..0bcc6bfd70e 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -127,7 +127,7 @@ typedef struct Object {
struct Object *proxy, *proxy_group, *proxy_from;
struct Ipo *ipo DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */
/* struct Path *path; */
- struct BoundBox *bb;
+ struct BoundBox *bb; /* axis aligned boundbox (in localspace) */
struct bAction *action DNA_DEPRECATED; // XXX deprecated... old animation system
struct bAction *poselib;
struct bPose *pose; /* pose data, armature objects only */
@@ -188,6 +188,7 @@ typedef struct Object {
char scavisflag; /* more display settings for game logic */
char depsflag;
+ /* dupli-frame settings */
int dupon, dupoff, dupsta, dupend;
int pad;
@@ -361,13 +362,13 @@ enum {
#define OB_TYPE_SUPPORT_VGROUP(_type) \
(ELEM(_type, OB_MESH, OB_LATTICE))
#define OB_TYPE_SUPPORT_EDITMODE(_type) \
- (ELEM7(_type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE))
+ (ELEM(_type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE))
#define OB_TYPE_SUPPORT_PARVERT(_type) \
- (ELEM4(_type, OB_MESH, OB_SURF, OB_CURVE, OB_LATTICE))
+ (ELEM(_type, OB_MESH, OB_SURF, OB_CURVE, OB_LATTICE))
/* is this ID type used as object data */
#define OB_DATA_SUPPORT_ID(_id_type) \
- (ELEM8(_id_type, ID_ME, ID_CU, ID_MB, ID_LA, ID_SPK, ID_CA, ID_LT, ID_AR))
+ (ELEM(_id_type, ID_ME, ID_CU, ID_MB, ID_LA, ID_SPK, ID_CA, ID_LT, ID_AR))
#define OB_DATA_SUPPORT_ID_CASE \
ID_ME: case ID_CU: case ID_MB: case ID_LA: case ID_SPK: case ID_CA: case ID_LT: case ID_AR
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 6cf2b338308..c8b8e4d52a4 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -811,7 +811,8 @@ typedef struct TimeMarker {
/* Paint Tool Base */
typedef struct Paint {
struct Brush *brush;
-
+ struct Palette *palette;
+
/* WM Paint cursor */
void *paint_cursor;
unsigned char paint_cursor_col[4];
@@ -840,9 +841,14 @@ typedef struct ImagePaintSettings {
short seam_bleed, normal_angle;
short screen_grab_size[2]; /* capture size for re-projection */
- int pad1;
+ int mode; /* mode used for texture painting */
- void *paintcursor; /* wm handle */
+ void *paintcursor; /* wm handle */
+ struct Image *stencil; /* workaround until we support true layer masks */
+ struct Image *clone; /* clone layer for image mode for projective texture painting */
+ struct Image *canvas; /* canvas when the explicit system is used for painting */
+ float stencil_col[3];
+ float pad1;
} ImagePaintSettings;
/* ------------------------------------------- */
@@ -966,6 +972,11 @@ typedef struct UnifiedPaintSettings {
/* unified brush weight, [0, 1] */
float weight;
+ /* unified brush color */
+ float rgb[3];
+ /* unified brush secondary color */
+ float secondary_rgb[3];
+
/* user preferences for sculpt and paint */
int flag;
@@ -973,7 +984,6 @@ typedef struct UnifiedPaintSettings {
/* record movement of mouse so that rake can start at an intuitive angle */
float last_rake[2];
- int pad;
float brush_rotation;
@@ -981,7 +991,14 @@ typedef struct UnifiedPaintSettings {
* all data below are used to communicate with cursor drawing and tex sampling *
*********************************************************************************/
int draw_anchored;
- int anchored_size;
+ int anchored_size;
+
+ char draw_inverted;
+ char pad3[7];
+
+ float overlap_factor; /* normalization factor due to accumulated value of curve along spacing.
+ * Calculated when brush spacing changes to dampen strength of stroke
+ * if space attenuation is used*/
float anchored_initial_mouse[2];
/* check is there an ongoing stroke right now */
@@ -1001,15 +1018,16 @@ typedef struct UnifiedPaintSettings {
struct ColorSpace *colorspace;
/* radius of brush, premultiplied with pressure.
- * In case of anchored brushes contains that radius */
+ * In case of anchored brushes contains the anchored radius */
float pixel_radius;
- int pad2;
+ int pad4;
} UnifiedPaintSettings;
typedef enum {
UNIFIED_PAINT_SIZE = (1 << 0),
UNIFIED_PAINT_ALPHA = (1 << 1),
UNIFIED_PAINT_WEIGHT = (1 << 5),
+ UNIFIED_PAINT_COLOR = (1 << 6),
/* only used if unified size is enabled, mirrors the brush flags
* BRUSH_LOCK_SIZE and BRUSH_SIZE_PRESSURE */
@@ -1620,8 +1638,8 @@ typedef enum eVGroupSelect {
#define SCE_FRAME_DROP (1<<3)
- /* return flag BKE_scene_base_iter_next function */
-#define F_ERROR -1
+ /* return flag BKE_scene_base_iter_next functions */
+/* #define F_ERROR -1 */ /* UNUSED */
#define F_START 0
#define F_SCENE 1
#define F_DUPLI 3
@@ -1647,7 +1665,7 @@ enum {
typedef enum {
PAINT_SHOW_BRUSH = (1 << 0),
PAINT_FAST_NAVIGATE = (1 << 1),
- PAINT_SHOW_BRUSH_ON_SURFACE = (1 << 2),
+ PAINT_SHOW_BRUSH_ON_SURFACE = (1 << 2)
} PaintFlags;
/* Paint.symmetry_flags
@@ -1692,6 +1710,11 @@ typedef enum SculptFlags {
SCULPT_DYNTOPO_DETAIL_CONSTANT = (1 << 13)
} SculptFlags;
+typedef enum ImagePaintMode {
+ IMAGEPAINT_MODE_MATERIAL, /* detect texture paint slots from the material */
+ IMAGEPAINT_MODE_IMAGE, /* select texture paint image directly */
+} ImagePaintMode;
+
#if (DNA_DEPRECATED_GCC_POISON == 1)
#pragma GCC poison SCULPT_SYMM_X SCULPT_SYMM_Y SCULPT_SYMM_Z SCULPT_SYMMETRY_FEATHER
#endif
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 38d3c2786ce..8a900c3946e 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -271,12 +271,12 @@ typedef struct ARegion {
// #define WIN_EQUAL 3 // UNUSED
/* area->flag */
-#define HEADER_NO_PULLDOWN 1
-#define AREA_FLAG_DRAWJOINTO 2
-#define AREA_FLAG_DRAWJOINFROM 4
-#define AREA_TEMP_INFO 8
-#define AREA_FLAG_DRAWSPLIT_H 16
-#define AREA_FLAG_DRAWSPLIT_V 32
+#define HEADER_NO_PULLDOWN (1 << 0)
+#define AREA_FLAG_DRAWJOINTO (1 << 1)
+#define AREA_FLAG_DRAWJOINFROM (1 << 2)
+#define AREA_TEMP_INFO (1 << 3)
+#define AREA_FLAG_DRAWSPLIT_H (1 << 4)
+#define AREA_FLAG_DRAWSPLIT_V (1 << 5)
#define EDGEWIDTH 1
#define AREAGRID 4
@@ -315,6 +315,9 @@ enum {
#define PNL_DEFAULT_CLOSED 1
#define PNL_NO_HEADER 2
+/* Fallback panel category (only for old scripts which need updating) */
+#define PNL_CATEGORY_FALLBACK "Misc"
+
/* uiList layout_type */
enum {
UILST_LAYOUT_DEFAULT = 0,
diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h
index cd1977c0ce3..8d59a13768b 100644
--- a/source/blender/makesdna/DNA_sensor_types.h
+++ b/source/blender/makesdna/DNA_sensor_types.h
@@ -57,7 +57,9 @@ typedef struct bMouseSensor {
short type;
short flag;
short pad1;
- short pad2;
+ short mode; /* flag to choose material or property */
+ char propname[64];
+ char matname[64];
} bMouseSensor;
/* DEPRECATED */
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index 69d4693ab05..4795048d346 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -249,6 +249,11 @@ typedef struct SpeedControlVars {
int lastValidFrame;
} SpeedControlVars;
+typedef struct GaussianBlurVars {
+ float size_x;
+ float size_y;
+} GaussianBlurVars;
+
/* ***************** Sequence modifiers ****************** */
typedef struct SequenceModifierData {
@@ -421,7 +426,8 @@ enum {
SEQ_TYPE_SPEED = 29,
SEQ_TYPE_MULTICAM = 30,
SEQ_TYPE_ADJUSTMENT = 31,
- SEQ_TYPE_EFFECT_MAX = 31
+ SEQ_TYPE_GAUSSIAN_BLUR = 40,
+ SEQ_TYPE_EFFECT_MAX = 40
};
#define SEQ_MOVIECLIP_RENDER_UNDISTORTED (1 << 0)
@@ -434,7 +440,7 @@ enum {
*/
-#define SEQ_HAS_PATH(_seq) (ELEM4((_seq)->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD))
+#define SEQ_HAS_PATH(_seq) (ELEM((_seq)->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD))
/* modifiers */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index c7a6d4809a5..6f57f549efb 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -809,6 +809,8 @@ typedef enum eSpaceImage_Flag {
SI_DRAW_OTHER = (1 << 23),
SI_COLOR_CORRECTION = (1 << 24),
+
+ SI_NO_DRAW_TEXPAINT = (1 << 25)
} eSpaceImage_Flag;
/* Text Editor ============================================ */
@@ -989,6 +991,7 @@ typedef enum eSpaceNode_TexFrom {
typedef enum eSpaceNode_ShaderFrom {
SNODE_SHADER_OBJECT = 0,
SNODE_SHADER_WORLD = 1,
+ SNODE_SHADER_LINESTYLE = 2,
} eSpaceNode_ShaderFrom;
/* Game Logic Editor ===================================== */
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
index 1906f71a230..d256cfb2e85 100644
--- a/source/blender/makesdna/DNA_texture_types.h
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -111,9 +111,12 @@ typedef struct CBData {
/* 32 = MAXCOLORBAND */
/* note that this has to remain a single struct, for UserDef */
typedef struct ColorBand {
- short flag, tot, cur, ipotype;
+ short tot, cur;
+ char ipotype, ipotype_hue;
+ char color_mode;
+ char pad[1];
+
CBData data[32];
-
} ColorBand;
typedef struct EnvMap {
@@ -498,7 +501,6 @@ typedef struct ColorMapping {
#define MTEX_BLEND_SAT 11
#define MTEX_BLEND_VAL 12
#define MTEX_BLEND_COLOR 13
-/* free for use */
#define MTEX_SOFT_LIGHT 15
#define MTEX_LIN_LIGHT 16
@@ -510,6 +512,32 @@ typedef struct ColorMapping {
#define MTEX_MAP_MODE_RANDOM 4
#define MTEX_MAP_MODE_STENCIL 5
+/* **************** ColorBand ********************* */
+
+/* colormode */
+enum {
+ COLBAND_BLEND_RGB = 0,
+ COLBAND_BLEND_HSV = 1,
+ COLBAND_BLEND_HSL = 2,
+};
+
+/* interpolation */
+enum {
+ COLBAND_INTERP_LINEAR = 0,
+ COLBAND_INTERP_EASE = 1,
+ COLBAND_INTERP_B_SPLINE = 2,
+ COLBAND_INTERP_CARDINAL = 3,
+ COLBAND_INTERP_CONSTANT = 4,
+};
+
+/* color interpolation */
+enum {
+ COLBAND_HUE_NEAR = 0,
+ COLBAND_HUE_FAR = 1,
+ COLBAND_HUE_CW = 2,
+ COLBAND_HUE_CCW = 3,
+};
+
/* **************** EnvMap ********************* */
/* type */
@@ -585,7 +613,7 @@ typedef struct ColorMapping {
#define TEX_VD_IMAGE_SEQUENCE 3
#define TEX_VD_SMOKE 4
/* for voxels which use VoxelData->source_path */
-#define TEX_VD_IS_SOURCE_PATH(_format) (ELEM3(_format, TEX_VD_BLENDERVOXEL, TEX_VD_RAW_8BIT, TEX_VD_RAW_16BIT))
+#define TEX_VD_IS_SOURCE_PATH(_format) (ELEM(_format, TEX_VD_BLENDERVOXEL, TEX_VD_RAW_8BIT, TEX_VD_RAW_16BIT))
/* smoke data types */
#define TEX_VD_SMOKEDENSITY 0
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index cb2341b0b7f..ed59014cf75 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -154,7 +154,6 @@ typedef struct uiGradientColors {
char high_gradient[4];
int show_grad;
int pad2;
-
} uiGradientColors;
typedef struct ThemeUI {
@@ -163,7 +162,7 @@ typedef struct ThemeUI {
uiWidgetColors wcol_radio, wcol_option, wcol_toggle;
uiWidgetColors wcol_num, wcol_numslider;
uiWidgetColors wcol_menu, wcol_pulldown, wcol_menu_back, wcol_menu_item, wcol_tooltip;
- uiWidgetColors wcol_box, wcol_scroll, wcol_progress, wcol_list_item;
+ uiWidgetColors wcol_box, wcol_scroll, wcol_progress, wcol_list_item, wcol_pie_menu;
uiWidgetStateColors wcol_state;
@@ -246,6 +245,7 @@ typedef struct ThemeSpace {
char extra_edge_len[4], extra_edge_angle[4], extra_face_angle[4], extra_face_area[4];
char normal[4];
char vertex_normal[4];
+ char loop_normal[4];
char bone_solid[4], bone_pose[4], bone_pose_active[4];
char strip[4], strip_select[4];
char cframe[4];
@@ -263,7 +263,7 @@ typedef struct ThemeSpace {
char keyborder[4], keyborder_select[4];
char console_output[4], console_input[4], console_info[4], console_error[4];
- char console_cursor[4], console_select[4], pad1[4];
+ char console_cursor[4], console_select[4];
char vertex_size, outline_width, facedot_size;
char noodle_curving;
@@ -328,6 +328,9 @@ typedef struct ThemeSpace {
char info_warning[4], info_warning_text[4];
char info_info[4], info_info_text[4];
char info_debug[4], info_debug_text[4];
+
+ char paint_curve_pivot[4];
+ char paint_curve_handle[4];
} ThemeSpace;
@@ -489,7 +492,8 @@ typedef struct UserDef {
short color_picker_type;
char ipo_new; /* interpolation mode for newly added F-Curves */
char keyhandles_new; /* handle types for newly added keyframes */
- char pad1[2];
+ char gpu_select_method;
+ char pad1;
short scrcastfps; /* frame rate for screencast to be played back */
short scrcastwait; /* milliseconds between screencast snapshots */
@@ -531,6 +535,15 @@ typedef struct UserDef {
float fcu_inactive_alpha; /* opacity of inactive F-Curves in F-Curve Editor */
float pixelsize; /* private, set by GHOST, to multiply DPI with */
+ short pie_interaction_type; /* if keeping a pie menu spawn button pressed after this time, it turns into
+ * a drag/release pie menu */
+ short pie_initial_timeout; /* direction in the pie menu will always be calculated from the initial position
+ * within this time limit */
+ int pie_animation_timeout;
+ int pad2;
+ short pie_menu_radius; /* pie menu radius */
+ short pie_menu_threshold; /* pie menu distance from center before a direction is set */
+
struct WalkNavigation walk_navigation;
} UserDef;
@@ -716,6 +729,13 @@ typedef enum eOpenGL_RenderingOptions {
/* USER_DISABLE_AA = (1 << 4), */ /* DEPRECATED */
} eOpenGL_RenderingOptions;
+/* selection method for opengl gpu_select_method */
+typedef enum eOpenGL_SelectOptions {
+ USER_SELECT_AUTO = 0,
+ USER_SELECT_USE_OCCLUSION_QUERY = 1,
+ USER_SELECT_USE_SELECT_RENDERMODE = 2
+} eOpenGL_SelectOptions;
+
/* wm draw method */
typedef enum eWM_DrawMethod {
USER_DRAW_TRIPLE = 0,
diff --git a/source/blender/makesdna/DNA_vfont_types.h b/source/blender/makesdna/DNA_vfont_types.h
index 14ec6c9b312..7025a5767c4 100644
--- a/source/blender/makesdna/DNA_vfont_types.h
+++ b/source/blender/makesdna/DNA_vfont_types.h
@@ -66,7 +66,7 @@ typedef struct VFont {
#define FO_SELCHANGE 10
/* BKE_vfont_to_curve will move the cursor in these cases */
-#define FO_CURS_IS_MOTION(mode) (ELEM4(mode, FO_CURSUP, FO_CURSDOWN, FO_PAGEUP, FO_PAGEDOWN))
+#define FO_CURS_IS_MOTION(mode) (ELEM(mode, FO_CURSUP, FO_CURSDOWN, FO_PAGEUP, FO_PAGEDOWN))
#define FO_BUILTIN_NAME "<builtin>"
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index add59bafc3f..8cbc198837b 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -262,6 +262,7 @@ extern StructRNA RNA_GameProperty;
extern StructRNA RNA_GameSoftBodySettings;
extern StructRNA RNA_GameStringProperty;
extern StructRNA RNA_GameTimerProperty;
+extern StructRNA RNA_GaussianBlurSequence;
extern StructRNA RNA_GlowSequence;
extern StructRNA RNA_GreasePencil;
extern StructRNA RNA_Group;
@@ -277,6 +278,7 @@ extern StructRNA RNA_ImagePaint;
extern StructRNA RNA_ImageSequence;
extern StructRNA RNA_ImageTexture;
extern StructRNA RNA_ImageUser;
+extern StructRNA RNA_ImapaintToolCapabilities;
extern StructRNA RNA_InflowFluidSettings;
extern StructRNA RNA_IntProperty;
extern StructRNA RNA_Itasc;
@@ -427,6 +429,9 @@ extern StructRNA RNA_OrController;
extern StructRNA RNA_OutflowFluidSettings;
extern StructRNA RNA_PackedFile;
extern StructRNA RNA_Paint;
+extern StructRNA RNA_PaintCurve;
+extern StructRNA RNA_Palette;
+extern StructRNA RNA_PaletteColor;
extern StructRNA RNA_Panel;
extern StructRNA RNA_Particle;
extern StructRNA RNA_ParticleBrush;
@@ -630,6 +635,7 @@ extern StructRNA RNA_TransformConstraint;
extern StructRNA RNA_TransformSequence;
extern StructRNA RNA_UILayout;
extern StructRNA RNA_UIList;
+extern StructRNA RNA_UIPieMenu;
extern StructRNA RNA_UIPopupMenu;
extern StructRNA RNA_UVWarpModifier;
extern StructRNA RNA_UVProjectModifier;
@@ -791,6 +797,8 @@ void RNA_property_enum_items(struct bContext *C, PointerRNA *ptr, PropertyRNA *p
EnumPropertyItem **item, int *r_totitem, bool *r_free);
void RNA_property_enum_items_gettexted(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop,
EnumPropertyItem **r_item, int *r_totitem, bool *r_free);
+void RNA_property_enum_items_gettexted_all(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop,
+ EnumPropertyItem **r_item, int *r_totitem, bool *r_free);
bool RNA_property_enum_value(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value);
bool RNA_property_enum_identifier(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier);
bool RNA_property_enum_name(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name);
@@ -924,9 +932,22 @@ bool RNA_path_resolve_property(PointerRNA *ptr, const char *path,
bool RNA_path_resolve_property_full(PointerRNA *ptr, const char *path,
PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index);
+typedef struct PropertyElemRNA PropertyElemRNA;
+struct PropertyElemRNA {
+ PropertyElemRNA *next, *prev;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+};
+bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, struct ListBase *r_elements);
+
char *RNA_path_from_ID_to_struct(PointerRNA *ptr);
char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop);
+char *RNA_path_resolve_from_type_to_property(
+ struct PointerRNA *ptr, struct PropertyRNA *prop,
+ const struct StructRNA *type);
+
char *RNA_path_full_ID_py(struct ID *id);
char *RNA_path_full_struct_py(struct PointerRNA *ptr);
char *RNA_path_full_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index ff4caabe636..e6bd9fb79b4 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -264,6 +264,10 @@ if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
endif()
+if(WITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
# Build makesrna executable
blender_include_dirs(
.
diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript
index ff75d9a1721..08cbd6143a5 100644
--- a/source/blender/makesrna/intern/SConscript
+++ b/source/blender/makesrna/intern/SConscript
@@ -141,6 +141,9 @@ if env['WITH_BF_COLLADA']:
if env['WITH_BF_CYCLES']:
defs.append('WITH_CYCLES')
+if env['WITH_BF_FREESTYLE']:
+ defs.append('WITH_FREESTYLE')
+
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 7f1f04cdb6a..9023f25e3d5 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -745,6 +745,24 @@ static void rna_clamp_value_range(FILE *f, PropertyRNA *prop)
}
}
+#ifdef USE_RNA_RANGE_CHECK
+static void rna_clamp_value_range_check(
+ FILE *f, PropertyRNA *prop,
+ const char *dnaname_prefix, const char *dnaname)
+{
+ if (prop->type == PROP_INT) {
+ IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
+ fprintf(f,
+ " { BLI_STATIC_ASSERT("
+ "(TYPEOF_MAX(%s%s) >= %d) && "
+ "(TYPEOF_MIN(%s%s) <= %d), "
+ "\"invalid limits\"); }\n",
+ dnaname_prefix, dnaname, iprop->hardmax,
+ dnaname_prefix, dnaname, iprop->hardmin);
+ }
+}
+#endif /* USE_RNA_RANGE_CHECK */
+
static void rna_clamp_value(FILE *f, PropertyRNA *prop, int array)
{
if (prop->type == PROP_INT) {
@@ -944,6 +962,18 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr
}
fprintf(f, " }\n");
}
+
+#ifdef USE_RNA_RANGE_CHECK
+ if (dp->dnaname && manualfunc == NULL) {
+ if (dp->dnaarraylength == 1) {
+ rna_clamp_value_range_check(f, prop, "data->", dp->dnaname);
+ }
+ else {
+ rna_clamp_value_range_check(f, prop, "*data->", dp->dnaname);
+ }
+ }
+#endif
+
fprintf(f, "}\n\n");
}
else {
@@ -975,6 +1005,13 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr
rna_clamp_value(f, prop, 0);
}
}
+
+#ifdef USE_RNA_RANGE_CHECK
+ if (dp->dnaname && manualfunc == NULL) {
+ rna_clamp_value_range_check(f, prop, "data->", dp->dnaname);
+ }
+#endif
+
fprintf(f, "}\n\n");
}
break;
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 7959e60da33..83fe56102ac 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -153,6 +153,8 @@ short RNA_type_to_ID_code(StructRNA *type)
if (RNA_struct_is_a(type, &RNA_WindowManager)) return ID_WM;
if (RNA_struct_is_a(type, &RNA_MovieClip)) return ID_MC;
if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK;
+ if (RNA_struct_is_a(type, &RNA_Palette)) return ID_PAL;
+ if (RNA_struct_is_a(type, &RNA_PaintCurve)) return ID_PC;
return 0;
}
@@ -190,6 +192,9 @@ StructRNA *ID_code_to_RNA_type(short idcode)
case ID_WM: return &RNA_WindowManager;
case ID_MC: return &RNA_MovieClip;
case ID_MSK: return &RNA_Mask;
+ case ID_PAL: return &RNA_Palette;
+ case ID_PC: return &RNA_PaintCurve;
+
default: return &RNA_ID;
}
}
@@ -620,6 +625,10 @@ static void rna_def_library(BlenderRNA *brna)
prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Library");
RNA_def_property_ui_text(prop, "Parent", "");
+
+ prop = RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "packedfile");
+ RNA_def_property_ui_text(prop, "Packed File", "");
}
void RNA_def_ID(BlenderRNA *brna)
{
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index ded0278b44d..34e78018b03 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -55,6 +55,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
@@ -359,12 +360,12 @@ static bool rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDPr
if (idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT)
return false;
- if (idprop->subtype == IDP_INT && !ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
+ if (idprop->subtype == IDP_INT && !ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
return false;
break;
case IDP_INT:
- if (!ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
+ if (!ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
return false;
break;
case IDP_FLOAT:
@@ -872,8 +873,8 @@ char RNA_property_array_item_char(PropertyRNA *prop, int index)
if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
return quatitem[index];
}
- else if ((index < 4) && ELEM8(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
- PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION, PROP_COORDS))
+ else if ((index < 4) && ELEM(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
+ PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION, PROP_COORDS))
{
return vectoritem[index];
}
@@ -902,7 +903,7 @@ int RNA_property_array_item_index(PropertyRNA *prop, char name)
return 3;
}
}
- else if (ELEM6(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ,
+ else if (ELEM(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ,
PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION))
{
switch (name) {
@@ -1249,12 +1250,9 @@ void RNA_property_enum_items(bContext *C, PointerRNA *ptr, PropertyRNA *prop, En
}
}
-void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop,
- EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
-{
- RNA_property_enum_items(C, ptr, prop, r_item, r_totitem, r_free);
-
#ifdef WITH_INTERNATIONAL
+static void property_enum_translate(PropertyRNA *prop, EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
+{
if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
int i;
@@ -1300,9 +1298,71 @@ void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA
*r_item = nitem;
}
+}
+#endif
+
+void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop,
+ EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
+{
+ RNA_property_enum_items(C, ptr, prop, r_item, r_totitem, r_free);
+
+#ifdef WITH_INTERNATIONAL
+ property_enum_translate(prop, r_item, r_totitem, r_free);
#endif
}
+void RNA_property_enum_items_gettexted_all(bContext *C, PointerRNA *ptr, PropertyRNA *prop,
+ EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
+{
+ EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
+ int mem_size = sizeof(EnumPropertyItem) * (eprop->totitem + 1);
+ /* first return all items */
+ *r_free = true;
+ *r_item = MEM_mallocN(mem_size, "enum_gettext_all");
+ memcpy(*r_item, eprop->item, mem_size);
+
+ if (r_totitem)
+ *r_totitem = eprop->totitem;
+
+ if (eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
+ EnumPropertyItem *item;
+ int i;
+ bool free = false;
+
+ if (prop->flag & PROP_ENUM_NO_CONTEXT)
+ item = eprop->itemf(NULL, ptr, prop, &free);
+ else
+ item = eprop->itemf(C, ptr, prop, &free);
+
+ /* any callbacks returning NULL should be fixed */
+ BLI_assert(item != NULL);
+
+ for (i = 0; i < eprop->totitem; i++) {
+ bool exists = false;
+ int i_fixed;
+
+ /* items that do not exist on list are returned, but have their names/identifiers NULLed out */
+ for (i_fixed = 0; item[i_fixed].identifier; i_fixed++) {
+ if (STREQ(item[i_fixed].identifier, (*r_item)[i].identifier)) {
+ exists = true;
+ break;
+ }
+ }
+
+ if (!exists) {
+ (*r_item)[i].name = NULL;
+ (*r_item)[i].identifier = "";
+ }
+ }
+
+ if (free)
+ MEM_freeN(item);
+ }
+
+#ifdef WITH_INTERNATIONAL
+ property_enum_translate(prop, r_item, r_totitem, r_free);
+#endif
+}
bool RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value)
{
@@ -3329,7 +3389,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro
/* check type */
itemtype = RNA_property_type(itemprop);
- if (!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
+ if (!ELEM(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
return 0;
}
@@ -3409,7 +3469,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro
break;
}
- if (!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
+ if (!ELEM(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
err = 1;
break;
@@ -4015,11 +4075,14 @@ static bool rna_path_parse_array_index(const char **path, PointerRNA *ptr, Prope
}
static bool rna_path_parse(PointerRNA *ptr, const char *path,
- PointerRNA *r_ptr, PropertyRNA **r_prop, int *index,
+ PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index,
+ ListBase *r_elements,
const bool eval_pointer)
{
PropertyRNA *prop;
PointerRNA curptr;
+ PropertyElemRNA *prop_elem = NULL;
+ int index = -1;
char fixedbuf[256];
int type;
@@ -4061,6 +4124,14 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path,
if (!prop)
return false;
+ if (r_elements) {
+ prop_elem = MEM_mallocN(sizeof(PropertyElemRNA), __func__);
+ prop_elem->ptr = curptr;
+ prop_elem->prop = prop;
+ prop_elem->index = -1; /* index will be added later, if needed. */
+ BLI_addtail(r_elements, prop_elem);
+ }
+
type = RNA_property_type(prop);
/* now look up the value of this property if it is a pointer or
@@ -4076,7 +4147,7 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path,
curptr = nextptr;
prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
- if (index) *index = -1;
+ index = -1;
}
break;
}
@@ -4093,21 +4164,38 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path,
curptr = nextptr;
prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
- if (index) *index = -1;
+ index = -1;
}
break;
}
default:
- if (index) {
- if (!rna_path_parse_array_index(&path, &curptr, prop, index))
+ if (r_index || prop_elem) {
+ if (!rna_path_parse_array_index(&path, &curptr, prop, &index)) {
return false;
+ }
+
+ if (prop_elem) {
+ prop_elem->index = index;
+ }
}
break;
}
}
- *r_ptr = curptr;
- *r_prop = prop;
+ if (r_ptr)
+ *r_ptr = curptr;
+ if (r_prop)
+ *r_prop = prop;
+ if (r_index)
+ *r_index = index;
+
+ if (prop_elem && (prop_elem->ptr.data != curptr.data || prop_elem->prop != prop || prop_elem->index != index)) {
+ PropertyElemRNA *prop_elem = MEM_mallocN(sizeof(PropertyElemRNA), __func__);
+ prop_elem->ptr = curptr;
+ prop_elem->prop = prop;
+ prop_elem->index = index;
+ BLI_addtail(r_elements, prop_elem);
+ }
return true;
}
@@ -4120,7 +4208,7 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path,
*/
bool RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
{
- if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, true))
+ if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, NULL, true))
return false;
return r_ptr->data != NULL;
@@ -4134,7 +4222,7 @@ bool RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, Prop
*/
bool RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
{
- if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, true))
+ if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, NULL, true))
return false;
return r_ptr->data != NULL;
@@ -4149,7 +4237,7 @@ bool RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr,
*/
bool RNA_path_resolve_property(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
{
- if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, false))
+ if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, NULL, false))
return false;
return r_ptr->data != NULL && *r_prop != NULL;
@@ -4165,12 +4253,25 @@ bool RNA_path_resolve_property(PointerRNA *ptr, const char *path, PointerRNA *r_
*/
bool RNA_path_resolve_property_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
{
- if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, false))
+ if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, NULL, false))
return false;
return r_ptr->data != NULL && *r_prop != NULL;
}
+/**
+ * Resolve the given RNA Path into a linked list of PropertyElemRNA's.
+ *
+ * To be used when complex operations over path are needed, like e.g. get relative paths, to avoid too much
+ * string operations.
+ *
+ * \return True if there was no error while resolving the path
+ * \note Assumes all pointers provided are valid
+ */
+bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, ListBase *r_elements)
+{
+ return rna_path_parse(ptr, path, NULL, NULL, NULL, r_elements, false);
+}
char *RNA_path_append(const char *path, PointerRNA *UNUSED(ptr), PropertyRNA *prop, int intkey, const char *strkey)
{
@@ -4498,6 +4599,47 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
}
/**
+ * \return the path to given ptr/prop from the closest ancestor of given type, if any (else return NULL).
+ */
+char *RNA_path_resolve_from_type_to_property(
+ PointerRNA *ptr, PropertyRNA *prop,
+ const StructRNA *type)
+{
+ /* Try to recursively find an "type"'d ancestor,
+ * to handle situations where path from ID is not enough. */
+ PointerRNA idptr;
+ ListBase path_elems = {NULL};
+ char *path = NULL;
+ char *full_path = RNA_path_from_ID_to_property(ptr, prop);
+
+ if (full_path == NULL) {
+ return NULL;
+ }
+
+ RNA_id_pointer_create(ptr->id.data, &idptr);
+
+ if (RNA_path_resolve_elements(&idptr, full_path, &path_elems)) {
+ PropertyElemRNA *prop_elem;
+
+ for (prop_elem = path_elems.last; prop_elem; prop_elem = prop_elem->prev) {
+ if (RNA_struct_is_a(prop_elem->ptr.type, type)) {
+ char *ref_path = RNA_path_from_ID_to_struct(&prop_elem->ptr);
+ if (ref_path) {
+ path = BLI_strdup(full_path + strlen(ref_path) + 1); /* +1 for the linking '.' */
+ MEM_freeN(ref_path);
+ }
+ break;
+ }
+ }
+
+ BLI_freelistN(&path_elems);
+ }
+
+ MEM_freeN(full_path);
+ return path;
+}
+
+/**
* Get the ID as a python representation, eg:
* bpy.data.foo["bar"]
*/
@@ -6323,18 +6465,29 @@ bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
return false;
}
}
-
+
bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index)
{
int len, fromlen;
+ PropertyRNA *fromprop = prop;
+
+ if (prop->magic != RNA_MAGIC) {
+ /* In case of IDProperty, we have to find the *real* idprop of ptr,
+ * since prop in this case is just a fake wrapper around actual IDProp data, and not a 'real' PropertyRNA. */
+ prop = (PropertyRNA *)rna_idproperty_find(ptr, ((IDProperty *)fromprop)->name);
+ /* Even though currently we now prop will always be the 'fromprop', this might not be the case in the future. */
+ if (prop == fromprop) {
+ fromprop = (PropertyRNA *)rna_idproperty_find(fromptr, ((IDProperty *)prop)->name);
+ }
+ }
/* get the length of the array to work with */
len = RNA_property_array_length(ptr, prop);
- fromlen = RNA_property_array_length(fromptr, prop);
+ fromlen = RNA_property_array_length(fromptr, fromprop);
if (len != fromlen)
return false;
-
+
/* get and set the default values as appropriate for the various types */
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
@@ -6342,18 +6495,18 @@ bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop,
if (index == -1) {
int *tmparray = MEM_callocN(sizeof(int) * len, "copy - boolean");
- RNA_property_boolean_get_array(fromptr, prop, tmparray);
+ RNA_property_boolean_get_array(fromptr, fromprop, tmparray);
RNA_property_boolean_set_array(ptr, prop, tmparray);
MEM_freeN(tmparray);
}
else {
- int value = RNA_property_boolean_get_index(fromptr, prop, index);
+ int value = RNA_property_boolean_get_index(fromptr, fromprop, index);
RNA_property_boolean_set_index(ptr, prop, index, value);
}
}
else {
- int value = RNA_property_boolean_get(fromptr, prop);
+ int value = RNA_property_boolean_get(fromptr, fromprop);
RNA_property_boolean_set(ptr, prop, value);
}
return true;
@@ -6362,18 +6515,18 @@ bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop,
if (index == -1) {
int *tmparray = MEM_callocN(sizeof(int) * len, "copy - int");
- RNA_property_int_get_array(fromptr, prop, tmparray);
+ RNA_property_int_get_array(fromptr, fromprop, tmparray);
RNA_property_int_set_array(ptr, prop, tmparray);
MEM_freeN(tmparray);
}
else {
- int value = RNA_property_int_get_index(fromptr, prop, index);
+ int value = RNA_property_int_get_index(fromptr, fromprop, index);
RNA_property_int_set_index(ptr, prop, index, value);
}
}
else {
- int value = RNA_property_int_get(fromptr, prop);
+ int value = RNA_property_int_get(fromptr, fromprop);
RNA_property_int_set(ptr, prop, value);
}
return true;
@@ -6382,36 +6535,36 @@ bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop,
if (index == -1) {
float *tmparray = MEM_callocN(sizeof(float) * len, "copy - float");
- RNA_property_float_get_array(fromptr, prop, tmparray);
+ RNA_property_float_get_array(fromptr, fromprop, tmparray);
RNA_property_float_set_array(ptr, prop, tmparray);
MEM_freeN(tmparray);
}
else {
- float value = RNA_property_float_get_index(fromptr, prop, index);
+ float value = RNA_property_float_get_index(fromptr, fromprop, index);
RNA_property_float_set_index(ptr, prop, index, value);
}
}
else {
- float value = RNA_property_float_get(fromptr, prop);
+ float value = RNA_property_float_get(fromptr, fromprop);
RNA_property_float_set(ptr, prop, value);
}
return true;
case PROP_ENUM:
{
- int value = RNA_property_enum_get(fromptr, prop);
+ int value = RNA_property_enum_get(fromptr, fromprop);
RNA_property_enum_set(ptr, prop, value);
return true;
}
case PROP_POINTER:
{
- PointerRNA value = RNA_property_pointer_get(fromptr, prop);
+ PointerRNA value = RNA_property_pointer_get(fromptr, fromprop);
RNA_property_pointer_set(ptr, prop, value);
return true;
}
case PROP_STRING:
{
- char *value = RNA_property_string_get_alloc(fromptr, prop, NULL, 0, NULL);
+ char *value = RNA_property_string_get_alloc(fromptr, fromprop, NULL, 0, NULL);
RNA_property_string_set(ptr, prop, value);
MEM_freeN(value);
return true;
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index ecfa1286a78..750c98a536d 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -281,7 +281,7 @@ static void rna_def_dopesheet(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", ADS_FLAG_SHOW_DBFILTERS);
RNA_def_property_ui_text(prop, "Show Datablock Filters",
"Show options for whether channels related to certain types of data are included");
- RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, -1);
+ RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, 1);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, NULL);
/* General Filtering Settings */
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index 62e681d1374..0114ffa35c0 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -150,7 +150,7 @@ static void rna_ConstraintActuator_type_set(struct PointerRNA *ptr, int value)
switch (ca->type) {
case ACT_CONST_TYPE_ORI:
/* negative axis not supported in the orientation mode */
- if (ELEM3(ca->mode, ACT_CONST_DIRNX, ACT_CONST_DIRNY, ACT_CONST_DIRNZ))
+ if (ELEM(ca->mode, ACT_CONST_DIRNX, ACT_CONST_DIRNY, ACT_CONST_DIRNZ))
ca->mode = ACT_CONST_NONE;
break;
@@ -1090,6 +1090,7 @@ static void rna_def_property_actuator(BlenderRNA *brna)
{ACT_PROP_ADD, "ADD", 0, "Add", ""},
{ACT_PROP_COPY, "COPY", 0, "Copy", ""},
{ACT_PROP_TOGGLE, "TOGGLE", 0, "Toggle", "For bool/int/float/timer properties only"},
+ {ACT_PROP_LEVEL, "LEVEL", 0, "Level", "For bool/int/float/timer properties only"},
{0, NULL, 0, NULL, NULL}
};
@@ -1369,6 +1370,23 @@ static void rna_def_edit_object_actuator(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_track_axis_items[] = {
+ {ACT_TRACK_TRAXIS_X, "TRACKAXISX", 0, "X axis", ""},
+ {ACT_TRACK_TRAXIS_Y, "TRACKAXISY", 0, "Y axis", ""},
+ {ACT_TRACK_TRAXIS_Z, "TRACKAXISZ", 0, "Z axis", ""},
+ {ACT_TRACK_TRAXIS_NEGX, "TRACKAXISNEGX", 0, "-X axis", ""},
+ {ACT_TRACK_TRAXIS_NEGY, "TRACKAXISNEGY", 0, "-Y axis", ""},
+ {ACT_TRACK_TRAXIS_NEGZ, "TRACKAXISNEGZ", 0, "-Z axis", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem prop_up_axis_items[] = {
+ {ACT_TRACK_UP_X, "UPAXISX", 0, "X axis", ""},
+ {ACT_TRACK_UP_Y, "UPAXISY", 0, "Y axis", ""},
+ {ACT_TRACK_UP_Z, "UPAXISZ", 0, "Z axis", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "EditObjectActuator", "Actuator");
RNA_def_struct_ui_text(srna, "Edit Object Actuator", "Actuator used to edit objects");
RNA_def_struct_sdna_from(srna, "bEditObjectActuator", "data");
@@ -1385,6 +1403,18 @@ static void rna_def_edit_object_actuator(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Dynamic Operation", "");
RNA_def_property_update(prop, NC_LOGIC, NULL);
+ prop = RNA_def_property(srna, "up_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "upflag");
+ RNA_def_property_enum_items(prop, prop_up_axis_items);
+ RNA_def_property_ui_text(prop, "Up Axis", "The axis that points upward");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
+ prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "trackflag");
+ RNA_def_property_enum_items(prop, prop_track_axis_items);
+ RNA_def_property_ui_text(prop, "Track Axis", "The axis that points to the target object");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_pointer_sdna(prop, NULL, "ob");
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 1bccceab5ab..421d7b28dda 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -475,7 +475,7 @@ static int rna_Armature_is_editmode_get(PointerRNA *ptr)
return (arm->edbo != NULL);
}
-void rna_Armature_transform(struct bArmature *arm, float *mat)
+static void rna_Armature_transform(struct bArmature *arm, float *mat)
{
ED_armature_transform(arm, (float (*)[4])mat);
}
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 893cad2b76a..1ff99271146 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -55,6 +55,9 @@ static EnumPropertyItem sculpt_stroke_method_items[] = {
{BRUSH_SPACE, "SPACE", 0, "Space", "Limit brush application to the distance specified by spacing"},
{BRUSH_AIRBRUSH, "AIRBRUSH", 0, "Airbrush", "Keep applying paint effect while holding mouse (spray)"},
{BRUSH_ANCHORED, "ANCHORED", 0, "Anchored", "Keep the brush anchored to the initial location"},
+ {BRUSH_LINE, "LINE", 0, "Line", "Draw a line with dabs separated according to spacing"},
+ {BRUSH_CURVE, "CURVE", 0, "Curve",
+ "Define the stroke curve with a bezier curve (dabs are separated according to spacing)"},
{0, NULL, 0, NULL, NULL}
};
@@ -99,6 +102,8 @@ EnumPropertyItem brush_image_tool_items[] = {
{PAINT_TOOL_SOFTEN, "SOFTEN", ICON_BRUSH_SOFTEN, "Soften", ""},
{PAINT_TOOL_SMEAR, "SMEAR", ICON_BRUSH_SMEAR, "Smear", ""},
{PAINT_TOOL_CLONE, "CLONE", ICON_BRUSH_CLONE, "Clone", ""},
+ {PAINT_TOOL_FILL, "FILL", ICON_BRUSH_TEXFILL, "Fill", ""},
+ {PAINT_TOOL_MASK, "MASK", ICON_BRUSH_TEXMASK, "Mask", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -120,9 +125,9 @@ EnumPropertyItem brush_image_tool_items[] = {
static int rna_SculptToolCapabilities_has_accumulate_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM6(br->sculpt_tool,
- SCULPT_TOOL_BLOB, SCULPT_TOOL_CLAY, SCULPT_TOOL_CREASE,
- SCULPT_TOOL_DRAW, SCULPT_TOOL_INFLATE, SCULPT_TOOL_LAYER);
+ return ELEM(br->sculpt_tool,
+ SCULPT_TOOL_BLOB, SCULPT_TOOL_CLAY, SCULPT_TOOL_CREASE,
+ SCULPT_TOOL_DRAW, SCULPT_TOOL_INFLATE, SCULPT_TOOL_LAYER);
}
static int rna_SculptToolCapabilities_has_auto_smooth_get(PointerRNA *ptr)
@@ -142,9 +147,9 @@ static int rna_SculptToolCapabilities_has_jitter_get(PointerRNA *ptr)
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
!(br->flag & BRUSH_DRAG_DOT) &&
- !ELEM4(br->sculpt_tool,
- SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
+ !ELEM(br->sculpt_tool,
+ SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
static int rna_SculptToolCapabilities_has_normal_weight_get(PointerRNA *ptr)
@@ -156,7 +161,7 @@ static int rna_SculptToolCapabilities_has_normal_weight_get(PointerRNA *ptr)
static int rna_BrushCapabilities_has_overlay_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM3(br->mtex.brush_map_mode,
+ return ELEM(br->mtex.brush_map_mode,
MTEX_MAP_MODE_VIEW,
MTEX_MAP_MODE_TILED,
MTEX_MAP_MODE_STENCIL);
@@ -177,22 +182,22 @@ static int rna_SculptToolCapabilities_has_pinch_factor_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_plane_offset_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM5(br->sculpt_tool, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS,
- SCULPT_TOOL_FILL, SCULPT_TOOL_FLATTEN, SCULPT_TOOL_SCRAPE);
+ return ELEM(br->sculpt_tool, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS,
+ SCULPT_TOOL_FILL, SCULPT_TOOL_FLATTEN, SCULPT_TOOL_SCRAPE);
}
static int rna_SculptToolCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return (!ELEM4(br->sculpt_tool,
- SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
+ return (!ELEM(br->sculpt_tool,
+ SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
static int rna_BrushCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return (ELEM3(br->mtex.brush_map_mode,
+ return (ELEM(br->mtex.brush_map_mode,
MTEX_MAP_MODE_VIEW,
MTEX_MAP_MODE_AREA,
MTEX_MAP_MODE_RANDOM) &&
@@ -202,19 +207,19 @@ static int rna_BrushCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_sculpt_plane_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return !ELEM4(br->sculpt_tool, SCULPT_TOOL_INFLATE,
- SCULPT_TOOL_MASK, SCULPT_TOOL_PINCH,
- SCULPT_TOOL_SMOOTH);
+ return !ELEM(br->sculpt_tool, SCULPT_TOOL_INFLATE,
+ SCULPT_TOOL_MASK, SCULPT_TOOL_PINCH,
+ SCULPT_TOOL_SMOOTH);
}
static int rna_SculptToolCapabilities_has_secondary_color_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM10(br->sculpt_tool,
- SCULPT_TOOL_BLOB, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS,
- SCULPT_TOOL_CREASE, SCULPT_TOOL_DRAW, SCULPT_TOOL_FILL,
- SCULPT_TOOL_FLATTEN, SCULPT_TOOL_INFLATE, SCULPT_TOOL_PINCH,
- SCULPT_TOOL_SCRAPE);
+ return ELEM(br->sculpt_tool,
+ SCULPT_TOOL_BLOB, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS,
+ SCULPT_TOOL_CREASE, SCULPT_TOOL_DRAW, SCULPT_TOOL_FILL,
+ SCULPT_TOOL_FLATTEN, SCULPT_TOOL_INFLATE, SCULPT_TOOL_PINCH,
+ SCULPT_TOOL_SCRAPE);
}
static int rna_SculptToolCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
@@ -222,19 +227,37 @@ static int rna_SculptToolCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
!(br->flag & BRUSH_DRAG_DOT) &&
- !ELEM4(br->sculpt_tool,
+ !(br->flag & BRUSH_LINE) &&
+ !(br->flag & BRUSH_CURVE) &&
+ !ELEM(br->sculpt_tool,
SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
+static int rna_BrushCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
+{
+ Brush *br = (Brush *)ptr->data;
+ return (!(br->flag & BRUSH_ANCHORED) &&
+ !(br->flag & BRUSH_DRAG_DOT) &&
+ !(br->flag & BRUSH_LINE) &&
+ !(br->flag & BRUSH_CURVE));
+}
+
static int rna_SculptToolCapabilities_has_space_attenuation_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ((br->flag & BRUSH_SPACE) &&
- !ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
+ return ((br->flag & (BRUSH_SPACE | BRUSH_LINE | BRUSH_CURVE)) &&
+ !ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SNAKE_HOOK));
}
+static int rna_ImapaintToolCapabilities_has_space_attenuation_get(PointerRNA *ptr)
+{
+ Brush *br = (Brush *)ptr->data;
+ return (br->flag & (BRUSH_SPACE | BRUSH_LINE | BRUSH_CURVE)) &&
+ br->imagepaint_tool != PAINT_TOOL_FILL;
+}
+
static int rna_BrushCapabilities_has_spacing_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
@@ -250,12 +273,12 @@ static int rna_SculptToolCapabilities_has_strength_get(PointerRNA *ptr)
static int rna_BrushCapabilities_has_texture_angle_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM5(br->mtex.brush_map_mode,
- MTEX_MAP_MODE_VIEW,
- MTEX_MAP_MODE_AREA,
- MTEX_MAP_MODE_TILED,
- MTEX_MAP_MODE_STENCIL,
- MTEX_MAP_MODE_RANDOM);
+ return ELEM(br->mtex.brush_map_mode,
+ MTEX_MAP_MODE_VIEW,
+ MTEX_MAP_MODE_AREA,
+ MTEX_MAP_MODE_TILED,
+ MTEX_MAP_MODE_STENCIL,
+ MTEX_MAP_MODE_RANDOM);
}
static int rna_SculptToolCapabilities_has_gravity_get(PointerRNA *ptr)
@@ -267,17 +290,46 @@ static int rna_SculptToolCapabilities_has_gravity_get(PointerRNA *ptr)
static int rna_BrushCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM3(br->mtex.brush_map_mode,
+ return ELEM(br->mtex.brush_map_mode,
MTEX_MAP_MODE_VIEW,
MTEX_MAP_MODE_AREA,
MTEX_MAP_MODE_RANDOM);
}
-static PointerRNA rna_Sculpt_sculpt_tool_capabilities_get(PointerRNA *ptr)
+static int rna_ImapaintToolCapabilities_has_accumulate_get(PointerRNA *ptr)
+{
+ /* only support for draw tool */
+ Brush *br = (Brush *)ptr->data;
+
+ return ((br->flag & BRUSH_AIRBRUSH) ||
+ (br->flag & BRUSH_DRAG_DOT) ||
+ (br->flag & BRUSH_ANCHORED) ||
+ (br->imagepaint_tool == PAINT_TOOL_SOFTEN) ||
+ (br->imagepaint_tool == PAINT_TOOL_SMEAR) ||
+ (br->imagepaint_tool == PAINT_TOOL_FILL) ||
+ (br->mtex.tex && !ELEM(br->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_3D))
+ ) ? false : true;
+}
+
+static int rna_ImapaintToolCapabilities_has_radius_get(PointerRNA *ptr)
+{
+ /* only support for draw tool */
+ Brush *br = (Brush *)ptr->data;
+
+ return (br->imagepaint_tool != PAINT_TOOL_FILL);
+}
+
+
+static PointerRNA rna_Sculpt_tool_capabilities_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_SculptToolCapabilities, ptr->id.data);
}
+static PointerRNA rna_Imapaint_tool_capabilities_get(PointerRNA *ptr)
+{
+ return rna_pointer_inherit_refine(ptr, &RNA_ImapaintToolCapabilities, ptr->id.data);
+}
+
static PointerRNA rna_Brush_capabilities_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilities, ptr->id.data);
@@ -328,7 +380,6 @@ static void rna_Brush_size_update(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Brush_sculpt_tool_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- BKE_paint_invalidate_overlay_all();
rna_Brush_reset_icon(br, "sculpt");
rna_Brush_update(bmain, scene, ptr);
}
@@ -336,7 +387,6 @@ static void rna_Brush_sculpt_tool_update(Main *bmain, Scene *scene, PointerRNA *
static void rna_Brush_vertex_tool_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- BKE_paint_invalidate_overlay_all();
rna_Brush_reset_icon(br, "vertex_paint");
rna_Brush_update(bmain, scene, ptr);
}
@@ -344,11 +394,16 @@ static void rna_Brush_vertex_tool_update(Main *bmain, Scene *scene, PointerRNA *
static void rna_Brush_imagepaint_tool_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- BKE_paint_invalidate_overlay_all();
rna_Brush_reset_icon(br, "image_paint");
rna_Brush_update(bmain, scene, ptr);
}
+static void rna_Brush_stroke_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, scene);
+ rna_Brush_update(bmain, scene, ptr);
+}
+
static void rna_Brush_icon_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
@@ -388,6 +443,17 @@ static void rna_Brush_set_size(PointerRNA *ptr, int value)
brush->size = value;
}
+static void rna_Brush_use_gradient_set(PointerRNA *ptr, int value)
+{
+ Brush *br = (Brush *)ptr->data;
+
+ if (value) br->flag |= BRUSH_USE_GRADIENT;
+ else br->flag &= ~BRUSH_USE_GRADIENT;
+
+ if ((br->flag & BRUSH_USE_GRADIENT) && br->gradient == NULL)
+ br->gradient = add_colorband(true);
+}
+
static void rna_Brush_set_unprojected_radius(PointerRNA *ptr, float value)
{
Brush *brush = ptr->data;
@@ -397,13 +463,16 @@ static void rna_Brush_set_unprojected_radius(PointerRNA *ptr, float value)
brush->unprojected_radius = value;
}
-static EnumPropertyItem *rna_Brush_direction_itemf(bContext *UNUSED(C), PointerRNA *ptr,
+static EnumPropertyItem *rna_Brush_direction_itemf(bContext *C, PointerRNA *ptr,
PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
{
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
+
static EnumPropertyItem prop_default_items[] = {
{0, NULL, 0, NULL, NULL}
};
+ /* sculpt mode */
static EnumPropertyItem prop_flatten_contrast_items[] = {
{0, "FLATTEN", 0, "Flatten", "Add effect of brush"},
{BRUSH_DIR_IN, "CONTRAST", 0, "Contrast", "Subtract effect of brush"},
@@ -434,41 +503,66 @@ static EnumPropertyItem *rna_Brush_direction_itemf(bContext *UNUSED(C), PointerR
{0, NULL, 0, NULL, NULL}
};
+ /* texture paint mode */
+ static EnumPropertyItem prop_soften_sharpen_items[] = {
+ {0, "SOFTEN", 0, "Soften", "Blur effect of brush"},
+ {BRUSH_DIR_IN, "SHARPEN", 0, "Sharpen", "Sharpen effect of brush"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
Brush *me = (Brush *)(ptr->data);
- switch (me->sculpt_tool) {
- case SCULPT_TOOL_DRAW:
- case SCULPT_TOOL_CREASE:
- case SCULPT_TOOL_BLOB:
- case SCULPT_TOOL_LAYER:
- case SCULPT_TOOL_CLAY:
- case SCULPT_TOOL_CLAY_STRIPS:
- return prop_direction_items;
-
- case SCULPT_TOOL_MASK:
- switch ((BrushMaskTool)me->mask_tool) {
- case BRUSH_MASK_DRAW:
+ switch (mode) {
+ case PAINT_SCULPT:
+ switch (me->sculpt_tool) {
+ case SCULPT_TOOL_DRAW:
+ case SCULPT_TOOL_CREASE:
+ case SCULPT_TOOL_BLOB:
+ case SCULPT_TOOL_LAYER:
+ case SCULPT_TOOL_CLAY:
+ case SCULPT_TOOL_CLAY_STRIPS:
return prop_direction_items;
- break;
- case BRUSH_MASK_SMOOTH:
- return prop_default_items;
- break;
- }
- case SCULPT_TOOL_FLATTEN:
- return prop_flatten_contrast_items;
+ case SCULPT_TOOL_MASK:
+ switch ((BrushMaskTool)me->mask_tool) {
+ case BRUSH_MASK_DRAW:
+ return prop_direction_items;
+ break;
+ case BRUSH_MASK_SMOOTH:
+ return prop_default_items;
+ break;
+ }
- case SCULPT_TOOL_FILL:
- return prop_fill_deepen_items;
+ case SCULPT_TOOL_FLATTEN:
+ return prop_flatten_contrast_items;
- case SCULPT_TOOL_SCRAPE:
- return prop_scrape_peaks_items;
+ case SCULPT_TOOL_FILL:
+ return prop_fill_deepen_items;
- case SCULPT_TOOL_PINCH:
- return prop_pinch_magnify_items;
+ case SCULPT_TOOL_SCRAPE:
+ return prop_scrape_peaks_items;
- case SCULPT_TOOL_INFLATE:
- return prop_inflate_deflate_items;
+ case SCULPT_TOOL_PINCH:
+ return prop_pinch_magnify_items;
+
+ case SCULPT_TOOL_INFLATE:
+ return prop_inflate_deflate_items;
+
+ default:
+ return prop_default_items;
+ }
+ break;
+
+ case PAINT_TEXTURE_2D:
+ case PAINT_TEXTURE_PROJECTIVE:
+ switch (me->imagepaint_tool) {
+ case PAINT_TOOL_SOFTEN:
+ return prop_soften_sharpen_items;
+
+ default:
+ return prop_default_items;
+ }
+ break;
default:
return prop_default_items;
@@ -484,11 +578,15 @@ static EnumPropertyItem *rna_Brush_stroke_itemf(bContext *C, PointerRNA *UNUSED(
{0, "DOTS", 0, "Dots", "Apply paint on each mouse move step"},
{BRUSH_SPACE, "SPACE", 0, "Space", "Limit brush application to the distance specified by spacing"},
{BRUSH_AIRBRUSH, "AIRBRUSH", 0, "Airbrush", "Keep applying paint effect while holding mouse (spray)"},
+ {BRUSH_LINE, "LINE", 0, "Line", "Drag a line with dabs separated according to spacing"},
+ {BRUSH_CURVE, "CURVE", 0, "Curve", "Define the stroke curve with a bezier curve. Dabs are separated according to spacing"},
{0, NULL, 0, NULL, NULL}
};
switch (mode) {
case PAINT_SCULPT:
+ case PAINT_TEXTURE_2D:
+ case PAINT_TEXTURE_PROJECTIVE:
return sculpt_stroke_method_items;
default:
@@ -622,10 +720,39 @@ static void rna_def_brush_capabilities(BlenderRNA *brna)
BRUSH_CAPABILITY(has_texture_angle, "Has Texture Angle");
BRUSH_CAPABILITY(has_texture_angle_source, "Has Texture Angle Source");
BRUSH_CAPABILITY(has_spacing, "Has Spacing");
+ BRUSH_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke");
+
#undef BRUSH_CAPABILITY
}
+static void rna_def_image_paint_capabilities(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ImapaintToolCapabilities", NULL);
+ RNA_def_struct_sdna(srna, "Brush");
+ RNA_def_struct_nested(brna, srna, "Brush");
+ RNA_def_struct_ui_text(srna, "Image Paint Capabilities",
+ "Read-only indications of which brush operations "
+ "are supported by the current image paint brush");
+
+#define IMAPAINT_TOOL_CAPABILITY(prop_name_, ui_name_) \
+ prop = RNA_def_property(srna, #prop_name_, \
+ PROP_BOOLEAN, PROP_NONE); \
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); \
+ RNA_def_property_boolean_funcs(prop, "rna_ImapaintToolCapabilities_" \
+ #prop_name_ "_get", NULL); \
+ RNA_def_property_ui_text(prop, ui_name_, NULL)
+
+ IMAPAINT_TOOL_CAPABILITY(has_accumulate, "Has Accumulate");
+ IMAPAINT_TOOL_CAPABILITY(has_space_attenuation, "Has Space Attenuation");
+ IMAPAINT_TOOL_CAPABILITY(has_radius, "Has Radius");
+
+#undef IMAPAINT_TOOL_CAPABILITY
+}
+
static void rna_def_brush(BlenderRNA *brna)
{
StructRNA *srna;
@@ -640,6 +767,22 @@ static void rna_def_brush(BlenderRNA *brna)
{IMB_BLEND_DARKEN, "DARKEN", 0, "Darken", "Use darken blending mode while painting"},
{IMB_BLEND_ERASE_ALPHA, "ERASE_ALPHA", 0, "Erase Alpha", "Erase alpha while painting"},
{IMB_BLEND_ADD_ALPHA, "ADD_ALPHA", 0, "Add Alpha", "Add alpha while painting"},
+ {IMB_BLEND_OVERLAY, "OVERLAY", 0, "Overlay", "Use overlay blending mode while painting"},
+ {IMB_BLEND_HARDLIGHT, "HARDLIGHT", 0, "Hard light", "Use hard light blending mode while painting"},
+ {IMB_BLEND_COLORBURN, "COLORBURN", 0, "Color burn", "Use color burn blending mode while painting"},
+ {IMB_BLEND_LINEARBURN, "LINEARBURN", 0, "Linear burn", "Use linear burn blending mode while painting"},
+ {IMB_BLEND_COLORDODGE, "COLORDODGE", 0, "Color dodge", "Use color dodge blending mode while painting"},
+ {IMB_BLEND_SCREEN, "SCREEN", 0, "Screen", "Use screen blending mode while painting"},
+ {IMB_BLEND_SOFTLIGHT, "SOFTLIGHT", 0, "Soft light", "Use softlight blending mode while painting"},
+ {IMB_BLEND_PINLIGHT, "PINLIGHT", 0, "Pin light", "Use pinlight blending mode while painting"},
+ {IMB_BLEND_VIVIDLIGHT, "VIVIDLIGHT", 0, "Vivid light", "Use vividlight blending mode while painting"},
+ {IMB_BLEND_LINEARLIGHT, "LINEARLIGHT", 0, "Linear light", "Use linearlight blending mode while painting"},
+ {IMB_BLEND_DIFFERENCE, "DIFFERENCE", 0, "Difference", "Use difference blending mode while painting"},
+ {IMB_BLEND_EXCLUSION, "EXCLUSION", 0, "Exclusion", "Use exclusion blending mode while painting"},
+ {IMB_BLEND_HUE, "HUE", 0, "Hue", "Use hue blending mode while painting"},
+ {IMB_BLEND_SATURATION, "SATURATION", 0, "Saturation", "Use saturation blending mode while painting"},
+ {IMB_BLEND_LUMINOSITY, "LUMINOSITY", 0, "Luminosity", "Use luminosity blending mode while painting"},
+ {IMB_BLEND_COLOR, "COLOR", 0, "Color", "Use color blending mode while painting"},
{0, NULL, 0, NULL, NULL}
};
@@ -671,6 +814,32 @@ static void rna_def_brush(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem brush_blur_mode_items[] = {
+ {KERNEL_BOX, "BOX", 0, "Box", ""},
+ {KERNEL_GAUSSIAN, "GAUSSIAN", 0, "Gaussian", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem brush_gradient_items[] = {
+ {BRUSH_GRADIENT_PRESSURE, "PRESSURE", 0, "Pressure", ""},
+ {BRUSH_GRADIENT_SPACING_REPEAT, "SPACING_REPEAT", 0, "Repeat", ""},
+ {BRUSH_GRADIENT_SPACING_CLAMP, "SPACING_CLAMP", 0, "Clamp", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem brush_gradient_fill_items[] = {
+ {BRUSH_GRADIENT_LINEAR, "LINEAR", 0, "Linear", ""},
+ {BRUSH_GRADIENT_RADIAL, "RADIAL", 0, "Radial", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem brush_mask_pressure_items[] = {
+ {0, "NONE", 0, "Off", ""},
+ {BRUSH_MASK_PRESSURE_RAMP, "RAMP", ICON_STYLUS_PRESSURE, "Ramp", ""},
+ {BRUSH_MASK_PRESSURE_CUTOFF, "CUTOFF", ICON_STYLUS_PRESSURE, "Cutoff", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "Brush", "ID");
RNA_def_struct_ui_text(srna, "Brush", "Brush datablock for storing brush settings for painting and sculpting");
RNA_def_struct_ui_icon(srna, ICON_BRUSH_DATA);
@@ -710,7 +879,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_enum_items(prop, sculpt_stroke_method_items);
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Brush_stroke_itemf");
RNA_def_property_ui_text(prop, "Stroke Method", "");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
+ RNA_def_property_update(prop, 0, "rna_Brush_stroke_update");
prop = RNA_def_property(srna, "texture_angle_source_random", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
@@ -769,6 +938,13 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Spacing", "Spacing between brush daubs as a percentage of brush diameter");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "grad_spacing", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "gradient_spacing");
+ RNA_def_property_range(prop, 1, 10000);
+ RNA_def_property_ui_range(prop, 1, 10000, 5, -1);
+ RNA_def_property_ui_text(prop, "Gradient Spacing", "Spacing before brush gradient goes full circle");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "smooth_stroke_radius", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 10, 200);
RNA_def_property_ui_text(prop, "Smooth Stroke Radius", "Minimum distance from last point before stroke continues");
@@ -791,7 +967,13 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "rgb");
RNA_def_property_ui_text(prop, "Color", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
-
+
+ prop = RNA_def_property(srna, "secondary_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "secondary_rgb");
+ RNA_def_property_ui_text(prop, "Secondary Color", "");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -884,6 +1066,32 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Mask Stencil Dimensions", "Dimensions of mask stencil in viewport");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "sharp_threshold", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 3);
+ RNA_def_property_float_sdna(prop, NULL, "sharp_threshold");
+ RNA_def_property_ui_text(prop, "Sharp Threshold", "Threshold below which, no sharpening is done");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "fill_threshold", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 3);
+ RNA_def_property_float_sdna(prop, NULL, "fill_threshold");
+ RNA_def_property_ui_text(prop, "Fill Threshold", "Threshold above which filling is not propagated");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "blur_kernel_radius", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "blur_kernel_radius");
+ RNA_def_property_range(prop, 1, 10000);
+ RNA_def_property_ui_range(prop, 1, 50, 1, -1);
+ RNA_def_property_ui_text(prop, "Kernel Radius", "Radius of kernel used for soften and sharpen in pixels");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "blur_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, brush_blur_mode_items);
+ RNA_def_property_ui_text(prop, "Blur Mode", "");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
/* flag */
prop = RNA_def_property(srna, "use_airbrush", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_AIRBRUSH);
@@ -919,7 +1127,13 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
RNA_def_property_ui_text(prop, "Size Pressure", "Enable tablet pressure sensitivity for size");
RNA_def_property_update(prop, 0, "rna_Brush_update");
-
+
+ prop = RNA_def_property(srna, "use_gradient", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_USE_GRADIENT);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_Brush_use_gradient_set");
+ RNA_def_property_ui_text(prop, "Use Gradient", "Use Gradient by utilizing a sampling method");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "use_pressure_jitter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_JITTER_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
@@ -932,6 +1146,12 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Spacing Pressure", "Enable tablet pressure sensitivity for spacing");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "use_pressure_masking", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mask_pressure");
+ RNA_def_property_enum_items(prop, brush_mask_pressure_items);
+ RNA_def_property_ui_text(prop, "Mask Pressure Mode", "Pen pressure makes texture influence smaller");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "use_inverse_smooth_pressure", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_INVERSE_SMOOTH_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
@@ -974,6 +1194,16 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Space", "Limit brush application to the distance specified by spacing");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "use_line", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_LINE);
+ RNA_def_property_ui_text(prop, "Line", "Draw a line with dabs separated according to spacing");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "use_curve", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_CURVE);
+ RNA_def_property_ui_text(prop, "Curve", "Define the stroke curve with a bezier curve. Dabs are separated according to spacing");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "use_smooth_stroke", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SMOOTH_STROKE);
RNA_def_property_ui_text(prop, "Smooth Stroke", "Brush lags behind mouse and follows a smoother path");
@@ -1015,7 +1245,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Edge-to-edge", "Drag anchor brush from edge-to-edge");
RNA_def_property_update(prop, 0, "rna_Brush_update");
- prop = RNA_def_property(srna, "use_drag_dot", PROP_BOOLEAN, PROP_NONE);
+ prop = RNA_def_property(srna, "use_restore_mesh", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_DRAG_DOT);
RNA_def_property_ui_text(prop, "Restore Mesh", "Allow a single dot to be carefully positioned");
RNA_def_property_update(prop, 0, "rna_Brush_update");
@@ -1031,6 +1261,28 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Curve", "Editable falloff curve");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "paint_curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Paint Curve", "Active Paint Curve");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "gradient", PROP_POINTER, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "gradient");
+ RNA_def_property_struct_type(prop, "ColorRamp");
+ RNA_def_property_ui_text(prop, "Gradient", "");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ /* gradient source */
+ prop = RNA_def_property(srna, "gradient_stroke_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, brush_gradient_items);
+ RNA_def_property_ui_text(prop, "Gradient Stroke Mode", "");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "gradient_fill_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, brush_gradient_fill_items);
+ RNA_def_property_ui_text(prop, "Gradient Fill Mode", "");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
/* overlay flags */
prop = RNA_def_property(srna, "use_primary_overlay", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay_flags", BRUSH_OVERLAY_PRIMARY);
@@ -1173,8 +1425,14 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "sculpt_capabilities", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "SculptToolCapabilities");
- RNA_def_property_pointer_funcs(prop, "rna_Sculpt_sculpt_tool_capabilities_get", NULL, NULL, NULL);
+ RNA_def_property_pointer_funcs(prop, "rna_Sculpt_tool_capabilities_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Sculpt Capabilities", "Brush's capabilities in sculpt mode");
+
+ prop = RNA_def_property(srna, "image_paint_capabilities", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "ImapaintToolCapabilities");
+ RNA_def_property_pointer_funcs(prop, "rna_Imapaint_tool_capabilities_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Image Painting Capabilities", "Brush's capabilities in image paint mode");
}
@@ -1211,6 +1469,11 @@ static void rna_def_operator_stroke_element(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Pressure", "Tablet pressure");
+ prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Brush Size", "Brush Size in screen space");
+
prop = RNA_def_property(srna, "pen_flip", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_ui_text(prop, "Flip", "");
@@ -1237,6 +1500,7 @@ void RNA_def_brush(BlenderRNA *brna)
rna_def_brush(brna);
rna_def_brush_capabilities(brna);
rna_def_sculpt_capabilities(brna);
+ rna_def_image_paint_capabilities(brna);
rna_def_brush_texture_slot(brna);
rna_def_operator_stroke_element(brna);
}
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index cca78ee2d8d..fa2a3258d1a 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -176,7 +176,7 @@ static char *rna_ColorRamp_path(PointerRNA *ptr)
char *node_path;
for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM3(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
+ if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
if (node->storage == ptr->data) {
/* all node color ramp properties called 'color_ramp'
* prepend path from ID to the node
@@ -193,7 +193,7 @@ static char *rna_ColorRamp_path(PointerRNA *ptr)
case ID_LS:
{
- char *path = BKE_path_from_ID_to_color_ramp((FreestyleLineStyle *)id, (ColorBand *)ptr->data);
+ char *path = BKE_linestyle_path_to_color_ramp((FreestyleLineStyle *)id, (ColorBand *)ptr->data);
if (path)
return path;
break;
@@ -265,7 +265,7 @@ static char *rna_ColorRampElement_path(PointerRNA *ptr)
bNode *node;
for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM3(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
+ if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
RNA_pointer_create(id, &RNA_ColorRamp, node->storage, &ramp_ptr);
COLRAMP_GETPATH;
}
@@ -277,7 +277,7 @@ static char *rna_ColorRampElement_path(PointerRNA *ptr)
ListBase listbase;
LinkData *link;
- BKE_list_modifier_color_ramps((FreestyleLineStyle *)id, &listbase);
+ BKE_linestyle_modifier_list_color_ramps((FreestyleLineStyle *)id, &listbase);
for (link = (LinkData *)listbase.first; link; link = link->next) {
RNA_pointer_create(id, &RNA_ColorRamp, link->data, &ramp_ptr);
COLRAMP_GETPATH;
@@ -324,7 +324,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
bNode *node;
for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM3(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
+ if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
ED_node_tag_update_nodetree(bmain, ntree);
}
}
@@ -378,7 +378,7 @@ static void rna_ColorRampElement_remove(struct ColorBand *coba, ReportList *repo
RNA_POINTER_INVALIDATE(element_ptr);
}
-void rna_CurveMap_remove_point(CurveMap *cuma, ReportList *reports, PointerRNA *point_ptr)
+static void rna_CurveMap_remove_point(CurveMap *cuma, ReportList *reports, PointerRNA *point_ptr)
{
CurveMapPoint *point = point_ptr->data;
if (curvemap_remove_point(cuma, point) == false) {
@@ -850,7 +850,12 @@ static void rna_def_color_ramp_element(BlenderRNA *brna)
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Color", "Set color of selected color stop");
RNA_def_property_update(prop, 0, "rna_ColorRamp_update");
-
+
+ prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_float_sdna(prop, NULL, "a");
+ RNA_def_property_ui_text(prop, "Alpha", "Set alpha of selected color stop");
+ RNA_def_property_update(prop, 0, "rna_ColorRamp_update");
+
prop = RNA_def_property(srna, "position", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "pos");
RNA_def_property_range(prop, 0, 1);
@@ -895,14 +900,29 @@ static void rna_def_color_ramp(BlenderRNA *brna)
FunctionRNA *func;
static EnumPropertyItem prop_interpolation_items[] = {
- {1, "EASE", 0, "Ease", ""},
- {3, "CARDINAL", 0, "Cardinal", ""},
- {0, "LINEAR", 0, "Linear", ""},
- {2, "B_SPLINE", 0, "B-Spline", ""},
- {4, "CONSTANT", 0, "Constant", ""},
+ {COLBAND_INTERP_EASE, "EASE", 0, "Ease", ""},
+ {COLBAND_INTERP_CARDINAL, "CARDINAL", 0, "Cardinal", ""},
+ {COLBAND_INTERP_LINEAR, "LINEAR", 0, "Linear", ""},
+ {COLBAND_INTERP_B_SPLINE, "B_SPLINE", 0, "B-Spline", ""},
+ {COLBAND_INTERP_CONSTANT, "CONSTANT", 0, "Constant", ""},
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_mode_items[] = {
+ {COLBAND_BLEND_RGB, "RGB", 0, "RGB", ""},
+ {COLBAND_BLEND_HSV, "HSV", 0, "HSV", ""},
+ {COLBAND_BLEND_HSL, "HSL", 0, "HSL", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem prop_hsv_items[] = {
+ {COLBAND_HUE_NEAR, "NEAR", 0, "Near", ""},
+ {COLBAND_HUE_FAR, "FAR", 0, "Far", ""},
+ {COLBAND_HUE_CW, "CW", 0, "Clockwise", ""},
+ {COLBAND_HUE_CCW, "CCW", 0, "Counter-Clockwise", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "ColorRamp", NULL);
RNA_def_struct_sdna(srna, "ColorBand");
RNA_def_struct_path_func(srna, "rna_ColorRamp_path");
@@ -921,6 +941,18 @@ static void rna_def_color_ramp(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Interpolation", "Set interpolation between color stops");
RNA_def_property_update(prop, 0, "rna_ColorRamp_update");
+ prop = RNA_def_property(srna, "hue_interpolation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "ipotype_hue");
+ RNA_def_property_enum_items(prop, prop_hsv_items);
+ RNA_def_property_ui_text(prop, "Color Interpolation", "Set color interpolation");
+ RNA_def_property_update(prop, 0, "rna_ColorRamp_update");
+
+ prop = RNA_def_property(srna, "color_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "color_mode");
+ RNA_def_property_enum_items(prop, prop_mode_items);
+ RNA_def_property_ui_text(prop, "Color Mode", "Set color mode to use for interpolation");
+ RNA_def_property_update(prop, 0, "rna_ColorRamp_update");
+
#if 0 /* use len(elements) */
prop = RNA_def_property(srna, "total", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "tot");
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 120992cffe8..5519b192ca4 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -351,7 +351,7 @@ static void rna_ActionConstraint_minmax_range(PointerRNA *ptr, float *min, float
bActionConstraint *acon = (bActionConstraint *)con->data;
/* 0, 1, 2 = magic numbers for rotX, rotY, rotZ */
- if (ELEM3(acon->type, 0, 1, 2)) {
+ if (ELEM(acon->type, 0, 1, 2)) {
*min = -180.0f;
*max = 180.0f;
}
@@ -2452,6 +2452,12 @@ static void rna_def_constraint_follow_track(BlenderRNA *brna)
RNA_def_property_enum_items(prop, frame_method_items);
RNA_def_property_ui_text(prop, "Frame Method", "How the footage fits in the camera frame");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
+
+ /* use undistortion */
+ prop = RNA_def_property(srna, "use_undistorted_position", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", FOLLOWTRACK_USE_UNDISTORTION);
+ RNA_def_property_ui_text(prop, "Undistort", "Parent to undistorted position of 2D track");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
}
static void rna_def_constraint_camera_solver(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_curve_api.c b/source/blender/makesrna/intern/rna_curve_api.c
index b689242f68f..e85511f08e9 100644
--- a/source/blender/makesrna/intern/rna_curve_api.c
+++ b/source/blender/makesrna/intern/rna_curve_api.c
@@ -38,14 +38,16 @@
#include "BLI_utildefines.h"
-#include "ED_curve.h"
+#include "BKE_curve.h"
#include "rna_internal.h" /* own include */
#ifdef RNA_RUNTIME
-void rna_Curve_transform(Curve *cu, float *mat)
+static void rna_Curve_transform(Curve *cu, float *mat, int shape_keys)
{
- ED_curve_transform(cu, (float (*)[4])mat);
+ BKE_curve_transform(cu, (float (*)[4])mat, shape_keys);
+
+ DAG_id_tag_update(&cu->id, 0);
}
#else
@@ -58,6 +60,13 @@ void RNA_api_curve(StructRNA *srna)
RNA_def_function_ui_description(func, "Transform curve by a matrix");
parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "shape_keys", 0, "", "Transform Shape Keys");
+
+ func = RNA_def_function(srna, "validate_material_indices", "BKE_curve_material_index_validate");
+ RNA_def_function_ui_description(func, "Validate material indices of splines or letters, return True when the curve "
+ "has had invalid indices corrected (to default 0)");
+ parm = RNA_def_boolean(func, "result", 0, "Result", "");
+ RNA_def_function_return(func, parm);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 9f9cc57a475..3b9078153f3 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -820,7 +820,7 @@ static FCM_EnvelopeData *rna_FModifierEnvelope_points_add(FModifier *fmod, Repor
return (env->data + i);
}
-void rna_FModifierEnvelope_points_remove(FModifier *fmod, ReportList *reports, PointerRNA *point)
+static void rna_FModifierEnvelope_points_remove(FModifier *fmod, ReportList *reports, PointerRNA *point)
{
FCM_EnvelopeData *cp = point->data;
FMod_Envelope *env = (FMod_Envelope *)fmod->data;
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index 8f4108c23d0..01feb3cb748 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -465,7 +465,8 @@ static void rna_def_fluidsim_volume(StructRNA *srna)
RNA_def_property_enum_bitflag_sdna(prop, NULL, "volumeInitType");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_enum_items(prop, volume_type_items);
- RNA_def_property_ui_text(prop, "Volume Initialization", "Volume initialization type");
+ RNA_def_property_ui_text(prop, "Volume Initialization", "Volume initialization type "
+ "(WARNING: complex volumes might require too much memory and break simulation)");
prop = RNA_def_property(srna, "use_animated_mesh", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "domainNovecgen", 0);
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index be275058957..83b7a81c649 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -202,6 +202,7 @@ void rna_def_texmat_common(struct StructRNA *srna, const char *texspace_editable
void rna_def_mtex_common(struct BlenderRNA *brna, struct StructRNA *srna, const char *begin, const char *activeget,
const char *activeset, const char *activeeditable, const char *structname,
const char *structname_slots, const char *update, const char *update_index);
+void rna_def_texpaint_slots(struct BlenderRNA *brna, struct StructRNA *srna);
void rna_def_render_layer_common(struct StructRNA *srna, int scene);
void rna_def_actionbone_group_common(struct StructRNA *srna, int update_flag, const char *update_cb);
@@ -412,4 +413,24 @@ void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);
# endif
#endif
+/* C11 for compile time range checks */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+# define USE_RNA_RANGE_CHECK
+# define TYPEOF_MAX(x) \
+ _Generic((x), \
+ bool: 1, \
+ char: CHAR_MAX, signed char: SCHAR_MAX, unsigned char: UCHAR_MAX, \
+ signed short: SHRT_MAX, unsigned short: USHRT_MAX, \
+ signed int: INT_MAX, unsigned int: UINT_MAX, \
+ float: FLT_MAX, double: DBL_MAX)
+
+# define TYPEOF_MIN(x) \
+ _Generic((x), \
+ bool: 0, \
+ char: CHAR_MIN, signed char: SCHAR_MIN, unsigned char: 0, \
+ signed short: SHRT_MIN, unsigned short: 0, \
+ signed int: INT_MIN, unsigned int: 0, \
+ float: -FLT_MAX, double: -DBL_MAX)
+#endif
+
#endif /* __RNA_INTERNAL_H__ */
diff --git a/source/blender/makesrna/intern/rna_lattice_api.c b/source/blender/makesrna/intern/rna_lattice_api.c
index acb71b29ea8..ed0489db1a2 100644
--- a/source/blender/makesrna/intern/rna_lattice_api.c
+++ b/source/blender/makesrna/intern/rna_lattice_api.c
@@ -38,14 +38,14 @@
#include "BLI_utildefines.h"
-#include "ED_lattice.h"
-
#include "rna_internal.h" /* own include */
#ifdef RNA_RUNTIME
-void rna_Lattice_transform(Lattice *lt, float *mat)
+static void rna_Lattice_transform(Lattice *lt, float *mat, int shape_keys)
{
- ED_lattice_transform(lt, (float (*)[4])mat);
+ BKE_lattice_transform(lt, (float (*)[4])mat, shape_keys);
+
+ DAG_id_tag_update(&lt->id, 0);
}
#else
@@ -58,6 +58,7 @@ void RNA_api_lattice(StructRNA *srna)
RNA_def_function_ui_description(func, "Transform lattice by a matrix");
parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "shape_keys", 0, "", "Transform Shape Keys");
}
#endif
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
index faff39e679a..96b81f12620 100644
--- a/source/blender/makesrna/intern/rna_linestyle.c
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -87,6 +87,8 @@ EnumPropertyItem linestyle_geometry_modifier_type_items[] = {
#include "BKE_texture.h"
#include "BKE_depsgraph.h"
+#include "ED_node.h"
+
#include "RNA_access.h"
static StructRNA *rna_LineStyle_color_modifier_refine(struct PointerRNA *ptr)
@@ -283,10 +285,20 @@ static void rna_LineStyle_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin
WM_main_add_notifier(NC_LINESTYLE, linestyle);
}
+static void rna_LineStyle_use_nodes_update(bContext *C, PointerRNA *ptr)
+{
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->data;
+
+ if (linestyle->use_nodes && linestyle->nodetree == NULL)
+ BKE_linestyle_default_shader(C, linestyle);
+
+ rna_LineStyle_update(CTX_data_main(C), CTX_data_scene(C), ptr);
+}
+
static LineStyleModifier *rna_LineStyle_color_modifier_add(FreestyleLineStyle *linestyle, ReportList *reports,
const char *name, int type)
{
- LineStyleModifier *modifier = BKE_add_linestyle_color_modifier(linestyle, name, type);
+ LineStyleModifier *modifier = BKE_linestyle_color_modifier_add(linestyle, name, type);
if (!modifier) {
BKE_report(reports, RPT_ERROR, "Failed to add the color modifier");
@@ -304,7 +316,7 @@ static void rna_LineStyle_color_modifier_remove(FreestyleLineStyle *linestyle, R
{
LineStyleModifier *modifier = modifier_ptr->data;
- if (BKE_remove_linestyle_color_modifier(linestyle, modifier) == -1) {
+ if (BKE_linestyle_color_modifier_remove(linestyle, modifier) == -1) {
BKE_reportf(reports, RPT_ERROR, "Color modifier '%s' could not be removed", modifier->name);
return;
}
@@ -318,7 +330,7 @@ static void rna_LineStyle_color_modifier_remove(FreestyleLineStyle *linestyle, R
static LineStyleModifier *rna_LineStyle_alpha_modifier_add(FreestyleLineStyle *linestyle, ReportList *reports,
const char *name, int type)
{
- LineStyleModifier *modifier = BKE_add_linestyle_alpha_modifier(linestyle, name, type);
+ LineStyleModifier *modifier = BKE_linestyle_alpha_modifier_add(linestyle, name, type);
if (!modifier) {
BKE_report(reports, RPT_ERROR, "Failed to add the alpha modifier");
@@ -336,7 +348,7 @@ static void rna_LineStyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, R
{
LineStyleModifier *modifier = modifier_ptr->data;
- if (BKE_remove_linestyle_alpha_modifier(linestyle, modifier) == -1) {
+ if (BKE_linestyle_alpha_modifier_remove(linestyle, modifier) == -1) {
BKE_reportf(reports, RPT_ERROR, "Alpha modifier '%s' could not be removed", modifier->name);
return;
}
@@ -350,7 +362,7 @@ static void rna_LineStyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, R
static LineStyleModifier *rna_LineStyle_thickness_modifier_add(FreestyleLineStyle *linestyle, ReportList *reports,
const char *name, int type)
{
- LineStyleModifier *modifier = BKE_add_linestyle_thickness_modifier(linestyle, name, type);
+ LineStyleModifier *modifier = BKE_linestyle_thickness_modifier_add(linestyle, name, type);
if (!modifier) {
BKE_report(reports, RPT_ERROR, "Failed to add the thickness modifier");
@@ -368,7 +380,7 @@ static void rna_LineStyle_thickness_modifier_remove(FreestyleLineStyle *linestyl
{
LineStyleModifier *modifier = modifier_ptr->data;
- if (BKE_remove_linestyle_thickness_modifier(linestyle, modifier) == -1) {
+ if (BKE_linestyle_thickness_modifier_remove(linestyle, modifier) == -1) {
BKE_reportf(reports, RPT_ERROR, "Thickness modifier '%s' could not be removed", modifier->name);
return;
}
@@ -382,7 +394,7 @@ static void rna_LineStyle_thickness_modifier_remove(FreestyleLineStyle *linestyl
static LineStyleModifier *rna_LineStyle_geometry_modifier_add(FreestyleLineStyle *linestyle, ReportList *reports,
const char *name, int type)
{
- LineStyleModifier *modifier = BKE_add_linestyle_geometry_modifier(linestyle, name, type);
+ LineStyleModifier *modifier = BKE_linestyle_geometry_modifier_add(linestyle, name, type);
if (!modifier) {
BKE_report(reports, RPT_ERROR, "Failed to add the geometry modifier");
@@ -400,7 +412,7 @@ static void rna_LineStyle_geometry_modifier_remove(FreestyleLineStyle *linestyle
{
LineStyleModifier *modifier = modifier_ptr->data;
- if (BKE_remove_linestyle_geometry_modifier(linestyle, modifier) == -1) {
+ if (BKE_linestyle_geometry_modifier_remove(linestyle, modifier) == -1) {
BKE_reportf(reports, RPT_ERROR, "Geometry modifier '%s' could not be removed", modifier->name);
return;
}
@@ -500,7 +512,7 @@ static void rna_def_linestyle_mtex(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_tips", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_TIPS);
- RNA_def_property_ui_text(prop, "Use tips", "Lower half of the texture is for tips of the stroke");
+ RNA_def_property_ui_text(prop, "Use Tips", "Lower half of the texture is for tips of the stroke");
RNA_def_property_update(prop, 0, "rna_LineStyle_update");
prop = RNA_def_property(srna, "texture_coords", PROP_ENUM, PROP_NONE);
@@ -571,6 +583,7 @@ static void rna_def_modifier_type_common(StructRNA *srna, EnumPropertyItem *modi
prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "modifier.flags", LS_MODIFIER_ENABLED);
RNA_def_property_ui_text(prop, "Use", "Enable or disable this modifier during stroke rendering");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
prop = RNA_def_property(srna, "expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "modifier.flags", LS_MODIFIER_EXPANDED);
@@ -1337,7 +1350,6 @@ static void rna_def_linestyle(BlenderRNA *brna)
RNA_def_property_enum_bitflag_sdna(prop, NULL, "panel");
RNA_def_property_enum_items(prop, panel_items);
RNA_def_property_ui_text(prop, "Panel", "Select the property panel to be shown");
- RNA_def_property_update(prop, NC_LINESTYLE, NULL);
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "r");
@@ -1606,14 +1618,14 @@ static void rna_def_linestyle(BlenderRNA *brna)
/* nodes */
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
- RNA_def_property_ui_text(prop, "Node Tree", "Node tree for node based textures");
+ RNA_def_property_ui_text(prop, "Node Tree", "Node tree for node-based shaders");
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_ui_text(prop, "Use Nodes", "Use texture nodes for the line style");
- RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update");
+ RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes for the line style");
+ RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_use_nodes_update");
}
void RNA_def_linestyle(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c
index f163808c61b..65d81359045 100644
--- a/source/blender/makesrna/intern/rna_main.c
+++ b/source/blender/makesrna/intern/rna_main.c
@@ -281,6 +281,14 @@ static void rna_Main_linestyle_begin(CollectionPropertyIterator *iter, PointerRN
rna_iterator_listbase_begin(iter, &bmain->linestyle, NULL);
}
+static void rna_Main_version_get(PointerRNA *ptr, int *value)
+{
+ Main *bmain = (Main *)ptr->data;
+ value[0] = bmain->versionfile / 100;
+ value[1] = bmain->versionfile % 100;
+ value[2] = bmain->subversionfile;
+}
+
#ifdef UNIT_TEST
static PointerRNA rna_Test_test_get(PointerRNA *ptr)
@@ -376,6 +384,12 @@ void RNA_def_main(BlenderRNA *brna)
RNA_def_property_boolean_funcs(prop, "rna_Main_use_autopack_get", "rna_Main_use_autopack_set");
RNA_def_property_ui_text(prop, "Use Autopack", "Automatically pack all external data into .blend file");
+ prop = RNA_def_int_vector(srna, "version", 3, NULL, 0, INT_MAX,
+ "Version", "Version of the blender the .blend was saved with", 0, INT_MAX);
+ RNA_def_property_int_funcs(prop, "rna_Main_version_get", NULL, NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_THICK_WRAP);
+
for (i = 0; lists[i].name; i++) {
prop = RNA_def_property(srna, lists[i].identifier, PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, lists[i].type);
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index bac1f132126..b4c332be373 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -683,14 +683,14 @@ static void rna_Main_grease_pencil_remove(Main *bmain, ReportList *reports, Poin
gpd->id.name + 2, ID_REAL_USERS(gpd));
}
-FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, const char *name)
+static FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, const char *name)
{
- FreestyleLineStyle *linestyle = BKE_new_linestyle(name, bmain);
+ FreestyleLineStyle *linestyle = BKE_linestyle_new(name, bmain);
id_us_min(&linestyle->id);
return linestyle;
}
-void rna_Main_linestyles_remove(Main *bmain, ReportList *reports, FreestyleLineStyle *linestyle)
+static void rna_Main_linestyles_remove(Main *bmain, ReportList *reports, FreestyleLineStyle *linestyle)
{
if (ID_REAL_USERS(linestyle) <= 0)
BKE_libblock_free(bmain, linestyle);
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 7ae15b0b06c..37b6947cfac 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -82,6 +82,8 @@ EnumPropertyItem ramp_blend_items[] = {
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
@@ -92,6 +94,8 @@ EnumPropertyItem ramp_blend_items[] = {
#include "BKE_paint.h"
#include "ED_node.h"
+#include "ED_image.h"
+#include "BKE_scene.h"
static void rna_Material_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
@@ -165,6 +169,49 @@ static void rna_Material_mtex_begin(CollectionPropertyIterator *iter, PointerRNA
rna_iterator_array_begin(iter, (void *)ma->mtex, sizeof(MTex *), MAX_MTEX, 0, NULL);
}
+static void rna_Material_texpaint_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Material *ma = (Material *)ptr->data;
+ rna_iterator_array_begin(iter, (void *)ma->texpaintslot, sizeof(TexPaintSlot), ma->tot_slots, 0, NULL);
+}
+
+
+static void rna_Material_active_paint_texture_index_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ bScreen *sc;
+ Material *ma = ptr->id.data;
+
+ if (ma->use_nodes && ma->nodetree && BKE_scene_use_new_shading_nodes(scene)) {
+ struct bNode *node;
+ int index = 0;
+ for (node = ma->nodetree->nodes.first; node; node = node->next) {
+ if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) {
+ if (index++ == ma->paint_active_slot) {
+ break;
+ }
+ }
+ }
+ if (node)
+ nodeSetActive(ma->nodetree, node);
+ }
+
+ for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+ ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[ma->paint_active_slot].ima);
+ }
+ }
+ }
+ }
+
+ DAG_id_tag_update(&ma->id, 0);
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING, ma);
+}
+
static PointerRNA rna_Material_active_texture_get(PointerRNA *ptr)
{
Material *ma = (Material *)ptr->data;
@@ -307,7 +354,7 @@ static EnumPropertyItem *rna_Material_texture_coordinates_itemf(bContext *UNUSED
if (ma->material_type == MA_TYPE_VOLUME) {
}
- else if (ELEM3(ma->material_type, MA_TYPE_SURFACE, MA_TYPE_HALO, MA_TYPE_WIRE)) {
+ else if (ELEM(ma->material_type, MA_TYPE_SURFACE, MA_TYPE_HALO, MA_TYPE_WIRE)) {
RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_UV);
RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_STRAND);
RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_WINDOW);
@@ -2059,6 +2106,8 @@ void RNA_def_material(BlenderRNA *brna)
"rna_Material_active_texture_set", "rna_Material_active_texture_editable",
"MaterialTextureSlot", "MaterialTextureSlots", "rna_Material_update", "rna_Material_update");
+ rna_def_texpaint_slots(brna, srna);
+
/* only material has this one */
prop = RNA_def_property(srna, "use_textures", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "septex", 1);
@@ -2147,4 +2196,56 @@ void rna_def_mtex_common(BlenderRNA *brna, StructRNA *srna, const char *begin,
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, update_index);
}
+static void rna_def_tex_slot(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "TexPaintSlot", NULL);
+ RNA_def_struct_ui_text(srna, "Texture Paint Slot",
+ "Slot that contains information about texture painting");
+
+ prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_maxlength(prop, 64); /* else it uses the pointer size! */
+ RNA_def_property_string_sdna(prop, NULL, "uvname");
+ RNA_def_property_ui_text(prop, "UV Map", "Name of UV map");
+ RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Material_update");
+
+ prop = RNA_def_property(srna, "index", PROP_INT, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Index", "Index of MTex slot in the material");
+}
+
+
+void rna_def_texpaint_slots(BlenderRNA *brna, StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ rna_def_tex_slot(brna);
+
+ /* mtex */
+ prop = RNA_def_property(srna, "texture_paint_images", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "texpaintslot", NULL);
+ RNA_def_property_collection_funcs(prop, "rna_Material_texpaint_begin", "rna_iterator_array_next", "rna_iterator_array_end",
+ "rna_iterator_array_dereference_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "Image");
+ RNA_def_property_ui_text(prop, "Texture Slot Images", "Texture images used for texture painting");
+
+ prop = RNA_def_property(srna, "texture_paint_slots", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_funcs(prop, "rna_Material_texpaint_begin", "rna_iterator_array_next", "rna_iterator_array_end",
+ "rna_iterator_array_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "TexPaintSlot");
+ RNA_def_property_ui_text(prop, "Texture Slots", "Texture slots defining the mapping and influence of textures");
+
+ prop = RNA_def_property(srna, "paint_active_slot", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_range(prop, 0, SHRT_MAX);
+ RNA_def_property_ui_text(prop, "Active Paint Texture Index", "Index of active texture paint slot");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_Material_active_paint_texture_index_update");
+
+ prop = RNA_def_property(srna, "paint_clone_slot", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_range(prop, 0, SHRT_MAX);
+ RNA_def_property_ui_text(prop, "Clone Paint Texture Index", "Index of clone texture paint slot");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, NULL);
+}
+
#endif
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 8c0f9980108..b0b99dcd2ca 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -3121,11 +3121,13 @@ static void rna_def_mesh(BlenderRNA *brna)
"rna_Mesh_uv_texture_stencil_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Mask UV Map", "UV map to mask the painted area");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop = RNA_def_property(srna, "uv_texture_stencil_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_funcs(prop, "rna_Mesh_uv_texture_stencil_index_get",
"rna_Mesh_uv_texture_stencil_index_set", "rna_Mesh_uv_texture_index_range");
RNA_def_property_ui_text(prop, "Mask UV Map Index", "Mask UV map index");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
/* Tessellated face colors - used by renderers */
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index 212859cfea4..cc1f57d8a14 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -139,9 +139,11 @@ static void rna_Mesh_calc_smooth_groups(Mesh *mesh, int use_bitflags, int *r_pol
r_group_total, use_bitflags);
}
-static void rna_Mesh_transform(Mesh *mesh, float *mat)
+static void rna_Mesh_transform(Mesh *mesh, float *mat, int shape_keys)
{
- ED_mesh_transform(mesh, (float (*)[4])mat);
+ BKE_mesh_transform(mesh, (float (*)[4])mat, shape_keys);
+
+ DAG_id_tag_update(&mesh->id, 0);
}
#else
@@ -155,6 +157,7 @@ void RNA_api_mesh(StructRNA *srna)
RNA_def_function_ui_description(func, "Transform mesh vertices by a matrix");
parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "shape_keys", 0, "", "Transform Shape Keys");
func = RNA_def_function(srna, "calc_normals", "BKE_mesh_calc_normals");
RNA_def_function_ui_description(func, "Calculate vertex normals");
@@ -206,11 +209,17 @@ void RNA_api_mesh(StructRNA *srna)
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "validate", "BKE_mesh_validate");
- RNA_def_function_ui_description(func, "validate geometry, return True when the mesh has had "
+ RNA_def_function_ui_description(func, "Validate geometry, return True when the mesh has had "
"invalid geometry corrected/removed");
RNA_def_boolean(func, "verbose", 0, "Verbose", "Output information about the errors found");
parm = RNA_def_boolean(func, "result", 0, "Result", "");
RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "validate_material_indices", "BKE_mesh_validate_material_indices");
+ RNA_def_function_ui_description(func, "Validate material indices of polygons, return True when the mesh has had "
+ "invalid indices corrected (to default 0)");
+ parm = RNA_def_boolean(func, "result", 0, "Result", "");
+ RNA_def_function_return(func, parm);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_meta_api.c b/source/blender/makesrna/intern/rna_meta_api.c
index 7fe59bc5be6..43dca6fe4f1 100644
--- a/source/blender/makesrna/intern/rna_meta_api.c
+++ b/source/blender/makesrna/intern/rna_meta_api.c
@@ -38,14 +38,16 @@
#include "BLI_utildefines.h"
-#include "ED_mball.h"
+#include "BKE_mball.h"
#include "rna_internal.h" /* own include */
#ifdef RNA_RUNTIME
-void rna_Meta_transform(struct MetaBall *mb, float *mat)
+static void rna_Meta_transform(struct MetaBall *mb, float *mat)
{
- ED_mball_transform(mb, (float (*)[4])mat);
+ BKE_mball_transform(mb, (float (*)[4])mat);
+
+ DAG_id_tag_update(&mb->id, 0);
}
#else
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 7ffc138e1a3..4911c106f53 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -2239,6 +2239,13 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0.15f, 1.0f, 0.05, 2);
RNA_def_property_ui_text(prop, "Profile", "The profile shape (0.5 = round)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "material", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "mat");
+ RNA_def_property_range(prop, -1, SHRT_MAX);
+ RNA_def_property_ui_text(prop, "Material", "Material index of generated faces, -1 for automatic");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
}
static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
@@ -2601,6 +2608,11 @@ static void rna_def_modifier_solidify(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SOLIDIFY_FLIP);
RNA_def_property_ui_text(prop, "Flip Normals", "Invert the face direction");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "use_rim_only", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SOLIDIFY_NOSHELL);
+ RNA_def_property_ui_text(prop, "Only Rim", "Only add the rim to the original data");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_screw(BlenderRNA *brna)
@@ -3681,26 +3693,27 @@ void RNA_def_modifier(BlenderRNA *brna)
/* flags */
prop = RNA_def_property(srna, "show_viewport", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Realtime);
- RNA_def_property_ui_text(prop, "Realtime", "Display modifier in realtime");
+ RNA_def_property_ui_text(prop, "Realtime", "Display modifier in viewport");
RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 0);
prop = RNA_def_property(srna, "show_render", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Render);
- RNA_def_property_ui_text(prop, "Render", "Use modifier during rendering");
+ RNA_def_property_ui_text(prop, "Render", "Use modifier during render");
RNA_def_property_ui_icon(prop, ICON_SCENE, 0);
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
prop = RNA_def_property(srna, "show_in_editmode", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Editmode);
- RNA_def_property_ui_text(prop, "Edit Mode", "Use modifier while in the Edit mode");
+ RNA_def_property_ui_text(prop, "Edit Mode", "Display modifier in Edit mode");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
RNA_def_property_ui_icon(prop, ICON_EDITMODE_HLT, 0);
prop = RNA_def_property(srna, "show_on_cage", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_OnCage);
- RNA_def_property_ui_text(prop, "On Cage", "Enable direct editing of modifier control cage");
+ RNA_def_property_ui_text(prop, "On Cage", "Adjust edit cage to modifier result");
+ RNA_def_property_ui_icon(prop, ICON_MESH_DATA, 0);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 065b6f787b6..e90de3631d6 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -3172,6 +3172,12 @@ static void def_sh_output(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_sh_output_linestyle(StructRNA *srna)
+{
+ def_sh_output(srna);
+ def_mix_rgb(srna);
+}
+
static void def_sh_material(StructRNA *srna)
{
PropertyRNA *prop;
@@ -3762,6 +3768,16 @@ static void def_sh_uvmap(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "bNode", NULL);
}
+static void def_sh_uvalongstroke(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "use_tips", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1);
+ RNA_def_property_ui_text(prop, "Use Tips", "Lower half of the texture is for tips of the stroke");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
static void def_sh_normal_map(StructRNA *srna)
{
static EnumPropertyItem prop_space_items[] = {
@@ -6187,6 +6203,27 @@ static void def_cmp_planetrackdeform(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_cmp_sunbeams(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeSunBeams", "storage");
+
+ prop = RNA_def_property(srna, "source", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "source");
+ RNA_def_property_range(prop, -100.0f, 100.0f);
+ RNA_def_property_ui_range(prop, -10.0f, 10.0f, 10, 3);
+ RNA_def_property_ui_text(prop, "Source", "Source point of rays as a factor of the image width & height");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "ray_length", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_float_sdna(prop, NULL, "ray_length");
+ RNA_def_property_range(prop, 0.0f, 100.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 10, 3);
+ RNA_def_property_ui_text(prop, "Ray Length", "Length of rays as a factor of the image size");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
/* -- Texture Nodes --------------------------------------------------------- */
static void def_tex_output(StructRNA *srna)
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 5d10a0a61c1..699bfaa0f93 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -61,12 +61,12 @@
EnumPropertyItem object_mode_items[] = {
{OB_MODE_OBJECT, "OBJECT", ICON_OBJECT_DATAMODE, "Object Mode", ""},
{OB_MODE_EDIT, "EDIT", ICON_EDITMODE_HLT, "Edit Mode", ""},
+ {OB_MODE_POSE, "POSE", ICON_POSE_HLT, "Pose Mode", ""},
{OB_MODE_SCULPT, "SCULPT", ICON_SCULPTMODE_HLT, "Sculpt Mode", ""},
{OB_MODE_VERTEX_PAINT, "VERTEX_PAINT", ICON_VPAINT_HLT, "Vertex Paint", ""},
{OB_MODE_WEIGHT_PAINT, "WEIGHT_PAINT", ICON_WPAINT_HLT, "Weight Paint", ""},
{OB_MODE_TEXTURE_PAINT, "TEXTURE_PAINT", ICON_TPAINT_HLT, "Texture Paint", ""},
{OB_MODE_PARTICLE_EDIT, "PARTICLE_EDIT", ICON_PARTICLEMODE, "Particle Edit", ""},
- {OB_MODE_POSE, "POSE", ICON_POSE_HLT, "Pose Mode", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -370,8 +370,14 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value)
Object *ob = (Object *)ptr->data;
ID *id = value.data;
- if (id == NULL || ob->mode & OB_MODE_EDIT)
+ if (ob->mode & OB_MODE_EDIT) {
return;
+ }
+
+ /* assigning NULL only for empties */
+ if ((id == NULL) && (ob->type != OB_EMPTY)) {
+ return;
+ }
if (ob->type == OB_EMPTY) {
if (ob->data) {
@@ -379,7 +385,7 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value)
ob->data = NULL;
}
- if (id && GS(id->name) == ID_IM) {
+ if (!id || GS(id->name) == ID_IM) {
id_us_plus(id);
ob->data = id;
}
@@ -391,11 +397,10 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value)
if (ob->data) {
id_us_min((ID *)ob->data);
}
- if (id) {
- /* no need to type-check here ID. this is done in the _typef() function */
- BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
- id_us_plus(id);
- }
+
+ /* no need to type-check here ID. this is done in the _typef() function */
+ BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
+ id_us_plus(id);
ob->data = id;
test_object_materials(G.main, id);
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 0f37575146b..84eb94cfef4 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -598,9 +598,20 @@ static char *rna_FieldSettings_path(PointerRNA *ptr)
static void rna_EffectorWeight_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DAG_id_tag_update((ID *)ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
+ ID *id = ptr->id.data;
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ if (id && GS(id->name) == ID_SCE) {
+ Scene *scene = (Scene *)id;
+ Base *base;
+
+ for (base = scene->base.first; base; base = base->next) {
+ BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH);
+ }
+ }
+ else {
+ DAG_id_tag_update(id, OB_RECALC_DATA | PSYS_RECALC_RESET);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ }
}
static void rna_EffectorWeight_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
@@ -733,7 +744,7 @@ static EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C), PointerRN
return curve_shape_items;
}
- else if (ELEM3(ob->type, OB_MESH, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_MESH, OB_SURF, OB_FONT)) {
if (ob->pd->forcefield == PFIELD_VORTEX)
return vortex_shape_items;
diff --git a/source/blender/makesrna/intern/rna_packedfile.c b/source/blender/makesrna/intern/rna_packedfile.c
index d0c0ed25d22..34810e8a91b 100644
--- a/source/blender/makesrna/intern/rna_packedfile.c
+++ b/source/blender/makesrna/intern/rna_packedfile.c
@@ -45,14 +45,14 @@ EnumPropertyItem unpack_method_items[] = {
#ifdef RNA_RUNTIME
-void rna_PackedImage_data_get(PointerRNA *ptr, char *value)
+static void rna_PackedImage_data_get(PointerRNA *ptr, char *value)
{
PackedFile *pf = (PackedFile *)ptr->data;
memcpy(value, pf->data, (size_t)pf->size);
value[pf->size] = '\0';
}
-int rna_PackedImage_data_len(PointerRNA *ptr)
+static int rna_PackedImage_data_len(PointerRNA *ptr)
{
PackedFile *pf = (PackedFile *)ptr->data;
return pf->size; /* No need to include trailing NULL char here! */
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 674ea92fcbe..113311383f4 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -316,9 +316,9 @@ static void rna_Particle_uv_on_emitter(ParticleData *particle, ReportList *repor
static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *object,
int particle_no, int step, float n_co[3])
{
- ParticleSettings *part = 0;
- ParticleData *pars = 0;
- ParticleCacheKey *cache = 0;
+ ParticleSettings *part = NULL;
+ ParticleData *pars = NULL;
+ ParticleCacheKey *cache = NULL;
int totchild = 0;
int path_nbr = 0;
int totpart;
@@ -432,25 +432,24 @@ static EnumPropertyItem *rna_Particle_Material_itemf(bContext *C, PointerRNA *UN
return item;
}
-static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ReportList *reports,
- ParticleSystemModifierData *modifier, ParticleData *particle,
- int particle_no, int uv_no,
- float r_uv[2])
+/* return < 0 means invalid (no matching tessellated face could be found). */
+static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesystem,
+ ParticleSystemModifierData *modifier, ParticleData *particle,
+ int particle_no, float (**r_fuv)[4])
{
- ParticleSettings *part = 0;
+ ParticleSettings *part = NULL;
int totpart;
int totchild = 0;
- int num;
+ int totface;
+ int num = -1;
- if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPUV)) {
- BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
- return;
- }
DM_ensure_tessface(modifier->dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
+ totface = modifier->dm->getNumTessFaces(modifier->dm);
/* 1. check that everything is ok & updated */
- if (particlesystem == NULL)
- return;
+ if (!particlesystem || !totface) {
+ return num;
+ }
part = particlesystem->part;
@@ -468,52 +467,31 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Rep
totpart = particlesystem->totpart;
if (particle_no >= totpart + totchild)
- return;
+ return num;
-/* 3. start creating renderable things */
- /* setup per particle individual stuff */
+ /* 2. get matching face index. */
if (particle_no < totpart) {
-
- /* get uvco & mcol */
- num = (ELEM(particle->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND)) ?
- particle->num : particle->num_dmcache;
+ num = (ELEM(particle->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND)) ? particle->num : particle->num_dmcache;
if (num == DMCACHE_NOTFOUND)
- if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
- num = particle->num;
+ num = particle->num;
- if (r_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
- mtface += num;
-
- psys_interpolate_uvs(mtface, mface->v4, particle->fuv, r_uv);
- }
- else {
- r_uv[0] = 0.0f;
- r_uv[1] = 0.0f;
+ if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (num != DMCACHE_NOTFOUND && num < totface) {
+ *r_fuv = &particle->fuv;
+ return num;
}
}
}
else {
ChildParticle *cpa = particlesystem->child + particle_no - totpart;
-
num = cpa->num;
- /* get uvco & mcol */
if (part->childtype == PART_CHILD_FACES) {
- if (r_uv && ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (cpa->num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, cpa->num, CD_MFACE);
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
- mtface += cpa->num;
-
- psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, r_uv);
- }
- else {
- r_uv[0] = 0.0f;
- r_uv[1] = 0.0f;
+ if (ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (num != DMCACHE_NOTFOUND && num < totface) {
+ *r_fuv = &cpa->fuv;
+ return num;
}
}
}
@@ -522,137 +500,78 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Rep
num = parent->num_dmcache;
if (num == DMCACHE_NOTFOUND)
- if (parent->num < modifier->dm->getNumTessFaces(modifier->dm))
- num = parent->num;
-
- if (r_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
- mtface += num;
-
- psys_interpolate_uvs(mtface, mface->v4, parent->fuv, r_uv);
- }
- else {
- r_uv[0] = 0.0f;
- r_uv[1] = 0.0f;
+ num = parent->num;
+
+ if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (num != DMCACHE_NOTFOUND && num < totface) {
+ *r_fuv = &parent->fuv;
+ return num;
}
}
}
}
+
+ return -1;
}
-static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, ParticleSystemModifierData *modifier,
- ParticleData *particle, int particle_no, int vcol_no,
- float n_mcol[3])
+static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ReportList *reports,
+ ParticleSystemModifierData *modifier, ParticleData *particle,
+ int particle_no, int uv_no, float r_uv[2])
{
- ParticleSettings *part;
- int totpart;
- int totchild = 0;
- int num;
- MCol mcol = {255, 255, 255, 255};
-
- /* 1. check that everything is ok & updated */
- if (particlesystem == NULL)
+ if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPUV)) {
+ BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
+ zero_v2(r_uv);
return;
-
- part = particlesystem->part;
-
- if (particlesystem->renderdata) {
- totchild = particlesystem->totchild;
- }
- else {
- totchild = (int)((float)particlesystem->totchild * (float)(part->disp) / 100.0f);
}
- /* can happen for disconnected/global hair */
- if (part->type == PART_HAIR && !particlesystem->childcache)
- totchild = 0;
-
- totpart = particlesystem->totpart;
-
- if (particle_no >= totpart + totchild)
- return;
-
- /* 3. start creating renderable things */
- /* setup per particle individual stuff */
- if (particle_no < totpart) {
+ {
+ float (*fuv)[4];
+ /* Note all sanity checks are done in this helper func. */
+ const int num = rna_ParticleSystem_tessfaceidx_on_emitter(particlesystem, modifier, particle,
+ particle_no, &fuv);
- /* get uvco & mcol */
- num = particle->num_dmcache;
+ if (num < 0) {
+ /* No matching face found. */
+ zero_v2(r_uv);
+ }
+ else {
+ MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+ MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
- if (num == DMCACHE_NOTFOUND)
- if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
- num = particle->num;
-
- if (n_mcol && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
- MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
- mc += num * 4;
-
- psys_interpolate_mcol(mc, mface->v4, particle->fuv, &mcol);
- n_mcol[0] = (float)mcol.b / 255.0f;
- n_mcol[1] = (float)mcol.g / 255.0f;
- n_mcol[2] = (float)mcol.r / 255.0f;
- }
- else {
- n_mcol[0] = 0.0f;
- n_mcol[1] = 0.0f;
- n_mcol[2] = 0.0f;
- }
+ psys_interpolate_uvs(&mtface[num], mface->v4, *fuv, r_uv);
}
}
- else {
- ChildParticle *cpa = particlesystem->child + particle_no - totpart;
+}
- num = cpa->num;
+static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, ReportList *reports,
+ ParticleSystemModifierData *modifier, ParticleData *particle,
+ int particle_no, int vcol_no, float r_mcol[3])
+{
+ if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPCOL)) {
+ BKE_report(reports, RPT_ERROR, "Mesh has no VCol data");
+ zero_v3(r_mcol);
+ return;
+ }
- /* get uvco & mcol */
- if (part->childtype == PART_CHILD_FACES) {
- if (n_mcol && ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (cpa->num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, cpa->num, CD_MFACE);
- MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
- mc += cpa->num * 4;
-
- psys_interpolate_mcol(mc, mface->v4, cpa->fuv, &mcol);
- n_mcol[0] = (float)mcol.b / 255.0f;
- n_mcol[1] = (float)mcol.g / 255.0f;
- n_mcol[2] = (float)mcol.r / 255.0f;
- }
- else {
- n_mcol[0] = 0.0f;
- n_mcol[1] = 0.0f;
- n_mcol[2] = 0.0f;
- }
- }
+ {
+ float (*fuv)[4];
+ /* Note all sanity checks are done in this helper func. */
+ const int num = rna_ParticleSystem_tessfaceidx_on_emitter(particlesystem, modifier, particle,
+ particle_no, &fuv);
+
+ if (num < 0) {
+ /* No matching face found. */
+ zero_v3(r_mcol);
}
else {
- ParticleData *parent = particlesystem->particles + cpa->parent;
- num = parent->num_dmcache;
-
- if (num == DMCACHE_NOTFOUND)
- if (parent->num < modifier->dm->getNumTessFaces(modifier->dm))
- num = parent->num;
-
- if (n_mcol && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
- MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
- mc += num * 4;
-
- psys_interpolate_mcol(mc, mface->v4, parent->fuv, &mcol);
- n_mcol[0] = (float)mcol.b / 255.0f;
- n_mcol[1] = (float)mcol.g / 255.0f;
- n_mcol[2] = (float)mcol.r / 255.0f;
- }
- else {
- n_mcol[0] = 0.0f;
- n_mcol[1] = 0.0f;
- n_mcol[2] = 0.0f;
- }
- }
+ MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+ MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
+ MCol mcol;
+
+ psys_interpolate_mcol(&mc[num * 4], mface->v4, *fuv, &mcol);
+ r_mcol[0] = (float)mcol.b / 255.0f;
+ r_mcol[1] = (float)mcol.g / 255.0f;
+ r_mcol[2] = (float)mcol.r / 255.0f;
}
}
}
@@ -2142,7 +2061,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_dynamic_rotation", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_ROT_DYN);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Dynamic", "Particle rotations are effected by collisions and effectors");
+ RNA_def_property_ui_text(prop, "Dynamic", "Particle rotations are affected by collisions and effectors");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
prop = RNA_def_property(srna, "use_multiply_size_mass", PROP_BOOLEAN, PROP_NONE);
@@ -2194,7 +2113,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_self_effect", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_SELF_EFFECT);
- RNA_def_property_ui_text(prop, "Self Effect", "Particle effectors effect themselves");
+ RNA_def_property_ui_text(prop, "Self Effect", "Particle effectors affect themselves");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
@@ -2520,7 +2439,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "simplify_refsize", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "simplify_refsize");
- RNA_def_property_range(prop, 1, 32768);
+ RNA_def_property_range(prop, 1, SHRT_MAX);
RNA_def_property_ui_text(prop, "Reference Size", "Reference size in pixels, after which simplification begins");
prop = RNA_def_property(srna, "simplify_rate", PROP_FLOAT, PROP_NONE);
@@ -3496,6 +3415,7 @@ static void rna_def_particle_system(BlenderRNA *brna)
/* extract hair mcols */
func = RNA_def_function(srna, "mcol_on_emitter", "rna_ParticleSystem_mcol_on_emitter");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Obtain mcol for all particles");
prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 13349446168..682a7f4ee31 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -880,7 +880,7 @@ static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *UNU
}
else {
const int depth_ok = BKE_imtype_valid_depths(imf->imtype);
- const int is_float = ELEM3(imf->imtype, R_IMF_IMTYPE_RADHDR, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER);
+ const int is_float = ELEM(imf->imtype, R_IMF_IMTYPE_RADHDR, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER);
EnumPropertyItem *item_8bit = &image_color_depth_items[0];
EnumPropertyItem *item_10bit = &image_color_depth_items[1];
@@ -1316,7 +1316,7 @@ static void object_simplify_update(Object *ob)
ob->id.flag &= ~LIB_DOIT;
for (md = ob->modifiers.first; md; md = md->next) {
- if (ELEM3(md->type, eModifierType_Subsurf, eModifierType_Multires, eModifierType_ParticleSystem)) {
+ if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires, eModifierType_ParticleSystem)) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
@@ -2120,6 +2120,11 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Unified Weight",
"Instead of per-brush weight, the weight is shared across brushes");
+ prop = RNA_def_property(srna, "use_unified_color", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", UNIFIED_PAINT_COLOR);
+ RNA_def_property_ui_text(prop, "Use Unified Color",
+ "Instead of per-brush color, the color is shared across brushes");
+
/* unified paint settings that override the equivalent settings
* from the active brush */
prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
@@ -2152,6 +2157,18 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Weight", "Weight to assign in vertex groups");
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "rgb");
+ RNA_def_property_ui_text(prop, "Color", "");
+ RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
+
+ prop = RNA_def_property(srna, "secondary_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "secondary_rgb");
+ RNA_def_property_ui_text(prop, "Secondary Color", "");
+ RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
+
prop = RNA_def_property(srna, "use_pressure_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", UNIFIED_PAINT_BRUSH_SIZE_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
@@ -3245,7 +3262,7 @@ static void rna_def_bake_data(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "cage_extrusion", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, MAXFLOAT);
+ RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 3);
RNA_def_property_ui_text(prop, "Cage Extrusion",
"Distance to use for the inward ray cast when using selected to active");
@@ -5621,7 +5638,7 @@ void RNA_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION);
RNA_def_property_float_sdna(prop, NULL, "physics_settings.gravity");
RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, -200.0f, 200.0f);
+ RNA_def_property_ui_range(prop, -200.0f, 200.0f, 1, 2);
RNA_def_property_ui_text(prop, "Gravity", "Constant acceleration in a given direction");
RNA_def_property_update(prop, 0, "rna_Physics_update");
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index e0431fcff16..cf591dc7750 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -128,6 +128,13 @@ static EnumPropertyItem *rna_Area_type_itemf(bContext *UNUSED(C), PointerRNA *UN
return space_type_items + 1;
}
+static int rna_Area_type_get(PointerRNA *ptr)
+{
+ ScrArea *sa = (ScrArea *)ptr->data;
+ /* read from this instead of 'spacetype' for correct reporting: T41435 */
+ return sa->butspacetype;
+}
+
static void rna_Area_type_set(PointerRNA *ptr, int value)
{
ScrArea *sa = (ScrArea *)ptr->data;
@@ -232,7 +239,7 @@ static void rna_def_area(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "spacetype");
RNA_def_property_enum_items(prop, space_type_items);
RNA_def_property_enum_default(prop, SPACE_VIEW3D);
- RNA_def_property_enum_funcs(prop, NULL, "rna_Area_type_set", "rna_Area_type_itemf");
+ RNA_def_property_enum_funcs(prop, "rna_Area_type_get", "rna_Area_type_set", "rna_Area_type_itemf");
RNA_def_property_ui_text(prop, "Editor Type", "Current editor type for this area");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index a3a06893522..d48d8589f96 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -34,8 +34,13 @@
#include "DNA_ID.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "BKE_paint.h"
+#include "BKE_material.h"
+
+#include "ED_image.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -71,11 +76,14 @@ EnumPropertyItem symmetrize_direction_items[] = {
#include "MEM_guardedalloc.h"
#include "BKE_context.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_pointcache.h"
#include "BKE_particle.h"
#include "BKE_depsgraph.h"
#include "BKE_pbvh.h"
+#include "GPU_buffers.h"
+
#include "ED_particle.h"
static EnumPropertyItem particle_edit_disconnected_hair_brush_items[] = {
@@ -285,8 +293,100 @@ static void rna_Paint_brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
BKE_paint_invalidate_overlay_all();
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
}
+
+static void rna_ImaPaint_viewport_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+{
+ /* not the best solution maybe, but will refresh the 3D viewport */
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+}
+
+static void rna_ImaPaint_mode_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+{
+ Object *ob = OBACT;
+
+ /* of course we need to invalidate here */
+ BKE_texpaint_slots_refresh_object(scene, ob);
+
+ /* we assume that changing the current mode will invalidate the uv layers so we need to refresh display */
+ GPU_drawobject_free(ob->derivedFinal);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, &ob->id);
+}
+
+static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
+{
+ bScreen *sc;
+ Image *ima = scene->toolsettings->imapaint.canvas;
+
+ for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+ ED_space_image_set(sima, scene, scene->obedit, ima);
+ }
+ }
+ }
+ }
+
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+}
#else
+static void rna_def_palettecolor(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "PaletteColor", NULL);
+ RNA_def_struct_ui_text(srna, "Palette Color", "");
+
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "rgb");
+ RNA_def_property_ui_text(prop, "Color", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Value", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Weight", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+}
+
+
+static void rna_def_palette(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "Palette", "ID");
+ RNA_def_struct_ui_text(srna, "Palette", "");
+ RNA_def_struct_ui_icon(srna, ICON_COLOR);
+
+ prop = RNA_def_property(srna, "colors", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "PaletteColor");
+ RNA_def_property_ui_text(prop, "Palette Color", "Colors that are part of this palette");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+}
+
+static void rna_def_paint_curve(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "PaintCurve", "ID");
+ RNA_def_struct_ui_text(srna, "Paint Curve", "");
+ RNA_def_struct_ui_icon(srna, ICON_CURVE_BEZCURVE);
+}
+
+
static void rna_def_paint(BlenderRNA *brna)
{
StructRNA *srna;
@@ -302,6 +402,11 @@ static void rna_def_paint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Brush", "Active Brush");
RNA_def_property_update(prop, 0, "rna_Paint_brush_update");
+ prop = RNA_def_property(srna, "palette", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Palette", "Active Palette");
+
prop = RNA_def_property(srna, "show_brush", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", PAINT_SHOW_BRUSH);
RNA_def_property_ui_text(prop, "Show Brush", "");
@@ -507,6 +612,14 @@ static void rna_def_image_paint(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+
+ static EnumPropertyItem paint_type_items[] = {
+ {IMAGEPAINT_MODE_MATERIAL, "MATERIAL", 0,
+ "Material", "Detect image slots from the material"},
+ {IMAGEPAINT_MODE_IMAGE, "IMAGE", 0,
+ "Image", "Set image for texture painting directly"},
+ {0, NULL, 0, NULL, NULL}
+ };
srna = RNA_def_struct(brna, "ImagePaint", "Paint");
RNA_def_struct_sdna(srna, "ImagePaintSettings");
@@ -532,13 +645,36 @@ static void rna_def_image_paint(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_stencil_layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL);
RNA_def_property_ui_text(prop, "Stencil Layer", "Set the mask layer from the UV map buttons");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
prop = RNA_def_property(srna, "invert_stencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL_INV);
RNA_def_property_ui_text(prop, "Invert", "Invert the stencil layer");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
+
+ prop = RNA_def_property(srna, "stencil_image", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "stencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Stencil Image", "Image used as stencil");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
+
+ prop = RNA_def_property(srna, "canvas", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Canvas", "Image used as canvas");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_canvas_update");
+
+ prop = RNA_def_property(srna, "clone_image", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "clone");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Clone Image", "Image used as clone source");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ prop = RNA_def_property(srna, "stencil_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "stencil_col");
+ RNA_def_property_ui_text(prop, "Stencil Color", "Stencil color in the viewport");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
+
prop = RNA_def_property(srna, "use_clone_layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_CLONE);
RNA_def_property_ui_text(prop, "Clone Map",
@@ -558,6 +694,11 @@ static void rna_def_image_paint(BlenderRNA *brna)
prop = RNA_def_int_array(srna, "screen_grab_size", 2, NULL, 0, 0, "screen_grab_size",
"Size to capture the image for re-projecting", 0, 0);
RNA_def_property_range(prop, 512, 16384);
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, paint_type_items);
+ RNA_def_property_ui_text(prop, "Mode", "Mode of operation for projection painting");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_mode_update");
}
static void rna_def_particle_edit(BlenderRNA *brna)
@@ -741,6 +882,9 @@ void RNA_def_sculpt_paint(BlenderRNA *brna)
{
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);
+ rna_def_palettecolor(brna);
+ rna_def_palette(brna);
+ rna_def_paint_curve(brna);
rna_def_paint(brna);
rna_def_sculpt(brna);
rna_def_uv_sculpt(brna);
diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c
index aeef04f4ac7..3944b59dff7 100644
--- a/source/blender/makesrna/intern/rna_sensor.c
+++ b/source/blender/makesrna/intern/rna_sensor.c
@@ -405,6 +405,12 @@ static void rna_def_mouse_sensor(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static const EnumPropertyItem prop_mouse_type_items[] = {
+ {SENS_COLLISION_PROPERTY, "PROPERTY", ICON_LOGIC, "Property", "Use a material for ray intersections"},
+ {SENS_COLLISION_MATERIAL, "MATERIAL", ICON_MATERIAL_DATA, "Material", "Use a property for ray intersections"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "MouseSensor", "Sensor");
RNA_def_struct_ui_text(srna, "Mouse Sensor", "Sensor to detect mouse events");
RNA_def_struct_sdna_from(srna, "bMouseSensor", "data");
@@ -419,6 +425,27 @@ static void rna_def_mouse_sensor(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", SENS_MOUSE_FOCUS_PULSE);
RNA_def_property_ui_text(prop, "Pulse", "Moving the mouse over a different object generates a pulse");
RNA_def_property_update(prop, NC_LOGIC, NULL);
+
+ prop = RNA_def_property(srna, "use_material", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "mode");
+ RNA_def_property_enum_items(prop, prop_mouse_type_items);
+ RNA_def_property_ui_text(prop, "M/P", "Toggle collision on material or property");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
+ prop = RNA_def_property(srna, "property", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "propname");
+ RNA_def_property_ui_text(prop, "Property", "Only look for objects with this property (blank = all objects)");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "matname");
+ RNA_def_property_ui_text(prop, "Material", "Only look for objects with this material (blank = all objects)");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
+ prop = RNA_def_property(srna, "use_x_ray", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SENS_RAY_XRAY);
+ RNA_def_property_ui_text(prop, "X-Ray", "Toggle X-Ray option (see through objects that don't have the property)");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
}
static void rna_def_keyboard_sensor(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index ddae8b2a01a..00f0a6ff487 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -539,6 +539,8 @@ static StructRNA *rna_Sequence_refine(struct PointerRNA *ptr)
return &RNA_ColorSequence;
case SEQ_TYPE_SPEED:
return &RNA_SpeedControlSequence;
+ case SEQ_TYPE_GAUSSIAN_BLUR:
+ return &RNA_GaussianBlurSequence;
default:
return &RNA_Sequence;
}
@@ -1374,6 +1376,7 @@ static void rna_def_sequence(BlenderRNA *brna)
{SEQ_TYPE_SPEED, "SPEED", 0, "Speed", ""},
{SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
+ {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -2203,6 +2206,23 @@ static void rna_def_speed_control(StructRNA *srna)
RNA_def_property_boolean_sdna(prop, NULL, "flags", SEQ_SPEED_COMPRESS_IPO_Y);
RNA_def_property_ui_text(prop, "Scale to length", "Scale values from 0.0 to 1.0 to target sequence length");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+}
+
+static void rna_def_gaussian_blur(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "GaussianBlurVars", "effectdata");
+ prop = RNA_def_property(srna, "size_x", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_ui_text(prop, "Size X", "Size of the blur along X axis");
+ RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, -1);
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "size_y", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_ui_text(prop, "Size Y", "Size of the blur along Y axis");
+ RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, -1);
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
}
static EffectInfo def_effects[] = {
@@ -2227,6 +2247,8 @@ static EffectInfo def_effects[] = {
"Sequence strip applying affine transformations to other strips", rna_def_transform, 1},
{"WipeSequence", "Wipe Sequence", "Sequence strip creating a wipe transition",
rna_def_wipe, 1},
+ {"GaussianBlurSequence", "Gaussian Blur Sequence", "Sequence strip creating a gaussian blur",
+ rna_def_gaussian_blur, 1},
{"", "", "", NULL, 0}
};
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 30fcb63169b..70370f1ae36 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -468,6 +468,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
{SEQ_TYPE_SPEED, "SPEED", 0, "Speed", ""},
{SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
+ {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index 6e0d374e3e9..887670eb5ff 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -633,21 +633,21 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vel_multi");
- RNA_def_property_range(prop, -2.0, 2.0);
+ RNA_def_property_range(prop, -100.0, 100.0);
RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5);
RNA_def_property_ui_text(prop, "Source", "Multiplier of source velocity passed to smoke");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
prop = RNA_def_property(srna, "velocity_normal", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vel_normal");
- RNA_def_property_range(prop, -2.0, 2.0);
+ RNA_def_property_range(prop, -100.0, 100.0);
RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5);
RNA_def_property_ui_text(prop, "Normal", "Amount of normal directional velocity");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
prop = RNA_def_property(srna, "velocity_random", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vel_random");
- RNA_def_property_range(prop, 0.0, 2.0);
+ RNA_def_property_range(prop, 0.0, 10.0);
RNA_def_property_ui_range(prop, 0.0, 2.0, 0.05, 5);
RNA_def_property_ui_text(prop, "Random", "Amount of random velocity");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 39d6e665077..5ca38aae9bc 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -87,6 +87,18 @@ EnumPropertyItem space_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
+static EnumPropertyItem pivot_items_full[] = {
+ {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center",
+ "Pivot around bounding box center of selected object(s)"},
+ {V3D_CURSOR, "CURSOR", ICON_CURSOR, "3D Cursor", "Pivot around the 3D cursor"},
+ {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION,
+ "Individual Origins", "Pivot around each object's own origin"},
+ {V3D_CENTROID, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point",
+ "Pivot around the median point of selected objects"},
+ {V3D_ACTIVE, "ACTIVE_ELEMENT", ICON_ROTACTIVE, "Active Element", "Pivot around active object"},
+ {0, NULL, 0, NULL, NULL}
+};
+
static EnumPropertyItem draw_channels_items[] = {
{SI_USE_ALPHA, "COLOR_ALPHA", ICON_IMAGE_RGB_ALPHA, "Color and Alpha",
"Draw image with RGB colors and alpha transparency"},
@@ -454,12 +466,12 @@ static void rna_SpaceView3D_layer_update(Main *bmain, Scene *UNUSED(scene), Poin
DAG_on_visible_update(bmain, false);
}
-static void rna_SpaceView3D_viewport_shade_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_SpaceView3D_viewport_shade_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
View3D *v3d = (View3D *)(ptr->data);
ScrArea *sa = rna_area_from_space(ptr);
- ED_view3d_shade_update(bmain, v3d, sa);
+ ED_view3d_shade_update(bmain, scene, v3d, sa);
}
static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -616,9 +628,7 @@ static int rna_SpaceView3D_viewport_shade_get(PointerRNA *ptr)
View3D *v3d = (View3D *)ptr->data;
int drawtype = v3d->drawtype;
- if (drawtype == OB_MATERIAL && !BKE_scene_use_new_shading_nodes(scene))
- return OB_SOLID;
- else if (drawtype == OB_RENDER && !(type && type->view_draw))
+ if (drawtype == OB_RENDER && !(type && type->view_draw))
return OB_SOLID;
return drawtype;
@@ -637,9 +647,7 @@ static EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C
RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_WIRE);
RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_SOLID);
RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_TEXTURE);
-
- if (BKE_scene_use_new_shading_nodes(scene))
- RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_MATERIAL);
+ RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_MATERIAL);
if (type && type->view_draw)
RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_RENDER);
@@ -803,6 +811,24 @@ static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene
ED_space_image_release_buffer(sima, ibuf, lock);
}
+static EnumPropertyItem *rna_SpaceImageEditor_pivot_itemf(bContext *UNUSED(C), PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
+{
+ static EnumPropertyItem pivot_items[] = {
+ {V3D_CENTER, "CENTER", ICON_ROTATE, "Bounding Box Center", ""},
+ {V3D_CENTROID, "MEDIAN", ICON_ROTATECENTER, "Median Point", ""},
+ {V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ SpaceImage *sima = (SpaceImage *)ptr->data;
+
+ if (sima->mode == SI_MODE_PAINT)
+ return pivot_items_full;
+ else
+ return pivot_items;
+}
+
/* Space Text Editor */
static void rna_SpaceTextEditor_word_wrap_set(PointerRNA *ptr, int value)
@@ -1274,25 +1300,25 @@ static int rna_SpaceNodeEditor_path_length(PointerRNA *ptr)
return ED_node_tree_path_length(snode);
}
-void rna_SpaceNodeEditor_path_clear(SpaceNode *snode, bContext *C)
+static void rna_SpaceNodeEditor_path_clear(SpaceNode *snode, bContext *C)
{
ED_node_tree_start(snode, NULL, NULL, NULL);
ED_node_tree_update(C);
}
-void rna_SpaceNodeEditor_path_start(SpaceNode *snode, bContext *C, PointerRNA *node_tree)
+static void rna_SpaceNodeEditor_path_start(SpaceNode *snode, bContext *C, PointerRNA *node_tree)
{
ED_node_tree_start(snode, (bNodeTree *)node_tree->data, NULL, NULL);
ED_node_tree_update(C);
}
-void rna_SpaceNodeEditor_path_append(SpaceNode *snode, bContext *C, PointerRNA *node_tree, PointerRNA *node)
+static void rna_SpaceNodeEditor_path_append(SpaceNode *snode, bContext *C, PointerRNA *node_tree, PointerRNA *node)
{
ED_node_tree_push(snode, node_tree->data, node->data);
ED_node_tree_update(C);
}
-void rna_SpaceNodeEditor_path_pop(SpaceNode *snode, bContext *C)
+static void rna_SpaceNodeEditor_path_pop(SpaceNode *snode, bContext *C)
{
ED_node_tree_pop(snode);
ED_node_tree_update(C);
@@ -1492,6 +1518,11 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Other Objects", "Draw other selected objects that share the same image");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
+ prop = RNA_def_property(srna, "show_texpaint", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SI_NO_DRAW_TEXPAINT);
+ RNA_def_property_ui_text(prop, "Draw Texture Paint UVs", "Draw overlay of texture paint uv layer");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
+
prop = RNA_def_property(srna, "show_normalized_coords", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_COORDFLOATS);
RNA_def_property_ui_text(prop, "Normalized Coordinates",
@@ -1752,24 +1783,12 @@ static void rna_def_space_view3d(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- static EnumPropertyItem pivot_items[] = {
- {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center",
- "Pivot around bounding box center of selected object(s)"},
- {V3D_CURSOR, "CURSOR", ICON_CURSOR, "3D Cursor", "Pivot around the 3D cursor"},
- {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION,
- "Individual Origins", "Pivot around each object's own origin"},
- {V3D_CENTROID, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point",
- "Pivot around the median point of selected objects"},
- {V3D_ACTIVE, "ACTIVE_ELEMENT", ICON_ROTACTIVE, "Active Element", "Pivot around active object"},
- {0, NULL, 0, NULL, NULL}
- };
-
static EnumPropertyItem manipulators_items[] = {
- {V3D_MANIP_TRANSLATE, "TRANSLATE", ICON_MAN_TRANS, "Manipulator Translate",
+ {V3D_MANIP_TRANSLATE, "TRANSLATE", ICON_MAN_TRANS, "Translate",
"Use the manipulator for movement transformations"},
- {V3D_MANIP_ROTATE, "ROTATE", ICON_MAN_ROT, "Manipulator Rotate",
+ {V3D_MANIP_ROTATE, "ROTATE", ICON_MAN_ROT, "Rotate",
"Use the manipulator for rotation transformations"},
- {V3D_MANIP_SCALE, "SCALE", ICON_MAN_SCALE, "Manipulator Scale",
+ {V3D_MANIP_SCALE, "SCALE", ICON_MAN_SCALE, "Scale",
"Use the manipulator for scale transformations"},
{0, NULL, 0, NULL, NULL}
};
@@ -2042,7 +2061,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
prop = RNA_def_property(srna, "pivot_point", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "around");
- RNA_def_property_enum_items(prop, pivot_items);
+ RNA_def_property_enum_items(prop, pivot_items_full);
RNA_def_property_ui_text(prop, "Pivot Point", "Pivot center for rotation/scaling");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_pivot_update");
@@ -2310,13 +2329,6 @@ static void rna_def_space_image(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem pivot_items[] = {
- {V3D_CENTER, "CENTER", ICON_ROTATE, "Bounding Box Center", ""},
- {V3D_CENTROID, "MEDIAN", ICON_ROTATECENTER, "Median Point", ""},
- {V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
StructRNA *srna;
PropertyRNA *prop;
@@ -2404,7 +2416,8 @@ static void rna_def_space_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "pivot_point", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "around");
- RNA_def_property_enum_items(prop, pivot_items);
+ RNA_def_property_enum_items(prop, pivot_items_full);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_SpaceImageEditor_pivot_itemf");
RNA_def_property_ui_text(prop, "Pivot", "Rotation/Scaling Pivot");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
@@ -3398,13 +3411,18 @@ static void rna_def_space_node(BlenderRNA *brna)
{SNODE_TEX_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Edit texture nodes from Object"},
{SNODE_TEX_WORLD, "WORLD", ICON_WORLD_DATA, "World", "Edit texture nodes from World"},
{SNODE_TEX_BRUSH, "BRUSH", ICON_BRUSH_DATA, "Brush", "Edit texture nodes from Brush"},
+#ifdef WITH_FREESTYLE
{SNODE_TEX_LINESTYLE, "LINESTYLE", ICON_LINE_DATA, "Line Style", "Edit texture nodes from Line Style"},
+#endif
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem shader_type_items[] = {
{SNODE_SHADER_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Edit shader nodes from Object"},
{SNODE_SHADER_WORLD, "WORLD", ICON_WORLD_DATA, "World", "Edit shader nodes from World"},
+#ifdef WITH_FREESTYLE
+ {SNODE_SHADER_LINESTYLE, "LINESTYLE", ICON_LINE_DATA, "Line Style", "Edit shader nodes from Line Style"},
+#endif
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index 537ffe630a2..899da62d9d3 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -393,6 +393,7 @@ static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerR
nodeUpdateID(scene->nodetree, &clip->id);
WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+ WM_main_add_notifier(NC_SCENE, NULL);
DAG_id_tag_update(&clip->id, 0);
}
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index f14fadfa722..92c5530202b 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -210,7 +210,12 @@ static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *dat
identifier, (int)sizeof(dummypt.idname));
return NULL;
}
-
+
+ if ((dummypt.category[0] == '\0') && (dummypt.region_type == RGN_TYPE_TOOLS)) {
+ /* Use a fallback, otherwise an empty value will draw the panel in every category. */
+ strcpy(dummypt.category, PNL_CATEGORY_FALLBACK);
+ }
+
if (!(art = region_type_find(reports, dummypt.space_type, dummypt.region_type)))
return NULL;
@@ -987,7 +992,6 @@ static void rna_def_panel(BlenderRNA *brna)
prop = RNA_def_property(srna, "bl_category", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->category");
- RNA_def_property_string_default(prop, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index d3d17a90f99..b13bdedaffd 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -462,6 +462,13 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_float(func, "percentage", 0.0f, 0.0f, 1.0f, "Percentage", "Percentage of width to split at", 0.0f, 1.0f);
RNA_def_boolean(func, "align", false, "", "Align buttons to each other");
+ /* radial/pie layout */
+ func = RNA_def_function(srna, "menu_pie", "uiLayoutRadial");
+ parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
+ RNA_def_function_return(func, parm);
+ RNA_def_function_ui_description(func, "Sublayout. Items placed in this sublayout are placed "
+ "in a radial fashion around the menu center)");
+
/* Icon of a rna pointer */
func = RNA_def_function(srna, "icon", "rna_ui_get_rnaptr_icon");
parm = RNA_def_int(func, "icon_value", ICON_NONE, 0, INT_MAX, "", "Icon identifier", 0, INT_MAX);
@@ -740,6 +747,11 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_boolean(func, "lock_luminosity", false, "", "Keep the color at its original vector length");
RNA_def_boolean(func, "cubic", false, "", "Cubic saturation for picking values close to white");
+ func = RNA_def_function(srna, "template_palette", "uiTemplatePalette");
+ RNA_def_function_ui_description(func, "Item. A palette used to pick colors");
+ api_ui_item_rna_common(func);
+ RNA_def_boolean(func, "color", 0, "", "Display the colors as colors or values");
+
func = RNA_def_function(srna, "template_image_layers", "uiTemplateImageLayers");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(func, "image", "Image", "", "");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index f4974266f60..aa378955fb0 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -91,6 +91,7 @@ EnumPropertyItem navigation_mode_items[] = {
#include "BKE_idprop.h"
#include "GPU_draw.h"
+#include "GPU_select.h"
#include "BLF_api.h"
@@ -332,6 +333,11 @@ static void rna_UserDef_viewport_lights_update(Main *bmain, Scene *scene, Pointe
rna_userdef_update(bmain, scene, ptr);
}
+static int rna_Scene_GPU_selection_supported(UserDef *UNUSED(U))
+{
+ return GPU_select_query_check_support();
+}
+
static void rna_userdef_autosave_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
wmWindowManager *wm = bmain->wm.first;
@@ -947,6 +953,12 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_ui_text(prop, "Menu Backdrop Colors", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "wcol_pie_menu", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_ui_text(prop, "Pie Menu Colors", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
prop = RNA_def_property(srna, "wcol_tooltip", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_ui_text(prop, "Tooltip Colors", "");
@@ -1292,7 +1304,23 @@ static void rna_def_userdef_theme_spaces_face(StructRNA *srna)
RNA_def_property_update(prop, 0, "rna_userdef_update");
}
-static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs, bool incl_lastsel, bool incl_vector)
+static void rna_def_userdef_theme_spaces_paint_curves(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "paint_curve_handle", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Paint Curve Handle", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "paint_curve_pivot", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Paint Curve Pivot", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+}
+
+static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs, bool incl_lastsel,
+ bool incl_vector, bool incl_verthandle)
{
PropertyRNA *prop;
@@ -1377,8 +1405,8 @@ static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Align handle selected color", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- if (incl_nurbs == false) {
+
+ if (!incl_nurbs) {
/* assume that when nurbs are off, this is for 2D (i.e. anim) editors */
prop = RNA_def_property(srna, "handle_auto_clamped", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "handle_auto_clamped");
@@ -1400,6 +1428,23 @@ static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs
RNA_def_property_ui_text(prop, "Last selected point", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
}
+
+ if (incl_verthandle) {
+ prop = RNA_def_property(srna, "handle_vertex", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Handle Vertex", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "handle_vertex_select", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Handle Vertex Select", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "handle_vertex_size", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 0, 255);
+ RNA_def_property_ui_text(prop, "Handle Vertex Size", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+ }
}
static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
@@ -1488,7 +1533,7 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
rna_def_userdef_theme_spaces_vertex(srna);
rna_def_userdef_theme_spaces_edge(srna);
rna_def_userdef_theme_spaces_face(srna);
- rna_def_userdef_theme_spaces_curves(srna, true, true, true);
+ rna_def_userdef_theme_spaces_curves(srna, true, true, true, false);
prop = RNA_def_property(srna, "extra_edge_len", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
@@ -1525,6 +1570,12 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vertex Normal", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ prop = RNA_def_property(srna, "split_normal", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "loop_normal");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Split Normal", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
prop = RNA_def_property(srna, "bone_solid", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Bone Solid", "");
@@ -1567,6 +1618,8 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Skin Root", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ rna_def_userdef_theme_spaces_paint_curves(srna);
}
@@ -1632,22 +1685,7 @@ static void rna_def_userdef_theme_space_graph(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_userdef_update");
rna_def_userdef_theme_spaces_vertex(srna);
- rna_def_userdef_theme_spaces_curves(srna, false, true, true);
-
- prop = RNA_def_property(srna, "handle_vertex", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Handle Vertex", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- prop = RNA_def_property(srna, "handle_vertex_select", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Handle Vertex Select", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- prop = RNA_def_property(srna, "handle_vertex_size", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 0, 255);
- RNA_def_property_ui_text(prop, "Handle Vertex Size", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
+ rna_def_userdef_theme_spaces_curves(srna, false, true, true, true);
}
static void rna_def_userdef_theme_space_file(BlenderRNA *brna)
@@ -2258,7 +2296,9 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- rna_def_userdef_theme_spaces_curves(srna, false, false, false);
+ rna_def_userdef_theme_spaces_curves(srna, false, false, false, true);
+
+ rna_def_userdef_theme_spaces_paint_curves(srna);
}
static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
@@ -2745,21 +2785,6 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "handle_vertex", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Handle Vertex", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- prop = RNA_def_property(srna, "handle_vertex_select", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Handle Vertex Select", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- prop = RNA_def_property(srna, "handle_vertex_size", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 0, 255);
- RNA_def_property_ui_text(prop, "Handle Vertex Size", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
prop = RNA_def_property(srna, "strips", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "strip");
RNA_def_property_array(prop, 3);
@@ -2772,7 +2797,7 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Strips Selected", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- rna_def_userdef_theme_spaces_curves(srna, false, false, false);
+ rna_def_userdef_theme_spaces_curves(srna, false, false, false, true);
}
static void rna_def_userdef_themes(BlenderRNA *brna)
@@ -3141,7 +3166,7 @@ static void rna_def_userdef_view(BlenderRNA *brna)
/* display */
prop = RNA_def_property(srna, "show_tooltips", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_TOOLTIPS);
- RNA_def_property_ui_text(prop, "Tooltips", "Display tooltips");
+ RNA_def_property_ui_text(prop, "Tooltips", "Display tooltips (when off hold Alt to force display)");
prop = RNA_def_property(srna, "show_tooltips_python", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_TOOLTIPS_PYTHON);
@@ -3195,6 +3220,26 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Sub Level Menu Open Delay",
"Time delay in 1/10 seconds before automatically opening sub level menus");
+ /* pie menus */
+ prop = RNA_def_property(srna, "pie_initial_timeout", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 0, 1000);
+ RNA_def_property_ui_text(prop, "Recenter Timeout",
+ "Pie menus will use the initial mouse position as center for this amount of time "
+ "(in 1/100ths of sec)");
+
+ prop = RNA_def_property(srna, "pie_animation_timeout", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 0, 1000);
+ RNA_def_property_ui_text(prop, "Animation Timeout",
+ "Time needed to fully animate the pie to unfolded state (in 1/100ths of sec)");
+
+ prop = RNA_def_property(srna, "pie_menu_radius", PROP_INT, PROP_PIXEL);
+ RNA_def_property_range(prop, 0, 1000);
+ RNA_def_property_ui_text(prop, "Radius", "Pie menu size in pixels");
+
+ prop = RNA_def_property(srna, "pie_menu_threshold", PROP_INT, PROP_PIXEL);
+ RNA_def_property_range(prop, 0, 1000);
+ RNA_def_property_ui_text(prop, "Threshold", "Distance from center needed before a selection can be made");
+
prop = RNA_def_property(srna, "use_quit_dialog", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_QUIT_PROMPT);
RNA_def_property_ui_text(prop, "Prompt Quit",
@@ -3569,7 +3614,9 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
static void rna_def_userdef_system(BlenderRNA *brna)
{
+ FunctionRNA *func;
PropertyRNA *prop;
+ PropertyRNA *parm;
StructRNA *srna;
static EnumPropertyItem gl_texture_clamp_items[] = {
@@ -3689,6 +3736,13 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem gpu_select_method_items[] = {
+ {USER_SELECT_AUTO, "AUTO", 0, "Automatic", ""},
+ {USER_SELECT_USE_SELECT_RENDERMODE, "GL_SELECT", 0, "OpenGL Select", ""},
+ {USER_SELECT_USE_OCCLUSION_QUERY, "GL_QUERY", 0, "OpenGL Occlusion Queries", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "UserPreferencesSystem", NULL);
RNA_def_struct_sdna(srna, "UserDef");
RNA_def_struct_nested(brna, srna, "UserPreferences");
@@ -3931,12 +3985,24 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_boolean_negative_sdna(prop, NULL, "text_render", USER_TEXT_DISABLE_AA);
RNA_def_property_ui_text(prop, "Text Anti-aliasing", "Draw user interface text anti-aliased");
RNA_def_property_update(prop, 0, "rna_userdef_text_update");
-
+
+ func = RNA_def_function(srna, "is_occlusion_query_supported", "rna_Scene_GPU_selection_supported");
+ parm = RNA_def_boolean(func, "is_supported", 0, "Occlusion Query Support",
+ "Check if GPU supports Occlusion Queries");
+ RNA_def_function_return(func, parm);
+
+ prop = RNA_def_property(srna, "select_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "gpu_select_method");
+ RNA_def_property_enum_items(prop, gpu_select_method_items);
+ RNA_def_property_ui_text(prop, "Selection Method",
+ "Use OpenGL occlusion queries or selection render mode to accelerate selection");
+
/* Full scene anti-aliasing */
prop = RNA_def_property(srna, "multi_sample", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "ogl_multisamples");
RNA_def_property_enum_items(prop, multi_sample_levels);
- RNA_def_property_ui_text(prop, "MultiSample", "Enable OpenGL multi-sampling, only for systems that support it, requires restart");
+ RNA_def_property_ui_text(prop, "MultiSample",
+ "Enable OpenGL multi-sampling, only for systems that support it, requires restart");
prop = RNA_def_property(srna, "use_region_overlap", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_REGION_OVERLAP);
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 23b6d1e41ae..7513a687978 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -565,6 +565,24 @@ static int rna_Event_unicode_length(PointerRNA *ptr)
}
}
+static float rna_Event_pressure_get(PointerRNA *ptr)
+{
+ wmEvent *event = ptr->data;
+ return WM_event_tablet_data(event, NULL, NULL);
+}
+
+static int rna_Event_is_tablet_get(PointerRNA *ptr)
+{
+ wmEvent *event = ptr->data;
+ return WM_event_is_tablet(event);
+}
+
+static void rna_Event_tilt_get(PointerRNA *ptr, float *values)
+{
+ wmEvent *event = ptr->data;
+ WM_event_tablet_data(event, NULL, values);
+}
+
static PointerRNA rna_PopupMenu_layout_get(PointerRNA *ptr)
{
struct uiPopupMenu *pup = ptr->data;
@@ -576,6 +594,17 @@ static PointerRNA rna_PopupMenu_layout_get(PointerRNA *ptr)
return rptr;
}
+static PointerRNA rna_PieMenu_layout_get(PointerRNA *ptr)
+{
+ struct uiPieMenu *pie = ptr->data;
+ uiLayout *layout = uiPieMenuLayout(pie);
+
+ PointerRNA rptr;
+ RNA_pointer_create(ptr->id.data, &RNA_UILayout, layout, &rptr);
+
+ return rptr;
+}
+
static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value)
{
wmWindow *win = (wmWindow *)ptr->data;
@@ -587,7 +616,7 @@ static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value)
win->newscreen = value.data;
}
-int rna_Window_screen_assign_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
+static int rna_Window_screen_assign_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
bScreen *screen = (bScreen *)value.id.data;
@@ -1608,6 +1637,21 @@ static void rna_def_event(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Mouse Previous Y Position", "The window relative vertical location of the mouse");
+ prop = RNA_def_property(srna, "pressure", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_float_funcs(prop, "rna_Event_pressure_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Tablet Pressure", "The pressure of the tablet or 1.0 if no tablet present");
+
+ prop = RNA_def_property(srna, "tilt", PROP_FLOAT, PROP_XYZ_LENGTH);
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_float_funcs(prop, "rna_Event_tilt_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Tablet Tilt", "The pressure of the tablet or zeroes if no tablet present");
+
+ prop = RNA_def_property(srna, "is_tablet", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_boolean_funcs(prop, "rna_Event_is_tablet_get", NULL);
+ RNA_def_property_ui_text(prop, "Tablet Pressure", "The pressure of the tablet or 1.0 if no tablet present");
/* modifiers */
prop = RNA_def_property(srna, "shift", PROP_BOOLEAN, PROP_NONE);
@@ -1683,6 +1727,26 @@ static void rna_def_popupmenu(BlenderRNA *brna)
RNA_define_verify_sdna(1); /* not in sdna */
}
+static void rna_def_piemenu(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "UIPieMenu", NULL);
+ RNA_def_struct_ui_text(srna, "PieMenu", "");
+ RNA_def_struct_sdna(srna, "uiPieMenu");
+
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ /* could wrap more, for now this is enough */
+ prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "UILayout");
+ RNA_def_property_pointer_funcs(prop, "rna_PieMenu_layout_get",
+ NULL, NULL, NULL);
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+}
+
static void rna_def_window(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2045,6 +2109,7 @@ void RNA_def_wm(BlenderRNA *brna)
rna_def_event(brna);
rna_def_timer(brna);
rna_def_popupmenu(brna);
+ rna_def_piemenu(brna);
rna_def_window(brna);
rna_def_windowmanager(brna);
rna_def_keyconfig(brna);
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index 9b288903aa2..ad638f2187c 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -111,7 +111,7 @@ static void rna_event_timer_remove(struct wmWindowManager *wm, wmTimer *timer)
}
/* placeholder data for final implementation of a true progressbar */
-struct wmStaticProgress {
+static struct wmStaticProgress {
float min;
float max;
bool is_valid;
@@ -310,6 +310,24 @@ static void rna_PupMenuEnd(bContext *C, PointerRNA *handle)
uiPupMenuEnd(C, handle->data);
}
+/* pie menu wrapper */
+static PointerRNA rna_PieMenuBegin(bContext *C, const char *title, int icon, PointerRNA *event)
+{
+ PointerRNA r_ptr;
+ void *data;
+
+ data = (void *)uiPieMenuBegin(C, title, icon, event->data);
+
+ RNA_pointer_create(NULL, &RNA_UIPieMenu, data, &r_ptr);
+
+ return r_ptr;
+}
+
+static void rna_PieMenuEnd(bContext *C, PointerRNA *handle)
+{
+ uiPieMenuEnd(C, handle->data);
+}
+
#else
#define WM_GEN_INVOKE_EVENT (1 << 0)
@@ -461,6 +479,26 @@ void RNA_api_wm(StructRNA *srna)
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
parm = RNA_def_pointer(func, "menu", "UIPopupMenu", "", "");
RNA_def_property_flag(parm, PROP_RNAPTR | PROP_NEVER_NULL);
+
+ /* wrap uiPieMenuBegin */
+ func = RNA_def_function(srna, "piemenu_begin__internal", "rna_PieMenuBegin");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+ parm = RNA_def_string(func, "title", NULL, 0, "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_property(func, "icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(parm, icon_items);
+ parm = RNA_def_pointer(func, "event", "Event", "", "");
+ RNA_def_property_flag(parm, PROP_RNAPTR | PROP_NEVER_NULL);
+ /* return */
+ parm = RNA_def_pointer(func, "menu_pie", "UIPieMenu", "", "");
+ RNA_def_property_flag(parm, PROP_RNAPTR | PROP_NEVER_NULL);
+ RNA_def_function_return(func, parm);
+
+ /* wrap uiPieMenuEnd */
+ func = RNA_def_function(srna, "piemenu_end__internal", "rna_PieMenuEnd");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+ parm = RNA_def_pointer(func, "menu", "UIPieMenu", "", "");
+ RNA_def_property_flag(parm, PROP_RNAPTR | PROP_NEVER_NULL);
}
void RNA_api_operator(StructRNA *srna)
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 0a4a6140c02..2768d9412d7 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -22,7 +22,8 @@
* Ton Roosendaal,
* Ben Batt,
* Brecht Van Lommel,
- * Campbell Barton
+ * Campbell Barton,
+ * Patrice Bertrand
*
* ***** END GPL LICENSE BLOCK *****
*
@@ -30,16 +31,14 @@
/** \file blender/modifiers/intern/MOD_array.c
* \ingroup modifiers
+ *
+ * Array modifier: duplicates the object multiple times along an axis.
*/
-
-/* Array modifier: duplicates the object multiple times along an axis */
-
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
#include "DNA_curve_types.h"
#include "DNA_meshdata_types.h"
@@ -53,14 +52,8 @@
#include "MOD_util.h"
-#include "bmesh.h"
-
#include "depsgraph_private.h"
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
/* Due to cyclic dependencies it's possible that curve used for
* deformation here is not evaluated at the time of evaluating
* this modifier.
@@ -140,7 +133,7 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
-static float vertarray_size(MVert *mvert, int numVerts, int axis)
+static float vertarray_size(const MVert *mvert, int numVerts, int axis)
{
int i;
float min_co, max_co;
@@ -159,206 +152,303 @@ static float vertarray_size(MVert *mvert, int numVerts, int axis)
return max_co - min_co;
}
-static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op,
- const ArrayModifierData *amd,
- int *index_map_length)
+BLI_INLINE float sum_v3(const float v[3])
{
- BMOperator find_op;
- BMOIter oiter;
- BMVert *v, *v2;
- BMElem *ele;
- int *index_map, i;
-
- BMO_op_initf(bm, &find_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
- "find_doubles verts=%av dist=%f keep_verts=%s",
- amd->merge_dist, dupe_op, "geom");
-
- BMO_op_exec(bm, &find_op);
-
- i = 0;
- BMO_ITER (ele, &oiter, dupe_op->slots_in, "geom", BM_ALL) {
- BM_elem_index_set(ele, i); /* set_dirty */
- i++;
- }
-
- BMO_ITER (ele, &oiter, dupe_op->slots_out, "geom.out", BM_ALL) {
- BM_elem_index_set(ele, i); /* set_dirty */
- i++;
- }
- /* above loops over all, so set all to dirty, if this is somehow
- * setting valid values, this line can be removed - campbell */
- bm->elem_index_dirty |= BM_ALL;
+ return v[0] + v[1] + v[2];
+}
- (*index_map_length) = i;
- index_map = MEM_callocN(sizeof(int) * (*index_map_length), "index_map");
+/* Structure used for sorting vertices, when processing doubles */
+typedef struct SortVertsElem {
+ int vertex_num; /* The original index of the vertex, prior to sorting */
+ float co[3]; /* Its coordinates */
+ float sum_co; /* sum_v3(co), just so we don't do the sum many times. */
+} SortVertsElem;
- /*element type argument doesn't do anything here*/
- BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) {
- v2 = BMO_iter_map_value_ptr(&oiter);
- index_map[BM_elem_index_get(v)] = BM_elem_index_get(v2) + 1;
- }
+static int svert_sum_cmp(const void *e1, const void *e2)
+{
+ const SortVertsElem *sv1 = (SortVertsElem *)e1;
+ const SortVertsElem *sv2 = (SortVertsElem *)e2;
- BMO_op_finish(bm, &find_op);
+ if (sv1->sum_co > sv2->sum_co) return 1;
+ else if (sv1->sum_co < sv2->sum_co) return -1;
+ else return 0;
+}
- return index_map;
+static void svert_from_mvert(SortVertsElem *sv, const MVert *mv, const int i_begin, const int i_end)
+{
+ int i;
+ for (i = i_begin; i < i_end; i++, sv++, mv++) {
+ sv->vertex_num = i;
+ copy_v3_v3(sv->co, mv->co);
+ sv->sum_co = sum_v3(mv->co);
+ }
}
-/* Used for start/end cap.
- *
- * this function expects all existing vertices to be tagged,
- * so we can know new verts are not tagged.
- *
- * All verts will be tagged on exit.
+/**
+ * Take as inputs two sets of verts, to be processed for detection of doubles and mapping.
+ * Each set of verts is defined by its start within mverts array and its num_verts;
+ * It builds a mapping for all vertices within source, to vertices within target, or -1 if no double found
+ * The int doubles_map[num_verts_source] array must have been allocated by caller.
*/
-static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4],
- const ArrayModifierData *amd,
- BMOperator *dupe_op,
- BMOpSlot dupe_op_slot_args[BMO_OP_MAX_SLOTS], const char *dupe_slot_name,
- BMOperator *weld_op)
+static void dm_mvert_map_doubles(
+ int *doubles_map,
+ const MVert *mverts,
+ const int target_start,
+ const int target_num_verts,
+ const int source_start,
+ const int source_num_verts,
+ const float dist,
+ const bool with_follow)
{
- const bool is_input = (dupe_op->slots_in == dupe_op_slot_args);
- BMVert *v, *v2, *v3;
- BMIter iter;
+ const float dist3 = (M_SQRT3 + 0.00005f) * dist; /* Just above sqrt(3) */
+ int i_source, i_target, i_target_low_bound, target_end, source_end;
+ SortVertsElem *sorted_verts_target, *sorted_verts_source;
+ SortVertsElem *sve_source, *sve_target, *sve_target_low_bound;
+ bool target_scan_completed;
+
+ target_end = target_start + target_num_verts;
+ source_end = source_start + source_num_verts;
+
+ /* build array of MVerts to be tested for merging */
+ sorted_verts_target = MEM_mallocN(sizeof(SortVertsElem) * target_num_verts, __func__);
+ sorted_verts_source = MEM_mallocN(sizeof(SortVertsElem) * source_num_verts, __func__);
+
+ /* Copy target vertices index and cos into SortVertsElem array */
+ svert_from_mvert(sorted_verts_target, mverts + target_start, target_start, target_end);
+
+ /* Copy source vertices index and cos into SortVertsElem array */
+ svert_from_mvert(sorted_verts_source, mverts + source_start, source_start, source_end);
+
+ /* sort arrays according to sum of vertex coordinates (sumco) */
+ qsort(sorted_verts_target, target_num_verts, sizeof(SortVertsElem), svert_sum_cmp);
+ qsort(sorted_verts_source, source_num_verts, sizeof(SortVertsElem), svert_sum_cmp);
+
+ sve_target_low_bound = sorted_verts_target;
+ i_target_low_bound = 0;
+ target_scan_completed = false;
+
+ /* Scan source vertices, in SortVertsElem sorted array, */
+ /* all the while maintaining the lower bound of possible doubles in target vertices */
+ for (i_source = 0, sve_source = sorted_verts_source;
+ i_source < source_num_verts;
+ i_source++, sve_source++)
+ {
+ bool double_found;
+ float sve_source_sumco;
- /* Add the DerivedMesh's elements to the BMesh. The pre-existing
- * elements were already tagged, so the new elements can be
- * identified by not having the BM_ELEM_TAG flag set. */
- DM_to_bmesh_ex(dm, bm, false);
+ /* If source has already been assigned to a target (in an earlier call, with other chunks) */
+ if (doubles_map[sve_source->vertex_num] != -1) {
+ continue;
+ }
- if (amd->flags & MOD_ARR_MERGE) {
- /* if merging is enabled, find doubles */
-
- BMOIter oiter;
- BMOperator find_op;
- BMOpSlot *slot_targetmap;
-
- BMO_op_initf(bm, &find_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
- is_input ? /* ugh */
- "find_doubles verts=%Hv dist=%f keep_verts=%s" :
- "find_doubles verts=%Hv dist=%f keep_verts=%S",
- BM_ELEM_TAG, amd->merge_dist,
- dupe_op, dupe_slot_name);
-
- /* append the dupe's geom to the findop input verts */
- if (is_input) {
- BMO_slot_buffer_append(&find_op, slots_in, "verts",
- dupe_op, slots_in, dupe_slot_name);
+ /* If target fully scanned already, then all remaining source vertices cannot have a double */
+ if (target_scan_completed) {
+ doubles_map[sve_source->vertex_num] = -1;
+ continue;
}
- else if (dupe_op->slots_out == dupe_op_slot_args) {
- BMO_slot_buffer_append(&find_op, slots_in, "verts",
- dupe_op, slots_out, dupe_slot_name);
+
+ sve_source_sumco = sum_v3(sve_source->co);
+
+ /* Skip all target vertices that are more than dist3 lower in terms of sumco */
+ /* and advance the overall lower bound, applicable to all remaining vertices as well. */
+ while ((i_target_low_bound < target_num_verts) &&
+ (sve_target_low_bound->sum_co < sve_source_sumco - dist3))
+ {
+ i_target_low_bound++;
+ sve_target_low_bound++;
}
- else {
- BLI_assert(0);
+ /* If end of target list reached, then no more possible doubles */
+ if (i_target_low_bound >= target_num_verts) {
+ doubles_map[sve_source->vertex_num] = -1;
+ target_scan_completed = true;
+ continue;
}
-
- /* transform and tag verts */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(v, BM_ELEM_TAG)) {
- mul_m4_v3(mat, v->co);
- BM_elem_flag_enable(v, BM_ELEM_TAG);
+ /* Test target candidates starting at the low bound of possible doubles, ordered in terms of sumco */
+ i_target = i_target_low_bound;
+ sve_target = sve_target_low_bound;
+
+ /* i_target will scan vertices in the [v_source_sumco - dist3; v_source_sumco + dist3] range */
+
+ double_found = false;
+ while ((i_target < target_num_verts) &&
+ (sve_target->sum_co <= sve_source_sumco + dist3))
+ {
+ /* Testing distance for candidate double in target */
+ /* v_target is within dist3 of v_source in terms of sumco; check real distance */
+ if (compare_len_v3v3(sve_source->co, sve_target->co, dist)) {
+ /* Double found */
+ /* If double target is itself already mapped to other vertex,
+ * behavior depends on with_follow option */
+ int target_vertex = sve_target->vertex_num;
+ if (doubles_map[target_vertex] != -1) {
+ if (with_follow) { /* with_follow option: map to initial target */
+ target_vertex = doubles_map[target_vertex];
+ }
+ else {
+ /* not with_follow: if target is mapped, then we do not map source, and stop searching */
+ break;
+ }
+ }
+ doubles_map[sve_source->vertex_num] = target_vertex;
+ double_found = true;
+ break;
}
+ i_target++;
+ sve_target++;
+ }
+ /* End of candidate scan: if none found then no doubles */
+ if (!double_found) {
+ doubles_map[sve_source->vertex_num] = -1;
}
+ }
- BMO_op_exec(bm, &find_op);
+ MEM_freeN(sorted_verts_source);
+ MEM_freeN(sorted_verts_target);
+}
- slot_targetmap = BMO_slot_get(weld_op->slots_in, "targetmap");
- /* add new merge targets to weld operator */
- BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) {
- v2 = BMO_iter_map_value_ptr(&oiter);
- /* check in case the target vertex (v2) is already marked
- * for merging */
- while ((v3 = BMO_slot_map_elem_get(slot_targetmap, v2))) {
- v2 = v3;
- }
- BMO_slot_map_elem_insert(weld_op, slot_targetmap, v, v2);
- }
+static void dm_merge_transform(
+ DerivedMesh *result, DerivedMesh *cap_dm, float cap_offset[4][4],
+ unsigned int cap_verts_index, unsigned int cap_edges_index, int cap_loops_index, int cap_polys_index,
+ int cap_nverts, int cap_nedges, int cap_nloops, int cap_npolys)
+{
+ int *index_orig;
+ int i;
+ MVert *mv;
+ MEdge *me;
+ MLoop *ml;
+ MPoly *mp;
+
+ /* needed for subsurf so arrays are allocated */
+ cap_dm->getVertArray(cap_dm);
+ cap_dm->getEdgeArray(cap_dm);
+ cap_dm->getNumLoops(cap_dm);
+ cap_dm->getNumPolys(cap_dm);
+
+ DM_copy_vert_data(cap_dm, result, 0, cap_verts_index, cap_nverts);
+ DM_copy_edge_data(cap_dm, result, 0, cap_edges_index, cap_nedges);
+ DM_copy_loop_data(cap_dm, result, 0, cap_loops_index, cap_nloops);
+ DM_copy_poly_data(cap_dm, result, 0, cap_polys_index, cap_npolys);
+
+ mv = CDDM_get_verts(result) + cap_verts_index;
+
+ for (i = 0; i < cap_nverts; i++, mv++) {
+ mul_m4_v3(cap_offset, mv->co);
+ /* Reset MVert flags for caps */
+ mv->flag = mv->bweight = 0;
+ }
- BMO_op_finish(bm, &find_op);
+ /* adjust cap edge vertex indices */
+ me = CDDM_get_edges(result) + cap_edges_index;
+ for (i = 0; i < cap_nedges; i++, me++) {
+ me->v1 += cap_verts_index;
+ me->v2 += cap_verts_index;
}
- else {
- /* transform and tag verts */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(v, BM_ELEM_TAG)) {
- mul_m4_v3(mat, v->co);
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- }
- }
+
+ /* adjust cap poly loopstart indices */
+ mp = CDDM_get_polys(result) + cap_polys_index;
+ for (i = 0; i < cap_npolys; i++, mp++) {
+ mp->loopstart += cap_loops_index;
}
-}
-static void merge_first_last(BMesh *bm,
- const ArrayModifierData *amd,
- BMOperator *dupe_first,
- BMOperator *dupe_last,
- BMOperator *weld_op)
-{
- BMOperator find_op;
- BMOIter oiter;
- BMVert *v, *v2;
- BMOpSlot *slot_targetmap;
-
- BMO_op_initf(bm, &find_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
- "find_doubles verts=%s dist=%f keep_verts=%s",
- dupe_first, "geom", amd->merge_dist,
- dupe_first, "geom");
-
- /* append the last dupe's geom to the findop input verts */
- BMO_slot_buffer_append(&find_op, slots_in, "verts",
- dupe_last, slots_out, "geom.out");
-
- BMO_op_exec(bm, &find_op);
-
- /* add new merge targets to weld operator */
- slot_targetmap = BMO_slot_get(weld_op->slots_in, "targetmap");
- BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) {
- if (!BMO_slot_map_contains(slot_targetmap, v)) {
- v2 = BMO_iter_map_value_ptr(&oiter);
- BMO_slot_map_elem_insert(weld_op, slot_targetmap, v, v2);
- }
+ /* adjust cap loop vertex and edge indices */
+ ml = CDDM_get_loops(result) + cap_loops_index;
+ for (i = 0; i < cap_nloops; i++, ml++) {
+ ml->v += cap_verts_index;
+ ml->e += cap_edges_index;
}
- BMO_op_finish(bm, &find_op);
+ /* set origindex */
+ index_orig = result->getVertDataArray(result, CD_ORIGINDEX);
+ if (index_orig) {
+ fill_vn_i(index_orig + cap_verts_index, cap_nverts, ORIGINDEX_NONE);
+ }
+
+ index_orig = result->getEdgeDataArray(result, CD_ORIGINDEX);
+ if (index_orig) {
+ fill_vn_i(index_orig + cap_edges_index, cap_nedges, ORIGINDEX_NONE);
+ }
+
+ index_orig = result->getPolyDataArray(result, CD_ORIGINDEX);
+ if (index_orig) {
+ fill_vn_i(index_orig + cap_polys_index, cap_npolys, ORIGINDEX_NONE);
+ }
+
+ index_orig = result->getLoopDataArray(result, CD_ORIGINDEX);
+ if (index_orig) {
+ fill_vn_i(index_orig + cap_loops_index, cap_nloops, ORIGINDEX_NONE);
+ }
}
-static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
- Scene *scene, Object *ob, DerivedMesh *dm,
- ModifierApplyFlag flag)
+static DerivedMesh *arrayModifier_doArray(
+ ArrayModifierData *amd,
+ Scene *scene, Object *ob, DerivedMesh *dm,
+ ModifierApplyFlag flag)
{
- DerivedMesh *result;
- BMesh *bm = DM_to_bmesh(dm, false);
- BMOperator first_dupe_op, dupe_op, old_dupe_op, weld_op;
- BMVert **first_geom = NULL;
- int i, j;
- int index_len = -1; /* initialize to an invalid value */
+ const float eps = 1e-6f;
+ const MVert *src_mvert;
+ MVert *mv, *mv_prev, *result_dm_verts;
+
+ MEdge *me;
+ MLoop *ml;
+ MPoly *mp;
+ int i, j, c, count;
+ float length = amd->length;
/* offset matrix */
float offset[4][4];
+ float scale[3];
+ bool offset_has_scale;
+ float current_offset[4][4];
float final_offset[4][4];
- float length = amd->length;
- int count = amd->count, maxVerts;
- int *indexMap = NULL;
- DerivedMesh *start_cap = NULL, *end_cap = NULL;
- MVert *src_mvert;
- BMOpSlot *slot_targetmap = NULL; /* for weld_op */
-
- /* need to avoid infinite recursion here */
- if (amd->start_cap && amd->start_cap != ob && amd->start_cap->type == OB_MESH)
- start_cap = get_dm_for_modifier(amd->start_cap, flag);
- if (amd->end_cap && amd->end_cap != ob && amd->end_cap->type == OB_MESH)
- end_cap = get_dm_for_modifier(amd->end_cap, flag);
+ int *full_doubles_map = NULL;
+ int tot_doubles;
+
+ int start_cap_nverts = 0, start_cap_nedges = 0, start_cap_npolys = 0, start_cap_nloops = 0;
+ int end_cap_nverts = 0, end_cap_nedges = 0, end_cap_npolys = 0, end_cap_nloops = 0;
+ int result_nverts = 0, result_nedges = 0, result_npolys = 0, result_nloops = 0;
+ int chunk_nverts, chunk_nedges, chunk_nloops, chunk_npolys;
+ int first_chunk_start, first_chunk_nverts, last_chunk_start, last_chunk_nverts;
+
+ DerivedMesh *result, *start_cap_dm = NULL, *end_cap_dm = NULL;
+
+ chunk_nverts = dm->getNumVerts(dm);
+ chunk_nedges = dm->getNumEdges(dm);
+ chunk_nloops = dm->getNumLoops(dm);
+ chunk_npolys = dm->getNumPolys(dm);
+
+ count = amd->count;
+
+ if (amd->start_cap && amd->start_cap != ob && amd->start_cap->type == OB_MESH) {
+ start_cap_dm = get_dm_for_modifier(amd->start_cap, flag);
+ if (start_cap_dm) {
+ start_cap_nverts = start_cap_dm->getNumVerts(start_cap_dm);
+ start_cap_nedges = start_cap_dm->getNumEdges(start_cap_dm);
+ start_cap_nloops = start_cap_dm->getNumLoops(start_cap_dm);
+ start_cap_npolys = start_cap_dm->getNumPolys(start_cap_dm);
+ }
+ }
+ if (amd->end_cap && amd->end_cap != ob && amd->end_cap->type == OB_MESH) {
+ end_cap_dm = get_dm_for_modifier(amd->end_cap, flag);
+ if (end_cap_dm) {
+ end_cap_nverts = end_cap_dm->getNumVerts(end_cap_dm);
+ end_cap_nedges = end_cap_dm->getNumEdges(end_cap_dm);
+ end_cap_nloops = end_cap_dm->getNumLoops(end_cap_dm);
+ end_cap_npolys = end_cap_dm->getNumPolys(end_cap_dm);
+ }
+ }
- unit_m4(offset);
+ /* Build up offset array, cumulating all settings options */
+ unit_m4(offset);
src_mvert = dm->getVertArray(dm);
- maxVerts = dm->getNumVerts(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_RELATIVE) {
for (j = 0; j < 3; j++)
- offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, maxVerts, j);
+ offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, chunk_nverts, j);
}
if ((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) {
@@ -370,12 +460,15 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
else
unit_m4(obinv);
- mul_serie_m4(result_mat, offset,
- obinv, amd->offset_ob->obmat,
- NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(result_mat, offset,
+ obinv, amd->offset_ob->obmat);
copy_m4_m4(offset, result_mat);
}
+ /* Check if there is some scaling. If scaling, then we will not translate mapping */
+ mat4_to_size(scale, offset);
+ offset_has_scale = !is_one_v3(scale);
+
if (amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
Curve *cu = amd->curve_ob->data;
if (cu) {
@@ -397,195 +490,236 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
if (amd->fit_type == MOD_ARR_FITLENGTH || amd->fit_type == MOD_ARR_FITCURVE) {
float dist = len_v3(offset[3]);
- if (dist > 1e-6f)
+ if (dist > eps) {
/* this gives length = first copy start to last copy end
* add a tiny offset for floating point rounding errors */
- count = (length + 1e-6f) / dist;
- else
+ count = (length + eps) / dist;
+ }
+ else {
/* if the offset has no translation, just make one copy */
count = 1;
+ }
}
if (count < 1)
count = 1;
- /* calculate the offset matrix of the final copy (for merging) */
- unit_m4(final_offset);
+ /* The number of verts, edges, loops, polys, before eventually merging doubles */
+ result_nverts = chunk_nverts * count + start_cap_nverts + end_cap_nverts;
+ result_nedges = chunk_nedges * count + start_cap_nedges + end_cap_nedges;
+ result_nloops = chunk_nloops * count + start_cap_nloops + end_cap_nloops;
+ result_npolys = chunk_npolys * count + start_cap_npolys + end_cap_npolys;
+
+ /* Initialize a result dm */
+ result = CDDM_from_template(dm, result_nverts, result_nedges, 0, result_nloops, result_npolys);
+ result_dm_verts = CDDM_get_verts(result);
- for (j = 0; j < count - 1; j++) {
- float tmp_mat[4][4];
- mul_m4_m4m4(tmp_mat, offset, final_offset);
- copy_m4_m4(final_offset, tmp_mat);
+ if (amd->flags & MOD_ARR_MERGE) {
+ /* Will need full_doubles_map for handling merge */
+ full_doubles_map = MEM_mallocN(sizeof(int) * result_nverts, "mod array doubles map");
+ fill_vn_i(full_doubles_map, result_nverts, -1);
}
- /* BMESH_TODO: bumping up the stack level avoids computing the normals
- * after every top-level operator execution (and this modifier has the
- * potential to execute a *lot* of top-level BMOps. There should be a
- * cleaner way to do this. One possibility: a "mirror" BMOp would
- * certainly help by compressing it all into one top-level BMOp that
- * executes a lot of second-level BMOps. */
- BM_mesh_elem_toolflags_ensure(bm);
- BMO_push(bm, NULL);
- bmesh_edit_begin(bm, 0);
+ /* copy customdata to original geometry */
+ DM_copy_vert_data(dm, result, 0, 0, chunk_nverts);
+ DM_copy_edge_data(dm, result, 0, 0, chunk_nedges);
+ DM_copy_loop_data(dm, result, 0, 0, chunk_nloops);
+ DM_copy_poly_data(dm, result, 0, 0, chunk_npolys);
- if (amd->flags & MOD_ARR_MERGE) {
- BMO_op_init(bm, &weld_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
- "weld_verts");
+ /* subsurf for eg wont have mesh data in the
+ * now add mvert/medge/mface layers */
- slot_targetmap = BMO_slot_get(weld_op.slots_in, "targetmap");
+ if (!CustomData_has_layer(&dm->vertData, CD_MVERT)) {
+ dm->copyVertArray(dm, result_dm_verts);
+ }
+ if (!CustomData_has_layer(&dm->edgeData, CD_MEDGE)) {
+ dm->copyEdgeArray(dm, CDDM_get_edges(result));
+ }
+ if (!CustomData_has_layer(&dm->polyData, CD_MPOLY)) {
+ dm->copyLoopArray(dm, CDDM_get_loops(result));
+ dm->copyPolyArray(dm, CDDM_get_polys(result));
}
- BMO_op_initf(bm, &dupe_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
- "duplicate geom=%avef");
- first_dupe_op = dupe_op;
-
- for (j = 0; j < count - 1; j++) {
- BMVert *v, *v2, *v3;
- BMOpSlot *geom_slot;
- BMOpSlot *geom_out_slot;
- BMOIter oiter;
+ /* Remember first chunk, in case of cap merge */
+ first_chunk_start = 0;
+ first_chunk_nverts = chunk_nverts;
- if (j != 0) {
- BMO_op_initf(bm, &dupe_op,
- (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
- "duplicate geom=%S", &old_dupe_op, "geom.out");
- }
- BMO_op_exec(bm, &dupe_op);
-
- geom_slot = BMO_slot_get(dupe_op.slots_in, "geom");
- geom_out_slot = BMO_slot_get(dupe_op.slots_out, "geom.out");
-
- if ((amd->flags & MOD_ARR_MERGEFINAL) && j == 0) {
- int first_geom_bytes = sizeof(BMVert *) * geom_slot->len;
-
- /* make a copy of the initial geometry ordering so the
- * last duplicate can be merged into it */
- first_geom = MEM_mallocN(first_geom_bytes, "first_geom");
- memcpy(first_geom, geom_slot->data.buf, first_geom_bytes);
- }
+ unit_m4(current_offset);
+ for (c = 1; c < count; c++) {
+ /* copy customdata to new geometry */
+ DM_copy_vert_data(result, result, 0, c * chunk_nverts, chunk_nverts);
+ DM_copy_edge_data(result, result, 0, c * chunk_nedges, chunk_nedges);
+ DM_copy_loop_data(result, result, 0, c * chunk_nloops, chunk_nloops);
+ DM_copy_poly_data(result, result, 0, c * chunk_npolys, chunk_npolys);
- /* apply transformation matrix */
- BMO_ITER (v, &oiter, dupe_op.slots_out, "geom.out", BM_VERT) {
- mul_m4_v3(offset, v->co);
- }
+ mv_prev = result_dm_verts;
+ mv = mv_prev + c * chunk_nverts;
- if (amd->flags & MOD_ARR_MERGE) {
- /*calculate merge mapping*/
- if (j == 0) {
- indexMap = find_doubles_index_map(bm, &dupe_op,
- amd, &index_len);
- }
+ /* recalculate cumulative offset here */
+ mul_m4_m4m4(current_offset, current_offset, offset);
-#define _E(s, i) ((BMVert **)(s)->data.buf)[i]
+ /* apply offset to all new verts */
+ for (i = 0; i < chunk_nverts; i++, mv++, mv_prev++) {
+ mul_m4_v3(current_offset, mv->co);
+ }
- /* ensure this is set */
- BLI_assert(index_len != -1);
+ /* adjust edge vertex indices */
+ me = CDDM_get_edges(result) + c * chunk_nedges;
+ for (i = 0; i < chunk_nedges; i++, me++) {
+ me->v1 += c * chunk_nverts;
+ me->v2 += c * chunk_nverts;
+ }
- for (i = 0; i < index_len; i++) {
- if (!indexMap[i]) continue;
+ mp = CDDM_get_polys(result) + c * chunk_npolys;
+ for (i = 0; i < chunk_npolys; i++, mp++) {
+ mp->loopstart += c * chunk_nloops;
+ }
- /* merge v (from 'geom.out') into v2 (from old 'geom') */
- v = _E(geom_out_slot, i - geom_slot->len);
- v2 = _E(geom_slot, indexMap[i] - 1);
+ /* adjust loop vertex and edge indices */
+ ml = CDDM_get_loops(result) + c * chunk_nloops;
+ for (i = 0; i < chunk_nloops; i++, ml++) {
+ ml->v += c * chunk_nverts;
+ ml->e += c * chunk_nedges;
+ }
- /* check in case the target vertex (v2) is already marked
- * for merging */
- while ((v3 = BMO_slot_map_elem_get(slot_targetmap, v2))) {
- v2 = v3;
+ /* Handle merge between chunk n and n-1 */
+ if ((amd->flags & MOD_ARR_MERGE) && (c >= 1)) {
+ if (!offset_has_scale && (c >= 2)) {
+ /* Mapping chunk 3 to chunk 2 is a translation of mapping 2 to 1
+ * ... that is except if scaling makes the distance grow */
+ int k;
+ int this_chunk_index = c * chunk_nverts;
+ int prev_chunk_index = (c - 1) * chunk_nverts;
+ for (k = 0; k < chunk_nverts; k++, this_chunk_index++, prev_chunk_index++) {
+ int target = full_doubles_map[prev_chunk_index];
+ if (target != -1) {
+ target += chunk_nverts; /* translate mapping */
+ /* The rule here is to not follow mapping to chunk N-2, which could be too far
+ * so if target vertex was itself mapped, then this vertex is not mapped */
+ if (full_doubles_map[target] != -1) {
+ target = -1;
+ }
+ }
+ full_doubles_map[this_chunk_index] = target;
}
-
- BMO_slot_map_elem_insert(&weld_op, slot_targetmap, v, v2);
}
-
-#undef _E
+ else {
+ dm_mvert_map_doubles(
+ full_doubles_map,
+ result_dm_verts,
+ (c - 1) * chunk_nverts,
+ chunk_nverts,
+ c * chunk_nverts,
+ chunk_nverts,
+ amd->merge_dist,
+ false);
+ }
}
-
- /* already copied earlier, but after executation more slot
- * memory may be allocated */
- if (j == 0)
- first_dupe_op = dupe_op;
-
- if (j >= 2)
- BMO_op_finish(bm, &old_dupe_op);
- old_dupe_op = dupe_op;
}
+ last_chunk_start = (count - 1) * chunk_nverts;
+ last_chunk_nverts = chunk_nverts;
+
+ copy_m4_m4(final_offset, current_offset);
+
if ((amd->flags & MOD_ARR_MERGE) &&
(amd->flags & MOD_ARR_MERGEFINAL) &&
(count > 1))
{
- /* Merge first and last copies. Note that we can't use the
- * indexMap for this because (unless the array is forming a
- * loop) the offset between first and last is different from
- * dupe X to dupe X+1. */
-
- merge_first_last(bm, amd, &first_dupe_op, &dupe_op, &weld_op);
+ /* Merge first and last copies */
+ dm_mvert_map_doubles(
+ full_doubles_map,
+ result_dm_verts,
+ last_chunk_start,
+ last_chunk_nverts,
+ first_chunk_start,
+ first_chunk_nverts,
+ amd->merge_dist,
+ false);
}
/* start capping */
- if (start_cap || end_cap) {
- BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false);
-
- if (start_cap) {
- float startoffset[4][4];
- invert_m4_m4(startoffset, offset);
- bm_merge_dm_transform(bm, start_cap, startoffset, amd,
- &first_dupe_op, first_dupe_op.slots_in, "geom", &weld_op);
+ if (start_cap_dm) {
+ float start_offset[4][4];
+ int start_cap_start = result_nverts - start_cap_nverts - end_cap_nverts;
+ invert_m4_m4(start_offset, offset);
+ dm_merge_transform(
+ result, start_cap_dm, start_offset,
+ result_nverts - start_cap_nverts - end_cap_nverts,
+ result_nedges - start_cap_nedges - end_cap_nedges,
+ result_nloops - start_cap_nloops - end_cap_nloops,
+ result_npolys - start_cap_npolys - end_cap_npolys,
+ start_cap_nverts, start_cap_nedges, start_cap_nloops, start_cap_npolys);
+ /* Identify doubles with first chunk */
+ if (amd->flags & MOD_ARR_MERGE) {
+ dm_mvert_map_doubles(
+ full_doubles_map,
+ result_dm_verts,
+ first_chunk_start,
+ first_chunk_nverts,
+ start_cap_start,
+ start_cap_nverts,
+ amd->merge_dist,
+ false);
}
+ }
- if (end_cap) {
- float endoffset[4][4];
- mul_m4_m4m4(endoffset, offset, final_offset);
- bm_merge_dm_transform(bm, end_cap, endoffset, amd,
- &dupe_op, (count == 1) ? dupe_op.slots_in : dupe_op.slots_out,
- (count == 1) ? "geom" : "geom.out", &weld_op);
+ if (end_cap_dm) {
+ float end_offset[4][4];
+ int end_cap_start = result_nverts - end_cap_nverts;
+ mul_m4_m4m4(end_offset, current_offset, offset);
+ dm_merge_transform(
+ result, end_cap_dm, end_offset,
+ result_nverts - end_cap_nverts,
+ result_nedges - end_cap_nedges,
+ result_nloops - end_cap_nloops,
+ result_npolys - end_cap_npolys,
+ end_cap_nverts, end_cap_nedges, end_cap_nloops, end_cap_npolys);
+ /* Identify doubles with last chunk */
+ if (amd->flags & MOD_ARR_MERGE) {
+ dm_mvert_map_doubles(
+ full_doubles_map,
+ result_dm_verts,
+ last_chunk_start,
+ last_chunk_nverts,
+ end_cap_start,
+ end_cap_nverts,
+ amd->merge_dist,
+ false);
}
}
/* done capping */
- /* free remaining dupe operators */
- BMO_op_finish(bm, &first_dupe_op);
- if (count > 2)
- BMO_op_finish(bm, &dupe_op);
-
- /* run merge operator */
- if (amd->flags & MOD_ARR_MERGE) {
- BMO_op_exec(bm, &weld_op);
- BMO_op_finish(bm, &weld_op);
- }
-
- /* Bump the stack level back down to match the adjustment up above */
- BMO_pop(bm);
-
- result = CDDM_from_bmesh(bm, false);
-
- if ((dm->dirty & DM_DIRTY_NORMALS) ||
- ((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)))
- {
- /* Update normals in case offset object has rotation. */
+ /* In case org dm has dirty normals, or we made some merging, mark normals as dirty in new dm!
+ * TODO: we may need to set other dirty flags as well?
+ */
+ if ((dm->dirty & DM_DIRTY_NORMALS) || full_doubles_map) {
result->dirty |= DM_DIRTY_NORMALS;
}
- BM_mesh_free(bm);
-
- if (indexMap)
- MEM_freeN(indexMap);
- if (first_geom)
- MEM_freeN(first_geom);
-
+ /* Handle merging */
+ tot_doubles = 0;
+ if (full_doubles_map) {
+ for (i = 0; i < result_nverts; i++) {
+ if (full_doubles_map[i] != -1) {
+ tot_doubles++;
+ }
+ }
+ if (tot_doubles > 0) {
+ result = CDDM_merge_verts(result, full_doubles_map, tot_doubles, CDDM_MERGE_VERTS_DUMP_IF_EQUAL);
+ }
+ MEM_freeN(full_doubles_map);
+ }
return result;
}
+
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DerivedMesh *dm,
ModifierApplyFlag flag)
{
- DerivedMesh *result;
ArrayModifierData *amd = (ArrayModifierData *) md;
-
- result = arrayModifier_doArray(amd, md->scene, ob, dm, flag);
-
- return result;
+ return arrayModifier_doArray(amd, md->scene, ob, dm, flag);
}
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index fc65990df20..2de3220e683 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -57,6 +57,7 @@ static void initData(ModifierData *md)
bmd->val_flags = MOD_BEVEL_AMT_OFFSET;
bmd->lim_flags = 0;
bmd->e_flags = 0;
+ bmd->mat = -1;
bmd->profile = 0.5f;
bmd->bevel_angle = DEG2RADF(30.0f);
bmd->defgrp_name[0] = '\0';
@@ -73,6 +74,7 @@ static void copyData(ModifierData *md, ModifierData *target)
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));
@@ -109,6 +111,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob,
const bool vertex_only = (bmd->flags & MOD_BEVEL_VERT) != 0;
const bool do_clamp = !(bmd->flags & MOD_BEVEL_OVERLAP_OK);
const int offset_type = bmd->val_flags;
+ const int mat = CLAMPIS(bmd->mat, -1, ob->totcol - 1);
bm = DM_to_bmesh(dm, true);
if ((bmd->lim_flags & MOD_BEVEL_VGROUP) && bmd->defgrp_name[0])
@@ -165,7 +168,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob,
BM_mesh_bevel(bm, bmd->value, offset_type, bmd->res, bmd->profile,
vertex_only, bmd->lim_flags & MOD_BEVEL_WEIGHT, do_clamp,
- dvert, vgroup);
+ dvert, vgroup, mat);
result = CDDM_from_bmesh(bm, true);
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index ec077631c85..c4654287cfc 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -151,8 +151,8 @@ static void sphere_do(
* we use its location, transformed to ob's local space */
if (ctrl_ob) {
if (flag & MOD_CAST_USE_OB_TRANSFORM) {
- invert_m4_m4(ctrl_ob->imat, ctrl_ob->obmat);
- mul_m4_m4m4(mat, ctrl_ob->imat, ob->obmat);
+ invert_m4_m4(imat, ctrl_ob->obmat);
+ mul_m4_m4m4(mat, imat, ob->obmat);
invert_m4_m4(imat, mat);
}
@@ -275,8 +275,8 @@ static void cuboid_do(
if (ctrl_ob) {
if (flag & MOD_CAST_USE_OB_TRANSFORM) {
- invert_m4_m4(ctrl_ob->imat, ctrl_ob->obmat);
- mul_m4_m4m4(mat, ctrl_ob->imat, ob->obmat);
+ invert_m4_m4(imat, ctrl_ob->obmat);
+ mul_m4_m4m4(mat, imat, ob->obmat);
invert_m4_m4(imat, mat);
}
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index c89bc8c1d41..f6d7c03df32 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -156,8 +156,7 @@ static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
copy_m4_m4(dmat, hmd->object->obmat);
}
invert_m4_m4(ob->imat, ob->obmat);
- mul_serie_m4(mat, ob->imat, dmat, hmd->parentinv,
- NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, ob->imat, dmat, hmd->parentinv);
modifier_get_vgroup(ob, dm, hmd->name, &dvert, &defgrp_index);
max_dvert = (dvert) ? numVerts : 0;
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index 7f21376ef48..838336a8f8a 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -153,7 +153,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
const int defbase_tot = BLI_countlist(&ob->defbase);
/* check that there is armature object with bones to use, otherwise return original mesh */
- if (ELEM3(NULL, oba, oba->pose, ob->defbase.first))
+ if (ELEM(NULL, oba, oba->pose, ob->defbase.first))
return dm;
/* determine whether each vertexgroup is associated with a selected bone or not
diff --git a/source/blender/modifiers/intern/MOD_meshcache_mdd.c b/source/blender/modifiers/intern/MOD_meshcache_mdd.c
index 0cbf07ca907..90fc750de3b 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_mdd.c
+++ b/source/blender/modifiers/intern/MOD_meshcache_mdd.c
@@ -30,9 +30,11 @@
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
-#include "BLI_endian_switch.h"
#include "BLI_fileops.h"
#include "BLI_math.h"
+#ifdef __LITTLE_ENDIAN__
+# include "BLI_endian_switch.h"
+#endif
#include "MOD_meshcache_util.h" /* own include */
diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
index ac0363f8673..3ef0ee54886 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_pc2.c
+++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
@@ -32,6 +32,9 @@
#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "BLI_math.h"
+#ifdef __BIG_ENDIAN__
+# include "BLI_endian_switch.h"
+#endif
#include "MOD_meshcache_util.h" /* own include */
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 5cece9d349f..5de4a76dcbe 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -290,7 +290,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
/* slow - so only call if one or more merge verts are found,
* users may leave this on and not realize there is nothing to merge - campbell */
if (tot_vtargetmap) {
- result = CDDM_merge_verts(result, vtargetmap, tot_vtargetmap);
+ result = CDDM_merge_verts(result, vtargetmap, tot_vtargetmap, CDDM_MERGE_VERTS_DUMP_IF_MAPPED);
}
MEM_freeN(vtargetmap);
}
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index ff7cc01232b..5900baaf537 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -362,7 +362,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (ltmd->flag & MOD_SCREW_UV_STRETCH_V) {
for (i = 0, mv_orig = mvert_orig; i < totvert; i++, mv_orig++) {
- const float v = dist_squared_to_plane_v3(mv_orig->co, uv_axis_plane);
+ const float v = dist_signed_squared_to_plane_v3(mv_orig->co, uv_axis_plane);
uv_v_minmax[0] = min_ff(v, uv_v_minmax[0]);
uv_v_minmax[1] = max_ff(v, uv_v_minmax[1]);
}
@@ -897,8 +897,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
if (has_mloop_orig == false && mloopuv_layers_tot) {
- uv_v_offset_a = dist_to_plane_v3(mvert_new[medge_new[i].v1].co, uv_axis_plane);
- uv_v_offset_b = dist_to_plane_v3(mvert_new[medge_new[i].v2].co, uv_axis_plane);
+ uv_v_offset_a = dist_signed_to_plane_v3(mvert_new[medge_new[i].v1].co, uv_axis_plane);
+ uv_v_offset_b = dist_signed_to_plane_v3(mvert_new[medge_new[i].v2].co, uv_axis_plane);
if (ltmd->flag & MOD_SCREW_UV_STRETCH_V) {
uv_v_offset_a = (uv_v_offset_a - uv_v_minmax[0]) * uv_v_range_inv;
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index eebb687aa8d..229f4911ab4 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -37,6 +37,7 @@
#include "DNA_object_types.h"
+#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index ccba2097264..3314196b776 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -42,7 +42,6 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
-#include "BKE_shrinkwrap.h"
#include "depsgraph_private.h"
@@ -166,7 +165,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
/* Calculate matrixs do convert between coordinate spaces */
if (smd->origin) {
transf = &tmp_transf;
- space_transform_from_matrixs(transf, ob->obmat, smd->origin->obmat);
+ BLI_SPACE_TRANSFORM_SETUP(transf, ob, smd->origin);
}
/* Setup vars,
@@ -182,7 +181,9 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
float tmp[3];
copy_v3_v3(tmp, vertexCos[i]);
- if (transf) space_transform_apply(transf, tmp);
+ if (transf) {
+ BLI_space_transform_apply(transf, tmp);
+ }
lower = min_ff(lower, tmp[limit_axis]);
upper = max_ff(upper, tmp[limit_axis]);
@@ -220,7 +221,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
float co[3], dcut[3] = {0.0f, 0.0f, 0.0f};
if (transf) {
- space_transform_apply(transf, vertexCos[i]);
+ BLI_space_transform_apply(transf, vertexCos[i]);
}
copy_v3_v3(co, vertexCos[i]);
@@ -236,7 +237,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
interp_v3_v3v3(vertexCos[i], vertexCos[i], co, weight); /* Use vertex weight has coef of linear interpolation */
if (transf) {
- space_transform_invert(transf, vertexCos[i]);
+ BLI_space_transform_invert(transf, vertexCos[i]);
}
}
}
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 95b0c37933c..813ef285058 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -20,6 +20,7 @@
*
* Contributor(s): Campbell Barton
* Shinsuke Irie
+ * Martin Felke
*
* ***** END GPL LICENSE BLOCK *****
*
@@ -208,7 +209,6 @@ static DerivedMesh *applyModifier(
DerivedMesh *dm,
ModifierApplyFlag UNUSED(flag))
{
- unsigned int i;
DerivedMesh *result;
const SolidifyModifierData *smd = (SolidifyModifierData *) md;
@@ -220,7 +220,7 @@ static DerivedMesh *applyModifier(
const unsigned int numEdges = (unsigned int)dm->getNumEdges(dm);
const unsigned int numFaces = (unsigned int)dm->getNumPolys(dm);
const unsigned int numLoops = (unsigned int)dm->getNumLoops(dm);
- unsigned int newLoops = 0, newFaces = 0, newEdges = 0;
+ unsigned int newLoops = 0, newFaces = 0, newEdges = 0, newVerts = 0;
/* only use material offsets if we have 2 or more materials */
const short mat_nr_max = ob->totcol > 1 ? ob->totcol - 1 : 0;
@@ -251,12 +251,16 @@ static DerivedMesh *applyModifier(
const float offset_fac_vg_inv = 1.0f - smd->offset_fac_vg;
const bool do_flip = (smd->flag & MOD_SOLIDIFY_FLIP) != 0;
const bool do_clamp = (smd->offset_clamp != 0.0f);
+ const bool do_shell = ((smd->flag & MOD_SOLIDIFY_RIM) && (smd->flag & MOD_SOLIDIFY_NOSHELL)) == 0;
/* weights */
- MDeformVert *dvert, *dv = NULL;
+ MDeformVert *dvert;
const int defgrp_invert = ((smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0);
int defgrp_index;
+ /* array size is doubled in case of using a shell */
+ const unsigned int stride = do_shell ? 2 : 1;
+
modifier_get_vgroup(ob, dm, smd->defgrp_name, &dvert, &defgrp_index);
orig_mvert = dm->getVertArray(dm);
@@ -280,6 +284,7 @@ static DerivedMesh *applyModifier(
if (smd->flag & MOD_SOLIDIFY_RIM) {
BLI_bitmap *orig_mvert_tag = BLI_BITMAP_NEW(numVerts, __func__);
unsigned int eidx;
+ unsigned int i;
#define INVALID_UNUSED ((unsigned int)-1)
#define INVALID_PAIR ((unsigned int)-2)
@@ -334,15 +339,15 @@ static DerivedMesh *applyModifier(
}
}
-#undef INVALID_UNUSED
-#undef INVALID_PAIR
-
for (i = 0; i < numVerts; i++) {
if (BLI_BITMAP_TEST(orig_mvert_tag, i)) {
old_vert_arr[i] = STACK_SIZE(new_vert_arr);
STACK_PUSH(new_vert_arr, i);
newEdges++;
}
+ else {
+ old_vert_arr[i] = INVALID_UNUSED;
+ }
}
MEM_freeN(orig_mvert_tag);
@@ -353,64 +358,126 @@ static DerivedMesh *applyModifier(
dm_calc_normal(dm, face_nors, vert_nors);
}
+ newVerts = do_shell ? 0 : newEdges;
+
result = CDDM_from_template(dm,
- (int)(numVerts * 2),
- (int)((numEdges * 2) + newEdges), 0,
- (int)((numLoops * 2) + newLoops),
- (int)((numFaces * 2) + newFaces));
+ (int)((numVerts * stride) + newVerts),
+ (int)((numEdges * stride) + newEdges + newVerts), 0,
+ (int)((numLoops * stride) + newLoops),
+ (int)((numFaces * stride) + newFaces));
mpoly = CDDM_get_polys(result);
mloop = CDDM_get_loops(result);
medge = CDDM_get_edges(result);
mvert = CDDM_get_verts(result);
- DM_copy_edge_data(dm, result, 0, 0, (int)numEdges);
- DM_copy_edge_data(dm, result, 0, (int)numEdges, (int)numEdges);
+ if (do_shell) {
+ DM_copy_vert_data(dm, result, 0, 0, (int)numVerts);
+ DM_copy_vert_data(dm, result, 0, (int)numVerts, (int)numVerts);
- DM_copy_vert_data(dm, result, 0, 0, (int)numVerts);
- DM_copy_vert_data(dm, result, 0, (int)numVerts, (int)numVerts);
+ DM_copy_edge_data(dm, result, 0, 0, (int)numEdges);
+ DM_copy_edge_data(dm, result, 0, (int)numEdges, (int)numEdges);
- DM_copy_loop_data(dm, result, 0, 0, (int)numLoops);
- DM_copy_loop_data(dm, result, 0, (int)numLoops, (int)numLoops);
+ DM_copy_loop_data(dm, result, 0, 0, (int)numLoops);
+ DM_copy_loop_data(dm, result, 0, (int)numLoops, (int)numLoops);
- DM_copy_poly_data(dm, result, 0, 0, (int)numFaces);
- DM_copy_poly_data(dm, result, 0, (int)numFaces, (int)numFaces);
-
- /* flip normals */
- mp = mpoly + numFaces;
- for (i = 0; i < dm->numPolyData; i++, mp++) {
- MLoop *ml2;
- unsigned int e;
- int j;
-
- ml2 = mloop + mp->loopstart + dm->numLoopData;
- for (j = 0; j < mp->totloop; j++) {
- CustomData_copy_data(&dm->loopData, &result->loopData, mp->loopstart + j,
- mp->loopstart + (mp->totloop - j - 1) + dm->numLoopData, 1);
+ DM_copy_poly_data(dm, result, 0, 0, (int)numFaces);
+ DM_copy_poly_data(dm, result, 0, (int)numFaces, (int)numFaces);
+ }
+ else {
+ int i, j;
+ DM_copy_vert_data(dm, result, 0, 0, (int)numVerts);
+ for (i = 0, j = (int)numVerts; i < numVerts; i++) {
+ if (old_vert_arr[i] != INVALID_UNUSED) {
+ DM_copy_vert_data(dm, result, i, j, 1);
+ j++;
+ }
}
- if (mat_ofs) {
- mp->mat_nr += mat_ofs;
- CLAMP(mp->mat_nr, 0, mat_nr_max);
- }
+ DM_copy_edge_data(dm, result, 0, 0, (int)numEdges);
- e = ml2[0].e;
- for (j = 0; j < mp->totloop - 1; j++) {
- ml2[j].e = ml2[j + 1].e;
+ for (i = 0, j = (int)numEdges; i < numEdges; i++) {
+ if (!ELEM(edge_users[i], INVALID_UNUSED, INVALID_PAIR)) {
+ MEdge *ed_src, *ed_dst;
+ DM_copy_edge_data(dm, result, i, j, 1);
+
+ ed_src = &medge[i];
+ ed_dst = &medge[j];
+ ed_dst->v1 = old_vert_arr[ed_src->v1] + numVerts;
+ ed_dst->v2 = old_vert_arr[ed_src->v2] + numVerts;
+ j++;
+ }
}
- ml2[mp->totloop - 1].e = e;
- mp->loopstart += dm->numLoopData;
+ /* will be created later */
+ DM_copy_loop_data(dm, result, 0, 0, (int)numLoops);
+ DM_copy_poly_data(dm, result, 0, 0, (int)numFaces);
+ }
+
+#undef INVALID_UNUSED
+#undef INVALID_PAIR
+
+
+ /* initializes: (i_end, do_shell_align, mv) */
+#define INIT_VERT_ARRAY_OFFSETS(test) \
+ if (((ofs_new >= ofs_orig) == do_flip) == test) { \
+ i_end = numVerts; \
+ do_shell_align = true; \
+ mv = mvert; \
+ } \
+ else { \
+ if (do_shell) { \
+ i_end = numVerts; \
+ do_shell_align = true; \
+ } \
+ else { \
+ i_end = newVerts ; \
+ do_shell_align = false; \
+ } \
+ mv = &mvert[numVerts]; \
+ } (void)0
+
+
+ /* flip normals */
+
+ if (do_shell) {
+ unsigned int i;
- for (j = 0; j < mp->totloop; j++) {
- ml2[j].e += numEdges;
- ml2[j].v += numVerts;
+ mp = mpoly + numFaces;
+ for (i = 0; i < dm->numPolyData; i++, mp++) {
+ MLoop *ml2;
+ unsigned int e;
+ int j;
+
+ ml2 = mloop + mp->loopstart + dm->numLoopData;
+ for (j = 0; j < mp->totloop; j++) {
+ CustomData_copy_data(&dm->loopData, &result->loopData, mp->loopstart + j,
+ mp->loopstart + (mp->totloop - j - 1) + dm->numLoopData, 1);
+ }
+
+ if (mat_ofs) {
+ mp->mat_nr += mat_ofs;
+ CLAMP(mp->mat_nr, 0, mat_nr_max);
+ }
+
+ e = ml2[0].e;
+ for (j = 0; j < mp->totloop - 1; j++) {
+ ml2[j].e = ml2[j + 1].e;
+ }
+ ml2[mp->totloop - 1].e = e;
+
+ mp->loopstart += dm->numLoopData;
+
+ for (j = 0; j < mp->totloop; j++) {
+ ml2[j].e += numEdges;
+ ml2[j].v += numVerts;
+ }
}
- }
- for (i = 0, ed = medge + numEdges; i < numEdges; i++, ed++) {
- ed->v1 += numVerts;
- ed->v2 += numVerts;
+ for (i = 0, ed = medge + numEdges; i < numEdges; i++, ed++) {
+ ed->v1 += numVerts;
+ ed->v2 += numVerts;
+ }
}
/* note, copied vertex layers don't have flipped normals yet. do this after applying offset */
@@ -425,6 +492,8 @@ static DerivedMesh *applyModifier(
const float offset_sq = offset * offset;
if (do_clamp) {
+ unsigned int i;
+
vert_lens = MEM_mallocN(sizeof(float) * numVerts, "vert_lens");
fill_vn_fl(vert_lens, (int)numVerts, FLT_MAX);
for (i = 0; i < numEdges; i++) {
@@ -435,19 +504,24 @@ static DerivedMesh *applyModifier(
}
if (ofs_new != 0.0f) {
+ unsigned int i_orig, i_end;
+ bool do_shell_align;
+
scalar_short = scalar_short_vgroup = ofs_new / 32767.0f;
- mv = mvert + (((ofs_new >= ofs_orig) == do_flip) ? numVerts : 0);
- dv = dvert;
- for (i = 0; i < numVerts; i++, mv++) {
- if (dv) {
+
+ INIT_VERT_ARRAY_OFFSETS(false);
+
+ for (i_orig = 0; i_orig < i_end; i_orig++, mv++) {
+ const unsigned int i = do_shell_align ? i_orig : new_vert_arr[i_orig];
+ if (dvert) {
+ MDeformVert *dv = &dvert[i];
if (defgrp_invert) scalar_short_vgroup = 1.0f - defvert_find_weight(dv, defgrp_index);
else scalar_short_vgroup = defvert_find_weight(dv, defgrp_index);
scalar_short_vgroup = (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) * scalar_short;
- dv++;
}
if (do_clamp) {
/* always reset becaise we may have set before */
- if (dv == NULL) {
+ if (dvert == NULL) {
scalar_short_vgroup = scalar_short;
}
if (vert_lens[i] < offset_sq) {
@@ -460,19 +534,25 @@ static DerivedMesh *applyModifier(
}
if (ofs_orig != 0.0f) {
+ unsigned int i_orig, i_end;
+ bool do_shell_align;
+
scalar_short = scalar_short_vgroup = ofs_orig / 32767.0f;
- mv = mvert + (((ofs_new >= ofs_orig) == do_flip) ? 0 : numVerts); /* as above but swapped */
- dv = dvert;
- for (i = 0; i < numVerts; i++, mv++) {
- if (dv) {
+
+ /* as above but swapped */
+ INIT_VERT_ARRAY_OFFSETS(true);
+
+ for (i_orig = 0; i_orig < i_end; i_orig++, mv++) {
+ const unsigned int i = do_shell_align ? i_orig : new_vert_arr[i_orig];
+ if (dvert) {
+ MDeformVert *dv = &dvert[i];
if (defgrp_invert) scalar_short_vgroup = 1.0f - defvert_find_weight(dv, defgrp_index);
else scalar_short_vgroup = defvert_find_weight(dv, defgrp_index);
scalar_short_vgroup = (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) * scalar_short;
- dv++;
}
if (do_clamp) {
/* always reset becaise we may have set before */
- if (dv == NULL) {
+ if (dvert == NULL) {
scalar_short_vgroup = scalar_short;
}
if (vert_lens[i] < offset_sq) {
@@ -496,6 +576,7 @@ static DerivedMesh *applyModifier(
float *vert_angles = MEM_callocN(sizeof(float) * numVerts * 2, "mod_solid_pair"); /* 2 in 1 */
float *vert_accum = vert_angles + numVerts;
unsigned int vidx;
+ unsigned int i;
if (vert_nors == NULL) {
vert_nors = MEM_mallocN(sizeof(float) * numVerts * 3, "mod_solid_vno");
@@ -558,9 +639,9 @@ static DerivedMesh *applyModifier(
/* vertex group support */
if (dvert) {
+ MDeformVert *dv = dvert;
float scalar;
- dv = dvert;
if (defgrp_invert) {
for (i = 0; i < numVerts; i++, dv++) {
scalar = 1.0f - defvert_find_weight(dv, defgrp_index);
@@ -596,21 +677,29 @@ static DerivedMesh *applyModifier(
MEM_freeN(vert_lens_sq);
}
- if (ofs_new) {
- mv = mvert + (((ofs_new >= ofs_orig) == do_flip) ? numVerts : 0);
+ if (ofs_new != 0.0f) {
+ unsigned int i_orig, i_end;
+ bool do_shell_align;
+
+ INIT_VERT_ARRAY_OFFSETS(false);
- for (i = 0; i < numVerts; i++, mv++) {
+ for (i_orig = 0; i_orig < i_end; i_orig++, mv++) {
+ const unsigned int i = do_shell_align ? i_orig : new_vert_arr[i_orig];
if (vert_accum[i]) { /* zero if unselected */
madd_v3_v3fl(mv->co, vert_nors[i], ofs_new * (vert_angles[i] / vert_accum[i]));
}
}
}
- if (ofs_orig) {
+ if (ofs_orig != 0.0f) {
+ unsigned int i_orig, i_end;
+ bool do_shell_align;
+
/* same as above but swapped, intentional use of 'ofs_new' */
- mv = mvert + (((ofs_new >= ofs_orig) == do_flip) ? 0 : numVerts);
+ INIT_VERT_ARRAY_OFFSETS(true);
- for (i = 0; i < numVerts; i++, mv++) {
+ for (i_orig = 0; i_orig < i_end; i_orig++, mv++) {
+ const unsigned int i = do_shell_align ? i_orig : new_vert_arr[i_orig];
if (vert_accum[i]) { /* zero if unselected */
madd_v3_v3fl(mv->co, vert_nors[i], ofs_orig * (vert_angles[i] / vert_accum[i]));
}
@@ -627,7 +716,8 @@ static DerivedMesh *applyModifier(
if ((dm->dirty & DM_DIRTY_NORMALS) || (smd->flag & MOD_SOLIDIFY_RIM) || dvert) {
result->dirty |= DM_DIRTY_NORMALS;
}
- else {
+ else if (do_shell) {
+ unsigned int i;
/* flip vertex normals for copied verts */
mv = mvert + numVerts;
for (i = 0; i < numVerts; i++, mv++) {
@@ -636,6 +726,7 @@ static DerivedMesh *applyModifier(
}
if (smd->flag & MOD_SOLIDIFY_RIM) {
+ unsigned int i;
/* bugger, need to re-calculate the normals for the new edge faces.
* This could be done in many ways, but probably the quickest way
@@ -668,11 +759,11 @@ static DerivedMesh *applyModifier(
/* add faces & edges */
origindex_edge = result->getEdgeDataArray(result, CD_ORIGINDEX);
- ed = &medge[numEdges * 2];
- orig_ed = &origindex_edge[numEdges * 2];
+ ed = &medge[(numEdges * stride) + newVerts]; /* start after copied edges */
+ orig_ed = &origindex_edge[(numEdges * stride) + newVerts];
for (i = 0; i < newEdges; i++, ed++, orig_ed++) {
ed->v1 = new_vert_arr[i];
- ed->v2 = new_vert_arr[i] + numVerts;
+ ed->v2 = (do_shell ? new_vert_arr[i] : i) + numVerts;
ed->flag |= ME_EDGEDRAW;
*orig_ed = ORIGINDEX_NONE;
@@ -683,8 +774,8 @@ static DerivedMesh *applyModifier(
}
/* faces */
- mp = mpoly + (numFaces * 2);
- ml = mloop + (numLoops * 2);
+ mp = mpoly + (numFaces * stride);
+ ml = mloop + (numLoops * stride);
j = 0;
for (i = 0; i < newFaces; i++, mp++) {
unsigned int eidx = new_edge_arr[i];
@@ -703,8 +794,8 @@ static DerivedMesh *applyModifier(
ed = medge + eidx;
/* copy most of the face settings */
- DM_copy_poly_data(dm, result, (int)fidx, (int)((numFaces * 2) + i), 1);
- mp->loopstart = (int)(j + numLoops * 2);
+ DM_copy_poly_data(dm, result, (int)fidx, (int)((numFaces * stride) + i), 1);
+ mp->loopstart = (int)(j + (numLoops * stride));
mp->flag = mpoly[fidx].flag;
/* notice we use 'mp->totloop' which is later overwritten,
@@ -715,36 +806,36 @@ static DerivedMesh *applyModifier(
mp->totloop = 4;
- CustomData_copy_data(&dm->loopData, &result->loopData, k2, (int)(numLoops * 2 + j + 0), 1);
- CustomData_copy_data(&dm->loopData, &result->loopData, k1, (int)(numLoops * 2 + j + 1), 1);
- CustomData_copy_data(&dm->loopData, &result->loopData, k1, (int)(numLoops * 2 + j + 2), 1);
- CustomData_copy_data(&dm->loopData, &result->loopData, k2, (int)(numLoops * 2 + j + 3), 1);
+ CustomData_copy_data(&dm->loopData, &result->loopData, k2, (int)((numLoops * stride) + j + 0), 1);
+ CustomData_copy_data(&dm->loopData, &result->loopData, k1, (int)((numLoops * stride) + j + 1), 1);
+ CustomData_copy_data(&dm->loopData, &result->loopData, k1, (int)((numLoops * stride) + j + 2), 1);
+ CustomData_copy_data(&dm->loopData, &result->loopData, k2, (int)((numLoops * stride) + j + 3), 1);
if (flip == false) {
ml[j].v = ed->v1;
ml[j++].e = eidx;
ml[j].v = ed->v2;
- ml[j++].e = numEdges * 2 + old_vert_arr[ed->v2];
+ ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v2] + newVerts;
- ml[j].v = ed->v2 + numVerts;
- ml[j++].e = eidx + numEdges;
+ ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + numVerts;
+ ml[j++].e = (do_shell ? eidx : i) + numEdges;
- ml[j].v = ed->v1 + numVerts;
- ml[j++].e = numEdges * 2 + old_vert_arr[ed->v1];
+ ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + numVerts;
+ ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v1] + newVerts;
}
else {
ml[j].v = ed->v2;
ml[j++].e = eidx;
ml[j].v = ed->v1;
- ml[j++].e = numEdges * 2 + old_vert_arr[ed->v1];
+ ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v1] + newVerts;
- ml[j].v = ed->v1 + numVerts;
- ml[j++].e = eidx + numEdges;
+ ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + numVerts;
+ ml[j++].e = (do_shell ? eidx : i) + numEdges;
- ml[j].v = ed->v2 + numVerts;
- ml[j++].e = numEdges * 2 + old_vert_arr[ed->v2];
+ ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + numVerts;
+ ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v2] + newVerts;
}
origindex_edge[ml[j - 3].e] = ORIGINDEX_NONE;
@@ -757,14 +848,14 @@ static DerivedMesh *applyModifier(
}
if (crease_outer) {
/* crease += crease_outer; without wrapping */
- unsigned char *cr = (unsigned char *)&(ed->crease);
+ char *cr = &(ed->crease);
int tcr = *cr + crease_outer;
*cr = tcr > 255 ? 255 : tcr;
}
if (crease_inner) {
/* crease += crease_inner; without wrapping */
- unsigned char *cr = (unsigned char *)&(medge[numEdges + eidx].crease);
+ char *cr = &(medge[numEdges + (do_shell ? eidx : i)].crease);
int tcr = *cr + crease_inner;
*cr = tcr > 255 ? 255 : tcr;
}
@@ -785,7 +876,7 @@ static DerivedMesh *applyModifier(
#ifdef SOLIDIFY_SIDE_NORMALS
if (do_side_normals) {
- ed = medge + (numEdges * 2);
+ ed = medge + (numEdges * stride);
for (i = 0; i < newEdges; i++, ed++) {
float nor_cpy[3];
short *nor_short;
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 386d6d985fb..829c2b88995 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -198,7 +198,7 @@ DerivedMesh *get_dm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm,
DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob));
}
}
- else if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+ else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
dm = CDDM_from_curve(ob);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c
index 12ecae8ad4f..744b6b62c2a 100644
--- a/source/blender/modifiers/intern/MOD_weightvg_util.c
+++ b/source/blender/modifiers/intern/MOD_weightvg_util.c
@@ -66,9 +66,9 @@ void weightvg_do_map(int num, float *new_w, short falloff_type, CurveMapping *cm
/* Return immediately, if we have nothing to do! */
/* Also security checks... */
if (((falloff_type == MOD_WVG_MAPPING_CURVE) && (cmap == NULL)) ||
- !ELEM7(falloff_type, MOD_WVG_MAPPING_CURVE, MOD_WVG_MAPPING_SHARP, MOD_WVG_MAPPING_SMOOTH,
- MOD_WVG_MAPPING_ROOT, MOD_WVG_MAPPING_SPHERE, MOD_WVG_MAPPING_RANDOM,
- MOD_WVG_MAPPING_STEP))
+ !ELEM(falloff_type, MOD_WVG_MAPPING_CURVE, MOD_WVG_MAPPING_SHARP, MOD_WVG_MAPPING_SMOOTH,
+ MOD_WVG_MAPPING_ROOT, MOD_WVG_MAPPING_SPHERE, MOD_WVG_MAPPING_RANDOM,
+ MOD_WVG_MAPPING_STEP))
{
return;
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index f5ae8561300..71d4742980e 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -43,7 +43,6 @@
#include "BKE_deform.h"
#include "BKE_library.h"
#include "BKE_modifier.h"
-#include "BKE_shrinkwrap.h" /* For SpaceTransform stuff. */
#include "BKE_texture.h" /* Texture masking. */
#include "depsgraph_private.h"
@@ -73,12 +72,12 @@ static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
DerivedMesh *target, const SpaceTransform *loc2trgt)
{
int i;
- BVHTreeFromMesh treeData_v = NULL_BVHTreeFromMesh;
- BVHTreeFromMesh treeData_e = NULL_BVHTreeFromMesh;
- BVHTreeFromMesh treeData_f = NULL_BVHTreeFromMesh;
- BVHTreeNearest nearest_v = NULL_BVHTreeNearest;
- BVHTreeNearest nearest_e = NULL_BVHTreeNearest;
- BVHTreeNearest nearest_f = NULL_BVHTreeNearest;
+ BVHTreeFromMesh treeData_v = {NULL};
+ BVHTreeFromMesh treeData_e = {NULL};
+ BVHTreeFromMesh treeData_f = {NULL};
+ BVHTreeNearest nearest_v = {0};
+ BVHTreeNearest nearest_e = {0};
+ BVHTreeNearest nearest_f = {0};
if (dist_v) {
/* Create a bvh-tree of the given target's verts. */
@@ -120,7 +119,7 @@ static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
/* Convert the vertex to tree coordinates. */
copy_v3_v3(tmp_co, v_cos[i]);
- space_transform_apply(loc2trgt, tmp_co);
+ BLI_space_transform_apply(loc2trgt, tmp_co);
/* Use local proximity heuristics (to reduce the nearest search).
*
@@ -465,7 +464,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
DerivedMesh *target_dm = obr->derivedFinal;
bool free_target_dm = false;
if (!target_dm) {
- if (ELEM3(obr->type, OB_CURVE, OB_SURF, OB_FONT))
+ if (ELEM(obr->type, OB_CURVE, OB_SURF, OB_FONT))
target_dm = CDDM_from_curve(obr);
else if (obr->type == OB_MESH) {
Mesh *me = (Mesh *)obr->data;
@@ -484,7 +483,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
float *dists_e = use_trgt_edges ? MEM_mallocN(sizeof(float) * numIdx, "dists_e") : NULL;
float *dists_f = use_trgt_faces ? MEM_mallocN(sizeof(float) * numIdx, "dists_f") : NULL;
- SPACE_TRANSFORM_SETUP(&loc2trgt, ob, obr);
+ BLI_SPACE_TRANSFORM_SETUP(&loc2trgt, ob, obr);
get_vert2geom_distance(numIdx, v_cos, dists_v, dists_e, dists_f,
target_dm, &loc2trgt);
for (i = 0; i < numIdx; i++) {
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 3899b3dce30..9eb6c1674a3 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -106,6 +106,7 @@ set(SRC
composite/nodes/node_composite_setalpha.c
composite/nodes/node_composite_splitViewer.c
composite/nodes/node_composite_stabilize2d.c
+ composite/nodes/node_composite_sunbeams.c
composite/nodes/node_composite_texture.c
composite/nodes/node_composite_tonemap.c
composite/nodes/node_composite_trackpos.c
@@ -184,6 +185,7 @@ set(SRC
shader/nodes/node_shader_output_lamp.c
shader/nodes/node_shader_output_material.c
shader/nodes/node_shader_output_world.c
+ shader/nodes/node_shader_output_linestyle.c
shader/nodes/node_shader_particle_info.c
shader/nodes/node_shader_script.c
shader/nodes/node_shader_subsurface_scattering.c
@@ -202,6 +204,7 @@ set(SRC
shader/nodes/node_shader_tex_wave.c
shader/nodes/node_shader_volume_scatter.c
shader/nodes/node_shader_volume_absorption.c
+ shader/nodes/node_shader_uvAlongStroke.c
shader/nodes/node_shader_uvmap.c
shader/node_shader_tree.c
shader/node_shader_util.c
@@ -279,4 +282,8 @@ endif()
add_definitions(${GL_DEFINITIONS})
+if(WITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index ad5f35b8faa..961fdbfc0fb 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -125,7 +125,7 @@ void register_node_type_cmp_mask(void);
void register_node_type_cmp_glare(void);
void register_node_type_cmp_tonemap(void);
void register_node_type_cmp_lensdist(void);
-
+void register_node_type_cmp_sunbeams(void);
void register_node_type_cmp_colorcorrection(void);
void register_node_type_cmp_boxmask(void);
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 255ad568bad..595a3b12bc6 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -114,10 +114,12 @@ void register_node_type_sh_subsurface_scattering(void);
void register_node_type_sh_mix_shader(void);
void register_node_type_sh_add_shader(void);
void register_node_type_sh_uvmap(void);
+void register_node_type_sh_uvalongstroke(void);
void register_node_type_sh_output_lamp(void);
void register_node_type_sh_output_material(void);
void register_node_type_sh_output_world(void);
+void register_node_type_sh_output_linestyle(void);
void register_node_type_sh_tex_image(void);
void register_node_type_sh_tex_environment(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 8d6c4abaef6..166fa29fca0 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -69,6 +69,7 @@ DefNode( ShaderNode, SH_NODE_HUE_SAT, 0, "HUE_S
DefNode( ShaderNode, SH_NODE_OUTPUT_MATERIAL, def_sh_output, "OUTPUT_MATERIAL", OutputMaterial, "Material Output", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_LAMP, def_sh_output, "OUTPUT_LAMP", OutputLamp, "Lamp Output", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_WORLD, def_sh_output, "OUTPUT_WORLD", OutputWorld, "World Output", "" )
+DefNode( ShaderNode, SH_NODE_OUTPUT_LINESTYLE, def_sh_output_linestyle,"OUTPUT_LINESTYLE", OutputLineStyle, "Line Style Output", "" )
DefNode( ShaderNode, SH_NODE_FRESNEL, 0, "FRESNEL", Fresnel, "Fresnel", "" )
DefNode( ShaderNode, SH_NODE_LAYER_WEIGHT, 0, "LAYER_WEIGHT", LayerWeight, "Layer Weight", "" )
DefNode( ShaderNode, SH_NODE_MIX_SHADER, 0, "MIX_SHADER", MixShader, "Mix Shader", "" )
@@ -120,6 +121,7 @@ DefNode( ShaderNode, SH_NODE_VECT_TRANSFORM, def_sh_vect_transform, "VE
DefNode( ShaderNode, SH_NODE_SEPHSV, 0, "SEPHSV", SeparateHSV, "Separate HSV", "" )
DefNode( ShaderNode, SH_NODE_COMBHSV, 0, "COMBHSV", CombineHSV, "Combine HSV", "" )
DefNode( ShaderNode, SH_NODE_UVMAP, def_sh_uvmap, "UVMAP", UVMap, "UV Map", "" )
+DefNode( ShaderNode, SH_NODE_UVALONGSTROKE, def_sh_uvalongstroke, "UVALONGSTROKE", UVAlongStroke, "UV Along Stroke", "" )
DefNode( ShaderNode, SH_NODE_SEPXYZ, 0, "SEPXYZ", SeparateXYZ, "Separate XYZ", "" )
DefNode( ShaderNode, SH_NODE_COMBXYZ, 0, "COMBXYZ", CombineXYZ, "Combine XYZ", "" )
@@ -208,6 +210,7 @@ DefNode( CompositorNode, CMP_NODE_TRACKPOS, def_cmp_trackpos, "TRACK
DefNode( CompositorNode, CMP_NODE_PIXELATE, 0, "PIXELATE", Pixelate, "Pixelate", "" )
DefNode( CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLANETRACKDEFORM",PlaneTrackDeform,"Plane Track Deform","" )
DefNode( CompositorNode, CMP_NODE_CORNERPIN, 0, "CORNERPIN", CornerPin, "Corner Pin", "" )
+DefNode( CompositorNode, CMP_NODE_SUNBEAMS, def_cmp_sunbeams, "SUNBEAMS", SunBeams, "Sun Beams", "" )
DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript
index 683a1c475e4..becf6e79d44 100644
--- a/source/blender/nodes/SConscript
+++ b/source/blender/nodes/SConscript
@@ -72,6 +72,9 @@ if env['WITH_BF_COMPOSITOR']:
incs += ' ../compositor '
defs.append("WITH_COMPOSITOR")
+if env['WITH_BF_FREESTYLE']:
+ defs.append('WITH_FREESTYLE')
+
env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [190,105] )
env.BlenderLib ( libname = 'bf_cmpnodes', sources = cmpsources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [175,101] )
env.BlenderLib ( libname = 'bf_shdnodes', sources = shdsources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [175,101] )
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index cd69cf4982d..6d5b85da569 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -104,9 +104,9 @@ static void free_cache(bNodeTree *ntree)
}
/* local tree then owns all compbufs */
-static void localize(bNodeTree *localtree, bNodeTree *ntree)
+static void localize(bNodeTree *UNUSED(localtree), bNodeTree *ntree)
{
- bNode *node, *node_next;
+ bNode *node;
bNodeSocket *sock;
for (node = ntree->nodes.first; node; node = node->next) {
@@ -132,26 +132,6 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree)
sock->new_sock->new_sock = sock;
}
}
-
- /* replace muted nodes and reroute nodes by internal links */
- for (node = localtree->nodes.first; node; node = node_next) {
- node_next = node->next;
-
- if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
- /* make sure the update tag isn't lost when removing the muted node.
- * propagate this to all downstream nodes.
- */
- if (node->need_exec) {
- bNodeLink *link;
- for (link = localtree->links.first; link; link = link->next)
- if (link->fromnode == node && link->tonode)
- link->tonode->need_exec = 1;
- }
-
- nodeInternalRelink(localtree, node);
- nodeFreeNode(localtree, node);
- }
- }
}
static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
diff --git a/source/blender/nodes/composite/nodes/node_composite_sunbeams.c b/source/blender/nodes/composite/nodes/node_composite_sunbeams.c
new file mode 100644
index 00000000000..4d937d63b75
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_sunbeams.c
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/nodes/node_composite_sunbeams.c
+ * \ingroup cmpnodes
+ */
+
+#include "node_composite_util.h"
+
+static bNodeSocketTemplate inputs[] = {
+ { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f},
+ { -1, 0, "" }
+};
+static bNodeSocketTemplate outputs[] = {
+ { SOCK_RGBA, 0, N_("Image")},
+ { -1, 0, "" }
+};
+
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeSunBeams *data = MEM_callocN(sizeof(NodeSunBeams), "sun beams node");
+
+ data->source[0] = 0.5f;
+ data->source[1] = 0.5f;
+
+ node->storage = data;
+}
+
+void register_node_type_cmp_sunbeams(void)
+{
+ static bNodeType ntype;
+
+ cmp_node_type_base(&ntype, CMP_NODE_SUNBEAMS, "Sun Beams", NODE_CLASS_OP_FILTER, 0);
+ node_type_socket_templates(&ntype, inputs, outputs);
+ node_type_init(&ntype, init);
+ node_type_storage(&ntype, "NodeSunBeams", node_free_standard_storage, node_copy_standard_storage);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c
index ae834f9e7cc..c58c9c902ec 100644
--- a/source/blender/nodes/intern/node_common.c
+++ b/source/blender/nodes/intern/node_common.c
@@ -336,6 +336,40 @@ void ntree_update_reroute_nodes(bNodeTree *ntree)
node_reroute_inherit_type_recursive(ntree, node);
}
+static bool node_is_connected_to_output_recursive(bNodeTree *ntree, bNode *node)
+{
+ bNodeLink *link;
+
+ /* avoid redundant checks, and infinite loops in case of cyclic node links */
+ if (node->done)
+ return false;
+ node->done = 1;
+
+ /* main test, done before child loop so it catches output nodes themselves as well */
+ if (node->typeinfo->nclass == NODE_CLASS_OUTPUT && node->flag & NODE_DO_OUTPUT)
+ return true;
+
+ /* test all connected nodes, first positive find is sufficient to return true */
+ for (link = ntree->links.first; link; link = link->next) {
+ if (link->fromnode == node) {
+ if (node_is_connected_to_output_recursive(ntree, link->tonode))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool BKE_node_is_connected_to_output(bNodeTree *ntree, bNode *node)
+{
+ bNode *tnode;
+
+ /* clear flags */
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
+ tnode->done = 0;
+
+ return node_is_connected_to_output_recursive(ntree, node);
+}
+
void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree)
{
bNode *node;
diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c
index 0e5f72c831b..0893d2022a0 100644
--- a/source/blender/nodes/intern/node_exec.c
+++ b/source/blender/nodes/intern/node_exec.c
@@ -47,7 +47,7 @@
/* supported socket types in old nodes */
int node_exec_socket_use_stack(bNodeSocket *sock)
{
- return ELEM4(sock->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER);
+ return ELEM(sock->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER);
}
/* for a given socket, find the actual stack entry */
@@ -159,6 +159,8 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNo
int index;
bNode **nodelist;
int totnodes, n;
+ /* XXX texnodes have threading issues with muting, have to disable it there ... */
+ bool use_muting = (ntree->type != NTREE_TEXTURE);
/* ensure all sock->link pointers and node levels are correct */
ntreeUpdateTree(G.main, ntree);
@@ -182,7 +184,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNo
for (sock = node->inputs.first; sock; sock = sock->next)
node_init_input_index(sock, &index);
- if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
+ if (use_muting && (node->flag & NODE_MUTED || node->type == NODE_REROUTE)) {
for (sock = node->outputs.first; sock; sock = sock->next)
node_init_output_index(sock, &index, &node->internal_links);
}
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 4288b8fbcdc..299172ae4cc 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -38,6 +38,7 @@
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
#include "DNA_world_types.h"
+#include "DNA_linestyle_types.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
@@ -48,6 +49,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_scene.h"
@@ -97,6 +99,16 @@ static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(tre
}
}
}
+#ifdef WITH_FREESTYLE
+ else if (snode->shaderfrom == SNODE_SHADER_LINESTYLE) {
+ FreestyleLineStyle *linestyle = BKE_linestyle_active_from_scene(scene);
+ if (linestyle) {
+ *r_from = NULL;
+ *r_id = &linestyle->id;
+ *r_ntree = linestyle->nodetree;
+ }
+ }
+#endif
else { /* SNODE_SHADER_WORLD */
if (scene->world) {
*r_from = NULL;
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
index 55dafaeca35..75ca4b87f09 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
@@ -30,7 +30,7 @@
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_bsdf_glass_in[] = {
- { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 1, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Roughness"), 0.0f, 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_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_linestyle.c b/source/blender/nodes/shader/nodes/node_shader_output_linestyle.c
new file mode 100644
index 00000000000..2eb68f23912
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_output_linestyle.c
@@ -0,0 +1,54 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_output_linestyle_in[] = {
+ { SOCK_RGBA, 1, N_("Color"), 1.0f, 0.0f, 1.0f, 1.0f },
+ { SOCK_FLOAT, 1, N_("Color Fac"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR },
+ { SOCK_FLOAT, 1, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR },
+ { SOCK_FLOAT, 1, N_("Alpha Fac"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR },
+ { -1, 0, "" }
+};
+
+/* node type definition */
+void register_node_type_sh_output_linestyle(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_OUTPUT_LINESTYLE, "Line Style Output", NODE_CLASS_OUTPUT, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_output_linestyle_in, NULL);
+ node_type_init(&ntype, NULL);
+
+ /* Do not allow muting output node. */
+ node_type_internal_links(&ntype, NULL);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c b/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c
new file mode 100644
index 00000000000..48eb4cadba4
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+#include "DNA_customdata_types.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_uvalongstroke_out[] = {
+ { SOCK_VECTOR, 0, N_("UV"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+/* node type definition */
+void register_node_type_sh_uvalongstroke(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_UVALONGSTROKE, "UV Along Stroke", NODE_CLASS_INPUT, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, NULL, sh_node_uvalongstroke_out);
+ node_type_init(&ntype, NULL);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_uvmap.c b/source/blender/nodes/shader/nodes/node_shader_uvmap.c
index fff1bc1df95..0f96cb45fe0 100644
--- a/source/blender/nodes/shader/nodes/node_shader_uvmap.c
+++ b/source/blender/nodes/shader/nodes/node_shader_uvmap.c
@@ -42,6 +42,14 @@ static void node_shader_init_uvmap(bNodeTree *UNUSED(ntree), bNode *node)
node->storage = attr;
}
+static int node_shader_gpu_uvmap(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ NodeShaderUVMap *attr = node->storage;
+ GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, attr->uv_map);
+
+ return GPU_stack_link(mat, "node_uvmap", in, out, mtface);
+}
+
/* node type definition */
void register_node_type_sh_uvmap(void)
{
@@ -53,6 +61,7 @@ void register_node_type_sh_uvmap(void)
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_init(&ntype, node_shader_init_uvmap);
node_type_storage(&ntype, "NodeShaderUVMap", node_free_standard_storage, node_copy_standard_storage);
+ node_type_gpu(&ntype, node_shader_gpu_uvmap);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index 882c843f317..02f15705ad1 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -44,6 +44,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_paint.h"
@@ -110,7 +111,7 @@ static void texture_get_from_context(const bContext *C, bNodeTreeType *UNUSED(tr
}
}
else if (snode->texfrom == SNODE_TEX_LINESTYLE) {
- FreestyleLineStyle *linestyle = CTX_data_linestyle_from_scene(scene);
+ FreestyleLineStyle *linestyle = BKE_linestyle_active_from_scene(scene);
if (linestyle) {
*r_from = (ID *)linestyle;
tx = give_current_linestyle_texture(linestyle);
@@ -136,6 +137,10 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa
func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
}
+/* XXX muting disabled in previews because of threading issues with the main execution
+ * it works here, but disabled for consistency
+ */
+#if 0
static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
{
bNode *node, *node_next;
@@ -150,6 +155,11 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
}
}
}
+#else
+static void localize(bNodeTree *UNUSED(localtree), bNodeTree *UNUSED(ntree))
+{
+}
+#endif
static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
{
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index c2b496f914b..a31345cd7f5 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -645,7 +645,7 @@ static int bpy_bmfaceseq_active_set(BPy_BMElem *self, PyObject *value, void *UNU
return 0;
}
else if (BPy_BMFace_Check(value)) {
- BPY_BM_CHECK_SOURCE_INT(value, bm, "faces.active = f");
+ BPY_BM_CHECK_SOURCE_INT(bm, "faces.active = f", value);
bm->act_face = ((BPy_BMFace *)value)->f;
return 0;
@@ -1217,6 +1217,44 @@ static PyObject *bpy_bmesh_calc_volume(BPy_BMElem *self, PyObject *args, PyObjec
}
}
+PyDoc_STRVAR(bpy_bmesh_calc_tessface_doc,
+".. method:: calc_tessface()\n"
+"\n"
+" Calculate triangle tessellation from quads/ngons.\n"
+"\n"
+" :return: The triangulated faces.\n"
+" :rtype: list of :class:`BMLoop` tuples\n"
+);
+static PyObject *bpy_bmesh_calc_tessface(BPy_BMElem *self)
+{
+ BMesh *bm;
+
+ int looptris_tot;
+ int tottri;
+ BMLoop *(*looptris)[3];
+
+ PyObject *ret;
+ int i;
+
+ BPY_BM_CHECK_OBJ(self);
+
+ bm = self->bm;
+
+ looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
+ looptris = PyMem_MALLOC(sizeof(*looptris) * looptris_tot);
+
+ BM_bmesh_calc_tessellation(bm, looptris, &tottri);
+
+ ret = PyList_New(tottri);
+ for (i = 0; i < tottri; i++) {
+ PyList_SET_ITEM(ret, i, BPy_BMLoop_Array_As_Tuple(bm, looptris[i], 3));
+ }
+
+ PyMem_FREE(looptris);
+
+ return ret;
+}
+
/* Elem
* ---- */
@@ -1373,7 +1411,7 @@ static PyObject *bpy_bmvert_copy_from_face_interp(BPy_BMVert *self, PyObject *ar
else {
BMesh *bm = self->bm;
- BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "copy_from_face_interp()");
+ BPY_BM_CHECK_SOURCE_OBJ(bm, "copy_from_face_interp()", py_face);
BM_vert_interp_from_face(bm, self->v, py_face->f);
@@ -1519,7 +1557,7 @@ static PyObject *bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value)
return NULL;
}
- BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "BMEdge.other_vert(vert)");
+ BPY_BM_CHECK_SOURCE_OBJ(self->bm, "BMEdge.other_vert(vert)", value);
other = BM_edge_other_vert(self->e, value->v);
@@ -1576,7 +1614,7 @@ static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *ar
else {
BMesh *bm = self->bm;
- BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "BMFace.copy_from_face_interp(face)");
+ BPY_BM_CHECK_SOURCE_OBJ(bm, "BMFace.copy_from_face_interp(face)", py_face);
BM_face_interp_from_face(bm, self->f, py_face->f, do_vertex);
@@ -1773,7 +1811,7 @@ static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *ar
else {
BMesh *bm = self->bm;
- BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "BMLoop.copy_from_face_interp(face)");
+ BPY_BM_CHECK_SOURCE_OBJ(bm, "BMLoop.copy_from_face_interp(face)", py_face);
BM_loop_interp_from_face(bm, self->l, py_face->f, do_vertex, do_multires);
@@ -2056,7 +2094,7 @@ static PyObject *bpy_bmvertseq_remove(BPy_BMElemSeq *self, BPy_BMVert *value)
else {
BMesh *bm = self->bm;
- BPY_BM_CHECK_SOURCE_OBJ(value, bm, "verts.remove(vert)");
+ BPY_BM_CHECK_SOURCE_OBJ(bm, "verts.remove(vert)", value);
BM_vert_kill(bm, value->v);
bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
@@ -2080,7 +2118,7 @@ static PyObject *bpy_bmedgeseq_remove(BPy_BMElemSeq *self, BPy_BMEdge *value)
else {
BMesh *bm = self->bm;
- BPY_BM_CHECK_SOURCE_OBJ(value, bm, "edges.remove(edges)");
+ BPY_BM_CHECK_SOURCE_OBJ(bm, "edges.remove(edges)", value);
BM_edge_kill(bm, value->e);
bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
@@ -2104,7 +2142,7 @@ static PyObject *bpy_bmfaceseq_remove(BPy_BMElemSeq *self, BPy_BMFace *value)
else {
BMesh *bm = self->bm;
- BPY_BM_CHECK_SOURCE_OBJ(value, bm, "faces.remove(face)");
+ BPY_BM_CHECK_SOURCE_OBJ(bm, "faces.remove(face)", value);
BM_face_kill(bm, value->f);
bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
@@ -2488,6 +2526,7 @@ static struct PyMethodDef bpy_bmesh_methods[] = {
/* calculations */
{"calc_volume", (PyCFunction)bpy_bmesh_calc_volume, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_calc_volume_doc},
+ {"calc_tessface", (PyCFunction)bpy_bmesh_calc_tessface, METH_NOARGS, bpy_bmesh_calc_tessface_doc},
{NULL, NULL, 0, NULL}
};
@@ -3545,18 +3584,34 @@ int bpy_bm_generic_valid_check(BPy_BMGeneric *self)
}
}
-int bpy_bm_generic_valid_check_source(BPy_BMGeneric *self, BMesh *bm_source, const char *error_prefix)
+int bpy_bm_generic_valid_check_source(BMesh *bm_source, const char *error_prefix, void **args, unsigned int args_tot)
{
- int ret = bpy_bm_generic_valid_check(self);
- if (LIKELY(ret == 0)) {
- if (UNLIKELY(self->bm != bm_source)) {
- /* could give more info here */
- PyErr_Format(PyExc_ValueError,
- "%.200s: BMesh data of type %.200s is from another mesh",
- error_prefix, Py_TYPE(self)->tp_name);
- ret = -1;
+ int ret = 0;
+
+ while (args_tot--) {
+ BPy_BMGeneric *py_bm_elem = args[args_tot];
+ if (py_bm_elem) {
+
+ BLI_assert(BPy_BMesh_Check(py_bm_elem) ||
+ BPy_BMElem_Check(py_bm_elem));
+
+ ret = bpy_bm_generic_valid_check(py_bm_elem);
+ if (UNLIKELY(ret == -1)) {
+ break;
+ }
+ else {
+ if (UNLIKELY(py_bm_elem->bm != bm_source)) {
+ /* could give more info here */
+ PyErr_Format(PyExc_ValueError,
+ "%.200s: BMesh data of type %.200s is from another mesh",
+ error_prefix, Py_TYPE(py_bm_elem)->tp_name);
+ ret = -1;
+ break;
+ }
+ }
}
}
+
return ret;
}
@@ -3669,7 +3724,6 @@ err_cleanup:
}
}
-
PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len)
{
Py_ssize_t i;
@@ -3677,6 +3731,44 @@ PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_
for (i = 0; i < elem_len; i++) {
PyTuple_SET_ITEM(ret, i, BPy_BMElem_CreatePyObject(bm, elem[i]));
}
+ return ret;
+}
+PyObject *BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len)
+{
+ Py_ssize_t i;
+ PyObject *ret = PyTuple_New(elem_len);
+ for (i = 0; i < elem_len; i++) {
+ PyTuple_SET_ITEM(ret, i, BPy_BMVert_CreatePyObject(bm, elem[i]));
+ }
+ return ret;
+}
+PyObject *BPy_BMEdge_Array_As_Tuple(BMesh *bm, BMEdge **elem, Py_ssize_t elem_len)
+{
+ Py_ssize_t i;
+ PyObject *ret = PyTuple_New(elem_len);
+ for (i = 0; i < elem_len; i++) {
+ PyTuple_SET_ITEM(ret, i, BPy_BMEdge_CreatePyObject(bm, elem[i]));
+ }
+
+ return ret;
+}
+PyObject *BPy_BMFace_Array_As_Tuple(BMesh *bm, BMFace **elem, Py_ssize_t elem_len)
+{
+ Py_ssize_t i;
+ PyObject *ret = PyTuple_New(elem_len);
+ for (i = 0; i < elem_len; i++) {
+ PyTuple_SET_ITEM(ret, i, BPy_BMFace_CreatePyObject(bm, elem[i]));
+ }
+
+ return ret;
+}
+PyObject *BPy_BMLoop_Array_As_Tuple(BMesh *bm, BMLoop **elem, Py_ssize_t elem_len)
+{
+ Py_ssize_t i;
+ PyObject *ret = PyTuple_New(elem_len);
+ for (i = 0; i < elem_len; i++) {
+ PyTuple_SET_ITEM(ret, i, BPy_BMLoop_CreatePyObject(bm, elem[i]));
+ }
return ret;
}
diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h
index 0909ce0d26a..a2c2c312e71 100644
--- a/source/blender/python/bmesh/bmesh_py_types.h
+++ b/source/blender/python/bmesh/bmesh_py_types.h
@@ -164,13 +164,18 @@ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_
const char *error_prefix);
PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len);
+PyObject *BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len);
+PyObject *BPy_BMEdge_Array_As_Tuple(BMesh *bm, BMEdge **elem, Py_ssize_t elem_len);
+PyObject *BPy_BMFace_Array_As_Tuple(BMesh *bm, BMFace **elem, Py_ssize_t elem_len);
+PyObject *BPy_BMLoop_Array_As_Tuple(BMesh *bm, BMLoop **elem, Py_ssize_t elem_len);
+
int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype);
char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32]);
char *BPy_BMElem_StringFromHType(const char htype);
// void bpy_bm_generic_invalidate(BPy_BMGeneric *self);
int bpy_bm_generic_valid_check(BPy_BMGeneric *self);
-int bpy_bm_generic_valid_check_source(BPy_BMGeneric *self, BMesh *bm_source, const char *error_prefix);
+int bpy_bm_generic_valid_check_source(BMesh *bm_source, const char *error_prefix, void **args, unsigned int args_n) ATTR_NONNULL(1, 2);
#define BPY_BM_CHECK_OBJ(obj) \
if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return NULL; } (void)0
@@ -178,10 +183,18 @@ int bpy_bm_generic_valid_check_source(BPy_BMGeneric *self, BMesh *bm_source, co
if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return -1; } (void)0
/* macros like BPY_BM_CHECK_OBJ/BPY_BM_CHECK_INT that ensure we're from the right BMesh */
-#define BPY_BM_CHECK_SOURCE_OBJ(obj, bm, errmsg) \
- if (UNLIKELY(bpy_bm_generic_valid_check_source((BPy_BMGeneric *)obj, bm, errmsg) == -1)) { return NULL; } (void)0
-#define BPY_BM_CHECK_SOURCE_INT(obj, bm, errmsg) \
- if (UNLIKELY(bpy_bm_generic_valid_check_source((BPy_BMGeneric *)obj, bm, errmsg) == -1)) { return -1; } (void)0
+#define BPY_BM_CHECK_SOURCE_OBJ(bm, errmsg, ...) { \
+ void *_args[] = {__VA_ARGS__}; \
+ if (UNLIKELY(bpy_bm_generic_valid_check_source(bm, errmsg, _args, ARRAY_SIZE(_args)) == -1)) { \
+ return NULL; \
+ } \
+} (void)0
+#define BPY_BM_CHECK_SOURCE_INT(bm, errmsg, ...) { \
+ void *_args[] = {__VA_ARGS__}; \
+ if (UNLIKELY(bpy_bm_generic_valid_check_source(bm, errmsg, _args, ARRAY_SIZE(_args)) == -1)) { \
+ return -1; \
+ } \
+} (void)0
#define BPY_BM_IS_VALID(obj) (LIKELY((obj)->bm != NULL))
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c
index dfb3ae75df4..6ecb01a8528 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c
@@ -281,7 +281,7 @@ static PyObject *bpy_bmlayeritem_copy_from(BPy_BMLayerItem *self, BPy_BMLayerIte
}
BPY_BM_CHECK_OBJ(self);
- BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "layer.copy_from()");
+ BPY_BM_CHECK_SOURCE_OBJ(self->bm, "layer.copy_from()", value);
if ((self->htype != value->htype) ||
(self->type != value->type))
diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c
index b8e04a0cab8..3c72112e7ce 100644
--- a/source/blender/python/bmesh/bmesh_py_types_select.c
+++ b/source/blender/python/bmesh/bmesh_py_types_select.c
@@ -112,7 +112,7 @@ static PyObject *bpy_bmeditselseq_add(BPy_BMEditSelSeq *self, BPy_BMElem *value)
return NULL;
}
- BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "select_history.add()");
+ BPY_BM_CHECK_SOURCE_OBJ(self->bm, "select_history.add()", value);
BM_select_history_store(self->bm, value->ele);
@@ -137,7 +137,7 @@ static PyObject *bpy_bmeditselseq_remove(BPy_BMEditSelSeq *self, BPy_BMElem *val
return NULL;
}
- BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "select_history.remove()");
+ BPY_BM_CHECK_SOURCE_OBJ(self->bm, "select_history.remove()", value);
if (BM_select_history_remove(self->bm, value->ele) == false) {
PyErr_SetString(PyExc_ValueError,
diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c
index 4f1ca568bb0..88e369af8bb 100644
--- a/source/blender/python/bmesh/bmesh_py_utils.c
+++ b/source/blender/python/bmesh/bmesh_py_utils.c
@@ -198,6 +198,65 @@ static PyObject *bpy_bm_utils_vert_dissolve(PyObject *UNUSED(self), PyObject *ar
return PyBool_FromLong((BM_vert_dissolve(bm, py_vert->v)));
}
+PyDoc_STRVAR(bpy_bm_utils_vert_splice_doc,
+".. method:: vert_splice(vert, vert_target)\n"
+"\n"
+" Splice vert into vert_target.\n"
+"\n"
+" :arg vert: The vertex to be removed.\n"
+" :type vert: :class:`bmesh.types.BMVert`\n"
+" :arg vert_target: The vertex to use.\n"
+" :type vert_target: :class:`bmesh.types.BMVert`\n"
+"\n"
+" .. note:: The verts mustn't share an edge or face.\n"
+);
+static PyObject *bpy_bm_utils_vert_splice(PyObject *UNUSED(self), PyObject *args)
+{
+ BPy_BMVert *py_vert;
+ BPy_BMVert *py_vert_target;
+
+ BMesh *bm;
+
+ bool ok;
+
+ if (!PyArg_ParseTuple(args, "O!O!:vert_splice",
+ &BPy_BMVert_Type, &py_vert,
+ &BPy_BMVert_Type, &py_vert_target))
+ {
+ return NULL;
+ }
+
+ BPY_BM_CHECK_OBJ(py_vert);
+ BPY_BM_CHECK_OBJ(py_vert_target);
+
+ bm = py_vert->bm;
+ BPY_BM_CHECK_SOURCE_OBJ(bm, "vert_splice", py_vert_target);
+
+ if (py_vert->v == py_vert_target->v) {
+ PyErr_SetString(PyExc_ValueError,
+ "vert_splice(...): vert arguments match");
+ return NULL;
+ }
+
+ if (BM_edge_exists(py_vert->v, py_vert_target->v)) {
+ PyErr_SetString(PyExc_ValueError,
+ "vert_splice(...): verts can't share an edge");
+ return NULL;
+ }
+
+ if (BM_vert_pair_share_face_check(py_vert->v, py_vert_target->v)) {
+ PyErr_SetString(PyExc_ValueError,
+ "vert_splice(...): verts can't share a face");
+ return NULL;
+ }
+
+ /* should always succeed */
+ ok = BM_vert_splice(bm, py_vert->v, py_vert_target->v);
+ BLI_assert(ok == true);
+
+ Py_RETURN_NONE;
+}
+
PyDoc_STRVAR(bpy_bm_utils_vert_separate_doc,
".. method:: vert_separate(vert, edges)\n"
"\n"
@@ -247,7 +306,7 @@ static PyObject *bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *ar
BM_vert_separate(bm, py_vert->v, &elem, &elem_len, edge_array, edge_array_len);
/* return collected verts */
- ret = BPy_BMElem_Array_As_Tuple(bm, (BMHeader **)elem, elem_len);
+ ret = BPy_BMVert_Array_As_Tuple(bm, elem, elem_len);
MEM_freeN(elem);
PyMem_FREE(edge_array);
@@ -477,6 +536,78 @@ static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args,
}
+PyDoc_STRVAR(bpy_bm_utils_face_split_edgenet_doc,
+".. method:: face_split_edgenet(face, edgenet)\n"
+"\n"
+" Splits a face into any number of regions defined by an edgenet.\n"
+"\n"
+" :arg face: The face to split.\n"
+" :type face: :class:`bmesh.types.BMFace`\n"
+" :arg face: The face to split.\n"
+" :type face: :class:`bmesh.types.BMFace`\n"
+" :arg edgenet: Sequence of edges.\n"
+" :type edgenet: :class:`bmesh.types.BMEdge`\n"
+" :return: The newly created faces.\n"
+" :rtype: tuple of (:class:`bmesh.types.BMFace`)\n"
+);
+static PyObject *bpy_bm_utils_face_split_edgenet(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ static const char *kwlist[] = {"face", "edgenet", NULL};
+
+ BPy_BMFace *py_face;
+ PyObject *edge_seq;
+
+ BMEdge **edge_array;
+ Py_ssize_t edge_array_len;
+
+ BMesh *bm;
+
+ BMFace **face_arr;
+ int face_arr_len;
+ bool ok;
+
+
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O:face_split_edgenet", (char **)kwlist,
+ &BPy_BMFace_Type, &py_face,
+ &edge_seq))
+ {
+ return NULL;
+ }
+
+ BPY_BM_CHECK_OBJ(py_face);
+
+ bm = py_face->bm;
+
+ edge_array = BPy_BMElem_PySeq_As_Array(&bm, edge_seq, 1, PY_SSIZE_T_MAX,
+ &edge_array_len, BM_EDGE,
+ true, true, "face_split_edgenet(...)");
+
+ if (edge_array == NULL) {
+ return NULL;
+ }
+
+ /* --- main function body --- */
+
+ ok = BM_face_split_edgenet(bm, py_face->f, edge_array, edge_array_len,
+ &face_arr, &face_arr_len);
+
+ PyMem_FREE(edge_array);
+
+ if (ok) {
+ PyObject *ret = BPy_BMFace_Array_As_Tuple(bm, face_arr, face_arr_len);
+ if (face_arr) {
+ MEM_freeN(face_arr);
+ }
+ return ret;
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError,
+ "face_split_edgenet(...): couldn't split the face, internal error");
+ return NULL;
+ }
+}
+
+
PyDoc_STRVAR(bpy_bm_utils_face_join_doc,
".. method:: face_join(faces, remove=True)\n"
"\n"
@@ -560,7 +691,7 @@ static PyObject *bpy_bm_utils_face_vert_separate(PyObject *UNUSED(self), PyObjec
bm = py_face->bm;
BPY_BM_CHECK_OBJ(py_face);
- BPY_BM_CHECK_SOURCE_OBJ(py_vert, bm, "face_vert_separate()");
+ BPY_BM_CHECK_SOURCE_OBJ(bm, "face_vert_separate()", py_vert);
l = BM_face_vert_share_loop(py_face->f, py_vert->v);
@@ -648,10 +779,12 @@ static struct PyMethodDef BPy_BM_utils_methods[] = {
{"vert_collapse_edge", (PyCFunction)bpy_bm_utils_vert_collapse_edge, METH_VARARGS, bpy_bm_utils_vert_collapse_edge_doc},
{"vert_collapse_faces", (PyCFunction)bpy_bm_utils_vert_collapse_faces, METH_VARARGS, bpy_bm_utils_vert_collapse_faces_doc},
{"vert_dissolve", (PyCFunction)bpy_bm_utils_vert_dissolve, METH_VARARGS, bpy_bm_utils_vert_dissolve_doc}, /* could use METH_O */
+ {"vert_splice", (PyCFunction)bpy_bm_utils_vert_splice, METH_VARARGS, bpy_bm_utils_vert_splice_doc},
{"vert_separate", (PyCFunction)bpy_bm_utils_vert_separate, METH_VARARGS, bpy_bm_utils_vert_separate_doc},
{"edge_split", (PyCFunction)bpy_bm_utils_edge_split, METH_VARARGS, bpy_bm_utils_edge_split_doc},
{"edge_rotate", (PyCFunction)bpy_bm_utils_edge_rotate, METH_VARARGS, bpy_bm_utils_edge_rotate_doc},
{"face_split", (PyCFunction)bpy_bm_utils_face_split, METH_VARARGS | METH_KEYWORDS, bpy_bm_utils_face_split_doc},
+ {"face_split_edgenet", (PyCFunction)bpy_bm_utils_face_split_edgenet, METH_VARARGS | METH_KEYWORDS, bpy_bm_utils_face_split_edgenet_doc},
{"face_join", (PyCFunction)bpy_bm_utils_face_join, METH_VARARGS, bpy_bm_utils_face_join_doc},
{"face_vert_separate", (PyCFunction)bpy_bm_utils_face_vert_separate, METH_VARARGS, bpy_bm_utils_face_vert_separate_doc},
{"face_flip", (PyCFunction)bpy_bm_utils_face_flip, METH_O, bpy_bm_utils_face_flip_doc},
diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c
index d18720598d1..08b8fa28db4 100644
--- a/source/blender/python/generic/bgl.c
+++ b/source/blender/python/generic/bgl.c
@@ -303,7 +303,7 @@ static PyObject *Buffer_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject
if (!PyArg_ParseTuple(args, "iO|O: bgl.Buffer", &type, &length_ob, &init)) {
return NULL;
}
- if (!ELEM5(type, GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE)) {
+ if (!ELEM(type, GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE)) {
PyErr_SetString(PyExc_AttributeError,
"invalid first argument type, should be one of "
"GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT or GL_DOUBLE");
@@ -1900,9 +1900,20 @@ PyObject *BPyInit_bgl(void)
EXPP_ADDCONST(GL_TEXTURE7);
EXPP_ADDCONST(GL_TEXTURE8);
+ EXPP_ADDCONST(GL_MAX_TEXTURE_UNITS);
+
EXPP_ADDCONST(GL_DEPTH_COMPONENT32);
EXPP_ADDCONST(GL_TEXTURE_COMPARE_MODE);
+ EXPP_ADDCONST(GL_MAX_VARYING_FLOATS);
+ EXPP_ADDCONST(GL_MAX_VERTEX_ATTRIBS);
+ EXPP_ADDCONST(GL_MAX_VARYING_FLOATS);
+ EXPP_ADDCONST(GL_MAX_VERTEX_UNIFORM_COMPONENTS);
+ EXPP_ADDCONST(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
+ EXPP_ADDCONST(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
+ EXPP_ADDCONST(GL_MAX_TEXTURE_IMAGE_UNITS);
+ EXPP_ADDCONST(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+
return submodule;
}
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index dcdda2c440e..8c9e84af8ed 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -1541,7 +1541,7 @@ PyObject *BPyInit_idprop(void)
}
-#ifdef DEBUG
+#ifndef NDEBUG
/* -------------------------------------------------------------------- */
/* debug only function */
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 5fd19d3ed88..134e718bce5 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -51,12 +51,15 @@
#include "bpy_operator.h"
#include "bpy_utils_units.h"
+#include "../generic/py_capi_utils.h"
+
#include "MEM_guardedalloc.h"
/* external util modules */
#include "../generic/idprop_py_api.h"
#include "../generic/bgl.h"
#include "../generic/blf_py_api.h"
+#include "../generic/blf_py_api.h"
#include "../mathutils/mathutils.h"
#ifdef WITH_FREESTYLE
@@ -80,11 +83,11 @@ static PyObject *bpy_script_paths(PyObject *UNUSED(self))
const char *path;
path = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, NULL);
- item = PyUnicode_DecodeFSDefault(path ? path : "");
+ item = PyC_UnicodeFromByte(path ? path : "");
BLI_assert(item != NULL);
PyTuple_SET_ITEM(ret, 0, item);
path = BLI_get_folder(BLENDER_USER_SCRIPTS, NULL);
- item = PyUnicode_DecodeFSDefault(path ? path : "");
+ item = PyC_UnicodeFromByte(path ? path : "");
BLI_assert(item != NULL);
PyTuple_SET_ITEM(ret, 1, item);
@@ -94,7 +97,7 @@ static PyObject *bpy_script_paths(PyObject *UNUSED(self))
static bool bpy_blend_paths_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src)
{
PyObject *list = (PyObject *)userdata;
- PyObject *item = PyUnicode_DecodeFSDefault(path_src);
+ PyObject *item = PyC_UnicodeFromByte(path_src);
PyList_Append(list, item);
Py_DECREF(item);
return false; /* never edits the path */
@@ -171,7 +174,7 @@ static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObj
if (!path)
path = BLI_get_user_folder_notest(folder_id, subdir);
- return PyUnicode_DecodeFSDefault(path ? path : "");
+ return PyC_UnicodeFromByte(path ? path : "");
}
PyDoc_STRVAR(bpy_resource_path_doc,
@@ -210,7 +213,7 @@ static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObj
path = BLI_get_folder_version(folder_id, (major * 100) + minor, false);
- return PyUnicode_DecodeFSDefault(path ? path : "");
+ return PyC_UnicodeFromByte(path ? path : "");
}
PyDoc_STRVAR(bpy_escape_identifier_doc,
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index 0c13230c365..41ca2d49ed6 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -49,6 +49,7 @@ static PyStructSequence_Field app_cb_info_fields[] = {
{(char *)"render_pre", (char *)"Callback list - on render (before)"},
{(char *)"render_post", (char *)"Callback list - on render (after)"},
{(char *)"render_stats", (char *)"Callback list - on printing render statistics"},
+ {(char *)"render_init", (char *)"Callback list - on initialization of a render job"},
{(char *)"render_complete", (char *)"Callback list - on completion of render job"},
{(char *)"render_cancel", (char *)"Callback list - on canceling a render job"},
{(char *)"load_pre", (char *)"Callback list - on loading a new blend file (before)"},
@@ -59,6 +60,7 @@ static PyStructSequence_Field app_cb_info_fields[] = {
{(char *)"scene_update_post", (char *)"Callback list - on updating the scenes data (after)"},
{(char *)"game_pre", (char *)"Callback list - on starting the game engine"},
{(char *)"game_post", (char *)"Callback list - on ending the game engine"},
+ {(char *)"version_update", (char *)"Callback list - on ending the versioning code"},
/* sets the permanent tag */
# define APP_CB_OTHER_FIELDS 1
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index 2c526601fcd..1e97d7aeada 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -58,7 +58,7 @@
#include "BKE_report.h"
#include "BKE_context.h"
-/* so operators called can spawn threads which aquire the GIL */
+/* so operators called can spawn threads which acquire the GIL */
#define BPY_RELEASE_GIL
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 440af035bcd..a24f73c8f17 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -604,18 +604,34 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
#ifdef USE_MATHUTILS
int subtype, totdim;
int len;
- bool is_thick;
const int flag = RNA_property_flag(prop);
+ const int type = RNA_property_type(prop);
+ const bool is_thick = (flag & PROP_THICK_WRAP) != 0;
/* disallow dynamic sized arrays to be wrapped since the size could change
* to a size mathutils does not support */
- if ((RNA_property_type(prop) != PROP_FLOAT) || (flag & PROP_DYNAMIC))
+ if (flag & PROP_DYNAMIC) {
return NULL;
+ }
len = RNA_property_array_length(ptr, prop);
+ if (type == PROP_FLOAT) {
+ /* pass */
+ }
+ else if (type == PROP_INT) {
+ if (is_thick) {
+ goto thick_wrap_slice;
+ }
+ else {
+ return NULL;
+ }
+ }
+ else {
+ return NULL;
+ }
+
subtype = RNA_property_subtype(prop);
totdim = RNA_property_array_dimension(ptr, prop, NULL);
- is_thick = (flag & PROP_THICK_WRAP) != 0;
if (totdim == 1 || (totdim == 2 && subtype == PROP_MATRIX)) {
if (!is_thick)
@@ -712,6 +728,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
if (is_thick) {
/* this is an array we cant reference (since its not thin wrappable)
* and cannot be coerced into a mathutils type, so return as a list */
+thick_wrap_slice:
ret = pyrna_prop_array_subscript_slice(NULL, ptr, prop, 0, len, len);
}
else {
@@ -1363,7 +1380,7 @@ PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
if (subtype == PROP_BYTESTRING) {
ret = PyBytes_FromStringAndSize(buf, buf_len);
}
- else if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
+ else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
ret = PyC_UnicodeFromByteAndSize(buf, buf_len);
}
else {
@@ -1629,7 +1646,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
/* Unicode String */
#ifdef USE_STRING_COERCE
PyObject *value_coerce = NULL;
- if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
+ if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
/* TODO, get size */
param = PyC_UnicodeAsByte(value, &value_coerce);
}
@@ -2312,12 +2329,11 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, Po
int count, totdim;
PyObject *tuple;
- PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self);
+ /* isn't needed, internal use only */
+ // PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self);
tuple = PyTuple_New(stop - start);
- /* PYRNA_PROP_CHECK_OBJ(self); isn't needed, internal use only */
-
totdim = RNA_property_array_dimension(ptr, prop, NULL);
if (totdim > 1) {
@@ -4894,7 +4910,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
if (subtype == PROP_BYTESTRING) {
ret = PyBytes_FromString(data_ch);
}
- else if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
+ else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
ret = PyC_UnicodeFromByte(data_ch);
}
else {
diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c
index 5d8252d3c72..f6d124938a4 100644
--- a/source/blender/python/mathutils/mathutils_Euler.c
+++ b/source/blender/python/mathutils/mathutils_Euler.c
@@ -83,14 +83,23 @@ static const char *euler_order_str(EulerObject *self)
short euler_order_from_string(const char *str, const char *error_prefix)
{
if ((str[0] && str[1] && str[2] && str[3] == '\0')) {
+
+#ifdef __LITTLE_ENDIAN__
+# define MAKE_ID3(a, b, c) (((a)) | ((b) << 8) | ((c) << 16))
+#else
+# define MAKE_ID3(a, b, c) (((a) << 24) | ((b) << 16) | ((c) << 8))
+#endif
+
switch (*((PY_INT32_T *)str)) {
- case 'X' | 'Y' << 8 | 'Z' << 16: return EULER_ORDER_XYZ;
- case 'X' | 'Z' << 8 | 'Y' << 16: return EULER_ORDER_XZY;
- case 'Y' | 'X' << 8 | 'Z' << 16: return EULER_ORDER_YXZ;
- case 'Y' | 'Z' << 8 | 'X' << 16: return EULER_ORDER_YZX;
- case 'Z' | 'X' << 8 | 'Y' << 16: return EULER_ORDER_ZXY;
- case 'Z' | 'Y' << 8 | 'X' << 16: return EULER_ORDER_ZYX;
+ case MAKE_ID3('X', 'Y', 'Z'): return EULER_ORDER_XYZ;
+ case MAKE_ID3('X', 'Z', 'Y'): return EULER_ORDER_XZY;
+ case MAKE_ID3('Y', 'X', 'Z'): return EULER_ORDER_YXZ;
+ case MAKE_ID3('Y', 'Z', 'X'): return EULER_ORDER_YZX;
+ case MAKE_ID3('Z', 'X', 'Y'): return EULER_ORDER_ZXY;
+ case MAKE_ID3('Z', 'Y', 'X'): return EULER_ORDER_ZYX;
}
+
+#undef MAKE_ID3
}
PyErr_Format(PyExc_ValueError,
@@ -203,7 +212,7 @@ static PyObject *Euler_rotate_axis(EulerObject *self, PyObject *args)
return NULL;
}
- if (!(ELEM3(axis, 'X', 'Y', 'Z'))) {
+ if (!(ELEM(axis, 'X', 'Y', 'Z'))) {
PyErr_SetString(PyExc_ValueError,
"Euler.rotate_axis(): "
"expected axis to be 'X', 'Y' or 'Z'");
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 34564007478..282f29b4934 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -910,56 +910,141 @@ static float matrix_determinant_internal(const MatrixObject *self)
}
}
+static void adjoint_matrix_n(float *mat_dst, const float *mat_src, const unsigned short dim)
+{
+ /* calculate the classical adjoint */
+ switch (dim) {
+ case 2:
+ {
+ adjoint_m2_m2((float (*)[2])mat_dst, (float (*)[2])mat_src);
+ break;
+ }
+ case 3:
+ {
+ adjoint_m3_m3((float (*)[3])mat_dst, (float (*)[3])mat_src);
+ break;
+ }
+ case 4:
+ {
+ adjoint_m4_m4((float (*)[4])mat_dst, (float (*)[4])mat_src);
+ break;
+ }
+ default:
+ BLI_assert(0);
+ }
+}
+
+static void matrix_invert_with_det_n_internal(float *mat_dst, const float *mat_src, const float det, const unsigned short dim)
+{
+ float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+ unsigned short i, j, k;
+
+ BLI_assert(det != 0.0f);
+
+ adjoint_matrix_n(mat, mat_src, dim);
+
+ /* divide by determinant & set values */
+ k = 0;
+ for (i = 0; i < dim; i++) { /* num_col */
+ for (j = 0; j < dim; j++) { /* num_row */
+ mat_dst[MATRIX_ITEM_INDEX_NUMROW(dim, j, i)] = mat[k++] / det;
+ }
+ }
+}
+
/**
- * \param r_mat can be from ``self->matrix`` or not. */
+ * \param r_mat can be from ``self->matrix`` or not.
+ */
static bool matrix_invert_internal(const MatrixObject *self, float *r_mat)
{
float det;
-
+ BLI_assert(self->num_col == self->num_row);
det = matrix_determinant_internal(self);
if (det != 0.0f) {
- float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
- int x, y, z;
+ matrix_invert_with_det_n_internal(r_mat, self->matrix, det, self->num_col);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/**
+ * Similar to ``matrix_invert_internal`` but should never error.
+ * \param r_mat can be from ``self->matrix`` or not.
+ */
+static void matrix_invert_safe_internal(const MatrixObject *self, float *r_mat)
+{
+ float det;
+ float *in_mat = self->matrix;
+ BLI_assert(self->num_col == self->num_row);
+ det = matrix_determinant_internal(self);
+
+ if (det == 0.0f) {
+ const float eps = PSEUDOINVERSE_EPSILON;
+
+ /* We will copy self->matrix into r_mat (if needed), and modify it in place to add diagonal epsilon. */
+ in_mat = r_mat;
- /* calculate the classical adjoint */
switch (self->num_col) {
case 2:
{
- adjoint_m2_m2((float (*)[2])mat, (float (*)[2])self->matrix);
+ float (*mat)[2] = (float (*)[2])in_mat;
+
+ if (in_mat != self->matrix) {
+ copy_m2_m2(mat, (float (*)[2])self->matrix);
+ }
+ mat[0][0] += eps;
+ mat[1][1] += eps;
+
+ if (UNLIKELY((det = determinant_m2(mat[0][0], mat[0][1], mat[1][0], mat[1][1])) == 0.0f)) {
+ unit_m2(mat);
+ det = 1.0f;
+ }
break;
}
case 3:
{
- adjoint_m3_m3((float (*)[3])mat, (float (*)[3])self->matrix);
+ float (*mat)[3] = (float (*)[3])in_mat;
+
+ if (in_mat != self->matrix) {
+ copy_m3_m3(mat, (float (*)[3])self->matrix);
+ }
+ mat[0][0] += eps;
+ mat[1][1] += eps;
+ mat[2][2] += eps;
+
+ if (UNLIKELY((det = determinant_m3_array(mat)) == 0.0f)) {
+ unit_m3(mat);
+ det = 1.0f;
+ }
break;
}
case 4:
{
- adjoint_m4_m4((float (*)[4])mat, (float (*)[4])self->matrix);
+ float (*mat)[4] = (float (*)[4])in_mat;
+
+ if (in_mat != self->matrix) {
+ copy_m4_m4(mat, (float (*)[4])self->matrix);
+ }
+ mat[0][0] += eps;
+ mat[1][1] += eps;
+ mat[2][2] += eps;
+ mat[3][3] += eps;
+
+ if (UNLIKELY(det = determinant_m4(mat)) == 0.0f) {
+ unit_m4(mat);
+ det = 1.0f;
+ }
break;
}
default:
BLI_assert(0);
}
- /* divide by determinate */
- for (x = 0; x < (self->num_col * self->num_row); x++) {
- mat[x] /= det;
- }
- /* set values */
- z = 0;
- for (x = 0; x < self->num_col; x++) {
- for (y = 0; y < self->num_row; y++) {
- r_mat[MATRIX_ITEM_INDEX(self, y, x)] = mat[z];
- z++;
- }
- }
-
- return true;
- }
- else {
- return false;
}
+
+ matrix_invert_with_det_n_internal(r_mat, in_mat, det, self->num_col);
}
@@ -1398,6 +1483,56 @@ static PyObject *Matrix_inverted_noargs(MatrixObject *self)
Py_RETURN_NONE;
}
+PyDoc_STRVAR(Matrix_invert_safe_doc,
+".. method:: invert_safe()\n"
+"\n"
+" Set the matrix to its inverse, will never error.\n"
+" If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, to get an invertible one.\n"
+" If tweaked matrix is still degenerated, set to the identity matrix instead.\n"
+"\n"
+" .. seealso:: <http://en.wikipedia.org/wiki/Inverse_matrix>\n"
+);
+static PyObject *Matrix_invert_safe(MatrixObject *self)
+{
+ if (BaseMath_ReadCallback(self) == -1)
+ return NULL;
+
+ if (matrix_invert_is_compat(self) == false) {
+ return NULL;
+ }
+
+ matrix_invert_safe_internal(self, self->matrix);
+
+ (void)BaseMath_WriteCallback(self);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Matrix_inverted_safe_doc,
+".. method:: inverted_safe()\n"
+"\n"
+" Return an inverted copy of the matrix, will never error.\n"
+" If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, to get an invertible one.\n"
+" If tweaked matrix is still degenerated, return the identity matrix instead.\n"
+"\n"
+" :return: the inverted matrix.\n"
+" :rtype: :class:`Matrix`\n"
+);
+static PyObject *Matrix_inverted_safe(MatrixObject *self)
+{
+ float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+
+ if (BaseMath_ReadCallback(self) == -1)
+ return NULL;
+
+ if (matrix_invert_is_compat(self) == false) {
+ return NULL;
+ }
+
+ matrix_invert_safe_internal(self, mat);
+
+ return Matrix_copy_notest(self, mat);
+}
+
/*---------------------------matrix.adjugate() ---------------------*/
PyDoc_STRVAR(Matrix_adjugate_doc,
".. method:: adjugate()\n"
@@ -1421,34 +1556,16 @@ static PyObject *Matrix_adjugate(MatrixObject *self)
}
/* calculate the classical adjoint */
- switch (self->num_col) {
- case 2:
- {
- float mat[2][2];
- adjoint_m2_m2(mat, (float (*)[2])self->matrix);
- copy_v4_v4((float *)self->matrix, (float *)mat);
- break;
- }
- case 3:
- {
- float mat[3][3];
- adjoint_m3_m3(mat, (float (*)[3])self->matrix);
- copy_m3_m3((float (*)[3])self->matrix, mat);
- break;
- }
- case 4:
- {
- float mat[4][4];
- adjoint_m4_m4(mat, (float (*)[4])self->matrix);
- copy_m4_m4((float (*)[4])self->matrix, mat);
- break;
- }
- default:
- PyErr_Format(PyExc_ValueError,
- "Matrix adjugate(d): size (%d) unsupported",
- (int)self->num_col);
- return NULL;
+ if (self->num_col <= 4) {
+ adjoint_matrix_n(self->matrix, self->matrix, self->num_col);
}
+ else {
+ PyErr_Format(PyExc_ValueError,
+ "Matrix adjugate(d): size (%d) unsupported",
+ (int)self->num_col);
+ return NULL;
+ }
+
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
@@ -1755,10 +1872,7 @@ static PyObject *Matrix_identity(MatrixObject *self)
}
if (self->num_col == 2) {
- MATRIX_ITEM(self, 0, 0) = 1.0f;
- MATRIX_ITEM(self, 0, 1) = 0.0f;
- MATRIX_ITEM(self, 1, 0) = 0.0f;
- MATRIX_ITEM(self, 1, 1) = 1.0f;
+ unit_m2((float (*)[2])self->matrix);
}
else if (self->num_col == 3) {
unit_m3((float (*)[3])self->matrix);
@@ -2559,6 +2673,8 @@ static struct PyMethodDef Matrix_methods[] = {
{"normalized", (PyCFunction) Matrix_normalized, METH_NOARGS, Matrix_normalized_doc},
{"invert", (PyCFunction) Matrix_invert, METH_VARARGS, Matrix_invert_doc},
{"inverted", (PyCFunction) Matrix_inverted, METH_VARARGS, Matrix_inverted_doc},
+ {"invert_safe", (PyCFunction) Matrix_invert_safe, METH_NOARGS, Matrix_invert_safe_doc},
+ {"inverted_safe", (PyCFunction) Matrix_inverted_safe, METH_NOARGS, Matrix_inverted_safe_doc},
{"adjugate", (PyCFunction) Matrix_adjugate, METH_NOARGS, Matrix_adjugate_doc},
{"adjugated", (PyCFunction) Matrix_adjugated, METH_NOARGS, Matrix_adjugated_doc},
{"to_3x3", (PyCFunction) Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc},
diff --git a/source/blender/python/mathutils/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h
index c7fb23d8776..f94af9e540e 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.h
+++ b/source/blender/python/mathutils/mathutils_Matrix.h
@@ -41,6 +41,7 @@ extern PyTypeObject matrix_access_Type;
# define MATRIX_ITEM_ASSERT(_mat, _row, _col) (void)0
#endif
+#define MATRIX_ITEM_INDEX_NUMROW(_totrow, _row, _col) ((_totrow * (_col)) + (_row))
#define MATRIX_ITEM_INDEX(_mat, _row, _col) (MATRIX_ITEM_ASSERT(_mat, _row, _col),(((_mat)->num_row * (_col)) + (_row)))
#define MATRIX_ITEM_PTR( _mat, _row, _col) ((_mat)->matrix + MATRIX_ITEM_INDEX(_mat, _row, _col))
#define MATRIX_ITEM( _mat, _row, _col) ((_mat)->matrix [MATRIX_ITEM_INDEX(_mat, _row, _col)])
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index a719691d5d4..15a9860be0a 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -814,17 +814,20 @@ static PyObject *Vector_orthogonal(VectorObject *self)
{
float vec[3];
- if (self->size != 3) {
+ if (self->size > 3) {
PyErr_SetString(PyExc_TypeError,
"Vector.orthogonal(): "
- "Vector must be 3D");
+ "Vector must be 3D or 2D");
return NULL;
}
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- ortho_v3_v3(vec, self->vec);
+ if (self->size == 3)
+ ortho_v3_v3(vec, self->vec);
+ else
+ ortho_v2_v2(vec, self->vec);
return Vector_CreatePyObject(vec, self->size, Py_NEW, Py_TYPE(self));
}
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 139764abb00..b4add0fc615 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -229,6 +229,11 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject
}
result = isect_line_line_v3(v1, v2, v3, v4, i1, i2);
+ /* The return-code isnt exposed,
+ * this way we can check know how close the lines are. */
+ if (result == 1) {
+ closest_to_line_v3(i2, i1, v3, v4);
+ }
if (result == 0) {
/* colinear */
@@ -597,7 +602,7 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec
return NULL;
}
- if (ELEM4(2, line_a->size, line_b->size, plane_co->size, plane_no->size)) {
+ if (ELEM(2, line_a->size, line_b->size, plane_co->size, plane_no->size)) {
PyErr_SetString(PyExc_ValueError,
"geometry.intersect_line_plane(...): "
" can't use 2D Vectors");
@@ -654,7 +659,7 @@ static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObje
return NULL;
}
- if (ELEM4(2, plane_a_co->size, plane_a_no->size, plane_b_co->size, plane_b_no->size)) {
+ if (ELEM(2, plane_a_co->size, plane_a_no->size, plane_b_co->size, plane_b_no->size)) {
PyErr_SetString(PyExc_ValueError,
"geometry.intersect_plane_plane(...): "
" can't use 2D Vectors");
@@ -726,7 +731,7 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
return NULL;
}
- if (ELEM3(2, line_a->size, line_b->size, sphere_co->size)) {
+ if (ELEM(2, line_a->size, line_b->size, sphere_co->size)) {
PyErr_SetString(PyExc_ValueError,
"geometry.intersect_line_sphere(...): "
" can't use 2D Vectors");
@@ -893,13 +898,69 @@ static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObjec
return ret;
}
+PyDoc_STRVAR(M_Geometry_intersect_point_tri_doc,
+".. function:: intersect_point_tri(pt, tri_p1, tri_p2, tri_p3)\n"
+"\n"
+" Takes 4 vectors: one is the point and the next 3 define the triangle.\n"
+"\n"
+" :arg pt: Point\n"
+" :type pt: :class:`mathutils.Vector`\n"
+" :arg tri_p1: First point of the triangle\n"
+" :type tri_p1: :class:`mathutils.Vector`\n"
+" :arg tri_p2: Second point of the triangle\n"
+" :type tri_p2: :class:`mathutils.Vector`\n"
+" :arg tri_p3: Third point of the triangle\n"
+" :type tri_p3: :class:`mathutils.Vector`\n"
+" :return: Point on the triangles plane or None if its outside the triangle\n"
+" :rtype: :class:`mathutils.Vector` or None\n"
+);
+static PyObject *M_Geometry_intersect_point_tri(PyObject *UNUSED(self), PyObject *args)
+{
+ VectorObject *pt_vec, *tri_p1, *tri_p2, *tri_p3;
+ float vi[3];
+
+ if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_point_tri",
+ &vector_Type, &pt_vec,
+ &vector_Type, &tri_p1,
+ &vector_Type, &tri_p2,
+ &vector_Type, &tri_p3))
+ {
+ return NULL;
+ }
+
+ if (BaseMath_ReadCallback(pt_vec) == -1 ||
+ BaseMath_ReadCallback(tri_p1) == -1 ||
+ BaseMath_ReadCallback(tri_p2) == -1 ||
+ BaseMath_ReadCallback(tri_p3) == -1)
+ {
+ return NULL;
+ }
+
+ if (pt_vec->size < 3 ||
+ tri_p1->size < 3 ||
+ tri_p2->size < 3 ||
+ tri_p3->size < 3)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "One of more of the vector arguments wasn't a 3D vector");
+ return NULL;
+ }
+
+ if (isect_point_tri_v3(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec, vi)) {
+ return Vector_CreatePyObject(vi, 3, Py_NEW, NULL);
+ }
+ else {
+ Py_RETURN_NONE;
+ }
+}
+
PyDoc_STRVAR(M_Geometry_intersect_point_tri_2d_doc,
".. function:: intersect_point_tri_2d(pt, tri_p1, tri_p2, tri_p3)\n"
"\n"
" Takes 4 vectors (using only the x and y coordinates): one is the point and the next 3 define the triangle. Returns 1 if the point is within the triangle, otherwise 0.\n"
"\n"
" :arg pt: Point\n"
-" :type v1: :class:`mathutils.Vector`\n"
+" :type pt: :class:`mathutils.Vector`\n"
" :arg tri_p1: First point of the triangle\n"
" :type tri_p1: :class:`mathutils.Vector`\n"
" :arg tri_p2: Second point of the triangle\n"
@@ -1021,7 +1082,7 @@ static PyObject *M_Geometry_distance_point_to_plane(PyObject *UNUSED(self), PyOb
}
plane_from_point_normal_v3(plane, plane_co->vec, plane_no->vec);
- return PyFloat_FromDouble(dist_to_plane_v3(pt->vec, plane));
+ return PyFloat_FromDouble(dist_signed_to_plane_v3(pt->vec, plane));
}
PyDoc_STRVAR(M_Geometry_barycentric_transform_doc,
@@ -1053,7 +1114,7 @@ static PyObject *M_Geometry_barycentric_transform(PyObject *UNUSED(self), PyObje
VectorObject *vec_t1_src, *vec_t2_src, *vec_t3_src;
float vec[3];
- if (!PyArg_ParseTuple(args, "O!O!O!O!O!O!O!:barycentric_transform",
+ if (!PyArg_ParseTuple(args, "O!O!O!O!O!O!O!::barycentric_transform",
&vector_Type, &vec_pt,
&vector_Type, &vec_t1_src,
&vector_Type, &vec_t2_src,
@@ -1089,9 +1150,10 @@ static PyObject *M_Geometry_barycentric_transform(PyObject *UNUSED(self), PyObje
return NULL;
}
- barycentric_transform(vec, vec_pt->vec,
- vec_t1_tar->vec, vec_t2_tar->vec, vec_t3_tar->vec,
- vec_t1_src->vec, vec_t2_src->vec, vec_t3_src->vec);
+ transform_point_by_tri_v3(
+ vec, vec_pt->vec,
+ vec_t1_tar->vec, vec_t2_tar->vec, vec_t3_tar->vec,
+ vec_t1_src->vec, vec_t2_src->vec, vec_t3_src->vec);
return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
}
@@ -1606,6 +1668,7 @@ static PyObject *M_Geometry_convex_hull_2d(PyObject *UNUSED(self), PyObject *poi
static PyMethodDef M_Geometry_methods[] = {
{"intersect_ray_tri", (PyCFunction) M_Geometry_intersect_ray_tri, METH_VARARGS, M_Geometry_intersect_ray_tri_doc},
{"intersect_point_line", (PyCFunction) M_Geometry_intersect_point_line, METH_VARARGS, M_Geometry_intersect_point_line_doc},
+ {"intersect_point_tri", (PyCFunction) M_Geometry_intersect_point_tri, METH_VARARGS, M_Geometry_intersect_point_tri_doc},
{"intersect_point_tri_2d", (PyCFunction) M_Geometry_intersect_point_tri_2d, METH_VARARGS, M_Geometry_intersect_point_tri_2d_doc},
{"intersect_point_quad_2d", (PyCFunction) M_Geometry_intersect_point_quad_2d, METH_VARARGS, M_Geometry_intersect_point_quad_2d_doc},
{"intersect_line_line", (PyCFunction) M_Geometry_intersect_line_line, METH_VARARGS, M_Geometry_intersect_line_line_doc},
diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h
index 8f2a0e382a4..481da452529 100644
--- a/source/blender/render/extern/include/RE_bake.h
+++ b/source/blender/render/extern/include/RE_bake.h
@@ -39,7 +39,7 @@ typedef struct BakeImage {
struct Image *image;
int width;
int height;
- int offset;
+ size_t offset;
} BakeImage;
typedef struct BakeImages {
@@ -72,35 +72,35 @@ bool RE_bake_has_engine(struct Render *re);
bool RE_bake_engine(
struct Render *re, struct Object *object, const BakePixel pixel_array[],
- const int num_pixels, const int depth, const ScenePassType pass_type, float result[]);
+ const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]);
/* bake.c */
int RE_pass_depth(const ScenePassType pass_type);
bool RE_bake_internal(
struct Render *re, struct Object *object, const BakePixel pixel_array[],
- const int num_pixels, const int depth, const ScenePassType pass_type, float result[]);
+ const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]);
bool RE_bake_pixels_populate_from_objects(
struct Mesh *me_low, BakePixel pixel_array_from[],
- BakeHighPolyData highpoly[], const int tot_highpoly, const int num_pixels, const bool is_custom_cage,
+ BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage,
const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage);
void RE_bake_pixels_populate(
struct Mesh *me, struct BakePixel *pixel_array,
- const int num_pixels, const struct BakeImages *bake_images, const char *uv_layer);
+ const size_t num_pixels, const struct BakeImages *bake_images, const char *uv_layer);
-void RE_bake_mask_fill(const BakePixel pixel_array[], const int num_pixels, char *mask);
+void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask);
void RE_bake_margin(struct ImBuf *ibuf, char *mask, const int margin);
void RE_bake_normal_world_to_object(
- const BakePixel pixel_array[], const int num_pixels, const int depth, float result[],
+ const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[],
struct Object *ob, const BakeNormalSwizzle normal_swizzle[3]);
void RE_bake_normal_world_to_tangent(
- const BakePixel pixel_array[], const int num_pixels, const int depth, float result[],
+ const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[],
struct Mesh *me, const BakeNormalSwizzle normal_swizzle[3], float mat[4][4]);
void RE_bake_normal_world_to_world(
- const BakePixel pixel_array[], const int num_pixels, const int depth, float result[],
+ const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[],
const BakeNormalSwizzle normal_swizzle[3]);
void RE_bake_ibuf_clear(struct Image *image, const bool is_tangent);
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 68ac0cd3073..3b54de4c943 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -194,6 +194,7 @@ void RE_InitState(struct Render *re, struct Render *source, struct RenderData *r
struct SceneRenderLayer *srl,
int winx, int winy, rcti *disprect);
void RE_ChangeResolution(struct Render *re, int winx, int winy, rcti *disprect);
+void RE_ChangeModeFlag(struct Render *re, int flag, bool clear);
/* set up the viewplane/perspective matrix, three choices */
struct Object *RE_GetCamera(struct Render *re); /* return camera override if set */
@@ -234,6 +235,7 @@ void RE_BlenderAnim(struct Render *re, struct Main *bmain, struct Scene *scene,
unsigned int lay_override, int sfra, int efra, int tfra);
#ifdef WITH_FREESTYLE
void RE_RenderFreestyleStrokes(struct Render *re, struct Main *bmain, struct Scene *scene, int render);
+void RE_RenderFreestyleExternal(struct Render *re);
#endif
/* error reporting */
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 536a2b8a85f..b87b1e6f367 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -595,7 +595,9 @@ typedef struct LampRen {
float imat[3][3];
float spottexfac;
float sh_invcampos[3], sh_zfac; /* sh_= spothalo */
-
+
+ float lampmat[4][4]; /* worls space lamp matrix, used for scene rotation */
+
float mat[3][3]; /* 3x3 part from lampmat x viewmat */
float area[8][3], areasize;
diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c
index f2793a9bc5b..15634c93491 100644
--- a/source/blender/render/intern/source/bake.c
+++ b/source/blender/render/intern/source/bake.c
@@ -174,7 +174,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
/* only do AO for a full bake (and obviously AO bakes)
* AO for light bakes is a leftover and might not be needed */
- if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT))
+ if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT))
shade_samples_do_AO(ssamp);
if (shi->mat->nodetree && shi->mat->use_nodes) {
@@ -303,7 +303,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
rgb_float_to_uchar(col, shr.combined);
}
- if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE, RE_BAKE_VERTEX_COLORS)) {
+ if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE, RE_BAKE_VERTEX_COLORS)) {
col[3] = FTOCHAR(shr.alpha);
}
else {
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index efa8c9b98f4..90deac2de32 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -120,7 +120,7 @@ static void store_bake_pixel(void *handle, int x, int y, float u, float v)
BakePixel *pixel;
const int width = bd->bk_image->width;
- const int offset = bd->bk_image->offset;
+ const size_t offset = bd->bk_image->offset;
const int i = offset + y * width + x;
pixel = &bd->pixel_array[i];
@@ -134,9 +134,9 @@ static void store_bake_pixel(void *handle, int x, int y, float u, float v)
pixel->dv_dy = bd->dv_dy;
}
-void RE_bake_mask_fill(const BakePixel pixel_array[], const int num_pixels, char *mask)
+void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask)
{
- int i;
+ size_t i;
if (!mask)
return;
@@ -356,7 +356,7 @@ static void mesh_calc_tri_tessface(
MFace *mface;
MVert *mvert;
TSpace *tspace;
- float *precomputed_normals;
+ float *precomputed_normals = NULL;
bool calculate_normal;
mface = CustomData_get_layer(&me->fdata, CD_MFACE);
@@ -379,7 +379,7 @@ static void mesh_calc_tri_tessface(
p_id = -1;
for (i = 0; i < me->totface; i++) {
MFace *mf = &mface[i];
- TSpace *ts = &tspace[i * 4];
+ TSpace *ts = tangent ? &tspace[i * 4] : NULL;
p_id++;
@@ -438,10 +438,10 @@ static void mesh_calc_tri_tessface(
bool RE_bake_pixels_populate_from_objects(
struct Mesh *me_low, BakePixel pixel_array_from[],
- BakeHighPolyData highpoly[], const int tot_highpoly, const int num_pixels, const bool is_custom_cage,
+ BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage,
const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage)
{
- int i;
+ size_t i;
int primitive_id;
float u, v;
float imat_low [4][4];
@@ -461,7 +461,7 @@ bool RE_bake_pixels_populate_from_objects(
tris_high = MEM_callocN(sizeof(TriTessFace *) * tot_highpoly, "MVerts Highpoly Mesh Array");
/* assume all highpoly tessfaces are triangles */
- dm_highpoly = MEM_callocN(sizeof(DerivedMesh *) * tot_highpoly, "Highpoly Derived Meshes");
+ dm_highpoly = MEM_mallocN(sizeof(DerivedMesh *) * tot_highpoly, "Highpoly Derived Meshes");
treeData = MEM_callocN(sizeof(BVHTreeFromMesh) * tot_highpoly, "Highpoly BVH Trees");
if (!is_cage) {
@@ -594,11 +594,11 @@ static void bake_differentials(BakeDataZSpan *bd, const float *uv1, const float
void RE_bake_pixels_populate(
Mesh *me, BakePixel pixel_array[],
- const int num_pixels, const BakeImages *bake_images, const char *uv_layer)
+ const size_t num_pixels, const BakeImages *bake_images, const char *uv_layer)
{
BakeDataZSpan bd;
- int i, a;
- int p_id;
+ size_t i;
+ int a, p_id;
MTFace *mtface;
MFace *mface;
@@ -725,11 +725,11 @@ static void normal_compress(float out[3], const float in[3], const BakeNormalSwi
* This function converts an object space normal map to a tangent space normal map for a given low poly mesh
*/
void RE_bake_normal_world_to_tangent(
- const BakePixel pixel_array[], const int num_pixels, const int depth,
+ const BakePixel pixel_array[], const size_t num_pixels, const int depth,
float result[], Mesh *me, const BakeNormalSwizzle normal_swizzle[3],
float mat[4][4])
{
- int i;
+ size_t i;
TriTessFace *triangles;
@@ -756,7 +756,7 @@ void RE_bake_normal_world_to_tangent(
float tsm[3][3]; /* tangent space matrix */
float itsm[3][3];
- int offset;
+ size_t offset;
float nor[3]; /* texture normal */
bool is_smooth;
@@ -834,16 +834,16 @@ void RE_bake_normal_world_to_tangent(
}
void RE_bake_normal_world_to_object(
- const BakePixel pixel_array[], const int num_pixels, const int depth,
+ const BakePixel pixel_array[], const size_t num_pixels, const int depth,
float result[], struct Object *ob, const BakeNormalSwizzle normal_swizzle[3])
{
- int i;
+ size_t i;
float iobmat[4][4];
invert_m4_m4(iobmat, ob->obmat);
for (i = 0; i < num_pixels; i++) {
- int offset;
+ size_t offset;
float nor[3];
if (pixel_array[i].primitive_id == -1)
@@ -852,7 +852,8 @@ void RE_bake_normal_world_to_object(
offset = i * depth;
normal_uncompress(nor, &result[offset]);
- mul_m4_v3(iobmat, nor);
+ /* rotates only without translation */
+ mul_mat3_m4_v3(iobmat, nor);
normalize_v3(nor);
/* save back the values */
@@ -861,13 +862,13 @@ void RE_bake_normal_world_to_object(
}
void RE_bake_normal_world_to_world(
- const BakePixel pixel_array[], const int num_pixels, const int depth,
+ const BakePixel pixel_array[], const size_t num_pixels, const int depth,
float result[], const BakeNormalSwizzle normal_swizzle[3])
{
- int i;
+ size_t i;
for (i = 0; i < num_pixels; i++) {
- int offset;
+ size_t offset;
float nor[3];
if (pixel_array[i].primitive_id == -1)
@@ -907,12 +908,12 @@ void RE_bake_ibuf_clear(Image *image, const bool is_tangent)
/**
* not the real UV, but the internal per-face UV instead
* I'm using it to test if everything is correct */
-static bool bake_uv(const BakePixel pixel_array[], const int num_pixels, const int depth, float result[])
+static bool bake_uv(const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[])
{
- int i;
+ size_t i;
for (i=0; i < num_pixels; i++) {
- int offset = i * depth;
+ size_t offset = i * depth;
copy_v2_v2(&result[offset], pixel_array[i].uv);
}
@@ -921,7 +922,7 @@ static bool bake_uv(const BakePixel pixel_array[], const int num_pixels, const i
bool RE_bake_internal(
Render *UNUSED(re), Object *UNUSED(object), const BakePixel pixel_array[],
- const int num_pixels, const int depth, const ScenePassType pass_type, float result[])
+ const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[])
{
switch (pass_type) {
case SCE_PASS_UV:
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 36fd1b2d6af..e6f054583b1 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -2930,8 +2930,7 @@ static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort)
/* make sorted table with edges and face indices in it */
for (a= totface, mf= mface; a>0; a--, mf++) {
- if (mf->v4) totedge+=4;
- else if (mf->v3) totedge+=3;
+ totedge += mf->v4 ? 4 : 3;
}
if (totedge==0)
@@ -2946,8 +2945,9 @@ static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort)
to_edgesort(ed++, 2, 3, mf->v3, mf->v4, a);
to_edgesort(ed++, 3, 0, mf->v4, mf->v1, a);
}
- else if (mf->v3)
+ else {
to_edgesort(ed++, 2, 3, mf->v3, mf->v1, a);
+ }
}
qsort(edsort, totedge, sizeof(struct edgesort), vergedgesort);
@@ -3650,6 +3650,7 @@ static GroupObject *add_render_lamp(Render *re, Object *ob)
mul_m4_m4m4(mat, re->viewmat, ob->obmat);
invert_m4_m4(ob->imat, mat);
+ copy_m4_m4(lar->lampmat, ob->obmat);
copy_m3_m4(lar->mat, mat);
copy_m3_m4(lar->imat, ob->imat);
@@ -3704,8 +3705,8 @@ static GroupObject *add_render_lamp(Render *re, Object *ob)
/* Annoying, lamp UI does this, but the UI might not have been used? - add here too.
* make sure this matches buttons_shading.c's logic */
- if (ELEM4(la->type, LA_AREA, LA_SPOT, LA_SUN, LA_LOCAL) && (la->mode & LA_SHAD_RAY))
- if (ELEM3(la->type, LA_SPOT, LA_SUN, LA_LOCAL))
+ if (ELEM(la->type, LA_AREA, LA_SPOT, LA_SUN, LA_LOCAL) && (la->mode & LA_SHAD_RAY))
+ if (ELEM(la->type, LA_SPOT, LA_SUN, LA_LOCAL))
if (la->ray_samp_method == LA_SAMP_CONSTANT) la->ray_samp_method = LA_SAMP_HALTON;
lar->ray_samp_method= la->ray_samp_method;
@@ -4546,8 +4547,7 @@ static void set_dupli_tex_mat(Render *re, ObjectInstanceRen *obi, DupliObject *d
obi->duplitexmat= BLI_memarena_alloc(re->memArena, sizeof(float)*4*4);
invert_m4_m4(imat, dob->mat);
- mul_serie_m4(obi->duplitexmat, re->viewmat, omat, imat, re->viewinv,
- NULL, NULL, NULL, NULL);
+ mul_m4_series(obi->duplitexmat, re->viewmat, omat, imat, re->viewinv);
}
copy_v3_v3(obi->dupliorco, dob->orco);
@@ -4791,13 +4791,12 @@ static int allow_render_object(Render *re, Object *ob, int nolamps, int onlysele
{
if (is_object_hidden(re, ob))
return 0;
-
- /* override not showing object when duplis are used with particles */
- if (ob->transflag & OB_DUPLIPARTS) {
- /* pass */ /* let particle system(s) handle showing vs. not showing */
- }
- else if ((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) {
- return 0;
+
+ /* Only handle dupli-hiding here if there is no particle systems. Else, let those handle show/noshow. */
+ if (!ob->particlesystem.first) {
+ if ((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) {
+ return 0;
+ }
}
/* don't add non-basic meta objects, ends up having renderobjects with no geometry */
@@ -4832,7 +4831,7 @@ static int allow_render_dupli_instance(Render *UNUSED(re), DupliObject *dob, Obj
}
for (psys=obd->particlesystem.first; psys; psys=psys->next)
- if (!ELEM5(psys->part->ren_as, PART_DRAW_BB, PART_DRAW_LINE, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR))
+ if (!ELEM(psys->part->ren_as, PART_DRAW_BB, PART_DRAW_LINE, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR))
return 0;
/* don't allow lamp, animated duplis, or radio render */
@@ -5834,8 +5833,8 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
Object *camera;
float mat[4][4];
float amb[3];
- const short onlyselected= !ELEM5(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW, RE_BAKE_AO, RE_BAKE_VERTEX_COLORS);
- const short nolamps= ELEM5(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS);
+ const short onlyselected= !ELEM(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW, RE_BAKE_AO, RE_BAKE_VERTEX_COLORS);
+ const short nolamps= ELEM(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS);
re->main= bmain;
re->scene= scene;
@@ -5859,7 +5858,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
if (type==RE_BAKE_VERTEX_COLORS)
re->flag |= R_NEED_VCOL;
- if (!actob && ELEM6(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS)) {
+ if (!actob && ELEM(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS)) {
re->r.mode &= ~R_SHADOW;
re->r.mode &= ~R_RAYTRACE;
}
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index 28b29261e4e..06be00a5a5e 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -329,9 +329,9 @@ void env_rotate_scene(Render *re, float mat[4][4], int do_rotate)
/* copy from add_render_lamp */
if (do_rotate == 1)
- mul_m4_m4m4(tmpmat, re->viewmat, go->ob->obmat);
+ mul_m4_m4m4(tmpmat, re->viewmat, lar->lampmat);
else
- mul_m4_m4m4(tmpmat, re->viewmat_orig, go->ob->obmat);
+ mul_m4_m4m4(tmpmat, re->viewmat_orig, lar->lampmat);
invert_m4_m4(go->ob->imat, tmpmat);
copy_m3_m4(lar->mat, tmpmat);
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 58e3038682c..888f1330373 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -425,7 +425,7 @@ bool RE_bake_has_engine(Render *re)
bool RE_bake_engine(
Render *re, Object *object, const BakePixel pixel_array[],
- const int num_pixels, const int depth,
+ const size_t num_pixels, const int depth,
const ScenePassType pass_type, float result[])
{
RenderEngineType *type = RE_engines_find(re->r.engine);
@@ -454,8 +454,8 @@ bool RE_bake_engine(
engine->resolution_y = re->winy;
RE_parts_init(re, false);
- engine->tile_x = re->partx;
- engine->tile_y = re->party;
+ engine->tile_x = re->r.tilex;
+ engine->tile_y = re->r.tiley;
/* update is only called so we create the engine.session */
if (type->update)
@@ -676,6 +676,11 @@ int RE_engine_render(Render *re, int do_all)
if (BKE_reports_contain(re->reports, RPT_ERROR))
G.is_break = true;
+#ifdef WITH_FREESTYLE
+ if (re->r.mode & R_EDGE_FRS)
+ RE_RenderFreestyleExternal(re);
+#endif
+
return 1;
}
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index 7d4b70cea15..12701099e18 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -791,176 +791,39 @@ static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata
texr->ta = texr->talpha ? texr->ta*xsd : (clip ? cw*xsd : 1.f);
}
-/* table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2
- * used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible */
-#define EWA_MAXIDX 255
-static const float EWA_WTS[EWA_MAXIDX + 1] = {
- 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f,
- 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f,
- 0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f,
- 0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f,
- 0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f,
- 0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f,
- 0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f,
- 0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f,
- 0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f,
- 0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f,
- 0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f,
- 0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f,
- 0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f,
- 0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f,
- 0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f,
- 0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f,
- 0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f,
- 0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f,
- 0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f,
- 0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f,
- 0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f,
- 0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f,
- 0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f,
- 0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f,
- 0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f,
- 0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f,
- 0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f,
- 0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f,
- 0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f,
- 0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f,
- 0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f,
- 0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f
-};
-
/* test if a float value is 'nan'
* there is a C99 function for this: isnan(), but blender seems to use C90 (according to gcc warns),
* and may not be supported by other compilers either */
+/* TODO(sergey): Consider using isnan(), it's used in the other areas. */
#ifndef ISNAN
-#define ISNAN(x) ((x) != (x))
+# define ISNAN(x) ((x) != (x))
#endif
-//static int ISNAN(float x) { return (x != x); }
-static void radangle2imp(float a2, float b2, float th, float *A, float *B, float *C, float *F)
-{
- float ct2 = cosf(th);
- const float st2 = 1.0f - ct2 * ct2; /* <- sin(th)^2 */
- ct2 *= ct2;
- *A = a2*st2 + b2*ct2;
- *B = (b2 - a2)*sinf(2.f*th);
- *C = a2*ct2 + b2*st2;
- *F = a2*b2;
-}
+typedef struct ReadEWAData {
+ ImBuf *ibuf;
+ afdata_t *AFD;
+} ReadEWAData;
-/* all tests here are done to make sure possible overflows are hopefully minimized */
-static void imp2radangle(float A, float B, float C, float F, float *a, float *b, float *th, float *ecc)
+static void ewa_read_pixel_cb(void *userdata, int x, int y, float result[4])
{
- if (F <= 1e-5f) { /* use arbitrary major radius, zero minor, infinite eccentricity */
- *a = sqrtf(A > C ? A : C);
- *b = 0.f;
- *ecc = 1e10f;
- *th = 0.5f*(atan2f(B, A - C) + (float)M_PI);
- }
- else {
- const float AmC = A - C, ApC = A + C, F2 = F*2.f;
- const float r = sqrtf(AmC*AmC + B*B);
- float d = ApC - r;
- *a = (d <= 0.f) ? sqrtf(A > C ? A : C) : sqrtf(F2 / d);
- d = ApC + r;
- if (d <= 0.f) {
- *b = 0.f;
- *ecc = 1e10f;
- }
- else {
- *b = sqrtf(F2 / d);
- *ecc = *a / *b;
- }
- /* incr theta by 0.5*pi (angle of major axis) */
- *th = 0.5f*(atan2f(B, AmC) + (float)M_PI);
- }
+ ReadEWAData *data = (ReadEWAData *) userdata;
+ ibuf_get_color_clip(result, data->ibuf, x, y, data->AFD->extflag);
}
static void ewa_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
{
- /* scaling dxt/dyt by full resolution can cause overflow because of huge A/B/C and esp. F values,
- * scaling by aspect ratio alone does the opposite, so try something in between instead... */
- const float ff2 = ibuf->x, ff = sqrtf(ff2), q = ibuf->y / ff;
- const float Ux = AFD->dxt[0]*ff, Vx = AFD->dxt[1]*q, Uy = AFD->dyt[0]*ff, Vy = AFD->dyt[1]*q;
- float A = Vx*Vx + Vy*Vy;
- float B = -2.f*(Ux*Vx + Uy*Vy);
- float C = Ux*Ux + Uy*Uy;
- float F = A*C - B*B*0.25f;
- float a, b, th, ecc, a2, b2, ue, ve, U0, V0, DDQ, U, ac1, ac2, BU, d; /* TXF alpha: cw = 0.f; */
- int u, v, u1, u2, v1, v2; /* TXF alpha: clip = 0; */
-
- /* The so-called 'high' quality ewa method simply adds a constant of 1 to both A & C,
- * so the ellipse always covers at least some texels. But since the filter is now always larger,
- * it also means that everywhere else it's also more blurry then ideally should be the case.
- * So instead here the ellipse radii are modified instead whenever either is too low.
- * Use a different radius based on interpolation switch, just enough to anti-alias when interpolation is off,
- * and slightly larger to make result a bit smoother than bilinear interpolation when interpolation is on
- * (minimum values: const float rmin = intpol ? 1.f : 0.5f;) */
- const float rmin = (AFD->intpol ? 1.5625f : 0.765625f)/ff2;
- imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
- if ((b2 = b*b) < rmin) {
- if ((a2 = a*a) < rmin) {
- B = 0.f;
- A = C = rmin;
- F = A*C;
- }
- else {
- b2 = rmin;
- radangle2imp(a2, b2, th, &A, &B, &C, &F);
- }
- }
-
- ue = ff*sqrtf(C);
- ve = ff*sqrtf(A);
- d = (float)(EWA_MAXIDX + 1) / (F*ff2);
- A *= d;
- B *= d;
- C *= d;
-
- U0 = fx*ibuf->x;
- V0 = fy*ibuf->y;
- u1 = (int)(floorf(U0 - ue));
- u2 = (int)(ceilf(U0 + ue));
- v1 = (int)(floorf(V0 - ve));
- v2 = (int)(ceilf(V0 + ve));
- U0 -= 0.5f;
- V0 -= 0.5f;
- DDQ = 2.f*A;
- U = u1 - U0;
- ac1 = A*(2.f*U + 1.f);
- ac2 = A*U*U;
- BU = B*U;
+ ReadEWAData data;
+ float uv[2] = {fx, fy};
+ data.ibuf = ibuf;
+ data.AFD = AFD;
+ BLI_ewa_filter(ibuf->x, ibuf->y,
+ AFD->intpol != 0,
+ texr->talpha,
+ uv, AFD->dxt, AFD->dyt,
+ ewa_read_pixel_cb,
+ &data,
+ &texr->tr);
- d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f;
- for (v=v1; v<=v2; ++v) {
- const float V = v - V0;
- float DQ = ac1 + B*V;
- float Q = (C*V + BU)*V + ac2;
- for (u=u1; u<=u2; ++u) {
- if (Q < (float)(EWA_MAXIDX + 1)) {
- float tc[4];
- const float wt = EWA_WTS[(Q < 0.f) ? 0 : (unsigned int)Q];
- /*const int out =*/ ibuf_get_color_clip(tc, ibuf, u, v, AFD->extflag);
- /* TXF alpha: clip |= out;
- * TXF alpha: cw += out ? 0.f : wt; */
- texr->tr += tc[0]*wt;
- texr->tg += tc[1]*wt;
- texr->tb += tc[2]*wt;
- texr->ta += texr->talpha ? tc[3]*wt : 0.f;
- d += wt;
- }
- Q += DQ;
- DQ += DDQ;
- }
- }
-
- /* d should hopefully never be zero anymore */
- d = 1.f/d;
- texr->tr *= d;
- texr->tg *= d;
- texr->tb *= d;
- /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */
- texr->ta = texr->talpha ? texr->ta*d : 1.f; /* TXF alpha (clip ? cw*d : 1.f); */
}
static void feline_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
@@ -1304,7 +1167,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
const float C = Ux*Ux + Uy*Uy;
const float F = A*C - B*B*0.25f;
float a, b, th, ecc;
- imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
+ BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
if (tex->texfilter == TXF_FELINE) {
float fProbes;
a *= ff;
@@ -1408,7 +1271,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
const float C = Ux*Ux + Uy*Uy;
const float F = A*C - B*B*0.25f;
float a, b, th, ecc, fProbes;
- imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
+ BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
a *= ff;
b *= ff;
a = max_ff(a, 1.0f);
diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c
index f0fe5d054f0..0c6341fe9e5 100644
--- a/source/blender/render/intern/source/occlusion.c
+++ b/source/blender/render/intern/source/occlusion.c
@@ -45,6 +45,7 @@
#include "BLF_translation.h"
+#include "BKE_node.h"
#include "BKE_scene.h"
@@ -194,14 +195,19 @@ static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr,
}
/* init material vars */
- /* note, keep this synced with render_types.h */
- memcpy(&shi->r, &shi->mat->r, 23 * sizeof(float));
- shi->har = shi->mat->har;
-
+ shade_input_init_material(shi);
+
/* render */
shade_input_set_shade_texco(shi);
- shade_material_loop(shi, shr); /* todo: nodes */
-
+
+ if (shi->mat->nodetree && shi->mat->use_nodes) {
+ ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
+ shi->mat = vlr->mat; /* shi->mat is being set in nodetree */
+ }
+ else {
+ shade_material_loop(shi, shr);
+ }
+
copy_v3_v3(rad, shr->combined);
}
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 2131b820bd4..8469d8c74f0 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -728,6 +728,7 @@ static void render_result_rescale(Render *re)
void RE_ChangeResolution(Render *re, int winx, int winy, rcti *disprect)
{
re_init_resolution(re, NULL, winx, winy, disprect);
+ RE_parts_clamp(re);
if (re->result) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
@@ -736,6 +737,20 @@ void RE_ChangeResolution(Render *re, int winx, int winy, rcti *disprect)
}
}
+/* TODO(sergey): This is a bit hackish, used to temporary disable freestyle when
+ * doing viewport render. Needs some better integration of BI viewport rendering
+ * into the pipeline.
+ */
+void RE_ChangeModeFlag(Render *re, int flag, bool clear)
+{
+ if (clear) {
+ re->r.mode &= ~flag;
+ }
+ else {
+ re->r.mode |= flag;
+ }
+}
+
/* update some variables that can be animated, and otherwise wouldn't be due to
* RenderData getting copied once at the start of animation render */
void render_update_anim_renderdata(Render *re, RenderData *rd)
@@ -1713,7 +1728,7 @@ static int composite_needs_render(Scene *sce, int this_scene)
if ((sce->r.scemode & R_DOCOMP) == 0) return 1;
for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_R_LAYERS)
+ if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0)
if (this_scene == 0 || node->id == NULL || node->id == &sce->id)
return 1;
}
@@ -1852,7 +1867,7 @@ static void tag_scenes_for_render(Render *re)
/* check for render-layers nodes using other scenes, we tag them LIB_DOIT */
for (node = re->scene->nodetree->nodes.first; node; node = node->next) {
node->flag &= ~NODE_TEST;
- if (node->type == CMP_NODE_R_LAYERS) {
+ if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) {
if (node->id) {
if (!MAIN_VERSION_ATLEAST(re->main, 265, 5)) {
if (rlayer_node_uses_alpha(re->scene->nodetree, node)) {
@@ -1901,7 +1916,7 @@ static void ntree_render_scenes(Render *re)
/* now foreach render-result node tagged we do a full render */
/* results are stored in a way compisitor will find it */
for (node = re->scene->nodetree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_R_LAYERS) {
+ if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) {
if (node->id && node->id != (ID *)re->scene) {
if (node->flag & NODE_TEST) {
Scene *scene = (Scene *)node->id;
@@ -1935,6 +1950,8 @@ static void add_freestyle(Render *re, int render)
{
SceneRenderLayer *srl, *actsrl;
LinkData *link;
+ Render *r;
+ const bool do_link = (re->r.mode & R_MBLUR) == 0 || re->i.curblur == re->r.mblur_samples;
actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
@@ -1951,15 +1968,17 @@ static void add_freestyle(Render *re, int render)
FRS_init_stroke_rendering(re);
- for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) {
-
- link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render");
- BLI_addtail(&re->freestyle_renders, link);
-
+ for (srl = (SceneRenderLayer *)re->r.layers.first; srl; srl = srl->next) {
+ if (do_link) {
+ link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render");
+ BLI_addtail(&re->freestyle_renders, link);
+ }
if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
continue;
if (FRS_is_freestyle_enabled(srl)) {
- link->data = (void *)FRS_do_stroke_rendering(re, srl, render);
+ r = FRS_do_stroke_rendering(re, srl, render);
+ if (do_link)
+ link->data = (void *)r;
}
}
@@ -2183,7 +2202,7 @@ void RE_MergeFullSample(Render *re, Main *bmain, Scene *sce, bNodeTree *ntree)
#endif
for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_R_LAYERS) {
+ if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) {
Scene *nodescene = (Scene *)node->id;
if (nodescene == NULL) nodescene = sce;
@@ -2478,7 +2497,7 @@ static bool check_valid_compositing_camera(Scene *scene, Object *camera_override
bNode *node = scene->nodetree->nodes.first;
while (node) {
- if (node->type == CMP_NODE_R_LAYERS) {
+ if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) {
Scene *sce = node->id ? (Scene *)node->id : scene;
if (!sce->camera && !BKE_scene_camera_find(sce)) {
@@ -2760,6 +2779,8 @@ void RE_SetReports(Render *re, ReportList *reports)
void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override,
unsigned int lay_override, int frame, const bool write_still)
{
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT);
+
/* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */
G.is_rendering = true;
@@ -2806,6 +2827,16 @@ void RE_RenderFreestyleStrokes(Render *re, Main *bmain, Scene *scene, int render
}
re->result_ok = 1;
}
+
+void RE_RenderFreestyleExternal(Render *re)
+{
+ if (!re->test_break(re->tbh)) {
+ RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
+ RE_Database_Preprocess(re);
+ add_freestyle(re, 1);
+ RE_Database_Free(re);
+ }
+}
#endif
static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override)
@@ -2924,6 +2955,8 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
int cfrao = scene->r.cfra;
int nfra, totrendered = 0, totskipped = 0;
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT);
+
/* do not fully call for each frame, it initializes & pops output window */
if (!render_initialize_from_main(re, &rd, bmain, scene, NULL, camera_override, lay_override, 0, 1))
return;
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 253f8a1383f..dd14c2495e8 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -3564,7 +3564,7 @@ Material *RE_init_sample_material(Material *orig_mat, Scene *scene)
/* depending of material type, strip non-compatible mapping modes */
if (mat->material_type == MA_TYPE_SURFACE) {
- if (!ELEM4(mtex->texco, TEXCO_ORCO, TEXCO_OBJECT, TEXCO_GLOB, TEXCO_UV)) {
+ if (!ELEM(mtex->texco, TEXCO_ORCO, TEXCO_OBJECT, TEXCO_GLOB, TEXCO_UV)) {
/* ignore this texture */
mtex->texco = 0;
continue;
@@ -3573,7 +3573,7 @@ Material *RE_init_sample_material(Material *orig_mat, Scene *scene)
mtex->mapto = (mtex->mapto & MAP_COL) | (mtex->mapto & MAP_ALPHA);
}
else if (mat->material_type == MA_TYPE_VOLUME) {
- if (!ELEM3(mtex->texco, TEXCO_OBJECT, TEXCO_ORCO, TEXCO_GLOB)) {
+ if (!ELEM(mtex->texco, TEXCO_OBJECT, TEXCO_ORCO, TEXCO_GLOB)) {
/* ignore */
mtex->texco = 0;
continue;
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 9d337e542a1..aa420d7e7c8 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -784,7 +784,7 @@ void makeshadowbuf(Render *re, LampRen *lar)
perspective_m4(shb->winmat, -wsize, wsize, -wsize, wsize, shb->d, shb->clipend);
mul_m4_m4m4(shb->persmat, shb->winmat, shb->viewmat);
- if (ELEM3(lar->buftype, LA_SHADBUF_REGULAR, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP)) {
+ if (ELEM(lar->buftype, LA_SHADBUF_REGULAR, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP)) {
shb->totbuf= lar->buffers;
/* jitter, weights - not threadsafe! */
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index ebf88efb50b..427d0eeed11 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -1706,9 +1706,19 @@ static void wrld_exposure_correct(float diff[3])
void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
{
+ /* Passes which might need to know material color.
+ *
+ * It seems to be faster to just calculate material color
+ * even if the pass doesn't really need it than trying to
+ * figure out whether color is really needed or not.
+ */
+ const int color_passes =
+ SCE_PASS_COMBINED | SCE_PASS_RGBA | SCE_PASS_DIFFUSE | SCE_PASS_SPEC |
+ SCE_PASS_REFLECT | SCE_PASS_NORMAL | SCE_PASS_REFRACT | SCE_PASS_EMIT;
+
Material *ma= shi->mat;
int passflag= shi->passflag;
-
+
memset(shr, 0, sizeof(ShadeResult));
if (!(shi->mode & MA_TRANSP)) shi->alpha = 1.0f;
@@ -1723,7 +1733,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0f;
/* material color itself */
- if (passflag & (SCE_PASS_COMBINED|SCE_PASS_RGBA)) {
+ if (passflag & color_passes) {
if (ma->mode & (MA_FACETEXTURE)) {
shi->r= shi->vcol[0];
shi->g= shi->vcol[1];
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
index fe3af5b840e..d5c4c407bf6 100644
--- a/source/blender/render/intern/source/volumetric.c
+++ b/source/blender/render/intern/source/volumetric.c
@@ -499,7 +499,7 @@ static void vol_shade_one_lamp(struct ShadeInput *shi, const float co[3], const
if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADOWED) {
mul_v3_fl(lacol, vol_get_shadow(shi, lar, co));
}
- else if (ELEM3(shi->mat->vol.shade_type, MA_VOL_SHADE_SHADED, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) {
+ else if (ELEM(shi->mat->vol.shade_type, MA_VOL_SHADE_SHADED, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) {
Isect is;
if (shi->mat->vol.shadeflag & MA_VOL_RECV_EXT_SHADOW) {
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 9886d403f74..35b7fb4b9c9 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -151,7 +151,7 @@ typedef void (*wmUIHandlerRemoveFunc)(struct bContext *C, void *userdata);
struct wmEventHandler *WM_event_add_ui_handler(
const struct bContext *C, ListBase *handlers,
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
- void *userdata);
+ void *userdata, const bool accept_dbl_click);
void WM_event_remove_ui_handler(
ListBase *handlers,
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
@@ -241,7 +241,8 @@ int WM_operator_call (struct bContext *C, struct wmOperator *op);
int WM_operator_call_notest(struct bContext *C, struct wmOperator *op);
int WM_operator_repeat (struct bContext *C, struct wmOperator *op);
bool WM_operator_repeat_check(const struct bContext *C, struct wmOperator *op);
-int WM_operator_name_call (struct bContext *C, const char *opstring, short context, struct PointerRNA *properties);
+int WM_operator_name_call_ptr(struct bContext *C, struct wmOperatorType *ot, short context, struct PointerRNA *properties);
+int WM_operator_name_call(struct bContext *C, const char *opstring, short context, struct PointerRNA *properties);
int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, short context, struct PointerRNA *properties, struct ReportList *reports, const bool is_undo);
void WM_operator_properties_alloc(struct PointerRNA **ptr, struct IDProperty **properties, const char *opstring); /* used for keymap and macro items */
@@ -343,8 +344,10 @@ void WM_event_print(const struct wmEvent *event);
void WM_operator_region_active_win_set(struct bContext *C);
/* drag and drop */
-struct wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value);
+struct wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value, unsigned int flags);
void WM_event_drag_image(struct wmDrag *, struct ImBuf *, float scale, int sx, int sy);
+void WM_drag_free(struct wmDrag *drag);
+void WM_drag_free_list(struct ListBase *lb);
struct wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(struct bContext *, struct wmDrag *, const struct wmEvent *event),
void (*copy)(struct wmDrag *, struct wmDropBox *));
@@ -448,6 +451,9 @@ void WM_event_ndof_rotate_get(const struct wmNDOFMotionData *ndof, float
float WM_event_ndof_to_axis_angle(const struct wmNDOFMotionData *ndof, float axis[3]);
void WM_event_ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4]);
+float WM_event_tablet_data(const struct wmEvent *event, int *pen_flip, float tilt[2]);
+bool WM_event_is_tablet(const struct wmEvent *event);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index 9645c95f62b..c6c7314e963 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -64,6 +64,8 @@ wmKeyMapItem *WM_keymap_add_item(struct wmKeyMap *keymap, const char *idname, in
int val, int modifier, int keymodifier);
wmKeyMapItem *WM_keymap_add_menu(struct wmKeyMap *keymap, const char *idname, int type,
int val, int modifier, int keymodifier);
+wmKeyMapItem *WM_keymap_add_menu_pie(struct wmKeyMap *keymap, const char *idname, int type,
+ int val, int modifier, int keymodifier);
bool WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi);
int WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, const int len);
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 9ad1bc97f4d..090d9516f1f 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -128,7 +128,7 @@ struct ImBuf;
#define OPTYPE_UNDO 2 /* do undo push after after */
#define OPTYPE_BLOCKING 4 /* let blender grab all input from the WM (X11) */
#define OPTYPE_MACRO 8
-#define OPTYPE_GRAB_POINTER 16 /* */
+#define OPTYPE_GRAB_POINTER 16 /* grabs the cursor and optionally enables continuous cursor wrapping */
#define OPTYPE_PRESET 32 /* show preset menu */
#define OPTYPE_INTERNAL 64 /* some operators are mainly for internal use
* and don't make sense to be accessed from the
@@ -597,6 +597,12 @@ typedef struct wmReport {
#define WM_DRAG_PATH 2
#define WM_DRAG_NAME 3
#define WM_DRAG_VALUE 4
+#define WM_DRAG_COLOR 5
+
+typedef enum wmDragFlags {
+ WM_DRAG_NOP = 0,
+ WM_DRAG_FREE_DATA = 1,
+} wmDragFlags;
/* note: structs need not exported? */
@@ -613,6 +619,7 @@ typedef struct wmDrag {
int sx, sy;
char opname[200]; /* if set, draws operator name*/
+ unsigned int flags;
} wmDrag;
/* dropboxes are like keymaps, part of the screen/area/region definition */
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 28bddb47778..d05cc572c45 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -462,7 +462,8 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
BLI_freelistN(&wm->queue);
BLI_freelistN(&wm->paintcursors);
- BLI_freelistN(&wm->drags);
+
+ WM_drag_free_list(&wm->drags);
wm_reports_free(wm);
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 2aa177602cb..e5bba9285b4 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -143,7 +143,7 @@ void wm_dropbox_free(void)
/* *********************************** */
/* note that the pointer should be valid allocated and not on stack */
-wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value)
+wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value, unsigned int flags)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmDrag *drag = MEM_callocN(sizeof(struct wmDrag), "new drag");
@@ -152,6 +152,7 @@ wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin,
/* if multiple drags are added, they're drawn as list */
BLI_addtail(&wm->drags, drag);
+ drag->flags = flags;
drag->icon = icon;
drag->type = type;
if (type == WM_DRAG_PATH)
@@ -171,6 +172,22 @@ void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy)
drag->sy = sy;
}
+void WM_drag_free(wmDrag *drag)
+{
+ if ((drag->flags & WM_DRAG_FREE_DATA) && drag->poin) {
+ MEM_freeN(drag->poin);
+ }
+
+ MEM_freeN(drag);
+}
+
+void WM_drag_free_list(struct ListBase *lb)
+{
+ wmDrag *drag;
+ while ((drag = BLI_pophead(lb))) {
+ WM_drag_free(drag);
+ }
+}
static const char *dropbox_active(bContext *C, ListBase *handlers, wmDrag *drag, wmEvent *event)
{
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 4116bee4a5f..7440570f4a0 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -592,7 +592,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
bScreen *screen = win->screen;
ScrArea *sa;
ARegion *ar;
- int copytex = 0, paintcursor = 1;
+ int copytex = 0;
if (win->drawdata) {
glClearColor(0, 0, 0, 0);
@@ -639,7 +639,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
wm_triple_copy_textures(win, triple);
}
- if (paintcursor && wm->paintcursors.first) {
+ if (wm->paintcursors.first) {
for (sa = screen->areabase.first; sa; sa = sa->next) {
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->swinid && ar->swinid == screen->subwinactive) {
@@ -685,8 +685,6 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
CTX_wm_menu_set(C, ar);
ED_region_do_draw(C, ar);
CTX_wm_menu_set(C, NULL);
- /* when a menu is being drawn, don't do the paint cursors */
- paintcursor = 0;
}
}
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 4b2ec0ef587..ab4b21d5e33 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -111,10 +111,13 @@ void wm_event_free(wmEvent *event)
if (event->customdata) {
if (event->customdatafree) {
/* note: pointer to listbase struct elsewhere */
- if (event->custom == EVT_DATA_LISTBASE)
- BLI_freelistN(event->customdata);
- else
+ if (event->custom == EVT_DATA_DRAGDROP) {
+ ListBase *lb = event->customdata;
+ WM_drag_free_list(lb);
+ }
+ else {
MEM_freeN(event->customdata);
+ }
}
}
@@ -289,7 +292,7 @@ void wm_event_do_notifiers(bContext *C)
do_anim = true;
}
}
- if (ELEM5(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_SCENE, NC_WM)) {
+ if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_SCENE, NC_WM)) {
ED_info_stats_clear(win->screen->scene);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
}
@@ -393,13 +396,17 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve
ARegion *region = CTX_wm_region(C);
ARegion *menu = CTX_wm_menu(C);
static bool do_wheel_ui = true;
- const bool is_wheel = ELEM3(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN);
+ const bool is_wheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN);
int retval;
/* UI code doesn't handle return values - it just always returns break.
* to make the DBL_CLICK conversion work, we just don't send this to UI, except mouse clicks */
- if (event->type != LEFTMOUSE && event->val == KM_DBL_CLICK)
+ if (((handler->flag & WM_HANDLER_ACCEPT_DBL_CLICK) == 0) &&
+ (event->type != LEFTMOUSE) &&
+ (event->val == KM_DBL_CLICK))
+ {
return WM_HANDLER_CONTINUE;
+ }
/* UI is quite aggressive with swallowing events, like scrollwheel */
/* I realize this is not extremely nice code... when UI gets keymaps it can be maybe smarter */
@@ -1261,11 +1268,17 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA
/* invokes operator in context */
+int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, short context, PointerRNA *properties)
+{
+ BLI_assert(ot == WM_operatortype_find(ot->idname, true));
+ return wm_operator_call_internal(C, ot, properties, NULL, context, false);
+}
int WM_operator_name_call(bContext *C, const char *opstring, short context, PointerRNA *properties)
{
wmOperatorType *ot = WM_operatortype_find(opstring, 0);
- if (ot)
- return wm_operator_call_internal(C, ot, properties, NULL, context, false);
+ if (ot) {
+ return WM_operator_name_call_ptr(C, ot, context, properties);
+ }
return 0;
}
@@ -1928,17 +1941,17 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
wmDropBox *drop = handler->dropboxes->first;
for (; drop; drop = drop->next) {
/* other drop custom types allowed */
- if (event->custom == EVT_DATA_LISTBASE) {
+ if (event->custom == EVT_DATA_DRAGDROP) {
ListBase *lb = (ListBase *)event->customdata;
wmDrag *drag;
for (drag = lb->first; drag; drag = drag->next) {
if (drop->poll(C, drag, event)) {
-
drop->copy(drag, drop);
/* free the drags before calling operator */
- BLI_freelistN(event->customdata);
+ WM_drag_free_list(lb);
+
event->customdata = NULL;
event->custom = 0;
@@ -2004,7 +2017,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
if (CTX_wm_window(C) == NULL)
return action;
- if (!ELEM3(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE, EVENT_NONE) && !ISTIMER(event->type)) {
+ if (!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE, EVENT_NONE) && !ISTIMER(event->type)) {
/* test for CLICK events */
if (wm_action_not_handled(action)) {
@@ -2140,10 +2153,12 @@ static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *even
return;
}
- if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type))
+ if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type)) {
win->screen->do_draw_drag = true;
+ }
else if (event->type == ESCKEY) {
- BLI_freelistN(&wm->drags);
+ WM_drag_free_list(&wm->drags);
+
win->screen->do_draw_drag = true;
}
else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
@@ -2155,7 +2170,7 @@ static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *even
MEM_freeN(event->customdata);
}
- event->custom = EVT_DATA_LISTBASE;
+ event->custom = EVT_DATA_DRAGDROP;
event->customdata = &wm->drags;
event->customdatafree = 1;
@@ -2552,7 +2567,7 @@ void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
wmEventHandler *WM_event_add_ui_handler(
const bContext *C, ListBase *handlers,
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
- void *userdata)
+ void *userdata, const bool accept_dbl_click)
{
wmEventHandler *handler = MEM_callocN(sizeof(wmEventHandler), "event ui handler");
handler->ui_handle = ui_handle;
@@ -2569,6 +2584,9 @@ wmEventHandler *WM_event_add_ui_handler(
handler->ui_menu = NULL;
}
+ if (accept_dbl_click) {
+ handler->flag |= WM_HANDLER_ACCEPT_DBL_CLICK;
+ }
BLI_addhead(handlers, handler);
@@ -2688,7 +2706,7 @@ bool WM_modal_tweak_exit(const wmEvent *event, int tweak_event)
else {
/* if the initial event wasn't a tweak event then
* ignore USER_RELEASECONFIRM setting: see [#26756] */
- if (ELEM3(tweak_event, EVT_TWEAK_L, EVT_TWEAK_M, EVT_TWEAK_R) == 0) {
+ if (ELEM(tweak_event, EVT_TWEAK_L, EVT_TWEAK_M, EVT_TWEAK_R) == 0) {
return 1;
}
}
@@ -3398,4 +3416,39 @@ void WM_event_ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4])
axis_angle_to_quat(q, axis, angle);
}
+/* if this is a tablet event, return tablet pressure and set *pen_flip
+ * to 1 if the eraser tool is being used, 0 otherwise */
+float WM_event_tablet_data(const wmEvent *event, int *pen_flip, float tilt[2])
+{
+ int erasor = 0;
+ float pressure = 1;
+
+ if (tilt)
+ zero_v2(tilt);
+
+ if (event->tablet_data) {
+ wmTabletData *wmtab = event->tablet_data;
+
+ erasor = (wmtab->Active == EVT_TABLET_ERASER);
+ if (wmtab->Active != EVT_TABLET_NONE) {
+ pressure = wmtab->Pressure;
+ if (tilt) {
+ tilt[0] = wmtab->Xtilt;
+ tilt[1] = wmtab->Ytilt;
+ }
+ }
+ }
+
+ if (pen_flip)
+ (*pen_flip) = erasor;
+
+ return pressure;
+}
+
+bool WM_event_is_tablet(const struct wmEvent *event)
+{
+ return (event->tablet_data) ? true : false;
+}
+
+
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 0bc6442348c..832fef404e3 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -278,11 +278,13 @@ 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 from_memory)
{
+ Main *bmain = CTX_data_main(C);
+
/* versioning is here */
UI_init_userdef();
MEM_CacheLimiter_set_maximum(((size_t)U.memcachelimit) * 1024 * 1024);
- sound_init(CTX_data_main(C));
+ sound_init(bmain);
/* needed so loading a file from the command line respects user-pref [#26156] */
BKE_BIT_TEST_SET(G.fileflags, U.flag & USER_FILENOUI, G_FILE_NO_UI);
@@ -295,7 +297,7 @@ static void wm_init_userdef(bContext *C, const bool from_memory)
/* avoid re-saving for every small change to our prefs, allow overrides */
if (from_memory) {
- UI_init_userdef_factory();
+ BLO_update_defaults_userpref_blend();
}
/* update tempdir from user preferences */
@@ -457,6 +459,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
#endif
/* important to do before NULL'ing the context */
+ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
if (!G.background) {
@@ -648,6 +651,7 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
#endif
/* important to do before NULL'ing the context */
+ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL);
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index c9ef473a442..3e287a3907b 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -74,7 +74,7 @@ wmGesture *WM_gesture_new(bContext *C, const wmEvent *event, int type)
wm_subwindow_origin_get(window, gesture->swinid, &sx, &sy);
- if (ELEM5(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK,
+ if (ELEM(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK,
WM_GESTURE_CIRCLE, WM_GESTURE_STRAIGHTLINE))
{
rcti *rect = MEM_callocN(sizeof(rcti), "gesture rect new");
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index b2c822f501c..6720bf89c77 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -188,6 +188,8 @@ void WM_init(bContext *C, int argc, const char **argv)
(void)argv; /* unused */
#endif
+ ED_spacemacros_init();
+
if (!G.background && !wm_start_with_console)
GHOST_toggleConsole(3);
@@ -236,6 +238,7 @@ void WM_init(bContext *C, int argc, const char **argv)
*
* unlikely any handlers are set but its possible,
* note that recovering the last session does its own callbacks. */
+ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
}
}
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 0163517545f..7b567142979 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -464,6 +464,13 @@ wmKeyMapItem *WM_keymap_add_menu(wmKeyMap *keymap, const char *idname, int type,
return kmi;
}
+wmKeyMapItem *WM_keymap_add_menu_pie(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
+{
+ wmKeyMapItem *kmi = WM_keymap_add_item(keymap, "WM_OT_call_menu_pie", type, val, modifier, keymodifier);
+ RNA_string_set(kmi->ptr, "name", idname);
+ return kmi;
+}
+
bool WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
{
if (BLI_findindex(&keymap->items, kmi) != -1) {
@@ -1108,9 +1115,9 @@ int WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2)
if (k1->val != KM_ANY && k2->val != KM_ANY) {
/* take click, press, release conflict into account */
- if (k1->val == KM_CLICK && ELEM3(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
+ if (k1->val == KM_CLICK && ELEM(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
return 0;
- if (k2->val == KM_CLICK && ELEM3(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
+ if (k2->val == KM_CLICK && ELEM(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
return 0;
if (k1->val != k2->val)
return 0;
@@ -1414,46 +1421,73 @@ wmKeyMapItem *WM_keymap_item_find_id(wmKeyMap *keymap, int id)
/* Needs to be kept up to date with Keymap and Operator naming */
wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
{
+ /* Op types purposely skipped for now:
+ * BRUSH_OT
+ * BOID_OT
+ * BUTTONS_OT
+ * CONSTRAINT_OT
+ * DPAINT_OT
+ * ED_OT
+ * FLUID_OT
+ * TEXTURE_OT
+ * UI_OT
+ * VIEW2D_OT
+ * WORLD_OT
+ */
+
wmKeyMap *km = NULL;
SpaceLink *sl = CTX_wm_space_data(C);
/* Window */
- if (strstr(opname, "WM_OT")) {
+ if (STRPREFIX(opname, "WM_OT")) {
km = WM_keymap_find_all(C, "Window", 0, 0);
}
- /* Screen */
- else if (strstr(opname, "SCREEN_OT")) {
+ /* Screen & Render */
+ else if (STRPREFIX(opname, "SCREEN_OT") ||
+ STRPREFIX(opname, "RENDER_OT") ||
+ STRPREFIX(opname, "SOUND_OT") ||
+ STRPREFIX(opname, "SCENE_OT"))
+ {
km = WM_keymap_find_all(C, "Screen", 0, 0);
}
/* Grease Pencil */
- else if (strstr(opname, "GPENCIL_OT")) {
+ else if (STRPREFIX(opname, "GPENCIL_OT")) {
km = WM_keymap_find_all(C, "Grease Pencil", 0, 0);
}
/* Markers */
- else if (strstr(opname, "MARKER_OT")) {
+ else if (STRPREFIX(opname, "MARKER_OT")) {
km = WM_keymap_find_all(C, "Markers", 0, 0);
}
/* Import/Export*/
- else if (strstr(opname, "IMPORT_") || strstr(opname, "EXPORT_")) {
+ else if (STRPREFIX(opname, "IMPORT_") ||
+ STRPREFIX(opname, "EXPORT_"))
+ {
km = WM_keymap_find_all(C, "Window", 0, 0);
}
/* 3D View */
- else if (strstr(opname, "VIEW3D_OT")) {
+ else if (STRPREFIX(opname, "VIEW3D_OT")) {
km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0);
}
- else if (strstr(opname, "OBJECT_OT")) {
+ else if (STRPREFIX(opname, "OBJECT_OT")) {
/* exception, this needs to work outside object mode too */
- if (strstr(opname, "OBJECT_OT_mode_set"))
+ if (STRPREFIX(opname, "OBJECT_OT_mode_set"))
km = WM_keymap_find_all(C, "Object Non-modal", 0, 0);
else
km = WM_keymap_find_all(C, "Object Mode", 0, 0);
}
-
+ /* Object mode related */
+ else if (STRPREFIX(opname, "GROUP_OT") ||
+ STRPREFIX(opname, "MATERIAL_OT") ||
+ STRPREFIX(opname, "PTCACHE_OT") ||
+ STRPREFIX(opname, "RIGIDBODY_OT"))
+ {
+ km = WM_keymap_find_all(C, "Object Mode", 0, 0);
+ }
/* Editing Modes */
- else if (strstr(opname, "MESH_OT")) {
+ else if (STRPREFIX(opname, "MESH_OT")) {
km = WM_keymap_find_all(C, "Mesh", 0, 0);
/* some mesh operators are active in object mode too, like add-prim */
@@ -1461,7 +1495,9 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
km = WM_keymap_find_all(C, "Object Mode", 0, 0);
}
}
- else if (strstr(opname, "CURVE_OT")) {
+ else if (STRPREFIX(opname, "CURVE_OT") ||
+ STRPREFIX(opname, "SURFACE_OT"))
+ {
km = WM_keymap_find_all(C, "Curve", 0, 0);
/* some curve operators are active in object mode too, like add-prim */
@@ -1469,13 +1505,17 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
km = WM_keymap_find_all(C, "Object Mode", 0, 0);
}
}
- else if (strstr(opname, "ARMATURE_OT")) {
+ else if (STRPREFIX(opname, "ARMATURE_OT") ||
+ STRPREFIX(opname, "SKETCH_OT"))
+ {
km = WM_keymap_find_all(C, "Armature", 0, 0);
}
- else if (strstr(opname, "POSE_OT")) {
+ else if (STRPREFIX(opname, "POSE_OT") ||
+ STRPREFIX(opname, "POSELIB_OT"))
+ {
km = WM_keymap_find_all(C, "Pose", 0, 0);
}
- else if (strstr(opname, "SCULPT_OT")) {
+ else if (STRPREFIX(opname, "SCULPT_OT")) {
switch (CTX_data_mode_enum(C)) {
case OB_MODE_SCULPT:
km = WM_keymap_find_all(C, "Sculpt", 0, 0);
@@ -1485,7 +1525,7 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
break;
}
}
- else if (strstr(opname, "MBALL_OT")) {
+ else if (STRPREFIX(opname, "MBALL_OT")) {
km = WM_keymap_find_all(C, "Metaball", 0, 0);
/* some mball operators are active in object mode too, like add-prim */
@@ -1493,16 +1533,16 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
km = WM_keymap_find_all(C, "Object Mode", 0, 0);
}
}
- else if (strstr(opname, "LATTICE_OT")) {
+ else if (STRPREFIX(opname, "LATTICE_OT")) {
km = WM_keymap_find_all(C, "Lattice", 0, 0);
}
- else if (strstr(opname, "PARTICLE_OT")) {
+ else if (STRPREFIX(opname, "PARTICLE_OT")) {
km = WM_keymap_find_all(C, "Particle", 0, 0);
}
- else if (strstr(opname, "FONT_OT")) {
+ else if (STRPREFIX(opname, "FONT_OT")) {
km = WM_keymap_find_all(C, "Font", 0, 0);
}
- else if (strstr(opname, "PAINT_OT")) {
+ else if (STRPREFIX(opname, "PAINT_OT")) {
/* check for relevant mode */
switch (CTX_data_mode_enum(C)) {
@@ -1518,69 +1558,86 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
}
}
/* Paint Face Mask */
- else if (strstr(opname, "PAINT_OT_face_select")) {
+ else if (STRPREFIX(opname, "PAINT_OT_face_select")) {
km = WM_keymap_find_all(C, "Face Mask", sl->spacetype, 0);
}
/* Timeline */
- else if (strstr(opname, "TIME_OT")) {
+ else if (STRPREFIX(opname, "TIME_OT")) {
km = WM_keymap_find_all(C, "Timeline", sl->spacetype, 0);
}
/* Image Editor */
- else if (strstr(opname, "IMAGE_OT")) {
+ else if (STRPREFIX(opname, "IMAGE_OT")) {
km = WM_keymap_find_all(C, "Image", sl->spacetype, 0);
}
+ /* Clip Editor */
+ else if (STRPREFIX(opname, "CLIP_OT")) {
+ km = WM_keymap_find_all(C, "Clip", sl->spacetype, 0);
+ }
+ else if (STRPREFIX(opname, "MASK_OT")) {
+ km = WM_keymap_find_all(C, "Mask Editing", 0, 0);
+ }
/* UV Editor */
- else if (strstr(opname, "UV_OT")) {
+ else if (STRPREFIX(opname, "UV_OT")) {
km = WM_keymap_find_all(C, "UV Editor", sl->spacetype, 0);
}
/* Node Editor */
- else if (strstr(opname, "NODE_OT")) {
+ else if (STRPREFIX(opname, "NODE_OT")) {
km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0);
}
/* Animation Editor Channels */
- else if (strstr(opname, "ANIM_OT_channels")) {
+ else if (STRPREFIX(opname, "ANIM_OT_channels")) {
km = WM_keymap_find_all(C, "Animation Channels", sl->spacetype, 0);
}
/* Animation Generic - after channels */
- else if (strstr(opname, "ANIM_OT")) {
+ else if (STRPREFIX(opname, "ANIM_OT")) {
km = WM_keymap_find_all(C, "Animation", 0, 0);
}
/* Graph Editor */
- else if (strstr(opname, "GRAPH_OT")) {
+ else if (STRPREFIX(opname, "GRAPH_OT")) {
km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0);
}
/* Dopesheet Editor */
- else if (strstr(opname, "ACTION_OT")) {
+ else if (STRPREFIX(opname, "ACTION_OT")) {
km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0);
}
/* NLA Editor */
- else if (strstr(opname, "NLA_OT")) {
+ else if (STRPREFIX(opname, "NLA_OT")) {
km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0);
}
/* Script */
- else if (strstr(opname, "SCRIPT_OT")) {
+ else if (STRPREFIX(opname, "SCRIPT_OT")) {
km = WM_keymap_find_all(C, "Script", sl->spacetype, 0);
}
/* Text */
- else if (strstr(opname, "TEXT_OT")) {
+ else if (STRPREFIX(opname, "TEXT_OT")) {
km = WM_keymap_find_all(C, "Text", sl->spacetype, 0);
}
/* Sequencer */
- else if (strstr(opname, "SEQUENCER_OT")) {
+ else if (STRPREFIX(opname, "SEQUENCER_OT")) {
km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0);
}
/* Console */
- else if (strstr(opname, "CONSOLE_OT")) {
+ else if (STRPREFIX(opname, "CONSOLE_OT")) {
km = WM_keymap_find_all(C, "Console", sl->spacetype, 0);
}
/* Console */
- else if (strstr(opname, "INFO_OT")) {
+ else if (STRPREFIX(opname, "INFO_OT")) {
km = WM_keymap_find_all(C, "Info", sl->spacetype, 0);
}
-
+ /* File browser */
+ else if (STRPREFIX(opname, "FILE_OT")) {
+ km = WM_keymap_find_all(C, "File Browser", sl->spacetype, 0);
+ }
+ /* Logic Editor */
+ else if (STRPREFIX(opname, "LOGIC_OT")) {
+ km = WM_keymap_find_all(C, "Logic Editor", sl->spacetype, 0);
+ }
+ /* Outliner */
+ else if (STRPREFIX(opname, "OUTLINER_OT")) {
+ km = WM_keymap_find_all(C, "Outliner", sl->spacetype, 0);
+ }
/* Transform */
- else if (strstr(opname, "TRANSFORM_OT")) {
-
+ else if (STRPREFIX(opname, "TRANSFORM_OT")) {
/* check for relevant editor */
switch (sl->spacetype) {
case SPACE_VIEW3D:
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index ba454bb1818..bc79879f1f4 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -56,6 +56,7 @@
#include "PIL_time.h"
#include "BLI_blenlib.h"
+#include "BLI_dial.h"
#include "BLI_dynstr.h" /*for WM_operator_pystring */
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -501,7 +502,7 @@ void WM_operator_py_idname(char *to, const char *from)
int ofs = (sep - from);
/* note, we use ascii tolower instead of system tolower, because the
- * latter depends on the locale, and can lead to idname mistmatch */
+ * latter depends on the locale, and can lead to idname mismatch */
memcpy(to, from, sizeof(char) * ofs);
BLI_ascii_strtolower(to, ofs);
@@ -1312,9 +1313,14 @@ void WM_operator_properties_gesture_border(wmOperatorType *ot, bool extend)
void WM_operator_properties_mouse_select(wmOperatorType *ot)
{
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from selection");
- RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Selection", "Toggle the selection");
+ PropertyRNA *prop;
+
+ prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Selection", "Toggle the selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor)
@@ -2049,6 +2055,41 @@ static void WM_OT_call_menu(wmOperatorType *ot)
RNA_def_string(ot->srna, "name", NULL, BKE_ST_MAXNAME, "Name", "Name of the menu");
}
+static int wm_call_pie_menu_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ char idname[BKE_ST_MAXNAME];
+ RNA_string_get(op->ptr, "name", idname);
+
+ uiPieMenuInvoke(C, idname, event);
+
+ return OPERATOR_CANCELLED;
+}
+
+static int wm_call_pie_menu_exec(bContext *C, wmOperator *op)
+{
+ char idname[BKE_ST_MAXNAME];
+ RNA_string_get(op->ptr, "name", idname);
+
+ uiPieMenuInvoke(C, idname, CTX_wm_window(C)->eventstate);
+
+ return OPERATOR_CANCELLED;
+}
+
+static void WM_OT_call_menu_pie(wmOperatorType *ot)
+{
+ ot->name = "Call Pie Menu";
+ ot->idname = "WM_OT_call_menu_pie";
+ ot->description = "Call (draw) a pre-defined pie menu";
+
+ ot->invoke = wm_call_pie_menu_invoke;
+ ot->exec = wm_call_pie_menu_exec;
+ ot->poll = WM_operator_winactive;
+
+ ot->flag = OPTYPE_INTERNAL;
+
+ RNA_def_string(ot->srna, "name", NULL, BKE_ST_MAXNAME, "Name", "Name of the pie menu");
+}
+
/* ************ window / screen operator definitions ************** */
/* this poll functions is needed in place of WM_operator_winactive
@@ -2336,8 +2377,8 @@ static void WM_OT_open_mainfile(wmOperatorType *ot)
WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
- RNA_def_boolean(ot->srna, "load_ui", 1, "Load UI", "Load user interface setup in the .blend file");
- RNA_def_boolean(ot->srna, "use_scripts", 1, "Trusted Source",
+ RNA_def_boolean(ot->srna, "load_ui", true, "Load UI", "Load user interface setup in the .blend file");
+ RNA_def_boolean(ot->srna, "use_scripts", true, "Trusted Source",
"Allow .blend file to execute scripts automatically, default available from system preferences");
}
@@ -2348,7 +2389,14 @@ static int wm_revert_mainfile_exec(bContext *C, wmOperator *op)
{
bool success;
- success = wm_file_read_opwrap(C, G.main->name, op->reports, true);
+ wm_open_init_use_scripts(op, false);
+
+ if (RNA_boolean_get(op->ptr, "use_scripts"))
+ G.f |= G_SCRIPT_AUTOEXEC;
+ else
+ G.f &= ~G_SCRIPT_AUTOEXEC;
+
+ success = wm_file_read_opwrap(C, G.main->name, op->reports, !(G.f & G_SCRIPT_AUTOEXEC));
if (success) {
return OPERATOR_FINISHED;
@@ -2370,6 +2418,9 @@ static void WM_OT_revert_mainfile(wmOperatorType *ot)
ot->description = "Reload the saved file";
ot->invoke = WM_operator_confirm;
+ RNA_def_boolean(ot->srna, "use_scripts", true, "Trusted Source",
+ "Allow .blend file to execute scripts automatically, default available from system preferences");
+
ot->exec = wm_revert_mainfile_exec;
ot->poll = wm_revert_mainfile_poll;
}
@@ -2419,7 +2470,7 @@ static short wm_link_append_flag(wmOperator *op)
if (RNA_boolean_get(op->ptr, "autoselect")) flag |= FILE_AUTOSELECT;
if (RNA_boolean_get(op->ptr, "active_layer")) flag |= FILE_ACTIVELAY;
- if (RNA_boolean_get(op->ptr, "relative_path")) flag |= FILE_RELPATH;
+ if (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path")) flag |= FILE_RELPATH;
if (RNA_boolean_get(op->ptr, "link")) flag |= FILE_LINK;
if (RNA_boolean_get(op->ptr, "instance_groups")) flag |= FILE_GROUP_INSTANCE;
@@ -2550,13 +2601,31 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static void WM_OT_link_append(wmOperatorType *ot)
+static void wm_link_append_properties_common(wmOperatorType *ot, bool is_link)
{
PropertyRNA *prop;
- ot->name = "Link/Append from Library";
- ot->idname = "WM_OT_link_append";
- ot->description = "Link or Append from a Library .blend file";
+ /* better not save _any_ settings for this operator */
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "link", is_link,
+ "Link", "Link the objects or datablocks rather than appending");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_boolean(ot->srna, "autoselect", true,
+ "Select", "Select new objects");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "active_layer", true,
+ "Active Layer", "Put new objects on the active layer");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "instance_groups", is_link,
+ "Instance Groups", "Create Dupli-Group instances for each group");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+static void WM_OT_link(wmOperatorType *ot)
+{
+ ot->name = "Link from Library";
+ ot->idname = "WM_OT_link";
+ ot->description = "Link from a Library .blend file";
ot->invoke = wm_link_append_invoke;
ot->exec = wm_link_append_exec;
@@ -2569,16 +2638,27 @@ static void WM_OT_link_append(wmOperatorType *ot)
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_RELPATH | WM_FILESEL_FILES,
FILE_DEFAULTDISPLAY);
- /* better not save _any_ settings for this operator */
- /* properties */
- prop = RNA_def_boolean(ot->srna, "link", 1, "Link", "Link the objects or datablocks rather than appending");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_boolean(ot->srna, "autoselect", 1, "Select", "Select the linked objects");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "active_layer", 1, "Active Layer", "Put the linked objects on the active layer");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "instance_groups", 1, "Instance Groups", "Create instances for each group as a DupliGroup");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ wm_link_append_properties_common(ot, true);
+}
+
+static void WM_OT_append(wmOperatorType *ot)
+{
+ ot->name = "Append from Library";
+ ot->idname = "WM_OT_append";
+ ot->description = "Append from a Library .blend file";
+
+ ot->invoke = wm_link_append_invoke;
+ ot->exec = wm_link_append_exec;
+ ot->poll = wm_link_append_poll;
+
+ ot->flag |= OPTYPE_UNDO;
+
+ WM_operator_properties_filesel(
+ ot, FOLDERFILE | BLENDERFILE, FILE_LOADLIB, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_FILES,
+ FILE_DEFAULTDISPLAY);
+
+ wm_link_append_properties_common(ot, false);
}
/* *************** recover last session **************** */
@@ -3291,7 +3371,7 @@ void wm_tweakevent_test(bContext *C, wmEvent *event, int action)
if (win->tweak == NULL) {
if (CTX_wm_region(C)) {
if (event->val == KM_PRESS) {
- if (ELEM3(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) {
+ if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) {
win->tweak = WM_gesture_new(C, event, WM_GESTURE_TWEAK);
}
}
@@ -3642,6 +3722,9 @@ typedef struct {
StructRNA *image_id_srna;
float initial_value, current_value, min_value, max_value;
int initial_mouse[2];
+ int slow_mouse[2];
+ bool slow_mode;
+ Dial *dial;
unsigned int gltex;
ListBase orig_paintcursors;
bool use_secondary_tex;
@@ -4032,7 +4115,7 @@ static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *eve
/* get subtype of property */
rc->subtype = RNA_property_subtype(rc->prop);
- if (!ELEM5(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_ANGLE, PROP_PIXEL)) {
+ if (!ELEM(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_ANGLE, PROP_PIXEL)) {
BKE_report(op->reports, RPT_ERROR, "Property must be a none, distance, a factor, or an angle");
MEM_freeN(rc);
return OPERATOR_CANCELLED;
@@ -4075,6 +4158,11 @@ static void radial_control_cancel(bContext *C, wmOperator *op)
RadialControl *rc = op->customdata;
wmWindowManager *wm = CTX_wm_manager(C);
+ if (rc->dial) {
+ MEM_freeN(rc->dial);
+ rc->dial = NULL;
+ }
+
WM_paint_cursor_end(wm, rc->cursor);
/* restore original paint cursors */
@@ -4094,24 +4182,61 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even
{
RadialControl *rc = op->customdata;
float new_value, dist, zoom[2];
- float delta[2], snap, ret = OPERATOR_RUNNING_MODAL;
-
+ float delta[2], ret = OPERATOR_RUNNING_MODAL;
+ bool snap;
+ float angle_precision = 0.0f;
/* TODO: fix hardcoded events */
- snap = event->ctrl;
+ snap = event->ctrl != 0;
switch (event->type) {
case MOUSEMOVE:
- delta[0] = rc->initial_mouse[0] - event->x;
- delta[1] = rc->initial_mouse[1] - event->y;
-
- if (rc->zoom_prop) {
- RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
- delta[0] /= zoom[0];
- delta[1] /= zoom[1];
+ if (rc->slow_mode) {
+ if (rc->subtype == PROP_ANGLE) {
+ float position[2] = {event->x, event->y};
+
+ /* calculate the initial angle here first */
+ delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
+ delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
+
+ /* precision angle gets calculated from dial and gets added later */
+ angle_precision = -0.1f * BLI_dial_angle(rc->dial, position);
+ }
+ else {
+ delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
+ delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
+
+ if (rc->zoom_prop) {
+ RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
+ delta[0] /= zoom[0];
+ delta[1] /= zoom[1];
+ }
+
+ dist = len_v2(delta);
+
+ delta[0] = event->x - rc->slow_mouse[0];
+ delta[1] = event->y - rc->slow_mouse[1];
+
+ if (rc->zoom_prop) {
+ delta[0] /= zoom[0];
+ delta[1] /= zoom[1];
+ }
+
+ dist = dist + 0.1f * (delta[0] + delta[1]);
+ }
}
+ else {
+ delta[0] = rc->initial_mouse[0] - event->x;
+ delta[1] = rc->initial_mouse[1] - event->y;
- dist = len_v2(delta);
+ if (rc->zoom_prop) {
+ RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
+ delta[0] /= zoom[0];
+ delta[1] /= zoom[1];
+ }
+
+ dist = len_v2(delta);
+ }
/* calculate new value and apply snapping */
switch (rc->subtype) {
@@ -4126,7 +4251,10 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even
if (snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f;
break;
case PROP_ANGLE:
- new_value = atan2(delta[1], delta[0]) + M_PI;
+ new_value = atan2(delta[1], delta[0]) + M_PI + angle_precision;
+ new_value = fmod(new_value, 2.0f * (float)M_PI);
+ if (new_value < 0.0f)
+ new_value += 2.0f * (float)M_PI;
if (snap) new_value = DEG2RADF(((int)RAD2DEGF(new_value) + 5) / 10 * 10);
break;
default:
@@ -4153,6 +4281,29 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even
RNA_property_update(C, &rc->ptr, rc->prop);
ret = OPERATOR_FINISHED;
break;
+
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ if (event->val == KM_PRESS) {
+ rc->slow_mouse[0] = event->x;
+ rc->slow_mouse[1] = event->y;
+ rc->slow_mode = true;
+ if (rc->subtype == PROP_ANGLE) {
+ float initial_position[2] = {UNPACK2(rc->initial_mouse)};
+ float current_position[2] = {UNPACK2(rc->slow_mouse)};
+ rc->dial = BLI_dial_initialize(initial_position, 0.0f);
+ /* immediately set the position to get a an initial direction */
+ BLI_dial_angle(rc->dial, current_position);
+ }
+ }
+ if (event->val == KM_RELEASE) {
+ rc->slow_mode = false;
+ if (rc->dial) {
+ MEM_freeN(rc->dial);
+ rc->dial = NULL;
+ }
+ }
+ break;
}
ED_region_tag_redraw(CTX_wm_region(C));
@@ -4165,8 +4316,6 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even
static void WM_OT_radial_control(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
ot->name = "Radial Control";
ot->idname = "WM_OT_radial_control";
ot->description = "Set some size property (like e.g. brush size) with mouse wheel";
@@ -4178,32 +4327,23 @@ static void WM_OT_radial_control(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
/* all paths relative to the context */
- prop = RNA_def_string(ot->srna, "data_path_primary", NULL, 0, "Primary Data Path", "Primary path of property to be set by the radial control");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "data_path_primary", NULL, 0, "Primary Data Path", "Primary path of property to be set by the radial control");
- prop = RNA_def_string(ot->srna, "data_path_secondary", NULL, 0, "Secondary Data Path", "Secondary path of property to be set by the radial control");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "data_path_secondary", NULL, 0, "Secondary Data Path", "Secondary path of property to be set by the radial control");
- prop = RNA_def_string(ot->srna, "use_secondary", NULL, 0, "Use Secondary", "Path of property to select between the primary and secondary data paths");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "use_secondary", NULL, 0, "Use Secondary", "Path of property to select between the primary and secondary data paths");
- prop = RNA_def_string(ot->srna, "rotation_path", NULL, 0, "Rotation Path", "Path of property used to rotate the texture display");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "rotation_path", NULL, 0, "Rotation Path", "Path of property used to rotate the texture display");
- prop = RNA_def_string(ot->srna, "color_path", NULL, 0, "Color Path", "Path of property used to set the color of the control");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "color_path", NULL, 0, "Color Path", "Path of property used to set the color of the control");
- prop = RNA_def_string(ot->srna, "fill_color_path", NULL, 0, "Fill Color Path", "Path of property used to set the fill color of the control");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "fill_color_path", NULL, 0, "Fill Color Path", "Path of property used to set the fill color of the control");
- prop = RNA_def_string(ot->srna, "zoom_path", NULL, 0, "Zoom Path", "Path of property used to set the zoom level for the control");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "zoom_path", NULL, 0, "Zoom Path", "Path of property used to set the zoom level for the control");
- prop = RNA_def_string(ot->srna, "image_id", NULL, 0, "Image ID", "Path of ID that is used to generate an image for the control");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "image_id", NULL, 0, "Image ID", "Path of ID that is used to generate an image for the control");
- prop = RNA_def_boolean(ot->srna, "secondary_tex", 0, "Secondary Texture", "Tweak brush secondary/mask texture");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_boolean(ot->srna, "secondary_tex", 0, "Secondary Texture", "Tweak brush secondary/mask texture");
}
/* ************************** timer for testing ***************** */
@@ -4425,7 +4565,8 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_quit_blender);
WM_operatortype_append(WM_OT_open_mainfile);
WM_operatortype_append(WM_OT_revert_mainfile);
- WM_operatortype_append(WM_OT_link_append);
+ WM_operatortype_append(WM_OT_link);
+ WM_operatortype_append(WM_OT_append);
WM_operatortype_append(WM_OT_recover_last_session);
WM_operatortype_append(WM_OT_recover_auto_save);
WM_operatortype_append(WM_OT_save_as_mainfile);
@@ -4438,6 +4579,7 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_splash);
WM_operatortype_append(WM_OT_search_menu);
WM_operatortype_append(WM_OT_call_menu);
+ WM_operatortype_append(WM_OT_call_menu_pie);
WM_operatortype_append(WM_OT_radial_control);
#if defined(WIN32)
WM_operatortype_append(WM_OT_console_toggle);
@@ -4651,10 +4793,8 @@ void wm_window_keymap(wmKeyConfig *keyconf)
WM_keymap_add_menu(keymap, "INFO_MT_file_open_recent", OKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
WM_keymap_add_item(keymap, "WM_OT_open_mainfile", OKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "WM_OT_open_mainfile", F1KEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "WM_OT_link_append", OKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
- kmi = WM_keymap_add_item(keymap, "WM_OT_link_append", F1KEY, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "link", false);
- RNA_boolean_set(kmi->ptr, "instance_groups", false);
+ WM_keymap_add_item(keymap, "WM_OT_link", OKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
+ WM_keymap_add_item(keymap, "WM_OT_append", F1KEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "WM_OT_save_mainfile", SKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "WM_OT_save_mainfile", WKEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index 1792ea40a1a..db4459b1799 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -308,7 +308,7 @@ void wmSubWindowScissorSet(wmWindow *win, int swinid, const rcti *srct, bool src
int scissor_height = BLI_rcti_size_y(srct);
/* typically a single pixel doesn't matter,
- * but one pixel offset is noticable with viewport border render */
+ * but one pixel offset is noticeable with viewport border render */
if (srct_pad) {
scissor_width += 1;
scissor_height += 1;
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 99f4ec6bd16..d83f876c2e1 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -973,14 +973,15 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
const char *path = GHOST_GetEventData(evt);
if (path) {
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_open_mainfile", false);
/* operator needs a valid window in context, ensures
* it is correctly set */
oldWindow = CTX_wm_window(C);
CTX_wm_window_set(C, win);
- WM_operator_properties_create(&props_ptr, "WM_OT_open_mainfile");
+ WM_operator_properties_create_ptr(&props_ptr, ot);
RNA_string_set(&props_ptr, "filepath", path);
- WM_operator_name_call(C, "WM_OT_open_mainfile", WM_OP_EXEC_DEFAULT, &props_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr);
WM_operator_properties_free(&props_ptr);
CTX_wm_window_set(C, oldWindow);
@@ -1014,7 +1015,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
/* make blender drop event with custom data pointing to wm drags */
event.type = EVT_DROP;
event.val = KM_RELEASE;
- event.custom = EVT_DATA_LISTBASE;
+ event.custom = EVT_DATA_DRAGDROP;
event.customdata = &wm->drags;
event.customdatafree = 1;
@@ -1033,7 +1034,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
/* try to get icon type from extension */
icon = ED_file_extension_icon((char *)stra->strings[a]);
- WM_event_start_drag(C, icon, WM_DRAG_PATH, stra->strings[a], 0.0);
+ WM_event_start_drag(C, icon, WM_DRAG_PATH, stra->strings[a], 0.0, WM_DRAG_NOP);
/* void poin should point to string, it makes a copy */
break; /* only one drop element supported now */
}
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index df084554c54..d1a94194108 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -81,8 +81,9 @@ enum {
/* handler flag */
enum {
- WM_HANDLER_BLOCKING = 1, /* after this handler all others are ignored */
- WM_HANDLER_DO_FREE = 2 /* handler tagged to be freed in wm_handlers_do() */
+ WM_HANDLER_BLOCKING = (1 << 0), /* after this handler all others are ignored */
+ WM_HANDLER_DO_FREE = (1 << 1), /* handler tagged to be freed in wm_handlers_do() */
+ WM_HANDLER_ACCEPT_DBL_CLICK = (1 << 2), /* handler accepts double key press events */
};
/* wm_event_system.c */
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 4a274d25170..f50f98ed40c 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -36,92 +36,230 @@
#define __WM_EVENT_TYPES_H__
/* customdata type */
-#define EVT_DATA_GESTURE 1
-#define EVT_DATA_TIMER 2
-#define EVT_DATA_LISTBASE 3
-#define EVT_DATA_NDOF_MOTION 4
+enum {
+ EVT_DATA_GESTURE = 1,
+ EVT_DATA_TIMER = 2,
+ EVT_DATA_DRAGDROP = 3,
+ EVT_DATA_NDOF_MOTION = 4,
+};
/* tablet active, matches GHOST_TTabletMode */
-#define EVT_TABLET_NONE 0
-#define EVT_TABLET_STYLUS 1
-#define EVT_TABLET_ERASER 2
-
-
-/* *** wmEvent.type *** */
-
-/* non-event, for example disabled timer */
-#define EVENT_NONE 0
-/* MOUSE : 0x00x */
-#define LEFTMOUSE 1
-#define MIDDLEMOUSE 2
-#define RIGHTMOUSE 3
-#define MOUSEMOVE 4
- /* only use if you want user option switch possible */
-#define ACTIONMOUSE 5
-#define SELECTMOUSE 6
- /* Extra mouse buttons */
-#define BUTTON4MOUSE 7
-#define BUTTON5MOUSE 8
- /* More mouse buttons - can't use 9 and 10 here (wheel) */
-#define BUTTON6MOUSE 18
-#define BUTTON7MOUSE 19
- /* Extra trackpad gestures */
-#define MOUSEPAN 14
-#define MOUSEZOOM 15
-#define MOUSEROTATE 16
- /* defaults from ghost */
-#define WHEELUPMOUSE 10
-#define WHEELDOWNMOUSE 11
- /* mapped with userdef */
-#define WHEELINMOUSE 12
-#define WHEELOUTMOUSE 13
- /* Successive MOUSEMOVE's are converted to this, so we can easily
- * ignore all but the most recent MOUSEMOVE (for better performance),
- * paint and drawing tools however will want to handle these. */
-#define INBETWEEN_MOUSEMOVE 17
-
-
-/* NDOF (from SpaceNavigator & friends)
- * These should be kept in sync with GHOST_NDOFManager.h
- * Ordering matters, exact values do not. */
-
-#define NDOF_MOTION 400
+enum {
+ EVT_TABLET_NONE = 0,
+ EVT_TABLET_STYLUS = 1,
+ EVT_TABLET_ERASER = 2,
+};
+/* ********** wmEvent.type ********** */
enum {
- // used internally, never sent
+ /* non-event, for example disabled timer */
+ EVENT_NONE = 0x0000,
+
+ /* ********** Start of Input devices. ********** */
+
+ /* MOUSE : 0x000x, 0x001x */
+ LEFTMOUSE = 0x0001,
+ MIDDLEMOUSE = 0x0002,
+ RIGHTMOUSE = 0x0003,
+ MOUSEMOVE = 0x0004,
+ /* only use if you want user option switch possible */
+ ACTIONMOUSE = 0x0005,
+ SELECTMOUSE = 0x0006,
+ /* Extra mouse buttons */
+ BUTTON4MOUSE = 0x0007,
+ BUTTON5MOUSE = 0x0008,
+ /* More mouse buttons - can't use 9 and 10 here (wheel) */
+ BUTTON6MOUSE = 0x0012,
+ BUTTON7MOUSE = 0x0013,
+ /* Extra trackpad gestures */
+ MOUSEPAN = 0x000e,
+ MOUSEZOOM = 0x000f,
+ MOUSEROTATE = 0x0010,
+ /* defaults from ghost */
+ WHEELUPMOUSE = 0x000a,
+ WHEELDOWNMOUSE = 0x000b,
+ /* mapped with userdef */
+ WHEELINMOUSE = 0x000c,
+ WHEELOUTMOUSE = 0x000d,
+ /* Successive MOUSEMOVE's are converted to this, so we can easily
+ * ignore all but the most recent MOUSEMOVE (for better performance),
+ * paint and drawing tools however will want to handle these. */
+ INBETWEEN_MOUSEMOVE = 0x0011,
+
+ /* *** Start of keyboard codes. *** */
+
+ /* standard keyboard.
+ * XXX from 0x0020 to 0x00ff, and 0x012c to 0x013f for function keys! */
+ AKEY = 0x0061, /* 'a' */
+ BKEY = 0x0062, /* 'b' */
+ CKEY = 0x0063, /* 'c' */
+ DKEY = 0x0064, /* 'd' */
+ EKEY = 0x0065, /* 'e' */
+ FKEY = 0x0066, /* 'f' */
+ GKEY = 0x0067, /* 'g' */
+#ifndef WIN32
+ HKEY = 0x0068, /* 'h' */
+#else
+#define HKEY 0x0068
+#endif
+ IKEY = 0x0069, /* 'i' */
+ JKEY = 0x006a, /* 'j' */
+ KKEY = 0x006b, /* 'k' */
+ LKEY = 0x006c, /* 'l' */
+ MKEY = 0x006d, /* 'm' */
+ NKEY = 0x006e, /* 'n' */
+ OKEY = 0x006f, /* 'o' */
+ PKEY = 0x0070, /* 'p' */
+ QKEY = 0x0071, /* 'q' */
+ RKEY = 0x0072, /* 'r' */
+ SKEY = 0x0073, /* 's' */
+ TKEY = 0x0074, /* 't' */
+ UKEY = 0x0075, /* 'u' */
+ VKEY = 0x0076, /* 'v' */
+ WKEY = 0x0077, /* 'w' */
+ XKEY = 0x0078, /* 'x' */
+ YKEY = 0x0079, /* 'y' */
+ ZKEY = 0x007a, /* 'z' */
+
+ ZEROKEY = 0x0030, /* '0' */
+ ONEKEY = 0x0031, /* '1' */
+ TWOKEY = 0x0032, /* '2' */
+ THREEKEY = 0x0033, /* '3' */
+ FOURKEY = 0x0034, /* '4' */
+ FIVEKEY = 0x0035, /* '5' */
+ SIXKEY = 0x0036, /* '6' */
+ SEVENKEY = 0x0037, /* '7' */
+ EIGHTKEY = 0x0038, /* '8' */
+ NINEKEY = 0x0039, /* '9' */
+
+ CAPSLOCKKEY = 0x00d3, /* 211 */
+
+ LEFTCTRLKEY = 0x00d4, /* 212 */
+ LEFTALTKEY = 0x00d5, /* 213 */
+ RIGHTALTKEY = 0x00d6, /* 214 */
+ RIGHTCTRLKEY = 0x00d7, /* 215 */
+ RIGHTSHIFTKEY = 0x00d8, /* 216 */
+ LEFTSHIFTKEY = 0x00d9, /* 217 */
+
+ ESCKEY = 0x00da, /* 218 */
+ TABKEY = 0x00db, /* 219 */
+ RETKEY = 0x00dc, /* 220 */
+ SPACEKEY = 0x00dd, /* 221 */
+ LINEFEEDKEY = 0x00de, /* 222 */
+ BACKSPACEKEY = 0x00df, /* 223 */
+ DELKEY = 0x00e0, /* 224 */
+ SEMICOLONKEY = 0x00e1, /* 225 */
+ PERIODKEY = 0x00e2, /* 226 */
+ COMMAKEY = 0x00e3, /* 227 */
+ QUOTEKEY = 0x00e4, /* 228 */
+ ACCENTGRAVEKEY = 0x00e5, /* 229 */
+ MINUSKEY = 0x00e6, /* 230 */
+ SLASHKEY = 0x00e8, /* 232 */
+ BACKSLASHKEY = 0x00e9, /* 233 */
+ EQUALKEY = 0x00ea, /* 234 */
+ LEFTBRACKETKEY = 0x00eb, /* 235 */
+ RIGHTBRACKETKEY = 0x00ec, /* 236 */
+
+ LEFTARROWKEY = 0x0089, /* 137 */
+ DOWNARROWKEY = 0x008a, /* 138 */
+ RIGHTARROWKEY = 0x008b, /* 139 */
+ UPARROWKEY = 0x008c, /* 140 */
+
+ PAD0 = 0x0096, /* 150 */
+ PAD1 = 0x0097, /* 151 */
+ PAD2 = 0x0098, /* 152 */
+ PAD3 = 0x0099, /* 153 */
+ PAD4 = 0x009a, /* 154 */
+ PAD5 = 0x009b, /* 155 */
+ PAD6 = 0x009c, /* 156 */
+ PAD7 = 0x009d, /* 157 */
+ PAD8 = 0x009e, /* 158 */
+ PAD9 = 0x009f, /* 159 */
+
+ PADPERIOD = 0x00c7, /* 199 */
+ PADASTERKEY = 0x00a0, /* 160 */
+ PADSLASHKEY = 0x00a1, /* 161 */
+ PADMINUS = 0x00a2, /* 162 */
+ PADENTER = 0x00a3, /* 163 */
+ PADPLUSKEY = 0x00a4, /* 164 */
+
+ PAUSEKEY = 0x00a5, /* 165 */
+ INSERTKEY = 0x00a6, /* 166 */
+ HOMEKEY = 0x00a7, /* 167 */
+ PAGEUPKEY = 0x00a8, /* 168 */
+ PAGEDOWNKEY = 0x00a9, /* 169 */
+ ENDKEY = 0x00aa, /* 170 */
+
+ UNKNOWNKEY = 0x00ab, /* 171 */
+ OSKEY = 0x00ac, /* 172 */
+ GRLESSKEY = 0x00ad, /* 173 */
+
+ /* XXX: are these codes ok? */
+ MEDIAPLAY = 0x00ae, /* 174 */
+ MEDIASTOP = 0x00af, /* 175 */
+ MEDIAFIRST = 0x00b0, /* 176 */
+ MEDIALAST = 0x00b1, /* 177 */
+
+ F1KEY = 0x012c, /* 300 */
+ F2KEY = 0x012d, /* 301 */
+ F3KEY = 0x012e, /* 302 */
+ F4KEY = 0x012f, /* 303 */
+ F5KEY = 0x0130, /* 304 */
+ F6KEY = 0x0131, /* 305 */
+ F7KEY = 0x0132, /* 306 */
+ F8KEY = 0x0133, /* 307 */
+ F9KEY = 0x0134, /* 308 */
+ F10KEY = 0x0135, /* 309 */
+ F11KEY = 0x0136, /* 310 */
+ F12KEY = 0x0137, /* 311 */
+ F13KEY = 0x0138, /* 312 */
+ F14KEY = 0x0139, /* 313 */
+ F15KEY = 0x013a, /* 314 */
+ F16KEY = 0x013b, /* 315 */
+ F17KEY = 0x013c, /* 316 */
+ F18KEY = 0x013d, /* 317 */
+ F19KEY = 0x013e, /* 318 */
+
+ /* *** End of keyboard codes. *** */
+
+ /* NDOF (from SpaceNavigator & friends)
+ * These should be kept in sync with GHOST_NDOFManager.h
+ * Ordering matters, exact values do not. */
+ NDOF_MOTION = 0x0190,
+ /* used internally, never sent */
NDOF_BUTTON_NONE = NDOF_MOTION,
- // these two are available from any 3Dconnexion device
+ /* these two are available from any 3Dconnexion device */
NDOF_BUTTON_MENU,
NDOF_BUTTON_FIT,
- // standard views
+ /* standard views */
NDOF_BUTTON_TOP,
NDOF_BUTTON_BOTTOM,
NDOF_BUTTON_LEFT,
NDOF_BUTTON_RIGHT,
NDOF_BUTTON_FRONT,
NDOF_BUTTON_BACK,
- // more views
+ /* more views */
NDOF_BUTTON_ISO1,
NDOF_BUTTON_ISO2,
- // 90 degree rotations
+ /* 90 degree rotations */
NDOF_BUTTON_ROLL_CW,
NDOF_BUTTON_ROLL_CCW,
NDOF_BUTTON_SPIN_CW,
NDOF_BUTTON_SPIN_CCW,
NDOF_BUTTON_TILT_CW,
NDOF_BUTTON_TILT_CCW,
- // device control
+ /* device control */
NDOF_BUTTON_ROTATE,
NDOF_BUTTON_PANZOOM,
NDOF_BUTTON_DOMINANT,
NDOF_BUTTON_PLUS,
NDOF_BUTTON_MINUS,
- // keyboard emulation
+ /* keyboard emulation */
NDOF_BUTTON_ESC,
NDOF_BUTTON_ALT,
NDOF_BUTTON_SHIFT,
NDOF_BUTTON_CTRL,
- // general-purpose buttons
+ /* general-purpose buttons */
NDOF_BUTTON_1,
NDOF_BUTTON_2,
NDOF_BUTTON_3,
@@ -132,180 +270,81 @@ enum {
NDOF_BUTTON_8,
NDOF_BUTTON_9,
NDOF_BUTTON_10,
- // more general-purpose buttons
+ /* more general-purpose buttons */
NDOF_BUTTON_A,
NDOF_BUTTON_B,
NDOF_BUTTON_C,
- // the end
- NDOF_LAST
+ /* the end */
+ NDOF_LAST,
+
+ /* ********** End of Input devices. ********** */
+
+ /* ********** Start of Blender internal events. ********** */
+
+ /* XXX Those are mixed inside keyboard 'area'! */
+ /* System: 0x010x */
+ INPUTCHANGE = 0x0103, /* input connected or disconnected */
+ WINDEACTIVATE = 0x0104, /* window is deactivated, focus lost */
+ /* Timer: 0x011x */
+ TIMER = 0x0110, /* timer event, passed on to all queues */
+ TIMER0 = 0x0111, /* timer event, slot for internal use */
+ TIMER1 = 0x0112, /* timer event, slot for internal use */
+ TIMER2 = 0x0113, /* timer event, slot for internal use */
+ TIMERJOBS = 0x0114, /* timer event, jobs system */
+ TIMERAUTOSAVE = 0x0115, /* timer event, autosave */
+ TIMERREPORT = 0x0116, /* timer event, reports */
+ TIMERREGION = 0x0117, /* timer event, region slide in/out */
+ TIMERF = 0x011F, /* last timer */
+
+ /* Tweak, gestures: 0x500x, 0x501x */
+ EVT_ACTIONZONE_AREA = 0x5000,
+ EVT_ACTIONZONE_REGION = 0x5001,
+ /* tweak events, for L M R mousebuttons */
+ EVT_TWEAK_L = 0x5002,
+ EVT_TWEAK_M = 0x5003,
+ EVT_TWEAK_R = 0x5004,
+ /* tweak events for action or select mousebutton */
+ EVT_TWEAK_A = 0x5005,
+ EVT_TWEAK_S = 0x5006,
+ EVT_GESTURE = 0x5010,
+
+ /* Misc Blender internals: 0x502x */
+ EVT_FILESELECT = 0x5020,
+ EVT_BUT_OPEN = 0x5021,
+ EVT_MODAL_MAP = 0x5022,
+ EVT_DROP = 0x5023,
+ EVT_BUT_CANCEL = 0x5024,
+
+ /* ********** End of Blender internal events. ********** */
};
-/* SYSTEM : 0x01xx */
-#define INPUTCHANGE 0x0103 /* input connected or disconnected */
-#define WINDEACTIVATE 0x0104 /* window is deactivated, focus lost */
-
-#define TIMER 0x0110 /* timer event, passed on to all queues */
-#define TIMER0 0x0111 /* timer event, slot for internal use */
-#define TIMER1 0x0112 /* timer event, slot for internal use */
-#define TIMER2 0x0113 /* timer event, slot for internal use */
-#define TIMERJOBS 0x0114 /* timer event, jobs system */
-#define TIMERAUTOSAVE 0x0115 /* timer event, autosave */
-#define TIMERREPORT 0x0116 /* timer event, reports */
-#define TIMERREGION 0x0117 /* timer event, region slide in/out */
-#define TIMERF 0x011F /* last timer */
+/* *********** wmEvent.type helpers. ********** */
/* test whether the event is timer event */
#define ISTIMER(event_type) (event_type >= TIMER && event_type <= TIMERF)
-/* standard keyboard */
-#define AKEY 'a'
-#define BKEY 'b'
-#define CKEY 'c'
-#define DKEY 'd'
-#define EKEY 'e'
-#define FKEY 'f'
-#define GKEY 'g'
-#define HKEY 'h'
-#define IKEY 'i'
-#define JKEY 'j'
-#define KKEY 'k'
-#define LKEY 'l'
-#define MKEY 'm'
-#define NKEY 'n'
-#define OKEY 'o'
-#define PKEY 'p'
-#define QKEY 'q'
-#define RKEY 'r'
-#define SKEY 's'
-#define TKEY 't'
-#define UKEY 'u'
-#define VKEY 'v'
-#define WKEY 'w'
-#define XKEY 'x'
-#define YKEY 'y'
-#define ZKEY 'z'
-
-#define ZEROKEY '0'
-#define ONEKEY '1'
-#define TWOKEY '2'
-#define THREEKEY '3'
-#define FOURKEY '4'
-#define FIVEKEY '5'
-#define SIXKEY '6'
-#define SEVENKEY '7'
-#define EIGHTKEY '8'
-#define NINEKEY '9'
-
-#define CAPSLOCKKEY 211
-
-#define LEFTCTRLKEY 212
-#define LEFTALTKEY 213
-#define RIGHTALTKEY 214
-#define RIGHTCTRLKEY 215
-#define RIGHTSHIFTKEY 216
-#define LEFTSHIFTKEY 217
-
-#define ESCKEY 218
-#define TABKEY 219
-#define RETKEY 220
-#define SPACEKEY 221
-#define LINEFEEDKEY 222
-#define BACKSPACEKEY 223
-#define DELKEY 224
-#define SEMICOLONKEY 225
-#define PERIODKEY 226
-#define COMMAKEY 227
-#define QUOTEKEY 228
-#define ACCENTGRAVEKEY 229
-#define MINUSKEY 230
-#define SLASHKEY 232
-#define BACKSLASHKEY 233
-#define EQUALKEY 234
-#define LEFTBRACKETKEY 235
-#define RIGHTBRACKETKEY 236
-
-#define LEFTARROWKEY 137
-#define DOWNARROWKEY 138
-#define RIGHTARROWKEY 139
-#define UPARROWKEY 140
-
-#define PAD0 150
-#define PAD1 151
-#define PAD2 152
-#define PAD3 153
-#define PAD4 154
-#define PAD5 155
-#define PAD6 156
-#define PAD7 157
-#define PAD8 158
-#define PAD9 159
-
-
-#define PADPERIOD 199
-#define PADSLASHKEY 161
-#define PADASTERKEY 160
-
-#define PADMINUS 162
-#define PADENTER 163
-#define PADPLUSKEY 164
-
-#define F1KEY 300
-#define F2KEY 301
-#define F3KEY 302
-#define F4KEY 303
-#define F5KEY 304
-#define F6KEY 305
-#define F7KEY 306
-#define F8KEY 307
-#define F9KEY 308
-#define F10KEY 309
-#define F11KEY 310
-#define F12KEY 311
-#define F13KEY 312
-#define F14KEY 313
-#define F15KEY 314
-#define F16KEY 315
-#define F17KEY 316
-#define F18KEY 317
-#define F19KEY 318
-
-#define PAUSEKEY 165
-#define INSERTKEY 166
-#define HOMEKEY 167
-#define PAGEUPKEY 168
-#define PAGEDOWNKEY 169
-#define ENDKEY 170
-
-#define UNKNOWNKEY 171
-#define OSKEY 172
-#define GRLESSKEY 173
-
-// XXX: are these codes ok?
-#define MEDIAPLAY 174
-#define MEDIASTOP 175
-#define MEDIAFIRST 176
-#define MEDIALAST 177
-
/* for event checks */
- /* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */
- /* UNUSED - see wm_eventmatch - BUG [#30479] */
-// #define ISTEXTINPUT(event_type) (event_type >= ' ' && event_type <= 255)
+/* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */
+/* UNUSED - see wm_eventmatch - BUG [#30479] */
+/* #define ISTEXTINPUT(event_type) (event_type >= ' ' && event_type <= 255) */
/* note, an alternative could be to check 'event->utf8_buf' */
- /* test whether the event is a key on the keyboard */
-#define ISKEYBOARD(event_type) (event_type >= ' ' && event_type <= 320)
+/* test whether the event is a key on the keyboard */
+#define ISKEYBOARD(event_type) \
+ ((event_type >= 0x0020 && event_type <= 0x00ff) || \
+ (event_type >= 0x012c && event_type <= 0x013f))
- /* test whether the event is a modifier key */
+/* test whether the event is a modifier key */
#define ISKEYMODIFIER(event_type) ((event_type >= LEFTCTRLKEY && event_type <= LEFTSHIFTKEY) || event_type == OSKEY)
- /* test whether the event is a mouse button */
+/* test whether the event is a mouse button */
#define ISMOUSE(event_type) (event_type >= LEFTMOUSE && event_type <= BUTTON7MOUSE)
- /* test whether the event is tweak event */
+/* test whether the event is tweak event */
#define ISTWEAK(event_type) (event_type >= EVT_TWEAK_L && event_type <= EVT_GESTURE)
- /* test whether the event is a NDOF event */
+/* test whether the event is a NDOF event */
#define ISNDOF(event_type) (event_type >= NDOF_MOTION && event_type < NDOF_LAST)
/* test whether event type is acceptable as hotkey, excluding modifiers */
@@ -315,76 +354,61 @@ enum {
(event_type >= LEFTCTRLKEY && event_type <= LEFTSHIFTKEY) == false && \
(event_type >= UNKNOWNKEY && event_type <= GRLESSKEY) == false)
-/* **************** BLENDER GESTURE EVENTS (0x5000) **************** */
-
-#define EVT_ACTIONZONE_AREA 20480
-#define EVT_ACTIONZONE_REGION 20481
-
- /* tweak events, for L M R mousebuttons */
-#define EVT_TWEAK_L 20482
-#define EVT_TWEAK_M 20483
-#define EVT_TWEAK_R 20484
- /* tweak events for action or select mousebutton */
-#define EVT_TWEAK_A 20485
-#define EVT_TWEAK_S 20486
-
-#define EVT_GESTURE 20496
-
-/* value of tweaks and line gestures, note, KM_ANY (-1) works for this case too */
-#define EVT_GESTURE_N 1
-#define EVT_GESTURE_NE 2
-#define EVT_GESTURE_E 3
-#define EVT_GESTURE_SE 4
-#define EVT_GESTURE_S 5
-#define EVT_GESTURE_SW 6
-#define EVT_GESTURE_W 7
-#define EVT_GESTURE_NW 8
-/* value of corner gestures */
-#define EVT_GESTURE_N_E 9
-#define EVT_GESTURE_N_W 10
-#define EVT_GESTURE_E_N 11
-#define EVT_GESTURE_E_S 12
-#define EVT_GESTURE_S_E 13
-#define EVT_GESTURE_S_W 14
-#define EVT_GESTURE_W_S 15
-#define EVT_GESTURE_W_N 16
-
-/* **************** OTHER BLENDER EVENTS ********************* */
-
-/* event->type */
-#define EVT_FILESELECT 0x5020
-
-/* event->val */
-#define EVT_FILESELECT_OPEN 1
-#define EVT_FILESELECT_FULL_OPEN 2
-#define EVT_FILESELECT_EXEC 3
-#define EVT_FILESELECT_CANCEL 4
-#define EVT_FILESELECT_EXTERNAL_CANCEL 5
-
-/* event->type */
-#define EVT_BUT_OPEN 0x5021
-#define EVT_MODAL_MAP 0x5022
-#define EVT_DROP 0x5023
-#define EVT_BUT_CANCEL 0x5024
-
-/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
-#define GESTURE_MODAL_CANCEL 1
-#define GESTURE_MODAL_CONFIRM 2
-
-#define GESTURE_MODAL_SELECT 3
-#define GESTURE_MODAL_DESELECT 4
-
-#define GESTURE_MODAL_NOP 5 /* circle select when no mouse button is pressed */
-
-#define GESTURE_MODAL_CIRCLE_ADD 6 /* circle sel: larger brush */
-#define GESTURE_MODAL_CIRCLE_SUB 7 /* circle sel: smaller brush */
-
-#define GESTURE_MODAL_BEGIN 8 /* border select/straight line, activate, use release to detect which button */
-
-#define GESTURE_MODAL_IN 9
-#define GESTURE_MODAL_OUT 10
-
-#define GESTURE_MODAL_CIRCLE_SIZE 11 /* circle sel: size brush (for trackpad event) */
+
+/* ********** wmEvent.val ********** */
+
+/* Gestures */
+enum {
+ /* value of tweaks and line gestures, note, KM_ANY (-1) works for this case too */
+ EVT_GESTURE_N = 1,
+ EVT_GESTURE_NE = 2,
+ EVT_GESTURE_E = 3,
+ EVT_GESTURE_SE = 4,
+ EVT_GESTURE_S = 5,
+ EVT_GESTURE_SW = 6,
+ EVT_GESTURE_W = 7,
+ EVT_GESTURE_NW = 8,
+ /* value of corner gestures */
+ EVT_GESTURE_N_E = 9,
+ EVT_GESTURE_N_W = 10,
+ EVT_GESTURE_E_N = 11,
+ EVT_GESTURE_E_S = 12,
+ EVT_GESTURE_S_E = 13,
+ EVT_GESTURE_S_W = 14,
+ EVT_GESTURE_W_S = 15,
+ EVT_GESTURE_W_N = 16,
+};
+
+/* File select */
+enum {
+ EVT_FILESELECT_OPEN = 1,
+ EVT_FILESELECT_FULL_OPEN = 2,
+ EVT_FILESELECT_EXEC = 3,
+ EVT_FILESELECT_CANCEL = 4,
+ EVT_FILESELECT_EXTERNAL_CANCEL = 5,
+};
+
+/* Gesture */
+/* NOTE: these values are saved in keymap files, do not change them but just add new ones */
+enum {
+ GESTURE_MODAL_CANCEL = 1,
+ GESTURE_MODAL_CONFIRM = 2,
+
+ GESTURE_MODAL_SELECT = 3,
+ GESTURE_MODAL_DESELECT = 4,
+
+ GESTURE_MODAL_NOP = 5, /* circle select when no mouse button is pressed */
+
+ GESTURE_MODAL_CIRCLE_ADD = 6, /* circle sel: larger brush */
+ GESTURE_MODAL_CIRCLE_SUB = 7, /* circle sel: smaller brush */
+
+ GESTURE_MODAL_BEGIN = 8, /* border select/straight line, activate, use release to detect which button */
+
+ GESTURE_MODAL_IN = 9,
+ GESTURE_MODAL_OUT = 10,
+
+ GESTURE_MODAL_CIRCLE_SIZE = 11, /* circle sel: size brush (for trackpad event) */
+};
#endif /* __WM_EVENT_TYPES_H__ */
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 7ce3fa82f8b..ce20371d91b 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -228,3 +228,9 @@ if(WITH_PLAYER)
endif()
setup_liblinks(blenderplayer)
+
+# We put CLEW and CUEW here because OPENSUBDIV_LIBRARIES dpeends on them..
+if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV)
+ target_link_libraries(blenderplayer "extern_clew")
+ target_link_libraries(blenderplayer "extern_cuew")
+endif()
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 72f411b4231..97e7d99c802 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -301,6 +301,8 @@ void ED_armature_transform(struct bArmature *arm, float mat[4][4]) 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
+float WM_event_tablet_data(const struct wmEvent *event, int *pen_flip, float tilt[2]) RET_ZERO
+bool WM_event_is_tablet(const struct wmEvent *event) RET_ZERO
void ED_armature_edit_bone_remove(struct bArmature *arm, struct EditBone *exBone) RET_NONE
void object_test_constraints(struct Object *owner) RET_NONE
void ED_armature_ebone_to_mat4(struct EditBone *ebone, float mat[4][4]) RET_NONE
@@ -385,7 +387,6 @@ void ED_area_tag_redraw(struct ScrArea *sa) RET_NONE
void ED_area_tag_refresh(struct ScrArea *sa) RET_NONE
void ED_area_newspace(struct bContext *C, struct ScrArea *sa, int type) RET_NONE
void ED_region_tag_redraw(struct ARegion *ar) RET_NONE
-void ED_curve_transform(struct Curve *cv, float mat[4][4]) RET_NONE
void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op) RET_NONE
void WM_cursor_wait(bool val) RET_NONE
void ED_node_texture_default(const struct bContext *C, struct Tex *tex) RET_NONE
@@ -411,7 +412,7 @@ void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic)
void ED_view3D_background_image_clear(struct View3D *v3d) RET_NONE
void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]) RET_NONE
float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) RET_ZERO
-void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa) RET_NONE
+void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa) RET_NONE
void ED_node_shader_default(const struct bContext *C, struct ID *id) RET_NONE
void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh) RET_NONE
struct bScreen *ED_screen_animation_playing(const struct wmWindowManager *wm) RET_NULL
@@ -437,7 +438,6 @@ void uiLayoutSetScaleX(struct uiLayout *layout, float scale) RET_NONE
void uiLayoutSetScaleY(struct uiLayout *layout, float scale) RET_NONE
void uiTemplateIconView(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) RET_NONE
void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Base *base) RET_NONE
-void ED_mesh_transform(struct Mesh *me, float mat[4][4]) RET_NONE
void ED_mesh_update(struct Mesh *mesh, struct bContext *C, int calc_edges, int calc_tessface) RET_NONE
void ED_mesh_vertices_add(struct Mesh *mesh, struct ReportList *reports, int count) RET_NONE
void ED_mesh_edges_add(struct Mesh *mesh, struct ReportList *reports, int count) RET_NONE
@@ -473,8 +473,6 @@ bool ED_texture_context_check_lamp(const struct bContext *C) RET_ZERO
bool ED_texture_context_check_particles(const struct bContext *C) RET_ZERO
bool ED_texture_context_check_others(const struct bContext *C) RET_ZERO
-void ED_mball_transform(struct MetaBall *mb, float mat[4][4]) RET_NONE
-
bool snapObjectsRayEx(struct Scene *scene, struct Base *base_act, struct View3D *v3d, struct ARegion *ar, struct Object *obedit, short snap_mode,
struct Object **r_ob, float r_obmat[4][4],
const float ray_start[3], const float ray_normal[3], float *r_ray_dist,
@@ -482,7 +480,6 @@ bool snapObjectsRayEx(struct Scene *scene, struct Base *base_act, struct View3D
void make_editLatt(struct Object *obedit) RET_NONE
void load_editLatt(struct Object *obedit) RET_NONE
-void ED_lattice_transform(struct Lattice *lt, float mat[4][4]) RET_NONE
void load_editNurb(struct Object *obedit) RET_NONE
void make_editNurb(struct Object *obedit) RET_NONE
@@ -561,6 +558,7 @@ void uiTemplateColorspaceSettings(struct uiLayout *layout, struct PointerRNA *pt
void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname) RET_NONE
void uiTemplateComponentMenu(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name) RET_NONE
void uiTemplateNodeSocket(struct uiLayout *layout, struct bContext *C, float *color) RET_NONE
+void uiTemplatePalette(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, int color) RET_NONE
/* rna render */
struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername) RET_NULL
@@ -619,6 +617,13 @@ struct wmKeyMap *WM_modalkeymap_add(struct wmKeyConfig *keyconf, const char *idn
struct uiPopupMenu *uiPupMenuBegin(struct bContext *C, const char *title, int icon) RET_NULL
void uiPupMenuEnd(struct bContext *C, struct uiPopupMenu *head) RET_NONE
struct uiLayout *uiPupMenuLayout(struct uiPopupMenu *head) RET_NULL
+struct uiLayout *uiPieMenuLayout(struct uiPieMenu *pie) RET_NULL
+void uiPieMenuInvoke(struct bContext *C, const char *idname, const struct wmEvent *event) RET_NONE
+struct uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const struct wmEvent *event) RET_NULL
+void uiPieMenuEnd(struct bContext *C, uiPieMenu *pie) RET_NONE
+struct uiLayout *uiLayoutRadial(struct uiLayout *layout) RET_NULL
+void uiPieOperatorEnumInvoke(struct bContext *C, const char *title, const char *opname,
+ const char *propname, const struct wmEvent *event) RET_NONE
/* RNA COLLADA dependency */
int collada_export(struct Scene *sce,
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 7df91df23c8..bd9dce01ed8 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -278,7 +278,7 @@ elseif(APPLE)
if(WITH_PYTHON_MODULE)
set(TARGETDIR_VER ${TARGETDIR}/${BLENDER_VERSION})
else()
- set(TARGETDIR_VER ${TARGETDIR}/blender.app/Contents/MacOS/${BLENDER_VERSION})
+ set(TARGETDIR_VER ${TARGETDIR}/blender.app/Contents/Resources/${BLENDER_VERSION})
endif()
endif()
@@ -395,19 +395,26 @@ endif()
if(UNIX AND NOT APPLE)
- install(
- CODE
- "
- execute_process(COMMAND
- ${CMAKE_SOURCE_DIR}/doc/manpage/blender.1.py
- ${TARGETDIR}/blender
- ${TARGETDIR}/blender.1)
- "
- )
+ if(NOT WITH_PYTHON_MODULE)
+ install(
+ CODE
+ "
+ execute_process(COMMAND
+ ${CMAKE_SOURCE_DIR}/doc/manpage/blender.1.py
+ ${TARGETDIR}/blender
+ ${TARGETDIR}/blender.1)
+ "
+ )
+ endif()
# there are a few differences between portable and system install
if(WITH_INSTALL_PORTABLE)
install(
+ FILES ${TARGETDIR}/blender.1
+ DESTINATION ${TARGETDIR}
+ )
+
+ install(
FILES
${CMAKE_SOURCE_DIR}/release/freedesktop/blender.desktop
${CMAKE_SOURCE_DIR}/release/freedesktop/icons/scalable/apps/blender.svg
@@ -438,6 +445,11 @@ if(UNIX AND NOT APPLE)
PROGRAMS ${TARGETDIR}/blender
DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
)
+ # manpage only with 'blender' binary
+ install(
+ FILES ${TARGETDIR}/blender.1
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man1
+ )
endif()
@@ -473,10 +485,6 @@ if(UNIX AND NOT APPLE)
DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
)
install(
- FILES ${TARGETDIR}/blender.1
- DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man1
- )
- install(
FILES ${BLENDER_TEXT_FILES}
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/doc/blender
)
@@ -515,16 +523,22 @@ if(UNIX AND NOT APPLE)
PATTERN "idlelib" EXCLUDE # ./idlelib
PATTERN "test" EXCLUDE # ./test
PATTERN "turtledemo" EXCLUDE # ./turtledemo
- PATTERN "turtle.py" EXCLUDE # ./turtle.py
+ PATTERN "turtle.py" EXCLUDE # ./turtle.py
)
# # doesnt work, todo
# install(CODE "execute_process(COMMAND find ${TARGETDIR}/${BLENDER_VERSION}/python/lib/ -name '*.so' -exec strip -s {} '\;')")
-
+
if(WITH_PYTHON_INSTALL_NUMPY)
+ # Install to the same directory as the source, so debian-like
+ # distros are happy with their policy.
+ set(_suffix "site-packages")
+ if(${PYTHON_NUMPY_PATH} MATCHES "dist-packages")
+ set(_suffix "dist-packages")
+ endif()
install(
DIRECTORY ${PYTHON_NUMPY_PATH}/numpy
- DESTINATION ${TARGETDIR_VER}/python/${_target_LIB}/python${PYTHON_VERSION}/site-packages
+ DESTINATION ${TARGETDIR_VER}/python/${_target_LIB}/python${PYTHON_VERSION}/${_suffix}
PATTERN ".svn" EXCLUDE
PATTERN "__pycache__" EXCLUDE # * any cache *
PATTERN "*.pyc" EXCLUDE # * any cache *
@@ -538,19 +552,47 @@ if(UNIX AND NOT APPLE)
PATTERN "*.h" EXCLUDE # some includes are not in include dirs
PATTERN "*.a" EXCLUDE # ./core/lib/libnpymath.a - for linking, we dont need.
)
+ unset(_suffix)
endif()
# Copy requests, we need to generalize site-packages
if(WITH_PYTHON_INSTALL_REQUESTS)
+ set(_suffix "site-packages")
+ if(${PYTHON_REQUESTS_PATH} MATCHES "dist-packages")
+ set(_suffix "dist-packages")
+ endif()
install(
- DIRECTORY ${PYTHON_LIBPATH}/python${PYTHON_VERSION}/site-packages/requests
- DESTINATION ${TARGETDIR_VER}/python/${_target_LIB}/python${PYTHON_VERSION}/site-packages
+ DIRECTORY ${PYTHON_REQUESTS_PATH}/requests
+ DESTINATION ${TARGETDIR_VER}/python/${_target_LIB}/python${PYTHON_VERSION}/${_suffix}
PATTERN ".svn" EXCLUDE
PATTERN "__pycache__" EXCLUDE # * any cache *
PATTERN "*.pyc" EXCLUDE # * any cache *
PATTERN "*.pyo" EXCLUDE # * any cache *
PATTERN "cacert.pem" EXCLUDE # for now we don't deal with security
)
+ # On some platforms requests does have extra dependencies.
+ set(_requests_deps "chardet" "urllib3")
+ foreach(_requests_dep ${_requests_deps})
+ if(EXISTS ${PYTHON_REQUESTS_PATH}/${_requests_dep})
+ install(
+ DIRECTORY ${PYTHON_REQUESTS_PATH}/${_requests_dep}
+ DESTINATION ${TARGETDIR_VER}/python/${_target_LIB}/python${PYTHON_VERSION}/${_suffix}
+ PATTERN ".svn" EXCLUDE
+ PATTERN "__pycache__" EXCLUDE # * any cache *
+ PATTERN "*.pyc" EXCLUDE # * any cache *
+ PATTERN "*.pyo" EXCLUDE # * any cache *
+ )
+ endif()
+ endforeach()
+ if(EXISTS ${PYTHON_REQUESTS_PATH}/six.py)
+ install(
+ FILES ${PYTHON_REQUESTS_PATH}/six.py
+ DESTINATION ${TARGETDIR_VER}/python/${_target_LIB}/python${PYTHON_VERSION}/${_suffix}
+ )
+ endif()
+ unset(_requests_dep)
+ unset(_requests_deps)
+ unset(_suffix)
endif()
unset(_target_LIB)
@@ -567,13 +609,13 @@ elseif(WIN32)
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
install(
- FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.dll
+ FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.dll ${LIBDIR}/python/lib/sqlite3.dll
DESTINATION ${TARGETDIR}
CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel
)
install(
- FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}_d.dll
+ FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}_d.dll ${LIBDIR}/python/lib/sqlite3_d.dll
DESTINATION ${TARGETDIR}
CONFIGURATIONS Debug
)
@@ -719,12 +761,10 @@ elseif(WIN32)
endif()
if(WITH_SDL)
- if(NOT CMAKE_CL_64)
- install(
- FILES ${LIBDIR}/sdl/lib/SDL.dll
- DESTINATION ${TARGETDIR}
- )
- endif()
+ install(
+ FILES ${LIBDIR}/sdl/lib/SDL.dll
+ DESTINATION ${TARGETDIR}
+ )
endif()
if(NOT CMAKE_CL_64)
@@ -810,6 +850,13 @@ elseif(APPLE)
)
endif()
+ if(WITH_LLVM AND NOT LLVM_STATIC)
+ install(
+ FILES ${LIBDIR}/llvm/lib/libLLVM-3.4.dylib
+ DESTINATION ${TARGETDIR}/blender.app/Contents/MacOS
+ )
+ endif()
+
# python
if(WITH_PYTHON AND NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK)
# the python zip is first extract as part of the build process,
@@ -909,3 +956,18 @@ setup_blender_sorted_libs()
target_link_libraries(blender ${BLENDER_SORTED_LIBS})
setup_liblinks(blender)
+
+# -----------------------------------------------------------------------------
+# Setup launcher
+
+if(WIN32 AND NOT WITH_PYTHON_MODULE)
+ set(LAUNCHER_SRC
+ creator_launch_win.c
+ ../icons/winblender.rc
+ )
+ add_executable(blender-launcher ${LAUNCHER_SRC})
+ target_link_libraries(blender-launcher bf_intern_utfconv ${PLATFORM_LINKLIBS})
+
+ set_target_properties(blender PROPERTIES OUTPUT_NAME blender-app)
+ set_target_properties(blender-launcher PROPERTIES OUTPUT_NAME blender)
+endif()
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 25455c99a71..10f82b90516 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -41,6 +41,9 @@
#endif
#ifdef WIN32
+# if defined(_MSC_VER) && _MSC_VER >= 1800 && defined(_M_X64)
+# include <math.h> /* needed for _set_FMA3_enable */
+# endif
# include <windows.h>
# include "utfconv.h"
#endif
@@ -1501,7 +1504,13 @@ int main(
bArgs *ba;
#endif
-#ifdef WIN32 /* Win32 Unicode Args */
+#ifdef WIN32
+ /* FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it. */
+# if defined(_MSC_VER) && _MSC_VER >= 1800 && defined(_M_X64)
+ _set_FMA3_enable(0);
+# endif
+
+ /* Win32 Unicode Args */
/* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized
* (it depends on the args passed in, which is what we're getting here!)
*/
diff --git a/source/creator/creator_launch_win.c b/source/creator/creator_launch_win.c
new file mode 100644
index 00000000000..a7e04b2dafc
--- /dev/null
+++ b/source/creator/creator_launch_win.c
@@ -0,0 +1,85 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* Binary name to launch. */
+#define BLENDER_BINARY L"blender-app.exe"
+
+#define WIN32_LEAN_AND_MEAN
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <windows.h>
+#include <Shellapi.h>
+
+#include "utfconv.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_winstuff.h"
+
+static void local_hacks_do(void)
+{
+ _putenv_s("OMP_WAIT_POLICY", "PASSIVE");
+}
+
+int main(int argc, const char **UNUSED(argv_c))
+{
+ PROCESS_INFORMATION processInformation = {0};
+ STARTUPINFOW startupInfo = {0};
+ BOOL result;
+ wchar_t command[65536];
+ int i, len = sizeof(command) / sizeof(wchar_t);
+ wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
+ int argci = 0;
+
+ local_hacks_do();
+
+ wcsncpy(command, BLENDER_BINARY, len - 1);
+ len -= wcslen(BLENDER_BINARY);
+ for (i = 1; i < argc; ++i) {
+ wcsncat(command, L" \"", len - 2);
+ wcsncat(command, argv_16[i], len - 3);
+ len -= wcslen(argv_16[i]) + 1;
+ wcsncat(command, L"\"", len - 1);
+ }
+
+ LocalFree(argv_16);
+
+ startupInfo.cb = sizeof(startupInfo);
+ result = CreateProcessW(NULL, command, NULL, NULL, TRUE,
+ 0, NULL, NULL,
+ &startupInfo, &processInformation);
+
+ if (!result) {
+ fprintf(stderr, "%S\n", L"Error launching " BLENDER_BINARY);
+ return EXIT_FAILURE;
+ }
+
+ WaitForSingleObject(processInformation.hProcess, INFINITE);
+
+ CloseHandle(processInformation.hProcess);
+ CloseHandle(processInformation.hThread);
+
+ return EXIT_SUCCESS;
+}
diff --git a/source/creator/osx_locals.map b/source/creator/osx_locals.map
index c3dd8b62792..a1d7e7fed57 100644
--- a/source/creator/osx_locals.map
+++ b/source/creator/osx_locals.map
@@ -1,3 +1,5 @@
## The symbols will be treated as if they were marked as __private_extern__
## (aka visibility=hidden) and will not be global in the output file
*boost*
+*__ZNSt6vector*
+
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index e11bc84a0da..8d73e591113 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -101,7 +101,7 @@ static void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
out->chanhash = NULL;
out->agroups.first= out->agroups.last= NULL;
out->ikdata = NULL;
- out->ikparam = MEM_dupallocN(out->ikparam);
+ out->ikparam = MEM_dupallocN(src->ikparam);
out->flag |= POSE_GAME_ENGINE;
BLI_duplicatelist(&out->chanbase, &src->chanbase);
@@ -231,6 +231,8 @@ BL_ArmatureObject::BL_ArmatureObject(
m_objArma = BKE_object_copy(armature);
m_objArma->data = BKE_armature_copy((bArmature *)armature->data);
m_pose = m_objArma->pose;
+ // need this to get iTaSC working ok in the BGE
+ m_pose->flag |= POSE_GAME_ENGINE;
memcpy(m_obmat, m_objArma->obmat, sizeof(m_obmat));
}
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index e511f01e9c6..87b64582e11 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -876,7 +876,7 @@ static bool ConvertMaterial(
material->alphablend = GEMAT_ALPHA;
// always zsort alpha + add
- if ((ELEM3(material->alphablend, GEMAT_ALPHA, GEMAT_ALPHA_SORT, GEMAT_ADD) || texalpha) && (material->alphablend != GEMAT_CLIP )) {
+ if ((ELEM(material->alphablend, GEMAT_ALPHA, GEMAT_ALPHA_SORT, GEMAT_ADD) || texalpha) && (material->alphablend != GEMAT_CLIP )) {
material->ras_mode |= ALPHA;
material->ras_mode |= (mat && (mat->game.alpha_blend & GEMAT_ALPHA_SORT))? ZSORT: 0;
}
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h
index f72275b79cf..e96d0e0ebb4 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.h
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.h
@@ -59,7 +59,7 @@ public:
virtual void ProcessReplica();
void SetBlendTime (float newtime);
- void BlendShape(struct Key* key, float weigth);
+ void BlendShape(struct Key* key, float weight);
bAction* GetAction() { return m_action; }
void SetAction(bAction* act) { m_action= act; }
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index 45fc11b97d2..f6ed3366625 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -538,8 +538,8 @@ void BL_ConvertActuators(const char* maggiename,
originalval,
editobact->time,
editobact->flag,
- blenderobject->trackflag,
- blenderobject->upflag);
+ editobact->trackflag,
+ editobact->upflag);
baseact = tmptrackact;
break;
}
diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp
index 93a5ee11366..0d706fcd924 100644
--- a/source/gameengine/Converter/KX_ConvertSensors.cpp
+++ b/source/gameengine/Converter/KX_ConvertSensors.cpp
@@ -329,12 +329,19 @@ void BL_ConvertSensors(struct Object* blenderobject,
gameobj);
} else {
/* give us a focus-aware sensor */
+ bool bFindMaterial = (bmouse->mode & SENS_COLLISION_MATERIAL);
+ bool bXRay = (bmouse->flag & SENS_RAY_XRAY);
+ STR_String checkname = (bFindMaterial? bmouse->matname : bmouse->propname);
+
gamesensor = new KX_MouseFocusSensor(eventmgr,
startx,
starty,
keytype,
trackfocus,
(bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false,
+ checkname,
+ bFindMaterial,
+ bXRay,
kxscene,
kxengine,
gameobj);
diff --git a/source/gameengine/Expressions/Expression.cpp b/source/gameengine/Expressions/Expression.cpp
index c1146aaa65c..2428df977d3 100644
--- a/source/gameengine/Expressions/Expression.cpp
+++ b/source/gameengine/Expressions/Expression.cpp
@@ -21,13 +21,13 @@
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
-#ifdef _DEBUG
+#ifdef DEBUG
//int gRefCountExpr;
#endif
CExpression::CExpression()// : m_cached_calculate(NULL)
{
m_refcount = 1;
-#ifdef _DEBUG
+#ifdef DEBUG
//gRefCountExpr++;
#endif
}
diff --git a/source/gameengine/Expressions/Expression.h b/source/gameengine/Expressions/Expression.h
index d1b7eda43f0..9a4f1f93284 100644
--- a/source/gameengine/Expressions/Expression.h
+++ b/source/gameengine/Expressions/Expression.h
@@ -116,7 +116,7 @@ public:
virtual CExpression * AddRef() { // please leave multiline, for debugger !!!
-#ifdef _DEBUG
+#ifdef DEBUG
//gRefCountExpr++;
assertd(m_refcount < 255);
#endif
@@ -124,7 +124,7 @@ public:
return this;
};
virtual CExpression* Release(CExpression* complicatedtrick=NULL) {
-#ifdef _DEBUG
+#ifdef DEBUG
//gRefCountExpr--;
#endif
if (--m_refcount < 1)
diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp
index a2d055974c3..82d2e94dbb0 100644
--- a/source/gameengine/Expressions/IntValue.cpp
+++ b/source/gameengine/Expressions/IntValue.cpp
@@ -35,7 +35,7 @@ effect: constructs a new CIntValue
*/
{
-#ifdef _DEBUG_
+#ifdef DEBUG_
m_textval = "Int illegal constructor";
#endif
m_pstrRep=NULL;
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index 1ced71e66a4..bdef2dbd5b0 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -86,7 +86,7 @@ struct SmartCValueRef
std::vector<SmartCValueRef> gRefList;
#endif
-#ifdef _DEBUG
+#ifdef DEBUG
//int gRefCountValue;
#endif
@@ -101,7 +101,7 @@ effect: constucts a CValue
*/
{
//debug(gRefCountValue++) // debugging
-#ifdef _DEBUG
+#ifdef DEBUG
//gRefCountValue++;
#ifdef CVALUE_DEBUG
gRefList.push_back(SmartCValueRef(this));
@@ -460,7 +460,7 @@ void CValue::DisableRefCount()
m_refcount--;
//debug(gRefCountValue--);
-#ifdef _DEBUG
+#ifdef DEBUG
//gRefCountValue--;
#endif
m_ValFlags.RefCountDisabled=true;
@@ -472,7 +472,7 @@ void CValue::ProcessReplica() /* was AddDataToReplica in 2.48 */
{
m_refcount = 1;
-#ifdef _DEBUG
+#ifdef DEBUG
//gRefCountValue++;
#endif
PyObjectPlus::ProcessReplica();
diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h
index 7f6ce9aa703..c7e9a40a059 100644
--- a/source/gameengine/Expressions/Value.h
+++ b/source/gameengine/Expressions/Value.h
@@ -90,7 +90,7 @@ enum VALUE_DATA_TYPE {
-#ifdef _DEBUG
+#ifdef DEBUG
//extern int gRefCountValue; // debugonly variable to check if all CValue Refences are Dereferenced at programexit
#endif
@@ -251,7 +251,7 @@ public:
// Increase global reference count, used to see at the end of the program
// if all CValue-derived classes have been dereferenced to 0
//debug(gRefCountValue++);
-#ifdef _DEBUG
+#ifdef DEBUG
//gRefCountValue++;
#endif
m_refcount++;
@@ -264,7 +264,7 @@ public:
// Decrease global reference count, used to see at the end of the program
// if all CValue-derived classes have been dereferenced to 0
//debug(gRefCountValue--);
-#ifdef _DEBUG
+#ifdef DEBUG
//gRefCountValue--;
#endif
// Decrease local reference count, if it reaches 0 the object should be freed
diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
index 37c867ef7d6..566e5567507 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
+++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
@@ -36,7 +36,7 @@
#undef main
#endif
-#ifndef _DEBUG
+#ifndef DEBUG
# define JOYSTICK_ECHO(x)
#else
# include <iostream>
diff --git a/source/gameengine/GameLogic/SCA_IScene.cpp b/source/gameengine/GameLogic/SCA_IScene.cpp
index c98c86639d3..3ca4b6607b3 100644
--- a/source/gameengine/GameLogic/SCA_IScene.cpp
+++ b/source/gameengine/GameLogic/SCA_IScene.cpp
@@ -70,6 +70,32 @@ std::vector<SCA_DebugProp*>& SCA_IScene::GetDebugProperties()
}
+bool SCA_IScene::PropertyInDebugList( class CValue *gameobj, const STR_String &name )
+{
+ for (std::vector<SCA_DebugProp*>::iterator it = m_debugList.begin();
+ !(it==m_debugList.end());++it) {
+ STR_String debugname = (*it)->m_name;
+ CValue *debugobj = (*it)->m_obj;
+
+ if (debugobj == gameobj && debugname == name)
+ return true;
+ }
+ return false;
+}
+
+
+bool SCA_IScene::ObjectInDebugList( class CValue *gameobj )
+{
+ for (std::vector<SCA_DebugProp*>::iterator it = m_debugList.begin();
+ !(it==m_debugList.end());++it) {
+ CValue* debugobj = (*it)->m_obj;
+
+ if (debugobj == gameobj)
+ return true;
+ }
+ return false;
+}
+
void SCA_IScene::AddDebugProperty(class CValue* debugprop,
const STR_String &name)
@@ -84,6 +110,24 @@ void SCA_IScene::AddDebugProperty(class CValue* debugprop,
}
+void SCA_IScene::RemoveDebugProperty(class CValue *gameobj,
+ const STR_String &name)
+{
+ vector<SCA_DebugProp*>::iterator it = m_debugList.begin();
+ while(it != m_debugList.end()) {
+ STR_String debugname = (*it)->m_name;
+ CValue *debugobj = (*it)->m_obj;
+
+ if (debugobj == gameobj && debugname == name) {
+ delete (*it);
+ m_debugList.erase(it);
+ break;
+ }
+ ++it;
+ }
+}
+
+
void SCA_IScene::RemoveObjectDebugProperties(class CValue* gameobj)
{
vector<SCA_DebugProp*>::iterator it = m_debugList.begin();
diff --git a/source/gameengine/GameLogic/SCA_IScene.h b/source/gameengine/GameLogic/SCA_IScene.h
index e2e1edd4354..b76b5636b13 100644
--- a/source/gameengine/GameLogic/SCA_IScene.h
+++ b/source/gameengine/GameLogic/SCA_IScene.h
@@ -67,9 +67,11 @@ public:
virtual void ReplaceMesh(class CValue* gameobj,
void* meshobj, bool use_gfx, bool use_phys)=0;
std::vector<SCA_DebugProp*>& GetDebugProperties();
+ bool PropertyInDebugList(class CValue *gameobj, const STR_String &name);
+ bool ObjectInDebugList(class CValue *gameobj);
void RemoveAllDebugProperties();
- void AddDebugProperty(class CValue* debugprop,
- const STR_String &name);
+ void AddDebugProperty(class CValue* debugprop, const STR_String &name);
+ void RemoveDebugProperty(class CValue *gameobj, const STR_String &name);
void RemoveObjectDebugProperties(class CValue* gameobj);
virtual void Update2DFilter(std::vector<STR_String>& propNames, void* gameObj,
diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
index 0eab6187d07..ea1b2a2bce3 100644
--- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
@@ -69,13 +69,24 @@ bool SCA_PropertyActuator::Update()
bool bNegativeEvent = IsNegativeEvent();
RemoveAllEvents();
-
+ CValue* propowner = GetParent();
if (bNegativeEvent)
- return false; // do nothing on negative events
+ {
+ if (m_type==KX_ACT_PROP_LEVEL)
+ {
+ CValue* newval = new CBoolValue(false);
+ CValue* oldprop = propowner->GetProperty(m_propname);
+ if (oldprop)
+ {
+ oldprop->SetValue(newval);
+ }
+ newval->Release();
+ }
+ return false;
+ }
- CValue* propowner = GetParent();
CParser parser;
parser.SetContext( propowner->AddRef());
@@ -97,6 +108,19 @@ bool SCA_PropertyActuator::Update()
}
newval->Release();
}
+ else if (m_type==KX_ACT_PROP_LEVEL)
+ {
+ CValue* newval = new CBoolValue(true);
+ CValue* oldprop = propowner->GetProperty(m_propname);
+ if (oldprop)
+ {
+ oldprop->SetValue(newval);
+ } else
+ {
+ propowner->SetProperty(m_propname,newval);
+ }
+ newval->Release();
+ }
else if ((userexpr = parser.ProcessText(m_exprtxt))) {
switch (m_type)
{
diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h
index 83a6d05df1b..228ecf94bc4 100644
--- a/source/gameengine/GameLogic/SCA_PropertyActuator.h
+++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h
@@ -44,6 +44,7 @@ class SCA_PropertyActuator : public SCA_IActuator
KX_ACT_PROP_ADD,
KX_ACT_PROP_COPY,
KX_ACT_PROP_TOGGLE,
+ KX_ACT_PROP_LEVEL,
KX_ACT_PROP_MAX
};
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index 0d0b99edee1..9f0b582045f 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -616,7 +616,7 @@ void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasteriz
/* we do blend modes here, because they can change per object
* with the same material due to obcolor/obalpha */
alphablend = mBlenderShader->GetAlphaBlend();
- if (ELEM3(alphablend, GEMAT_SOLID, GEMAT_ALPHA, GEMAT_ALPHA_SORT) && mMaterial->alphablend != GEMAT_SOLID)
+ if (ELEM(alphablend, GEMAT_SOLID, GEMAT_ALPHA, GEMAT_ALPHA_SORT) && mMaterial->alphablend != GEMAT_SOLID)
alphablend = mMaterial->alphablend;
rasty->SetAlphaBlend(alphablend);
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
index 793324fab75..29d92762285 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
@@ -114,6 +114,7 @@ PyMethodDef KX_ConstraintWrapper::Methods[] = {
PyAttributeDef KX_ConstraintWrapper::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("constraint_id", KX_ConstraintWrapper, pyattr_get_constraintId),
+ KX_PYATTRIBUTE_RO_FUNCTION("constraint_type", KX_ConstraintWrapper, pyattr_get_constraintType),
{ NULL } //Sentinel
};
@@ -123,4 +124,10 @@ PyObject *KX_ConstraintWrapper::pyattr_get_constraintId(void *self_v, const KX_P
return self->PyGetConstraintId();
}
+PyObject *KX_ConstraintWrapper::pyattr_get_constraintType(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_ConstraintWrapper* self = static_cast<KX_ConstraintWrapper*>(self_v);
+ return PyLong_FromLong(self->m_constraintType);
+}
+
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
index eafc45b5a70..b7124c76439 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
@@ -49,6 +49,7 @@ public:
KX_PYMETHOD(KX_ConstraintWrapper,GetParam);
static PyObject *pyattr_get_constraintId(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_constraintType(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
#endif
private:
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
index f58fee88d48..a77269c116d 100644
--- a/source/gameengine/Ketsji/KX_Dome.cpp
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -2044,6 +2044,7 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i)
cam->NodeUpdateGS(0.f);
scene->CalculateVisibleMeshes(m_rasterizer,cam);
+ scene->UpdateAnimations(m_engine->GetFrameTime());
scene->RenderBuckets(camtrans, m_rasterizer);
}
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index de528aeac63..c681e0842c4 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -51,6 +51,7 @@ typedef unsigned long uint_ptr;
#include "KX_Light.h" // only for their ::Type
#include "KX_FontObject.h" // only for their ::Type
#include "RAS_MeshObject.h"
+#include "KX_NavMeshObject.h"
#include "KX_MeshProxy.h"
#include "KX_PolyProxy.h"
#include <stdio.h> // printf
@@ -68,6 +69,7 @@ typedef unsigned long uint_ptr;
#include "SCA_IController.h"
#include "NG_NetworkScene.h" //Needed for sendMessage()
#include "KX_ObstacleSimulation.h"
+#include "KX_Scene.h"
#include "BKE_object.h"
@@ -928,6 +930,27 @@ KX_GameObject::SetVisible(
}
}
+bool KX_GameObject::GetCulled()
+{
+ // If we're set to not cull, double-check with
+ // the mesh slots first. This is kind of nasty, but
+ // it allows us to get proper culling information.
+ if (!m_bCulled)
+ {
+ SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
+ for (mit.begin(); !mit.end(); ++mit)
+ {
+ if ((*mit)->m_bCulled)
+ {
+ m_bCulled = true;
+ break;
+ }
+ }
+ }
+
+ return m_bCulled;
+}
+
static void setOccluder_recursive(SG_Node* node, bool v)
{
NodeList& children = node->GetSGChildren();
@@ -958,6 +981,44 @@ KX_GameObject::SetOccluder(
}
}
+static void setDebug_recursive(SG_Node *node, bool debug)
+{
+ NodeList& children = node->GetSGChildren();
+ KX_Scene *scene = KX_GetActiveScene();
+
+ for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) {
+ SG_Node *childnode = (*childit);
+ KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
+ if (clientgameobj != NULL) {
+ if (debug) {
+ if (!scene->ObjectInDebugList(clientgameobj))
+ scene->AddObjectDebugProperties(clientgameobj);
+ }
+ else
+ scene->RemoveObjectDebugProperties(clientgameobj);
+ }
+
+ /* if the childobj is NULL then this may be an inverse parent link
+ * so a non recursive search should still look down this node. */
+ setDebug_recursive(childnode, debug);
+ }
+}
+
+void KX_GameObject::SetUseDebugProperties( bool debug, bool recursive )
+{
+ KX_Scene *scene = KX_GetActiveScene();
+
+ if (debug) {
+ if (!scene->ObjectInDebugList(this))
+ scene->AddObjectDebugProperties(this);
+ }
+ else
+ scene->RemoveObjectDebugProperties(this);
+
+ if (recursive)
+ setDebug_recursive(GetSGNode(), debug);
+}
+
void
KX_GameObject::SetLayer(
int l
@@ -1807,6 +1868,7 @@ PyMethodDef KX_GameObject::Methods[] = {
KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo),
KX_PYMETHODTABLE_O(KX_GameObject, getVectTo),
KX_PYMETHODTABLE(KX_GameObject, sendMessage),
+ KX_PYMETHODTABLE(KX_GameObject, addDebugProperty),
KX_PYMETHODTABLE_KEYWORDS(KX_GameObject, playAction),
KX_PYMETHODTABLE(KX_GameObject, stopAction),
@@ -1859,6 +1921,8 @@ PyAttributeDef KX_GameObject::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive),
KX_PYATTRIBUTE_RO_FUNCTION("attrDict", KX_GameObject, pyattr_get_attrDict),
KX_PYATTRIBUTE_RW_FUNCTION("color", KX_GameObject, pyattr_get_obcolor, pyattr_set_obcolor),
+ KX_PYATTRIBUTE_RW_FUNCTION("debug", KX_GameObject, pyattr_get_debug, pyattr_set_debug),
+ KX_PYATTRIBUTE_RW_FUNCTION("debugRecursive", KX_GameObject, pyattr_get_debugRecursive, pyattr_set_debugRecursive),
/* experimental, don't rely on these yet */
KX_PYATTRIBUTE_RO_FUNCTION("sensors", KX_GameObject, pyattr_get_sensors),
@@ -2775,6 +2839,52 @@ PyObject *KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_
return self->m_attr_dict;
}
+PyObject *KX_GameObject::pyattr_get_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Scene *scene = KX_GetActiveScene();
+ KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
+
+ return PyBool_FromLong(scene->ObjectInDebugList(self));
+}
+
+int KX_GameObject::pyattr_set_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
+ int param = PyObject_IsTrue(value);
+
+ if (param == -1) {
+ PyErr_SetString(PyExc_AttributeError, "gameOb.debug = bool: KX_GameObject, expected True or False");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ self->SetUseDebugProperties(param, false);
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_GameObject::pyattr_get_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Scene *scene = KX_GetActiveScene();
+ KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
+
+ return PyBool_FromLong(scene->ObjectInDebugList(self));
+}
+
+int KX_GameObject::pyattr_set_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
+ int param = PyObject_IsTrue(value);
+
+ if (param == -1) {
+ PyErr_SetString(PyExc_AttributeError, "gameOb.debugRecursive = bool: KX_GameObject, expected True or False");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ self->SetUseDebugProperties(param, true);
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyObject *KX_GameObject::PyApplyForce(PyObject *args)
{
int local = 0;
@@ -3596,6 +3706,29 @@ KX_PYMETHODDEF_DOC(KX_GameObject, isPlayingAction,
}
+KX_PYMETHODDEF_DOC(KX_GameObject, addDebugProperty,
+"addDebugProperty(name, visible=1)\n"
+"Added or remove a debug property to the debug list.\n")
+{
+ KX_Scene *scene = KX_GetActiveScene();
+ char *name;
+ int visible = 1;
+
+ if (!PyArg_ParseTuple(args,"s|i:debugProperty", &name , &visible))
+ return NULL;
+
+ if (visible) {
+ if (!scene->PropertyInDebugList(this, name))
+ scene->AddDebugProperty(this, name);
+ }
+ else {
+ scene->RemoveDebugProperty(this, name);
+ }
+
+ Py_RETURN_NONE;
+}
+
+
/* dict style access */
@@ -3663,7 +3796,8 @@ bool ConvertPythonToGameObject(PyObject *value, KX_GameObject **object, bool py_
if ( PyObject_TypeCheck(value, &KX_GameObject::Type) ||
PyObject_TypeCheck(value, &KX_LightObject::Type) ||
PyObject_TypeCheck(value, &KX_Camera::Type) ||
- PyObject_TypeCheck(value, &KX_FontObject::Type))
+ PyObject_TypeCheck(value, &KX_FontObject::Type) ||
+ PyObject_TypeCheck(value, &KX_NavMeshObject::Type))
{
*object = static_cast<KX_GameObject*>BGE_PROXY_REF(value);
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 7450be4fdef..d4fa4851696 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -852,10 +852,10 @@ public:
/**
* Was this object culled?
*/
- inline bool
+ bool
GetCulled(
void
- ) { return m_bCulled; }
+ );
/**
* Set culled flag of this object
@@ -934,6 +934,11 @@ public:
m_pObstacleSimulation = NULL;
}
+ /**
+ * add debug object to the debuglist.
+ */
+ void SetUseDebugProperties(bool debug, bool recursive);
+
KX_ClientObjectInfo* getClientInfo() { return m_pClient_info; }
CListValue* GetChildren();
@@ -993,6 +998,7 @@ public:
KX_PYMETHOD_DOC_O(KX_GameObject,getVectTo);
KX_PYMETHOD_DOC_VARARGS(KX_GameObject, sendMessage);
KX_PYMETHOD_VARARGS(KX_GameObject, ReinstancePhysicsMesh);
+ KX_PYMETHOD_DOC(KX_GameObject, addDebugProperty);
KX_PYMETHOD_DOC(KX_GameObject, playAction);
KX_PYMETHOD_DOC(KX_GameObject, stopAction);
@@ -1060,7 +1066,11 @@ public:
static int pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_collisionCallbacks(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-
+ static PyObject* pyattr_get_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+
/* Experimental! */
static PyObject* pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index 7d7e15a5141..14772cda113 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -140,7 +140,6 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
m_frameTime(0.f),
m_clockTime(0.f),
m_previousClockTime(0.f),
- m_previousAnimTime(0.f),
m_exitcode(KX_EXIT_REQUEST_NO_REQUEST),
@@ -164,6 +163,7 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
m_showProperties(false),
m_showBackground(false),
m_show_debug_properties(false),
+ m_autoAddDebugProperties(true),
m_animation_record(false),
@@ -686,16 +686,6 @@ bool KX_KetsjiEngine::NextFrame()
SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE);
scene->UpdateParents(m_frameTime);
- // update levels of detail
- scene->UpdateObjectLods();
-
- if (!GetRestrictAnimationFPS())
- {
- m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
- SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
- scene->UpdateAnimations(m_frameTime);
- }
-
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
SG_SetActiveStage(SG_STAGE_PHYSICS2);
scene->GetPhysicsEnvironment()->BeginFrame();
@@ -797,27 +787,6 @@ bool KX_KetsjiEngine::NextFrame()
m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
}
}
-
-
- // Handle the animations independently of the logic time step
- if (GetRestrictAnimationFPS())
- {
- double clocktime = m_kxsystem->GetTimeInSeconds();
- m_logger->StartLog(tc_animations, clocktime, true);
- SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
-
- double anim_timestep = 1.0/KX_GetActiveScene()->GetAnimationFPS();
- if (clocktime - m_previousAnimTime > anim_timestep)
- {
- // Sanity/debug print to make sure we're actually going at the fps we want (should be close to anim_timestep)
- // printf("Anim fps: %f\n", 1.0/(m_clockTime - m_previousAnimTime));
- m_previousAnimTime = clocktime;
- for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
- {
- (*sceneit)->UpdateAnimations(clocktime);
- }
- }
- }
// Start logging time spend outside main loop
m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true);
@@ -1186,8 +1155,15 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
raslight->BindShadowBuffer(m_canvas, cam, camtrans);
/* update scene */
+ m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
scene->CalculateVisibleMeshes(m_rasterizer, cam, raslight->GetShadowLayer());
+ m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
+ scene->UpdateAnimations(GetFrameTime());
+
+ m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
+
+
/* render */
m_rasterizer->ClearDepthBuffer();
m_rasterizer->ClearColorBuffer();
@@ -1319,6 +1295,11 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
scene->CalculateVisibleMeshes(m_rasterizer,cam);
+ m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
+
+ scene->UpdateAnimations(GetFrameTime());
+
m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
SG_SetActiveStage(SG_STAGE_RENDER);
@@ -1751,9 +1732,20 @@ void KX_KetsjiEngine::AddScheduledScenes()
-void KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene)
+bool KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene)
{
- m_replace_scenes.push_back(std::make_pair(oldscene,newscene));
+ // Don't allow replacement if the new scene doesn't exists.
+ // Allows smarter game design (used to have no check here).
+ // Note that it creates a small backward compatbility issue
+ // for a game that did a replace followed by a lib load with the
+ // new scene in the lib => it won't work anymore, the lib
+ // must be loaded before doing the replace.
+ if (m_sceneconverter->GetBlenderSceneForName(newscene) != NULL)
+ {
+ m_replace_scenes.push_back(std::make_pair(oldscene,newscene));
+ return true;
+ }
+ return false;
}
// replace scene is not the same as removing and adding because the
@@ -1777,13 +1769,19 @@ void KX_KetsjiEngine::ReplaceScheduledScenes()
KX_SceneList::iterator sceneit;
for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
{
- KX_Scene* scene = *sceneit;
+ KX_Scene* scene = *sceneit;
if (scene->GetName() == oldscenename)
{
- m_sceneconverter->RemoveScene(scene);
- KX_Scene* tmpscene = CreateScene(newscenename);
- m_scenes[i]=tmpscene;
- PostProcessScene(tmpscene);
+ // avoid crash if the new scene doesn't exist, just do nothing
+ Scene *blScene = m_sceneconverter->GetBlenderSceneForName(newscenename);
+ if (blScene) {
+ m_sceneconverter->RemoveScene(scene);
+ KX_Scene* tmpscene = CreateScene(blScene);
+ m_scenes[i]=tmpscene;
+ PostProcessScene(tmpscene);
+ } else {
+ printf("warning: scene %s could not be found, not replaced!\n",newscenename.ReadPtr());
+ }
}
i++;
}
@@ -1917,6 +1915,46 @@ short KX_KetsjiEngine::GetExitKey()
return m_exitkey;
}
+void KX_KetsjiEngine::SetShowFramerate(bool frameRate)
+{
+ m_show_framerate = frameRate;
+}
+
+bool KX_KetsjiEngine::GetShowFramerate()
+{
+ return m_show_framerate;
+}
+
+void KX_KetsjiEngine::SetShowProfile(bool profile)
+{
+ m_show_profile = profile;
+}
+
+bool KX_KetsjiEngine::GetShowProfile()
+{
+ return m_show_profile;
+}
+
+void KX_KetsjiEngine::SetShowProperties(bool properties)
+{
+ m_show_debug_properties = properties;
+}
+
+bool KX_KetsjiEngine::GetShowProperties()
+{
+ return m_show_debug_properties;
+}
+
+void KX_KetsjiEngine::SetAutoAddDebugProperties(bool add)
+{
+ m_autoAddDebugProperties = add;
+}
+
+bool KX_KetsjiEngine::GetAutoAddDebugProperties()
+{
+ return m_autoAddDebugProperties;
+}
+
void KX_KetsjiEngine::SetTimingDisplay(bool frameRate, bool profile, bool properties)
{
m_show_framerate = frameRate;
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
index 9e5d1893320..2b80e3bd69a 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.h
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -111,7 +111,6 @@ private:
double m_frameTime;//discrete timestamp of the 'game logic frame'
double m_clockTime;//current time
double m_previousClockTime;//previous clock time
- double m_previousAnimTime; //the last time animations were updated
double m_remainingTime;
static int m_maxLogicFrame; /* maximum number of consecutive logic frame */
@@ -175,8 +174,10 @@ private:
bool m_showProperties;
/** Show background behind text for readability? */
bool m_showBackground;
-
+ /** Show debug properties on the game display*/
bool m_show_debug_properties;
+ /** Automatic add debug properties to the debug list*/
+ bool m_autoAddDebugProperties;
/** record physics into keyframes */
bool m_animation_record;
@@ -222,6 +223,7 @@ public:
PyObject* GetPyProfileDict();
#endif
void SetSceneConverter(KX_ISceneConverter* sceneconverter);
+ KX_ISceneConverter* GetSceneConverter() { return m_sceneconverter; }
void SetAnimRecordMode(bool animation_record, int startFrame);
RAS_IRasterizer* GetRasterizer() { return m_rasterizer; }
@@ -256,7 +258,7 @@ public:
void ConvertAndAddScene(const STR_String& scenename,bool overlay);
void RemoveScene(const STR_String& scenename);
- void ReplaceScene(const STR_String& oldscene,const STR_String& newscene);
+ bool ReplaceScene(const STR_String& oldscene,const STR_String& newscene);
void SuspendScene(const STR_String& scenename);
void ResumeScene(const STR_String& scenename);
@@ -354,6 +356,46 @@ public:
static short GetExitKey();
/**
+ * \Sets the display for frame rate on or off.
+ */
+ void SetShowFramerate(bool frameRate);
+
+ /**
+ * \Gets the display for frame rate on or off.
+ */
+ bool GetShowFramerate();
+
+ /**
+ * \Sets the display for individual components on or off.
+ */
+ void SetShowProfile(bool profile);
+
+ /**
+ * \Gets the display for individual components on or off.
+ */
+ bool GetShowProfile();
+
+ /**
+ * \Sets the display of scene object debug properties on or off.
+ */
+ void SetShowProperties(bool properties);
+
+ /**
+ * \Gets the display of scene object debug properties on or off.
+ */
+ bool GetShowProperties();
+
+ /**
+ * \Sets if the auto adding of scene object debug properties on or off.
+ */
+ bool GetAutoAddDebugProperties();
+
+ /**
+ * \Sets the auto adding of scene object debug properties on or off.
+ */
+ void SetAutoAddDebugProperties(bool add);
+
+ /**
* Activates or deactivates timing information display.
* \param frameRate Display for frame rate on or off.
* \param profile Display for individual components on or off.
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index 37c36da0db3..33cfec57fc0 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -231,7 +231,7 @@ int KX_LightObject::pyattr_set_distance(void *self_v, const KX_PYATTRIBUTE_DEF *
else if (val > 5000.f)
val = 5000.f;
- self->m_lightobj->m_energy = val;
+ self->m_lightobj->m_distance = val;
return PY_SET_ATTR_SUCCESS;
}
@@ -242,7 +242,7 @@ int KX_LightObject::pyattr_set_distance(void *self_v, const KX_PYATTRIBUTE_DEF *
PyObject *KX_LightObject::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
- return Py_BuildValue("[fff]", self->m_lightobj->m_color[0], self->m_lightobj->m_color[1], self->m_lightobj->m_color[1]);
+ return Py_BuildValue("[fff]", self->m_lightobj->m_color[0], self->m_lightobj->m_color[1], self->m_lightobj->m_color[2]);
}
int KX_LightObject::pyattr_set_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
diff --git a/source/gameengine/Ketsji/KX_MouseActuator.cpp b/source/gameengine/Ketsji/KX_MouseActuator.cpp
index 3d74bd7c98a..aae5d18189a 100644
--- a/source/gameengine/Ketsji/KX_MouseActuator.cpp
+++ b/source/gameengine/Ketsji/KX_MouseActuator.cpp
@@ -208,6 +208,9 @@ bool KX_MouseActuator::Update()
parent->ApplyRotation(rotation, m_local_x);
}
}
+ else {
+ setposition[0] = 0.5;
+ }
//Calculating Y axis.
if (m_use_axis_y) {
@@ -266,6 +269,9 @@ bool KX_MouseActuator::Update()
parent->ApplyRotation(rotation, m_local_y);
}
}
+ else {
+ setposition[1] = 0.5;
+ }
setMousePosition(setposition[0], setposition[1]);
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
index 2dbafdad3d9..a9f6bb0d2ff 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
@@ -60,15 +60,21 @@
KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr,
int startx,
int starty,
- short int mousemode,
- int focusmode,
- bool bTouchPulse,
- KX_Scene* kxscene,
- KX_KetsjiEngine *kxengine,
- SCA_IObject* gameobj)
+ short int mousemode,
+ int focusmode,
+ bool bTouchPulse,
+ const STR_String& propname,
+ bool bFindMaterial,
+ bool bXRay,
+ KX_Scene* kxscene,
+ KX_KetsjiEngine *kxengine,
+ SCA_IObject* gameobj)
: SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj),
m_focusmode(focusmode),
m_bTouchPulse(bTouchPulse),
+ m_bXRay(bXRay),
+ m_bFindMaterial(bFindMaterial),
+ m_propertyname(propname),
m_kxscene(kxscene),
m_kxengine(kxengine)
{
@@ -146,20 +152,73 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo *client_info, KX_RayCast *r
* self-hits are excluded by setting the correct ignore-object.)
* Hitspots now become valid. */
KX_GameObject* thisObj = (KX_GameObject*) GetParent();
+
+ bool bFound = false;
+
if ((m_focusmode == 2) || hitKXObj == thisObj)
{
- m_hitObject = hitKXObj;
- m_hitPosition = result->m_hitPoint;
- m_hitNormal = result->m_hitNormal;
- m_hitUV = result->m_hitUV;
- return true;
+ if (m_propertyname.Length() == 0)
+ {
+ bFound = true;
+ }
+ else
+ {
+ if (m_bFindMaterial)
+ {
+ if (client_info->m_auxilary_info)
+ {
+ bFound = (m_propertyname== ((char*)client_info->m_auxilary_info));
+ }
+ }
+ else
+ {
+ bFound = hitKXObj->GetProperty(m_propertyname) != NULL;
+ }
+ }
+
+ if (bFound)
+ {
+ m_hitObject = hitKXObj;
+ m_hitPosition = result->m_hitPoint;
+ m_hitNormal = result->m_hitNormal;
+ m_hitUV = result->m_hitUV;
+ return true;
+ }
}
return true; // object must be visible to trigger
//return false; // occluded objects can trigger
}
-
+/* this function is used to pre-filter the object before casting the ray on them.
+ * This is useful for "X-Ray" option when we want to see "through" unwanted object.
+ */
+bool KX_MouseFocusSensor::NeedRayCast(KX_ClientObjectInfo* client)
+{
+ if (client->m_type > KX_ClientObjectInfo::ACTOR)
+ {
+ // Unknown type of object, skip it.
+ // Should not occur as the sensor objects are filtered in RayTest()
+ printf("Invalid client type %d found ray casting\n", client->m_type);
+ return false;
+ }
+ if (m_bXRay && m_propertyname.Length() != 0)
+ {
+ if (m_bFindMaterial)
+ {
+ // not quite correct: an object may have multiple material
+ // should check all the material and not only the first one
+ if (!client->m_auxilary_info || (m_propertyname != ((char*)client->m_auxilary_info)))
+ return false;
+ }
+ else
+ {
+ if (client->m_gameobject->GetProperty(m_propertyname) == NULL)
+ return false;
+ }
+ }
+ return true;
+}
bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam)
{
@@ -384,7 +443,10 @@ PyAttributeDef KX_MouseFocusSensor::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("hitPosition", KX_MouseFocusSensor, pyattr_get_hit_position),
KX_PYATTRIBUTE_RO_FUNCTION("hitNormal", KX_MouseFocusSensor, pyattr_get_hit_normal),
KX_PYATTRIBUTE_RO_FUNCTION("hitUV", KX_MouseFocusSensor, pyattr_get_hit_uv),
- KX_PYATTRIBUTE_BOOL_RW("usePulseFocus", KX_MouseFocusSensor,m_bTouchPulse),
+ KX_PYATTRIBUTE_BOOL_RW("usePulseFocus", KX_MouseFocusSensor, m_bTouchPulse),
+ KX_PYATTRIBUTE_BOOL_RW("useXRay", KX_MouseFocusSensor, m_bXRay),
+ KX_PYATTRIBUTE_BOOL_RW("useMaterial", KX_MouseFocusSensor, m_bFindMaterial),
+ KX_PYATTRIBUTE_STRING_RW("propName", 0, MAX_PROP_NAME, false, KX_MouseFocusSensor, m_propertyname),
{ NULL } //Sentinel
};
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
index 1f7809831e7..0c7c8ab676a 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
@@ -57,6 +57,9 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
short int mousemode,
int focusmode,
bool bTouchPulse,
+ const STR_String& propname,
+ bool bFindMaterial,
+ bool bXRay,
KX_Scene* kxscene,
KX_KetsjiEngine* kxengine,
SCA_IObject* gameobj);
@@ -88,7 +91,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
};
bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
- bool NeedRayCast(KX_ClientObjectInfo* client) { return true; }
+ bool NeedRayCast(KX_ClientObjectInfo* client);
const MT_Point3& RaySource() const;
const MT_Point3& RayTarget() const;
@@ -134,6 +137,21 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
bool m_bTouchPulse;
/**
+ * Flags get through other objects
+ */
+ bool m_bXRay;
+
+ /**
+ * Flags material
+ */
+ bool m_bFindMaterial;
+
+ /**
+ * Property or material name
+ */
+ STR_String m_propertyname;
+
+ /**
* Flags whether the previous test evaluated positive.
*/
bool m_positive_event;
diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.cpp b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
index 998b856497e..8360681759a 100644
--- a/source/gameengine/Ketsji/KX_NavMeshObject.cpp
+++ b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
@@ -111,7 +111,7 @@ bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts,
float *&dvertices, int &ndvertsuniq, unsigned short *&dtris,
int& ndtris, int &vertsPerPoly)
{
- DerivedMesh* dm = mesh_create_derived_no_virtual(KX_GetActiveScene()->GetBlenderScene(), GetBlenderObject(),
+ DerivedMesh* dm = mesh_create_derived_no_virtual(GetScene()->GetBlenderScene(), GetBlenderObject(),
NULL, CD_MASK_MESH);
CustomData *pdata = dm->getPolyDataLayout(dm);
int* recastData = (int*) CustomData_get_layer(pdata, CD_RECAST);
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
index e9843b0af5b..ebf1b9ec577 100644
--- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
@@ -740,6 +740,7 @@ PyObject *initPythonConstraintBinding()
KX_MACRO_addTypesToDict(d, ANGULAR_CONSTRAINT, PHY_ANGULAR_CONSTRAINT);
KX_MACRO_addTypesToDict(d, CONETWIST_CONSTRAINT, PHY_CONE_TWIST_CONSTRAINT);
KX_MACRO_addTypesToDict(d, VEHICLE_CONSTRAINT, PHY_VEHICLE_CONSTRAINT);
+ KX_MACRO_addTypesToDict(d, GENERIC_6DOF_CONSTRAINT, PHY_GENERIC_6DOF_CONSTRAINT);
// Check for errors
if (PyErr_Occurred()) {
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index ca6658773e9..fefc64b4bad 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -88,6 +88,7 @@ extern "C" {
#include "KX_SteeringActuator.h"
#include "KX_NavMeshObject.h"
#include "KX_MouseActuator.h"
+#include "KX_TrackToActuator.h"
#include "SCA_IInputDevice.h"
#include "SCA_PropertySensor.h"
@@ -200,7 +201,16 @@ static PyObject *gp_OrigPythonSysModules= NULL;
//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyLong_FromLong(SCA_IInputDevice::KX_##name))
//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name)); Py_DECREF(item)
/* For the defines for types from logic bricks, we do stuff explicitly... */
-#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name2)); Py_DECREF(item)
+#define KX_MACRO_addTypesToDict(dict, name, value) KX_MACRO_addTypesToDict_fn(dict, #name, value)
+static void KX_MACRO_addTypesToDict_fn(PyObject *dict, const char *name, long value)
+{
+ PyObject *item;
+
+ item = PyLong_FromLong(value);
+ PyDict_SetItemString(dict, name, item);
+ Py_DECREF(item);
+}
+
// temporarily python stuff, will be put in another place later !
@@ -247,7 +257,7 @@ static PyObject *gPyExpandPath(PyObject *, PyObject *args)
BLI_strncpy(expanded, filename, FILE_MAX);
BLI_path_abs(expanded, gp_GamePythonPath);
- return PyUnicode_DecodeFSDefault(expanded);
+ return PyC_UnicodeFromByte(expanded);
}
static char gPyStartGame_doc[] =
@@ -536,7 +546,7 @@ static PyObject *gPyGetBlendFileList(PyObject *, PyObject *args)
while ((dirp = readdir(dp)) != NULL) {
if (BLI_testextensie(dirp->d_name, ".blend")) {
- value= PyUnicode_DecodeFSDefault(dirp->d_name);
+ value = PyC_UnicodeFromByte(dirp->d_name);
PyList_Append(list, value);
Py_DECREF(value);
}
@@ -1391,6 +1401,71 @@ static PyObject *gPyGetVsync(PyObject *)
return PyLong_FromLong(interval);
}
+static PyObject *gPyShowFramerate(PyObject *, PyObject *args)
+{
+ int visible;
+ if (!PyArg_ParseTuple(args,"i:showFramerate",&visible))
+ return NULL;
+
+ if (visible && gp_KetsjiEngine)
+ gp_KetsjiEngine->SetShowFramerate(true);
+ else
+ gp_KetsjiEngine->SetShowFramerate(false);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *gPyShowProfile(PyObject *, PyObject *args)
+{
+ int visible;
+ if (!PyArg_ParseTuple(args,"i:showProfile",&visible))
+ return NULL;
+
+ if (visible && gp_KetsjiEngine)
+ gp_KetsjiEngine->SetShowProfile(true);
+ else
+ gp_KetsjiEngine->SetShowProfile(false);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *gPyShowProperties(PyObject *, PyObject *args)
+{
+ int visible;
+ if (!PyArg_ParseTuple(args,"i:showProperties",&visible))
+ return NULL;
+
+ if (visible && gp_KetsjiEngine)
+ gp_KetsjiEngine->SetShowProperties(true);
+ else
+ gp_KetsjiEngine->SetShowProperties(false);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *gPyAutoDebugList(PyObject *, PyObject *args)
+{
+ int add;
+ if (!PyArg_ParseTuple(args,"i:autoAddProperties",&add))
+ return NULL;
+
+ if (add && gp_KetsjiEngine)
+ gp_KetsjiEngine->SetAutoAddDebugProperties(true);
+ else
+ gp_KetsjiEngine->SetAutoAddDebugProperties(false);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *gPyClearDebugList(PyObject *)
+{
+ if (gp_KetsjiScene)
+ gp_KetsjiScene->RemoveAllDebugProperties();
+
+ Py_RETURN_NONE;
+}
+
+
static struct PyMethodDef rasterizer_methods[] = {
{"getWindowWidth",(PyCFunction) gPyGetWindowWidth,
METH_VARARGS, "getWindowWidth doc"},
@@ -1438,6 +1513,11 @@ static struct PyMethodDef rasterizer_methods[] = {
{"getMipmapping", (PyCFunction) gPyGetMipmapping, METH_NOARGS, ""},
{"setVsync", (PyCFunction) gPySetVsync, METH_VARARGS, ""},
{"getVsync", (PyCFunction) gPyGetVsync, METH_NOARGS, ""},
+ {"showFramerate",(PyCFunction) gPyShowFramerate, METH_VARARGS, "show or hide the framerate"},
+ {"showProfile",(PyCFunction) gPyShowProfile, METH_VARARGS, "show or hide the profile"},
+ {"showProperties",(PyCFunction) gPyShowProperties, METH_VARARGS, "show or hide the debug properties"},
+ {"autoDebugList",(PyCFunction) gPyAutoDebugList, METH_VARARGS, "enable or disable auto adding debug properties to the debug list"},
+ {"clearDebugList",(PyCFunction) gPyClearDebugList, METH_NOARGS, "clears the debug property list"},
{ NULL, (PyCFunction) NULL, 0, NULL }
};
@@ -1686,6 +1766,17 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_NEG_Y, KX_RaySensor::KX_RAY_AXIS_NEG_Y);
KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_NEG_Z, KX_RaySensor::KX_RAY_AXIS_NEG_Z);
+ /* TrackTo Actuator */
+ KX_MACRO_addTypesToDict(d, KX_TRACK_UPAXIS_POS_X, KX_TrackToActuator::KX_TRACK_UPAXIS_POS_X);
+ KX_MACRO_addTypesToDict(d, KX_TRACK_UPAXIS_POS_Y, KX_TrackToActuator::KX_TRACK_UPAXIS_POS_Y);
+ KX_MACRO_addTypesToDict(d, KX_TRACK_UPAXIS_POS_Z, KX_TrackToActuator::KX_TRACK_UPAXIS_POS_Z);
+ KX_MACRO_addTypesToDict(d, KX_TRACK_TRAXIS_POS_X, KX_TrackToActuator::KX_TRACK_TRAXIS_POS_X);
+ KX_MACRO_addTypesToDict(d, KX_TRACK_TRAXIS_POS_Y, KX_TrackToActuator::KX_TRACK_TRAXIS_POS_Y);
+ KX_MACRO_addTypesToDict(d, KX_TRACK_TRAXIS_POS_Z, KX_TrackToActuator::KX_TRACK_TRAXIS_POS_Z);
+ KX_MACRO_addTypesToDict(d, KX_TRACK_TRAXIS_NEG_X, KX_TrackToActuator::KX_TRACK_TRAXIS_NEG_X);
+ KX_MACRO_addTypesToDict(d, KX_TRACK_TRAXIS_NEG_Y, KX_TrackToActuator::KX_TRACK_TRAXIS_NEG_Y);
+ KX_MACRO_addTypesToDict(d, KX_TRACK_TRAXIS_NEG_Z, KX_TrackToActuator::KX_TRACK_TRAXIS_NEG_Z);
+
/* Dynamic actuator */
KX_MACRO_addTypesToDict(d, KX_DYN_RESTORE_DYNAMICS, KX_SCA_DynamicActuator::KX_DYN_RESTORE_DYNAMICS);
KX_MACRO_addTypesToDict(d, KX_DYN_DISABLE_DYNAMICS, KX_SCA_DynamicActuator::KX_DYN_DISABLE_DYNAMICS);
@@ -1885,7 +1976,7 @@ static void initPySysObjects__append(PyObject *sys_path, const char *filename)
BLI_split_dir_part(filename, expanded, sizeof(expanded)); /* get the dir part of filename only */
BLI_path_abs(expanded, gp_GamePythonPath); /* filename from lib->filename is (always?) absolute, so this may not be needed but it wont hurt */
BLI_cleanup_file(gp_GamePythonPath, expanded); /* Don't use BLI_cleanup_dir because it adds a slash - BREAKS WIN32 ONLY */
- item= PyUnicode_DecodeFSDefault(expanded);
+ item = PyC_UnicodeFromByte(expanded);
// printf("SysPath - '%s', '%s', '%s'\n", expanded, filename, gp_GamePythonPath);
@@ -2190,7 +2281,6 @@ PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
PyObject *m;
PyObject *d;
- PyObject *item;
/* Use existing module where possible
* be careful not to init any runtime vars after this */
@@ -2320,7 +2410,6 @@ PyObject *initGameKeys()
{
PyObject *m;
PyObject *d;
- PyObject *item;
/* Use existing module where possible */
m = PyImport_ImportModule( "GameKeys" );
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 3d71327828e..625bbee2c8e 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -595,7 +595,9 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal
void KX_Scene::ReplicateLogic(KX_GameObject* newobj)
{
/* add properties to debug list, for added objects and DupliGroups */
- AddObjectDebugProperties(newobj);
+ if (KX_GetActiveEngine()->GetAutoAddDebugProperties()) {
+ AddObjectDebugProperties(newobj);
+ }
// also relink the controller to sensors/actuators
SCA_ControllerList& controllers = newobj->GetControllers();
//SCA_SensorList& sensors = newobj->GetSensors();
@@ -1005,7 +1007,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
int ret;
KX_GameObject* newobj = (KX_GameObject*) gameobj;
- /* remove property to debug list */
+ /* remove property from debug list */
RemoveObjectDebugProperties(newobj);
/* Invalidate the python reference, since the object may exist in script lists
@@ -1529,6 +1531,9 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int
MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam, layer);
}
}
+
+ // Now that we know visible meshes, update LoDs
+ UpdateObjectLods();
}
// logic stuff
@@ -1634,6 +1639,20 @@ static void update_anim_thread_func(TaskPool *pool, void *taskdata, int UNUSED(t
void KX_Scene::UpdateAnimations(double curtime)
{
+ KX_KetsjiEngine *engine = KX_GetActiveEngine();
+
+ if (engine->GetRestrictAnimationFPS())
+ {
+ // Handle the animations independently of the logic time step
+ double anim_timestep = 1.0 / GetAnimationFPS();
+ if (curtime - m_previousAnimTime < anim_timestep)
+ return;
+
+ // Sanity/debug print to make sure we're actually going at the fps we want (should be close to anim_timestep)
+ // printf("Anim fps: %f\n", 1.0/(m_clockTime - m_previousAnimTime));
+ m_previousAnimTime = curtime;
+ }
+
TaskPool *pool = BLI_task_pool_create(KX_GetActiveEngine()->GetTaskScheduler(), &curtime);
for (int i=0; i<m_animatedlist->GetCount(); ++i) {
@@ -2005,7 +2024,11 @@ bool KX_Scene::MergeScene(KX_Scene *other)
{
KX_GameObject* gameobj = (KX_GameObject*)other->GetObjectList()->GetValue(i);
MergeScene_GameObject(gameobj, this, other);
- AddObjectDebugProperties(gameobj); // add properties to debug list for LibLoad objects
+
+ /* add properties to debug list for LibLoad objects */
+ if (KX_GetActiveEngine()->GetAutoAddDebugProperties()) {
+ AddObjectDebugProperties(gameobj);
+ }
gameobj->UpdateBuckets(false); /* only for active objects */
}
@@ -2478,16 +2501,18 @@ KX_PYMETHODDEF_DOC(KX_Scene, restart,
KX_PYMETHODDEF_DOC(KX_Scene, replace,
"replace(newScene)\n"
- "Replaces this scene with another one.\n")
+ "Replaces this scene with another one.\n"
+ "Return True if the new scene exists and scheduled for replacement, False otherwise.\n")
{
char* name;
if (!PyArg_ParseTuple(args, "s:replace", &name))
return NULL;
- KX_GetActiveEngine()->ReplaceScene(m_sceneName, name);
+ if (KX_GetActiveEngine()->ReplaceScene(m_sceneName, name))
+ Py_RETURN_TRUE;
- Py_RETURN_NONE;
+ Py_RETURN_FALSE;
}
KX_PYMETHODDEF_DOC(KX_Scene, suspend,
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index 2e1ee9f101d..c5840c28041 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -289,6 +289,8 @@ protected:
double m_suspendedtime;
double m_suspendeddelta;
+ double m_previousAnimTime; //the last time animations were updated
+
struct Scene* m_blenderScene;
RAS_2DFilterManager m_filtermanager;
diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.cpp b/source/gameengine/Ketsji/KX_SteeringActuator.cpp
index 2fa72c04a20..ff192299702 100644
--- a/source/gameengine/Ketsji/KX_SteeringActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SteeringActuator.cpp
@@ -602,7 +602,7 @@ int KX_SteeringActuator::pyattr_set_navmesh(void *self, const struct KX_PYATTRIB
if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_SteeringActuator"))
return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
- if (!PyObject_TypeCheck(value, &KX_NavMeshObject::Type))
+ if (dynamic_cast<KX_NavMeshObject *>(gameobj) == NULL)
{
PyErr_Format(PyExc_TypeError, "KX_NavMeshObject is expected");
return PY_SET_ATTR_FAIL;
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
index 90b7850946b..75baf5fac1d 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
@@ -31,8 +31,7 @@
* Replace the mesh for this actuator's parent
*/
-/* todo: not all trackflags / upflags are implemented/tested !
- * m_trackflag is used to determine the forward tracking direction
+/* m_trackflag is used to determine the forward tracking direction
* m_upflag for the up direction
* normal situation is +y for forward, +z for up */
@@ -177,7 +176,77 @@ static MT_Matrix3x3 matrix3x3_interpol(MT_Matrix3x3 oldmat, MT_Matrix3x3 mat, in
return EulToMat3(eul);
}
+static float basis_cross(int n, int m)
+{
+ switch (n - m) {
+ case 1:
+ case -2:
+ return 1.0f;
+
+ case -1:
+ case 2:
+ return -1.0f;
+
+ default:
+ return 0.0f;
+ }
+}
+/* vectomat function obtained from constrain.c and modified to work with MOTO library */
+static MT_Matrix3x3 vectomat(MT_Vector3 vec, short axis, short upflag, short threedimup)
+{
+ MT_Matrix3x3 mat;
+ MT_Vector3 y(MT_Scalar(0.0), MT_Scalar(1.0), MT_Scalar(0.0));
+ MT_Vector3 z(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(1.0)); /* world Z axis is the global up axis */
+ MT_Vector3 proj;
+ MT_Vector3 right;
+ MT_Scalar mul;
+ int right_index;
+
+ /* Normalized Vec vector*/
+ vec = vec.safe_normalized_vec(z);
+
+ /* if 2D doesn't move the up vector */
+ if (!threedimup){
+ vec.setValue(MT_Scalar(vec[0]), MT_Scalar(vec[1]), MT_Scalar(0.0));
+ vec = (vec - z.dot(vec)*z).safe_normalized_vec(z);
+ }
+
+ if (axis > 2)
+ axis -= 3;
+ else
+ vec = -vec;
+
+ /* project the up vector onto the plane specified by vec */
+ /* first z onto vec... */
+ mul = z.dot(vec) / vec.dot(vec);
+ proj = vec * mul;
+ /* then onto the plane */
+ proj = z - proj;
+ /* proj specifies the transformation of the up axis */
+ proj = proj.safe_normalized_vec(y);
+
+ /* Normalized cross product of vec and proj specifies transformation of the right axis */
+ right = proj.cross(vec);
+ right.normalize();
+
+ if (axis != upflag) {
+ right_index = 3 - axis - upflag;
+
+ /* account for up direction, track direction */
+ right = right * basis_cross(axis, upflag);
+ mat.setRow(right_index, right);
+ mat.setRow(upflag, proj);
+ mat.setRow(axis, vec);
+ mat = mat.inverse();
+ }
+ /* identity matrix - don't do anything if the two axes are the same */
+ else {
+ mat.setIdentity();
+ }
+
+ return mat;
+}
KX_TrackToActuator::~KX_TrackToActuator()
{
@@ -247,153 +316,24 @@ bool KX_TrackToActuator::Update(double curtime, bool frame)
else if (m_object)
{
KX_GameObject* curobj = (KX_GameObject*) GetParent();
- MT_Vector3 dir = ((KX_GameObject*)m_object)->NodeGetWorldPosition() - curobj->NodeGetWorldPosition();
- if (dir.length2())
- dir.normalize();
- MT_Vector3 up(0,0,1);
-
-
-#ifdef DSADSA
- switch (m_upflag)
- {
- case 0:
- {
- up.setValue(1.0,0,0);
- break;
- }
- case 1:
- {
- up.setValue(0,1.0,0);
- break;
- }
- case 2:
- default:
- {
- up.setValue(0,0,1.0);
- }
- }
-#endif
- if (m_allow3D)
- {
- up = (up - up.dot(dir) * dir).safe_normalized();
-
- }
- else
- {
- dir = (dir - up.dot(dir)*up).safe_normalized();
- }
-
- MT_Vector3 left;
+ MT_Vector3 dir = curobj->NodeGetWorldPosition() - ((KX_GameObject*)m_object)->NodeGetWorldPosition();
MT_Matrix3x3 mat;
-
- switch (m_trackflag)
- {
- case 0: // TRACK X
- {
- // (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up
- left = dir.safe_normalized();
- dir = up.cross(left).safe_normalized();
- mat.setValue (
- left[0], dir[0],up[0],
- left[1], dir[1],up[1],
- left[2], dir[2],up[2]
- );
-
- break;
- };
- case 1: // TRACK Y
- {
- // (0.0 , 1.0 , 0.0 ) y direction is forward, z (0.0 , 0.0 , 1.0 ) up
- left = (dir.cross(up)).safe_normalized();
- mat.setValue (
- left[0], dir[0],up[0],
- left[1], dir[1],up[1],
- left[2], dir[2],up[2]
- );
-
- break;
- }
-
- case 2: // track Z
- {
- left = up.safe_normalized();
- up = dir.safe_normalized();
- dir = left;
- left = (dir.cross(up)).safe_normalized();
- mat.setValue (
- left[0], dir[0],up[0],
- left[1], dir[1],up[1],
- left[2], dir[2],up[2]
- );
- break;
- }
-
- case 3: // TRACK -X
- {
- // (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up
- left = -dir.safe_normalized();
- dir = up.cross(left).safe_normalized();
- mat.setValue (
- left[0], dir[0],up[0],
- left[1], dir[1],up[1],
- left[2], dir[2],up[2]
- );
-
- break;
- };
- case 4: // TRACK -Y
- {
- // (0.0 , -1.0 , 0.0 ) -y direction is forward, z (0.0 , 0.0 , 1.0 ) up
- left = (-dir.cross(up)).safe_normalized();
- mat.setValue (
- left[0], -dir[0],up[0],
- left[1], -dir[1],up[1],
- left[2], -dir[2],up[2]
- );
- break;
- }
- case 5: // track -Z
- {
- left = up.safe_normalized();
- up = -dir.safe_normalized();
- dir = left;
- left = (dir.cross(up)).safe_normalized();
- mat.setValue (
- left[0], dir[0],up[0],
- left[1], dir[1],up[1],
- left[2], dir[2],up[2]
- );
-
- break;
- }
-
- default:
- {
- // (1.0 , 0.0 , 0.0 ) -x direction is forward, z (0.0 , 0.0 , 1.0 ) up
- left = -dir.safe_normalized();
- dir = up.cross(left).safe_normalized();
- mat.setValue (
- left[0], dir[0],up[0],
- left[1], dir[1],up[1],
- left[2], dir[2],up[2]
- );
- }
- }
-
MT_Matrix3x3 oldmat;
- oldmat= curobj->NodeGetWorldOrientation();
+
+ mat = vectomat(dir, m_trackflag, m_upflag, m_allow3D);
+ oldmat = curobj->NodeGetWorldOrientation();
/* erwin should rewrite this! */
- mat= matrix3x3_interpol(oldmat, mat, m_time);
+ mat = matrix3x3_interpol(oldmat, mat, m_time);
-
- if (m_parentobj) { // check if the model is parented and calculate the child transform
+ /* check if the model is parented and calculate the child transform */
+ if (m_parentobj) {
MT_Point3 localpos;
localpos = curobj->GetSGNode()->GetLocalPosition();
// Get the inverse of the parent matrix
MT_Matrix3x3 parentmatinv;
- parentmatinv = m_parentobj->NodeGetWorldOrientation ().inverse ();
+ parentmatinv = m_parentobj->NodeGetWorldOrientation().inverse();
// transform the local coordinate system into the parents system
mat = parentmatinv * mat;
// append the initial parent local rotation matrix
@@ -404,8 +344,7 @@ bool KX_TrackToActuator::Update(double curtime, bool frame)
curobj->NodeSetLocalPosition(localpos);
//curobj->UpdateTransform();
}
- else
- {
+ else {
curobj->NodeSetLocalOrientation(mat);
}
@@ -451,6 +390,8 @@ PyMethodDef KX_TrackToActuator::Methods[] = {
PyAttributeDef KX_TrackToActuator::Attributes[] = {
KX_PYATTRIBUTE_INT_RW("time",0,1000,true,KX_TrackToActuator,m_time),
KX_PYATTRIBUTE_BOOL_RW("use3D",KX_TrackToActuator,m_allow3D),
+ KX_PYATTRIBUTE_INT_RW("upAxis", 0, 2, true, KX_TrackToActuator,m_upflag),
+ KX_PYATTRIBUTE_INT_RW("trackAxis", 0, 5, true, KX_TrackToActuator,m_trackflag),
KX_PYATTRIBUTE_RW_FUNCTION("object", KX_TrackToActuator, pyattr_get_object, pyattr_set_object),
{ NULL } //Sentinel
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h
index 4df240a0063..124014eede2 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.h
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.h
@@ -68,6 +68,21 @@ class KX_TrackToActuator : public SCA_IActuator
virtual void Relink(CTR_Map<CTR_HashedPtr, void*> *obj_map);
virtual bool Update(double curtime, bool frame);
+ //Python Interface
+ enum UpAxis {
+ KX_TRACK_UPAXIS_POS_X = 0,
+ KX_TRACK_UPAXIS_POS_Y,
+ KX_TRACK_UPAXIS_POS_Z
+ };
+ enum TrackAxis {
+ KX_TRACK_TRAXIS_POS_X = 0,
+ KX_TRACK_TRAXIS_POS_Y,
+ KX_TRACK_TRAXIS_POS_Z,
+ KX_TRACK_TRAXIS_NEG_X,
+ KX_TRACK_TRAXIS_NEG_Y,
+ KX_TRACK_TRAXIS_NEG_Z
+ };
+
#ifdef WITH_PYTHON
/* Python part */
diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt
index e295b701b36..e52dc1ba052 100644
--- a/source/gameengine/Physics/Bullet/CMakeLists.txt
+++ b/source/gameengine/Physics/Bullet/CMakeLists.txt
@@ -29,6 +29,7 @@ remove_strict_flags()
set(INC
.
../common
+ ../../Converter
../../Expressions
../../GameLogic
../../Ketsji
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index 69e190c79db..e17d4402556 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -42,6 +42,7 @@ subject to the following restrictions:
#include "PHY_Pro.h"
#include "KX_GameObject.h"
#include "KX_PythonInit.h" // for KX_RasterizerDrawDebugLine
+#include "KX_BlenderSceneConverter.h"
#include "RAS_MeshObject.h"
#include "RAS_Polygon.h"
#include "RAS_TexVert.h"
@@ -83,7 +84,7 @@ void DrawRasterizerLine(const float* from,const float* to,int color);
// This was copied from the old KX_ConvertPhysicsObjects
#ifdef WIN32
-#if defined(_MSC_VER) && (_MSC_VER >= 1310)
+#ifdef _MSC_VER
//only use SIMD Hull code under Win32
//#define TEST_HULL 1
#ifdef TEST_HULL
@@ -877,6 +878,14 @@ void CcdPhysicsEnvironment::ProcessFhSprings(double curTime,float interval)
}
}
+int CcdPhysicsEnvironment::GetDebugMode() const
+{
+ if (m_debugDrawer) {
+ return m_debugDrawer->getDebugMode();
+ }
+ return 0;
+}
+
void CcdPhysicsEnvironment::SetDebugMode(int debugMode)
{
if (m_debugDrawer) {
@@ -2085,7 +2094,7 @@ void CcdPhysicsEnvironment::SetConstraintParam(int constraintId,int param,float
case 12: case 13: case 14: case 15: case 16: case 17:
{
- //param 13-17 are for motorized springs on each of the degrees of freedom
+ //param 12-17 are for motorized springs on each of the degrees of freedom
btGeneric6DofSpringConstraint* genCons = (btGeneric6DofSpringConstraint*)typedConstraint;
int springIndex = param-12;
if (value0!=0.f)
@@ -3036,9 +3045,17 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
CcdConstructionInfo ci;
class CcdShapeConstructionInfo *shapeInfo = new CcdShapeConstructionInfo();
- KX_GameObject *parent = gameobj->GetParent();
- if (parent)
+ // get Root Parent of blenderobject
+ Object *blenderparent = blenderobject->parent;
+ while (blenderparent && blenderparent->parent) {
+ blenderparent = blenderparent->parent;
+ }
+
+ KX_GameObject *parent = NULL;
+ if (blenderparent)
{
+ KX_BlenderSceneConverter *converter = (KX_BlenderSceneConverter*)KX_GetActiveEngine()->GetSceneConverter();
+ parent = converter->FindGameObject(blenderparent);
isbulletdyna = false;
isbulletsoftbody = false;
shapeprops->m_mass = 0.f;
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
index a94e205b160..ff8a3f4f9f9 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
@@ -139,6 +139,7 @@ protected:
virtual float GetFixedTimeStep() { return 0.f; }
virtual void SetDebugMode(int debugMode);
+ virtual int GetDebugMode()const;
virtual void SetGravity(float x,float y,float z);
virtual void GetGravity(MT_Vector3& grav);
diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript
index 2700997ccd4..2a8249b9558 100644
--- a/source/gameengine/Physics/Bullet/SConscript
+++ b/source/gameengine/Physics/Bullet/SConscript
@@ -39,6 +39,7 @@ incs = [
'#source/blender/blenkernel',
'#source/blender/blenlib',
'#source/blender/makesdna',
+ '#source/gameengine/Converter',
'#source/gameengine/Expressions',
'#source/gameengine/GameLogic',
'#source/gameengine/Ketsji',
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
index 1bb5431c749..979128370ee 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
@@ -78,8 +78,10 @@ float DummyPhysicsEnvironment::GetFixedTimeStep()
return 0.f;
}
-
-
+int DummyPhysicsEnvironment::GetDebugMode() const
+{
+ return 0;
+}
void DummyPhysicsEnvironment::SetGravity(float x,float y,float z)
{
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
index a645af1e471..cfc8841cac2 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
@@ -56,6 +56,8 @@ public:
virtual void SetFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep);
virtual float GetFixedTimeStep();
+ virtual int GetDebugMode() const;
+
virtual void SetGravity(float x,float y,float z);
virtual void GetGravity(class MT_Vector3& grav);
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
index 81a45f93993..dd762b02b4e 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
@@ -126,6 +126,8 @@ class PHY_IPhysicsEnvironment
//returns 0.f if no fixed timestep is used
virtual float GetFixedTimeStep()=0;
+ ///getDebugMode return the actual debug visualization state
+ virtual int GetDebugMode()const=0;
///setDebugMode is used to support several ways of debug lines, contact point visualization
virtual void SetDebugMode(int debugMode) {}
///setNumIterations set the number of iterations for iterative solvers
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
index 61c658b22fd..e0613350b77 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
@@ -247,7 +247,7 @@ void RAS_StorageIM::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
//ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
current_blmat_nr = current_polymat->GetMaterialIndex();
current_image = current_polymat->GetBlenderImage();
- ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL);
+ ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL, DM_DRAW_USE_ACTIVE_UV);
}
return;
}
diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp
index 6cc8d287e66..705d9136cbe 100644
--- a/source/gameengine/VideoTexture/ImageBuff.cpp
+++ b/source/gameengine/VideoTexture/ImageBuff.cpp
@@ -163,7 +163,7 @@ void ImageBuff::plot(unsigned char *img, short width, short height, short x, sho
// assign temporarily our buffer to the ImBuf buffer, we use the same format
tmpbuf->rect = (unsigned int*)img;
m_imbuf->rect = m_image;
- IMB_rectblend(m_imbuf, m_imbuf, tmpbuf, NULL, NULL, 0, x, y, x, y, 0, 0, width, height, (IMB_BlendMode)mode);
+ IMB_rectblend(m_imbuf, m_imbuf, tmpbuf, NULL, NULL, NULL, 0, x, y, x, y, 0, 0, width, height, (IMB_BlendMode)mode, false);
// remove so that MB_freeImBuf will free our buffer
m_imbuf->rect = NULL;
tmpbuf->rect = NULL;
@@ -186,7 +186,7 @@ void ImageBuff::plot(ImageBuff *img, short x, short y, short mode)
// assign temporarily our buffer to the ImBuf buffer, we use the same format
img->m_imbuf->rect = img->m_image;
m_imbuf->rect = m_image;
- IMB_rectblend(m_imbuf, m_imbuf, img->m_imbuf, NULL, NULL, 0, x, y, x, y, 0, 0, img->m_imbuf->x, img->m_imbuf->y, (IMB_BlendMode)mode);
+ IMB_rectblend(m_imbuf, m_imbuf, img->m_imbuf, NULL, NULL, NULL, 0, x, y, x, y, 0, 0, img->m_imbuf->x, img->m_imbuf->y, (IMB_BlendMode)mode, false);
// remove so that MB_freeImBuf will free our buffer
m_imbuf->rect = NULL;
img->m_imbuf->rect = NULL;
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp
index 57b2e85845c..617e7fd1d8e 100644
--- a/source/gameengine/VideoTexture/ImageRender.cpp
+++ b/source/gameengine/VideoTexture/ImageRender.cpp
@@ -274,6 +274,8 @@ void ImageRender::Render()
m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera);
+ m_scene->UpdateAnimations(m_engine->GetFrameTime());
+
m_scene->RenderBuckets(camtrans, m_rasterizer);
m_scene->RenderFonts();
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
index 179f1ced03b..edf3c58bcbe 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
@@ -545,6 +545,7 @@ void VideoFFmpeg::openFile (char *filename)
// but it is really not desirable to seek on http file, so force streaming.
// It would be good to find this information from the context but there are no simple indication
!strncmp(filename, "http://", 7) ||
+ !strncmp(filename, "rtsp://", 7) ||
(m_formatCtx->pb && !m_formatCtx->pb->seekable)
)
{
@@ -680,6 +681,12 @@ bool VideoFFmpeg::play (void)
{
// set video position
setPositions();
+
+ if (m_isStreaming)
+ {
+ av_read_play(m_formatCtx);
+ }
+
// return success
return true;
}
@@ -696,6 +703,10 @@ bool VideoFFmpeg::pause (void)
{
if (VideoBase::pause())
{
+ if (m_isStreaming)
+ {
+ av_read_pause(m_formatCtx);
+ }
return true;
}
}
diff --git a/tests/gtests/blenlib/BLI_listbase_test.cc b/tests/gtests/blenlib/BLI_listbase_test.cc
new file mode 100644
index 00000000000..4b4d5d80a43
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_listbase_test.cc
@@ -0,0 +1,39 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+extern "C" {
+#include "BLI_listbase.h"
+#include "MEM_guardedalloc.h"
+}
+
+TEST(listbase, FindLinkOrIndex)
+{
+ ListBase lb;
+ void *link1 = MEM_callocN(sizeof(Link), "link1");
+ void *link2 = MEM_callocN(sizeof(Link), "link2");
+
+ /* Empty list */
+ BLI_listbase_clear(&lb);
+ EXPECT_EQ(NULL, BLI_findlink(&lb, -1));
+ EXPECT_EQ(NULL, BLI_findlink(&lb, 0));
+ EXPECT_EQ(NULL, BLI_findlink(&lb, 1));
+ EXPECT_EQ(NULL, BLI_rfindlink(&lb, -1));
+ EXPECT_EQ(NULL, BLI_rfindlink(&lb, 0));
+ EXPECT_EQ(NULL, BLI_rfindlink(&lb, 1));
+ EXPECT_EQ(-1, BLI_findindex(&lb, link1));
+
+ /* One link */
+ BLI_addtail(&lb, link1);
+ EXPECT_EQ(link1, BLI_findlink(&lb, 0));
+ EXPECT_EQ(link1, BLI_rfindlink(&lb, 0));
+ EXPECT_EQ(0, BLI_findindex(&lb, link1));
+
+ /* Two links */
+ BLI_addtail(&lb, link2);
+ EXPECT_EQ(link2, BLI_findlink(&lb, 1));
+ EXPECT_EQ(link2, BLI_rfindlink(&lb, 0));
+ EXPECT_EQ(1, BLI_findindex(&lb, link2));
+
+ BLI_freelistN(&lb);
+}
diff --git a/tests/gtests/blenlib/BLI_math_color_test.cc b/tests/gtests/blenlib/BLI_math_color_test.cc
index be6d7c6a55f..2118822a9d8 100644
--- a/tests/gtests/blenlib/BLI_math_color_test.cc
+++ b/tests/gtests/blenlib/BLI_math_color_test.cc
@@ -4,7 +4,7 @@
#include "BLI_math.h"
-TEST(mathutils, RGBToHSVRoundtrip)
+TEST(math_color, RGBToHSVRoundtrip)
{
float orig_rgb[3] = {0.1f, 0.2f, 0.3f};
float hsv[3], rgb[3];
@@ -13,7 +13,7 @@ TEST(mathutils, RGBToHSVRoundtrip)
EXPECT_V3_NEAR(orig_rgb, rgb, 1e-5);
}
-TEST(mathutils, RGBToHSLRoundtrip)
+TEST(math_color, RGBToHSLRoundtrip)
{
float orig_rgb[3] = {0.1f, 0.2f, 0.3f};
float hsl[3], rgb[3];
@@ -22,7 +22,7 @@ TEST(mathutils, RGBToHSLRoundtrip)
EXPECT_V3_NEAR(orig_rgb, rgb, 1e-5);
}
-TEST(mathutils, RGBToYUVRoundtrip)
+TEST(math_color, RGBToYUVRoundtrip)
{
float orig_rgb[3] = {0.1f, 0.2f, 0.3f};
float yuv[3], rgb[3];
@@ -33,7 +33,7 @@ TEST(mathutils, RGBToYUVRoundtrip)
EXPECT_V3_NEAR(orig_rgb, rgb, 1e-4);
}
-TEST(mathutils, RGBToYCCRoundtrip)
+TEST(math_color, RGBToYCCRoundtrip)
{
float orig_rgb[3] = {0.1f, 0.2f, 0.3f};
float ycc[3], rgb[3];
@@ -63,21 +63,21 @@ TEST(mathutils, RGBToYCCRoundtrip)
EXPECT_V3_NEAR(orig_rgb, rgb, 1e-3);
}
-TEST(mathutils, LinearRGBTosRGBNearZero)
+TEST(math_color, LinearRGBTosRGBNearZero)
{
float linear_color = 0.002f;
float srgb_color = linearrgb_to_srgb(linear_color);
EXPECT_NEAR(0.02584f, srgb_color, 1e-5);
}
-TEST(mathutils, LinearRGBTosRGB)
+TEST(math_color, LinearRGBTosRGB)
{
float linear_color = 0.75f;
float srgb_color = linearrgb_to_srgb(linear_color);
EXPECT_NEAR(0.880824f, srgb_color, 1e-5);
}
-TEST(mathutils, LinearRGBTosRGBRoundtrip)
+TEST(math_color, LinearRGBTosRGBRoundtrip)
{
const int N = 50;
int i;
diff --git a/tests/gtests/blenlib/BLI_math_geom_test.cc b/tests/gtests/blenlib/BLI_math_geom_test.cc
index 2f85e6b4d7d..cd15a4eb8ff 100644
--- a/tests/gtests/blenlib/BLI_math_geom_test.cc
+++ b/tests/gtests/blenlib/BLI_math_geom_test.cc
@@ -4,7 +4,7 @@
#include "BLI_math.h"
-TEST(mathutils, DistToLine2DSimple)
+TEST(math_geom, DistToLine2DSimple)
{
float p[2] = {5.0f, 1.0f},
a[2] = {0.0f, 0.0f},
@@ -13,7 +13,7 @@ TEST(mathutils, DistToLine2DSimple)
EXPECT_NEAR(1.0f, distance, 1e-6);
}
-TEST(mathutils, DistToLineSegment2DSimple)
+TEST(math_geom, DistToLineSegment2DSimple)
{
float p[2] = {3.0f, 1.0f},
a[2] = {0.0f, 0.0f},
diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc
index e3a3699e5c1..ea761bcf32e 100644
--- a/tests/gtests/blenlib/BLI_path_util_test.cc
+++ b/tests/gtests/blenlib/BLI_path_util_test.cc
@@ -46,7 +46,7 @@ char *zLhm65070058860608_br_find_exe(const char *default_exe)
/* tests */
/* BLI_cleanup_path */
-TEST(pathutils, PathUtilClean)
+TEST(path_util, PathUtilClean)
{
/* "/./" -> "/" */
{
@@ -102,7 +102,7 @@ TEST(pathutils, PathUtilClean)
}
/* BLI_path_frame */
-TEST(pathutils, PathUtilFrame)
+TEST(path_util, PathUtilFrame)
{
bool ret;
@@ -165,7 +165,7 @@ TEST(pathutils, PathUtilFrame)
}
/* BLI_split_dirfile */
-TEST(pathutils, PathUtilSplitDirfile)
+TEST(path_util, PathUtilSplitDirfile)
{
{
const char *path = "";
diff --git a/tests/gtests/blenlib/BLI_stack_test.cc b/tests/gtests/blenlib/BLI_stack_test.cc
index 8ad4d957813..c4884cb8940 100644
--- a/tests/gtests/blenlib/BLI_stack_test.cc
+++ b/tests/gtests/blenlib/BLI_stack_test.cc
@@ -17,6 +17,7 @@ TEST(stack, Empty)
stack = BLI_stack_new(sizeof(int), __func__);
EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_EQ(BLI_stack_count(stack), 0);
BLI_stack_free(stack);
}
@@ -29,9 +30,11 @@ TEST(stack, One)
BLI_stack_push(stack, (void *)&in);
EXPECT_EQ(BLI_stack_is_empty(stack), false);
+ EXPECT_EQ(BLI_stack_count(stack), 1);
BLI_stack_pop(stack, (void *)&out);
EXPECT_EQ(in, out);
EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_EQ(BLI_stack_count(stack), 0);
BLI_stack_free(stack);
}
@@ -79,7 +82,6 @@ TEST(stack, String)
*((int *)in) = i;
BLI_stack_pop(stack, (void *)&out);
EXPECT_STREQ(in, out);
-
}
EXPECT_EQ(BLI_stack_is_empty(stack), true);
@@ -133,5 +135,14 @@ TEST(stack, Reuse)
EXPECT_EQ(i, 0);
EXPECT_EQ(memcmp(sizes, sizes_test, sizeof(sizes) - sizeof(int)), 0);
+
+ /* finally test BLI_stack_pop_n */
+ for (i = ARRAY_SIZE(sizes); i--; ) {
+ BLI_stack_push(stack, (void *)&sizes[i]);
+ }
+ EXPECT_EQ(BLI_stack_count(stack), ARRAY_SIZE(sizes));
+ BLI_stack_pop_n(stack, (void *)sizes_test, ARRAY_SIZE(sizes));
+ EXPECT_EQ(memcmp(sizes, sizes_test, sizeof(sizes) - sizeof(int)), 0);
+
BLI_stack_free(stack);
}
diff --git a/tests/gtests/blenlib/BLI_string_test.cc b/tests/gtests/blenlib/BLI_string_test.cc
index 13091d9e074..4c5c410dcb2 100644
--- a/tests/gtests/blenlib/BLI_string_test.cc
+++ b/tests/gtests/blenlib/BLI_string_test.cc
@@ -267,3 +267,37 @@ TEST(string, StrRPartitionUtf8)
EXPECT_EQ(NULL, suf);
}
}
+
+/* BLI_str_format_int_grouped */
+TEST(string, StrFormatIntGrouped)
+{
+ char num_str[16];
+ int num;
+
+ BLI_str_format_int_grouped(num_str, num = 0);
+ EXPECT_STREQ("0", num_str);
+
+ BLI_str_format_int_grouped(num_str, num = 1);
+ EXPECT_STREQ("1", num_str);
+
+ BLI_str_format_int_grouped(num_str, num = -1);
+ EXPECT_STREQ("-1", num_str);
+
+ BLI_str_format_int_grouped(num_str, num = -2147483648);
+ EXPECT_STREQ("-2,147,483,648", num_str);
+
+ BLI_str_format_int_grouped(num_str, num = 2147483647);
+ EXPECT_STREQ("2,147,483,647", num_str);
+
+ BLI_str_format_int_grouped(num_str, num = 1000);
+ EXPECT_STREQ("1,000", num_str);
+
+ BLI_str_format_int_grouped(num_str, num = -1000);
+ EXPECT_STREQ("-1,000", num_str);
+
+ BLI_str_format_int_grouped(num_str, num = 999);
+ EXPECT_STREQ("999", num_str);
+
+ BLI_str_format_int_grouped(num_str, num = -999);
+ EXPECT_STREQ("-999", num_str);
+}
diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt
index d55fdd1cd2a..07b89a9042e 100644
--- a/tests/gtests/blenlib/CMakeLists.txt
+++ b/tests/gtests/blenlib/CMakeLists.txt
@@ -25,6 +25,7 @@ set(INC
.
..
../../../source/blender/blenlib
+ ../../../source/blender/makesdna
../../../intern/guardedalloc
)
@@ -39,3 +40,4 @@ BLENDER_TEST(BLI_math_color "bf_blenlib")
BLENDER_TEST(BLI_math_geom "bf_blenlib")
BLENDER_TEST(BLI_string "bf_blenlib")
BLENDER_TEST(BLI_path_util "bf_blenlib;extern_wcwidth;${ZLIB_LIBRARIES}")
+BLENDER_TEST(BLI_listbase "bf_blenlib")
diff --git a/tests/python/bl_mesh_modifiers.py b/tests/python/bl_mesh_modifiers.py
index b3f77aed96b..1c05eaafa0d 100644
--- a/tests/python/bl_mesh_modifiers.py
+++ b/tests/python/bl_mesh_modifiers.py
@@ -434,11 +434,6 @@ def modifier_hook_add(scene, obj, use_vgroup=True):
for v in mesh.vertices:
v.select = False
- if IS_BMESH:
- face_verts = mesh_bmesh_poly_vertices(mesh.polygons[0])
- else:
- face_verts = mesh.faces[0].vertices[:]
-
for i in mesh.faces[0].vertices:
mesh.vertices[i].select = True
diff --git a/tests/python/bl_pyapi_mathutils.py b/tests/python/bl_pyapi_mathutils.py
index d204e58dbd4..85232e465d7 100644
--- a/tests/python/bl_pyapi_mathutils.py
+++ b/tests/python/bl_pyapi_mathutils.py
@@ -1,8 +1,7 @@
# Apache License, Version 2.0
-# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_mathutils.py
+# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_mathutils.py -- --verbose
import unittest
-from test import support
from mathutils import Matrix, Vector
from mathutils import kdtree
import math
@@ -163,6 +162,29 @@ class MatrixTesting(unittest.TestCase):
self.assertEqual(mat.inverted(), inv_mat)
+ def test_matrix_inverse_safe(self):
+ mat = Matrix(((1, 4, 0, -1),
+ (2, -1, 0, -2),
+ (0, 3, 0, 3),
+ (-2, 9, 0, 0)))
+
+ # Warning, if we change epsilon in py api we have to update this!!!
+ epsilon = 1e-8
+ inv_mat_safe = mat.copy()
+ inv_mat_safe[0][0] += epsilon
+ inv_mat_safe[1][1] += epsilon
+ inv_mat_safe[2][2] += epsilon
+ inv_mat_safe[3][3] += epsilon
+ inv_mat_safe.invert()
+ '''
+ inv_mat_safe = Matrix(((1.0, -0.5, 0.0, -0.5),
+ (0.222222, -0.111111, -0.0, 0.0),
+ (-333333344.0, 316666656.0, 100000000.0, 150000000.0),
+ (0.888888, -0.9444444, 0.0, -0.5)))
+ '''
+
+ self.assertEqual(mat.inverted_safe(), inv_mat_safe)
+
def test_matrix_mult(self):
mat = Matrix(((1, 4, 0, -1),
(2, -1, 2, -2),
@@ -291,19 +313,7 @@ class KDTreeTesting(unittest.TestCase):
with self.assertRaises(RuntimeError):
k.find(co)
-
-def test_main():
- try:
- support.run_unittest(MatrixTesting)
- support.run_unittest(VectorTesting)
- support.run_unittest(KDTreeTesting)
- except:
- import traceback
- traceback.print_exc()
-
- # alert CTest we failed
- import sys
- sys.exit(1)
-
if __name__ == '__main__':
- test_main()
+ import sys
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [])
+ unittest.main()
diff --git a/tests/python/bl_pyapi_units.py b/tests/python/bl_pyapi_units.py
index 478adef51b2..128cc100b25 100644
--- a/tests/python/bl_pyapi_units.py
+++ b/tests/python/bl_pyapi_units.py
@@ -1,8 +1,7 @@
# Apache License, Version 2.0
-# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_units.py
+# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_units.py -- --verbose
import unittest
-from test import support
from bpy.utils import units
@@ -23,7 +22,10 @@ class UnitsTesting(unittest.TestCase):
('METRIC', 'LENGTH', "33.3dm", "1", 0.1),
('IMPERIAL', 'LENGTH', "33.3cm", "1", 0.3048), # ref unit is not in IMPERIAL system, default to feet...
('IMPERIAL', 'LENGTH', "33.3ft", "1\"", 0.0254), # unused ref unit, since one is given already!
- #('IMPERIAL', 'LENGTH', "", "1+1ft", 0.3048 * 2), # Will fail with current code!
+ ('IMPERIAL', 'LENGTH', "", "1+1ft", 0.3048 * 2), # default unit taken from current string (feet).
+ ('METRIC', 'LENGTH', "", "1+1ft", 1.3048), # no metric units, we default to meters.
+ ('IMPERIAL', 'LENGTH', "", "3+1in+1ft", 0.3048 * 4 + 0.0254), # bigger unit becomes default one!
+ ('IMPERIAL', 'LENGTH', "", "(3+1)in+1ft", 0.3048 + 0.0254 * 4),
)
# From 'internal' Blender value to user-friendly printing
@@ -67,16 +69,7 @@ class UnitsTesting(unittest.TestCase):
"\"%s\", expected \"%s\"" % (usys, utype, val, prec, sep, compat, opt_str, output))
-def test_main():
- try:
- support.run_unittest(UnitsTesting)
- except:
- import traceback
- traceback.print_exc()
-
- # alert CTest we failed
- import sys
- sys.exit(1)
-
if __name__ == '__main__':
- test_main()
+ import sys
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [])
+ unittest.main()