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:
-rw-r--r--CMakeLists.txt58
-rw-r--r--GNUmakefile74
-rw-r--r--SConstruct7
-rwxr-xr-xbuild_files/build_environment/install_deps.sh15
-rw-r--r--build_files/buildbot/config/user-config-cuda-glibc211-i686.py2
-rw-r--r--build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py2
-rw-r--r--build_files/buildbot/config/user-config-glibc211-i686.py2
-rw-r--r--build_files/buildbot/config/user-config-glibc211-x86_64.py2
-rw-r--r--build_files/buildbot/config/user-config-player-glibc211-i686.py2
-rw-r--r--build_files/buildbot/config/user-config-player-glibc211-x86_64.py2
-rw-r--r--build_files/cmake/Modules/FindOpenColorIO.cmake3
-rw-r--r--build_files/cmake/Modules/FindOpenImageIO.cmake8
-rw-r--r--build_files/cmake/Modules/FindPugiXML.cmake73
-rw-r--r--build_files/cmake/Modules/GTestTesting.cmake2
-rwxr-xr-xbuild_files/cmake/cmake_qtcreator_project.py2
-rw-r--r--build_files/cmake/config/blender_lite.cmake1
-rw-r--r--build_files/cmake/macros.cmake30
-rw-r--r--build_files/package_spec/pacman/PKGBUILD14
-rw-r--r--build_files/scons/config/darwin-config.py4
-rw-r--r--build_files/scons/config/win32-mingw-config.py5
-rw-r--r--build_files/scons/config/win32-vc-config.py7
-rw-r--r--build_files/scons/config/win64-mingw-config.py5
-rw-r--r--build_files/scons/config/win64-vc-config.py7
-rw-r--r--[-rwxr-xr-x]build_files/scons/tools/Blender.py6
-rw-r--r--build_files/scons/tools/btools.py6
-rwxr-xr-xbuild_files/utils/build_tgz.sh11
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst30
-rw-r--r--doc/python_api/rst/info_quickstart.rst146
-rw-r--r--doc/python_api/rst/info_tutorial_addon.rst64
-rw-r--r--doc/python_api/sphinx_doc_gen.py9
-rwxr-xr-xdoc/python_api/sphinx_doc_gen.sh6
-rw-r--r--[-rwxr-xr-x]extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp0
-rw-r--r--[-rwxr-xr-x]extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h0
-rw-r--r--extern/libmv/CMakeLists.txt71
-rw-r--r--extern/libmv/ChangeLog73
-rw-r--r--extern/libmv/SConscript50
-rwxr-xr-xextern/libmv/bundle.sh124
-rw-r--r--extern/libmv/files.txt10
-rw-r--r--extern/libmv/intern/logging.cc18
-rw-r--r--extern/libmv/intern/reconstruction.cc13
-rw-r--r--extern/libmv/intern/reconstruction.h2
-rw-r--r--extern/libmv/intern/stub.cc4
-rw-r--r--extern/libmv/third_party/gflags/AUTHORS.txt (renamed from extern/libmv/third_party/gflags/AUTHORS)0
-rw-r--r--extern/libmv/third_party/gflags/COPYING.txt (renamed from extern/libmv/third_party/gflags/COPYING)0
-rw-r--r--extern/libmv/third_party/gflags/ChangeLog195
-rw-r--r--extern/libmv/third_party/gflags/ChangeLog.txt208
-rw-r--r--extern/libmv/third_party/gflags/NEWS.txt (renamed from extern/libmv/third_party/gflags/NEWS)86
-rw-r--r--extern/libmv/third_party/gflags/README.libmv16
-rw-r--r--extern/libmv/third_party/gflags/config.h162
-rw-r--r--extern/libmv/third_party/gflags/gflags.cc117
-rw-r--r--extern/libmv/third_party/gflags/gflags/gflags.h180
-rw-r--r--extern/libmv/third_party/gflags/gflags/gflags_completions.h17
-rw-r--r--extern/libmv/third_party/gflags/gflags/gflags_declare.h92
-rw-r--r--extern/libmv/third_party/gflags/gflags_completions.cc14
-rw-r--r--extern/libmv/third_party/gflags/gflags_reporting.cc52
-rw-r--r--extern/libmv/third_party/gflags/mutex.h19
-rw-r--r--extern/libmv/third_party/gflags/util.h114
-rw-r--r--extern/libmv/third_party/gflags/windows_port.cc71
-rw-r--r--extern/libmv/third_party/gflags/windows_port.h127
-rw-r--r--extern/libmv/third_party/glog/README.libmv2
-rw-r--r--extern/libmv/third_party/glog/src/demangle.cc5
-rw-r--r--extern/libmv/third_party/glog/src/logging.cc5
-rw-r--r--extern/libmv/third_party/glog/src/symbolize.cc239
-rw-r--r--extern/libmv/third_party/glog/src/symbolize.h41
-rw-r--r--extern/sdlew/src/sdlew.c29
-rw-r--r--intern/atomic/atomic_ops.h9
-rw-r--r--intern/audaspace/intern/AUD_C-API.cpp9
-rw-r--r--intern/audaspace/intern/AUD_C-API.h2
-rw-r--r--intern/audaspace/intern/AUD_SequencerHandle.cpp253
-rw-r--r--intern/audaspace/intern/AUD_SequencerHandle.h18
-rw-r--r--intern/cycles/CMakeLists.txt53
-rw-r--r--intern/cycles/SConscript12
-rw-r--r--intern/cycles/app/CMakeLists.txt76
-rw-r--r--intern/cycles/app/cycles_server.cpp19
-rw-r--r--intern/cycles/app/cycles_standalone.cpp32
-rw-r--r--intern/cycles/app/cycles_xml.cpp10
-rw-r--r--intern/cycles/app/cycles_xml.h2
-rw-r--r--intern/cycles/app/io_export_cycles_xml.py2
-rw-r--r--intern/cycles/blender/CCL_api.h2
-rw-r--r--intern/cycles/blender/CMakeLists.txt2
-rw-r--r--intern/cycles/blender/addon/__init__.py2
-rw-r--r--intern/cycles/blender/addon/engine.py6
-rw-r--r--intern/cycles/blender/addon/osl.py2
-rw-r--r--intern/cycles/blender/addon/presets.py2
-rw-r--r--intern/cycles/blender/addon/properties.py30
-rw-r--r--intern/cycles/blender/addon/ui.py31
-rw-r--r--intern/cycles/blender/addon/version_update.py2
-rw-r--r--intern/cycles/blender/blender_camera.cpp18
-rw-r--r--intern/cycles/blender/blender_curves.cpp18
-rw-r--r--intern/cycles/blender/blender_logging.cpp40
-rw-r--r--intern/cycles/blender/blender_mesh.cpp5
-rw-r--r--intern/cycles/blender/blender_object.cpp18
-rw-r--r--intern/cycles/blender/blender_particles.cpp2
-rw-r--r--intern/cycles/blender/blender_python.cpp21
-rw-r--r--intern/cycles/blender/blender_session.cpp62
-rw-r--r--intern/cycles/blender/blender_session.h5
-rw-r--r--intern/cycles/blender/blender_shader.cpp2
-rw-r--r--intern/cycles/blender/blender_sync.cpp14
-rw-r--r--intern/cycles/blender/blender_sync.h4
-rw-r--r--intern/cycles/blender/blender_util.h2
-rw-r--r--intern/cycles/bvh/bvh.cpp262
-rw-r--r--intern/cycles/bvh/bvh.h4
-rw-r--r--intern/cycles/bvh/bvh_build.cpp181
-rw-r--r--intern/cycles/bvh/bvh_build.h10
-rw-r--r--intern/cycles/bvh/bvh_node.cpp14
-rw-r--r--intern/cycles/bvh/bvh_node.h3
-rw-r--r--intern/cycles/bvh/bvh_params.h8
-rw-r--r--intern/cycles/cmake/external_libs.cmake107
-rw-r--r--intern/cycles/device/CMakeLists.txt2
-rw-r--r--intern/cycles/device/device.cpp30
-rw-r--r--intern/cycles/device/device.h3
-rw-r--r--intern/cycles/device/device_cpu.cpp16
-rw-r--r--intern/cycles/device/device_cuda.cpp189
-rw-r--r--intern/cycles/device/device_intern.h6
-rw-r--r--intern/cycles/device/device_memory.h2
-rw-r--r--intern/cycles/device/device_multi.cpp2
-rw-r--r--intern/cycles/device/device_network.cpp2
-rw-r--r--intern/cycles/device/device_network.h2
-rw-r--r--intern/cycles/device/device_opencl.cpp13
-rw-r--r--intern/cycles/device/device_task.cpp2
-rw-r--r--intern/cycles/device/device_task.h2
-rw-r--r--intern/cycles/kernel/CMakeLists.txt21
-rw-r--r--intern/cycles/kernel/closure/bsdf.h2
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h6
-rw-r--r--intern/cycles/kernel/closure/bsdf_hair.h4
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h12
-rw-r--r--intern/cycles/kernel/closure/bsdf_oren_nayar.h2
-rw-r--r--intern/cycles/kernel/closure/bsdf_phong_ramp.h2
-rw-r--r--intern/cycles/kernel/closure/bssrdf.h2
-rw-r--r--intern/cycles/kernel/closure/volume.h2
-rw-r--r--intern/cycles/kernel/geom/geom.h3
-rw-r--r--intern/cycles/kernel/geom/geom_attribute.h2
-rw-r--r--intern/cycles/kernel/geom/geom_bvh.h16
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_shadow.h98
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_subsurface.h132
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_traversal.h195
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_volume.h147
-rw-r--r--intern/cycles/kernel/geom/geom_object.h59
-rw-r--r--intern/cycles/kernel/geom/geom_primitive.h12
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh.h147
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_shadow.h397
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_subsurface.h320
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_traversal.h412
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_volume.h349
-rw-r--r--intern/cycles/kernel/geom/geom_triangle.h205
-rw-r--r--intern/cycles/kernel/geom/geom_triangle_intersect.h417
-rw-r--r--intern/cycles/kernel/geom/geom_volume.h2
-rw-r--r--intern/cycles/kernel/kernel.cl2
-rw-r--r--intern/cycles/kernel/kernel.cpp2
-rw-r--r--intern/cycles/kernel/kernel.cu2
-rw-r--r--intern/cycles/kernel/kernel.h2
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h2
-rw-r--r--intern/cycles/kernel/kernel_avx.cpp2
-rw-r--r--intern/cycles/kernel/kernel_avx2.cpp2
-rw-r--r--intern/cycles/kernel/kernel_bake.h2
-rw-r--r--intern/cycles/kernel/kernel_camera.h8
-rw-r--r--intern/cycles/kernel/kernel_compat_cpu.h10
-rw-r--r--intern/cycles/kernel/kernel_compat_cuda.h2
-rw-r--r--intern/cycles/kernel/kernel_compat_opencl.h2
-rw-r--r--intern/cycles/kernel/kernel_debug.h2
-rw-r--r--intern/cycles/kernel/kernel_differential.h2
-rw-r--r--intern/cycles/kernel/kernel_emission.h6
-rw-r--r--intern/cycles/kernel/kernel_film.h2
-rw-r--r--intern/cycles/kernel/kernel_globals.h2
-rw-r--r--intern/cycles/kernel/kernel_jitter.h2
-rw-r--r--intern/cycles/kernel/kernel_light.h2
-rw-r--r--intern/cycles/kernel/kernel_math.h2
-rw-r--r--intern/cycles/kernel/kernel_passes.h2
-rw-r--r--intern/cycles/kernel/kernel_path.h2
-rw-r--r--intern/cycles/kernel/kernel_path_state.h2
-rw-r--r--intern/cycles/kernel/kernel_path_surface.h2
-rw-r--r--intern/cycles/kernel/kernel_path_volume.h2
-rw-r--r--intern/cycles/kernel/kernel_projection.h26
-rw-r--r--intern/cycles/kernel/kernel_random.h2
-rw-r--r--intern/cycles/kernel/kernel_shader.h4
-rw-r--r--intern/cycles/kernel/kernel_shadow.h2
-rw-r--r--intern/cycles/kernel/kernel_sse2.cpp2
-rw-r--r--intern/cycles/kernel/kernel_sse3.cpp2
-rw-r--r--intern/cycles/kernel/kernel_sse41.cpp2
-rw-r--r--intern/cycles/kernel/kernel_subsurface.h2
-rw-r--r--intern/cycles/kernel/kernel_textures.h2
-rw-r--r--intern/cycles/kernel/kernel_types.h96
-rw-r--r--intern/cycles/kernel/kernel_volume.h2
-rw-r--r--intern/cycles/kernel/osl/SConscript12
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp6
-rw-r--r--intern/cycles/kernel/osl/osl_globals.h2
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp2
-rw-r--r--intern/cycles/kernel/osl/osl_services.h2
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp2
-rw-r--r--intern/cycles/kernel/osl/osl_shader.h2
-rw-r--r--intern/cycles/kernel/shaders/node_absorption_volume.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_add_closure.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_ambient_occlusion.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_attribute.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_background.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_blackbody.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_brick_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_brightness.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_bump.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_camera.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_checker_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_color.h2
-rw-r--r--intern/cycles/kernel/shaders/node_combine_hsv.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_combine_rgb.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_combine_xyz.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_color.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_float.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_int.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_normal.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_point.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_string.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_vector.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_diffuse_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_emission.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_environment_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_fresnel.h2
-rw-r--r--intern/cycles/kernel/shaders/node_fresnel.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_gamma.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_geometry.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_glass_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_glossy_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_gradient_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_hair_info.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_holdout.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_hsv.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_image_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_invert.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_layer_weight.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_light_falloff.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_light_path.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_magic_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_mapping.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_math.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_mix.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_mix_closure.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_musgrave_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_noise_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_normal.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_normal_map.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_object_info.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_output_displacement.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_output_surface.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_output_volume.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_particle_info.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_refraction_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_rgb_curves.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_rgb_ramp.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_scatter_volume.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_separate_hsv.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_separate_rgb.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_separate_xyz.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_set_normal.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_sky_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_subsurface_scattering.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_tangent.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_texture.h2
-rw-r--r--intern/cycles/kernel/shaders/node_texture_coordinate.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_toon_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_translucent_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_transparent_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_uv_map.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_value.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_vector_curves.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_vector_math.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_vector_transform.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_velvet_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_voronoi_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_wave_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_wavelength.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_wireframe.osl2
-rw-r--r--intern/cycles/kernel/svm/svm.h2
-rw-r--r--intern/cycles/kernel/svm/svm_attribute.h2
-rw-r--r--intern/cycles/kernel/svm/svm_brick.h2
-rw-r--r--intern/cycles/kernel/svm/svm_brightness.h2
-rw-r--r--intern/cycles/kernel/svm/svm_camera.h2
-rw-r--r--intern/cycles/kernel/svm/svm_checker.h2
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h2
-rw-r--r--intern/cycles/kernel/svm/svm_convert.h2
-rw-r--r--intern/cycles/kernel/svm/svm_displace.h2
-rw-r--r--intern/cycles/kernel/svm/svm_fresnel.h2
-rw-r--r--intern/cycles/kernel/svm/svm_gamma.h2
-rw-r--r--intern/cycles/kernel/svm/svm_geometry.h2
-rw-r--r--intern/cycles/kernel/svm/svm_gradient.h2
-rw-r--r--intern/cycles/kernel/svm/svm_hsv.h2
-rw-r--r--intern/cycles/kernel/svm/svm_image.h2
-rw-r--r--intern/cycles/kernel/svm/svm_invert.h2
-rw-r--r--intern/cycles/kernel/svm/svm_light_path.h2
-rw-r--r--intern/cycles/kernel/svm/svm_magic.h2
-rw-r--r--intern/cycles/kernel/svm/svm_mapping.h2
-rw-r--r--intern/cycles/kernel/svm/svm_math.h40
-rw-r--r--intern/cycles/kernel/svm/svm_math_util.h40
-rw-r--r--intern/cycles/kernel/svm/svm_mix.h2
-rw-r--r--intern/cycles/kernel/svm/svm_musgrave.h2
-rw-r--r--intern/cycles/kernel/svm/svm_noisetex.h2
-rw-r--r--intern/cycles/kernel/svm/svm_normal.h2
-rw-r--r--intern/cycles/kernel/svm/svm_ramp.h2
-rw-r--r--intern/cycles/kernel/svm/svm_sepcomb_hsv.h2
-rw-r--r--intern/cycles/kernel/svm/svm_sepcomb_vector.h2
-rw-r--r--intern/cycles/kernel/svm/svm_sky.h2
-rw-r--r--intern/cycles/kernel/svm/svm_tex_coord.h2
-rw-r--r--intern/cycles/kernel/svm/svm_texture.h2
-rw-r--r--intern/cycles/kernel/svm/svm_types.h2
-rw-r--r--intern/cycles/kernel/svm/svm_value.h2
-rw-r--r--intern/cycles/kernel/svm/svm_vector_transform.h2
-rw-r--r--intern/cycles/kernel/svm/svm_voronoi.h2
-rw-r--r--intern/cycles/kernel/svm/svm_wave.h2
-rw-r--r--intern/cycles/render/CMakeLists.txt2
-rw-r--r--intern/cycles/render/attribute.cpp2
-rw-r--r--intern/cycles/render/attribute.h2
-rw-r--r--intern/cycles/render/background.cpp2
-rw-r--r--intern/cycles/render/background.h2
-rw-r--r--intern/cycles/render/bake.cpp2
-rw-r--r--intern/cycles/render/bake.h2
-rw-r--r--intern/cycles/render/blackbody.h2
-rw-r--r--intern/cycles/render/buffers.cpp2
-rw-r--r--intern/cycles/render/buffers.h2
-rw-r--r--intern/cycles/render/camera.cpp14
-rw-r--r--intern/cycles/render/camera.h6
-rw-r--r--intern/cycles/render/curves.cpp2
-rw-r--r--intern/cycles/render/curves.h2
-rw-r--r--intern/cycles/render/film.cpp2
-rw-r--r--intern/cycles/render/film.h2
-rw-r--r--intern/cycles/render/graph.cpp4
-rw-r--r--intern/cycles/render/graph.h2
-rw-r--r--intern/cycles/render/image.cpp2
-rw-r--r--intern/cycles/render/image.h2
-rw-r--r--intern/cycles/render/integrator.cpp6
-rw-r--r--intern/cycles/render/integrator.h2
-rw-r--r--intern/cycles/render/light.cpp2
-rw-r--r--intern/cycles/render/light.h2
-rw-r--r--intern/cycles/render/mesh.cpp14
-rw-r--r--intern/cycles/render/mesh.h2
-rw-r--r--intern/cycles/render/mesh_displace.cpp2
-rw-r--r--intern/cycles/render/nodes.cpp26
-rw-r--r--intern/cycles/render/nodes.h2
-rw-r--r--intern/cycles/render/object.cpp5
-rw-r--r--intern/cycles/render/object.h2
-rw-r--r--intern/cycles/render/osl.cpp5
-rw-r--r--intern/cycles/render/osl.h2
-rw-r--r--intern/cycles/render/particles.cpp2
-rw-r--r--intern/cycles/render/particles.h2
-rw-r--r--intern/cycles/render/scene.cpp38
-rw-r--r--intern/cycles/render/scene.h7
-rw-r--r--intern/cycles/render/session.cpp22
-rw-r--r--intern/cycles/render/session.h2
-rw-r--r--intern/cycles/render/shader.cpp2
-rw-r--r--intern/cycles/render/shader.h11
-rw-r--r--intern/cycles/render/sobol.h2
-rw-r--r--intern/cycles/render/svm.cpp2
-rw-r--r--intern/cycles/render/svm.h2
-rw-r--r--intern/cycles/render/tables.cpp2
-rw-r--r--intern/cycles/render/tables.h2
-rw-r--r--intern/cycles/render/tile.cpp2
-rw-r--r--intern/cycles/render/tile.h2
-rw-r--r--intern/cycles/subd/subd_dice.cpp2
-rw-r--r--intern/cycles/subd/subd_dice.h2
-rw-r--r--intern/cycles/subd/subd_patch.cpp2
-rw-r--r--intern/cycles/subd/subd_patch.h2
-rw-r--r--intern/cycles/subd/subd_split.cpp2
-rw-r--r--intern/cycles/subd/subd_split.h2
-rw-r--r--intern/cycles/util/CMakeLists.txt9
-rw-r--r--intern/cycles/util/util_algorithm.h2
-rw-r--r--intern/cycles/util/util_args.h2
-rw-r--r--intern/cycles/util/util_atomic.h (renamed from intern/cycles/util/util_dynlib.h)30
-rw-r--r--intern/cycles/util/util_boundbox.h2
-rw-r--r--intern/cycles/util/util_cache.cpp2
-rw-r--r--intern/cycles/util/util_cache.h2
-rw-r--r--intern/cycles/util/util_color.h2
-rw-r--r--intern/cycles/util/util_debug.h2
-rw-r--r--intern/cycles/util/util_dynlib.cpp94
-rw-r--r--intern/cycles/util/util_foreach.h2
-rw-r--r--intern/cycles/util/util_function.h2
-rw-r--r--intern/cycles/util/util_half.h2
-rw-r--r--intern/cycles/util/util_hash.h2
-rw-r--r--intern/cycles/util/util_image.h2
-rw-r--r--intern/cycles/util/util_list.h2
-rw-r--r--intern/cycles/util/util_logging.cpp50
-rw-r--r--intern/cycles/util/util_logging.h6
-rw-r--r--intern/cycles/util/util_map.h2
-rw-r--r--intern/cycles/util/util_math.h36
-rw-r--r--intern/cycles/util/util_opengl.h10
-rw-r--r--intern/cycles/util/util_optimization.h5
-rw-r--r--intern/cycles/util/util_param.h2
-rw-r--r--intern/cycles/util/util_path.cpp2
-rw-r--r--intern/cycles/util/util_path.h2
-rw-r--r--intern/cycles/util/util_progress.h54
-rw-r--r--intern/cycles/util/util_set.h2
-rw-r--r--intern/cycles/util/util_simd.cpp2
-rw-r--r--intern/cycles/util/util_simd.h2
-rw-r--r--intern/cycles/util/util_sseb.h2
-rw-r--r--intern/cycles/util/util_ssef.h2
-rw-r--r--intern/cycles/util/util_ssei.h2
-rw-r--r--intern/cycles/util/util_stats.h11
-rw-r--r--intern/cycles/util/util_string.cpp2
-rw-r--r--intern/cycles/util/util_string.h2
-rw-r--r--intern/cycles/util/util_system.cpp2
-rw-r--r--intern/cycles/util/util_system.h2
-rw-r--r--intern/cycles/util/util_task.cpp2
-rw-r--r--intern/cycles/util/util_task.h2
-rw-r--r--intern/cycles/util/util_thread.h2
-rw-r--r--intern/cycles/util/util_time.cpp2
-rw-r--r--intern/cycles/util/util_time.h2
-rw-r--r--intern/cycles/util/util_transform.cpp2
-rw-r--r--intern/cycles/util/util_transform.h2
-rw-r--r--intern/cycles/util/util_types.h15
-rw-r--r--intern/cycles/util/util_vector.h2
-rw-r--r--intern/cycles/util/util_view.cpp2
-rw-r--r--intern/cycles/util/util_view.h2
-rw-r--r--intern/cycles/util/util_xml.h6
-rw-r--r--intern/ghost/CMakeLists.txt10
-rw-r--r--intern/ghost/GHOST_C-api.h24
-rw-r--r--intern/ghost/GHOST_IWindow.h23
-rw-r--r--intern/ghost/GHOST_Types.h20
-rw-r--r--intern/ghost/SConscript8
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp18
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm7
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.cpp517
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.h401
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.cpp61
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.h4
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm56
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp78
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h9
-rw-r--r--intern/ghost/intern/GHOST_Window.h16
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm2
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp13
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h19
-rw-r--r--intern/opennl/superlu/smemory.c6
-rw-r--r--release/datafiles/blender_icons.svg657
-rw-r--r--release/datafiles/blender_icons16/icon16_file_hidden.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_mod_data_transfer.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_file_hidden.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_mod_data_transfer.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/colormanagement/config.ocio2
m---------release/datafiles/locale0
-rw-r--r--release/datafiles/splash.pngbin187919 -> 255011 bytes
-rw-r--r--release/datafiles/splash_2x.pngbin582704 -> 877592 bytes
-rw-r--r--release/datafiles/startup.blendbin443048 -> 432264 bytes
m---------[l---------]release/scripts/addons1
m---------release/scripts/addons_contrib0
-rw-r--r--release/scripts/freestyle/modules/parameter_editor.py50
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils_spell_check.py2
-rw-r--r--release/scripts/modules/bpy/__init__.py4
-rw-r--r--release/scripts/modules/bpy/ops.py1
-rw-r--r--release/scripts/modules/bpy_extras/io_utils.py38
-rw-r--r--release/scripts/modules/bpy_extras/keyconfig_utils.py6
-rw-r--r--release/scripts/modules/bpy_extras/object_utils.py14
-rw-r--r--release/scripts/modules/bpy_extras/view3d_utils.py27
-rw-r--r--release/scripts/modules/rna_info.py6
-rw-r--r--release/scripts/modules/rna_keymap_ui.py2
-rw-r--r--release/scripts/modules/sys_info.py6
-rw-r--r--release/scripts/presets/interface_theme/back_to_black.xml2
-rw-r--r--release/scripts/presets/interface_theme/blender_24x.xml2
-rw-r--r--release/scripts/presets/interface_theme/elsyiun.xml2
-rw-r--r--release/scripts/presets/interface_theme/graph.xml2
-rw-r--r--release/scripts/presets/interface_theme/hexagon.xml2
-rw-r--r--release/scripts/presets/interface_theme/science_lab.xml2
-rw-r--r--release/scripts/presets/interface_theme/softimage.xml2
-rw-r--r--release/scripts/presets/interface_theme/ubuntu_ambiance.xml2
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py32
-rw-r--r--release/scripts/startup/bl_ui/__init__.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_constraint.py20
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py115
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py451
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py40
-rw-r--r--release/scripts/startup/bl_ui/properties_render_layer.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py3
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py36
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py12
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py6
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py7
-rw-r--r--release/scripts/startup/bl_ui/space_image.py23
-rw-r--r--release/scripts/startup/bl_ui/space_info.py17
-rw-r--r--release/scripts/startup/bl_ui/space_node.py45
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py57
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py2
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py45
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py29
-rw-r--r--release/scripts/startup/nodeitems_builtins.py1
-rw-r--r--release/scripts/templates_py/operator_modal_view3d_raycast.py4
-rw-r--r--release/text/readme.html2
-rw-r--r--source/blender/blenfont/BLF_translation.h8
-rw-r--r--source/blender/blenfont/CMakeLists.txt6
-rw-r--r--source/blender/blenfont/intern/blf_font.c4
-rw-r--r--source/blender/blenfont/intern/blf_font_win32_compat.c145
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c4
-rw-r--r--source/blender/blenfont/intern/blf_internal.h7
-rw-r--r--source/blender/blenfont/intern/blf_lang.c5
-rw-r--r--source/blender/blenfont/intern/blf_translation.c6
-rw-r--r--source/blender/blenfont/intern/blf_util.c1
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h3
-rw-r--r--source/blender/blenkernel/BKE_appdir.h80
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_brush.h5
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h46
-rw-r--r--source/blender/blenkernel/BKE_camera.h4
-rw-r--r--source/blender/blenkernel/BKE_constraint.h3
-rw-r--r--source/blender/blenkernel/BKE_context.h11
-rw-r--r--source/blender/blenkernel/BKE_customdata.h88
-rw-r--r--source/blender/blenkernel/BKE_data_transfer.h158
-rw-r--r--source/blender/blenkernel/BKE_deform.h17
-rw-r--r--source/blender/blenkernel/BKE_editmesh_bvh.h14
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h9
-rw-r--r--source/blender/blenkernel/BKE_idprop.h12
-rw-r--r--source/blender/blenkernel/BKE_image.h1
-rw-r--r--source/blender/blenkernel/BKE_key.h11
-rw-r--r--source/blender/blenkernel/BKE_mesh_mapping.h63
-rw-r--r--source/blender/blenkernel/BKE_mesh_remap.h171
-rw-r--r--source/blender/blenkernel/BKE_movieclip.h1
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/BKE_object.h2
-rw-r--r--source/blender/blenkernel/BKE_object_deform.h50
-rw-r--r--source/blender/blenkernel/BKE_paint.h13
-rw-r--r--source/blender/blenkernel/BKE_particle.h2
-rw-r--r--source/blender/blenkernel/BKE_screen.h1
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h19
-rw-r--r--source/blender/blenkernel/BKE_sound.h4
-rw-r--r--source/blender/blenkernel/BKE_text.h2
-rw-r--r--source/blender/blenkernel/BKE_tracking.h3
-rw-r--r--source/blender/blenkernel/CMakeLists.txt21
-rw-r--r--source/blender/blenkernel/SConscript5
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c42
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.h22
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c30
-rw-r--r--source/blender/blenkernel/intern/action.c12
-rw-r--r--source/blender/blenkernel/intern/addon.c6
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c38
-rw-r--r--source/blender/blenkernel/intern/appdir.c808
-rw-r--r--source/blender/blenkernel/intern/armature.c57
-rw-r--r--source/blender/blenkernel/intern/autoexec.c5
-rw-r--r--source/blender/blenkernel/intern/blender.c23
-rw-r--r--source/blender/blenkernel/intern/brush.c29
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c578
-rw-r--r--source/blender/blenkernel/intern/camera.c219
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c1042
-rw-r--r--source/blender/blenkernel/intern/colortools.c1
-rw-r--r--source/blender/blenkernel/intern/constraint.c71
-rw-r--r--source/blender/blenkernel/intern/context.c34
-rw-r--r--source/blender/blenkernel/intern/curve.c4
-rw-r--r--source/blender/blenkernel/intern/customdata.c346
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c1241
-rw-r--r--source/blender/blenkernel/intern/data_transfer_intern.h60
-rw-r--r--source/blender/blenkernel/intern/deform.c391
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c9
-rw-r--r--source/blender/blenkernel/intern/displist.c3
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c43
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c30
-rw-r--r--source/blender/blenkernel/intern/editmesh_bvh.c96
-rw-r--r--source/blender/blenkernel/intern/fcurve.c24
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c14
-rw-r--r--source/blender/blenkernel/intern/gpencil.c60
-rw-r--r--source/blender/blenkernel/intern/group.c4
-rw-r--r--source/blender/blenkernel/intern/idprop.c62
-rw-r--r--source/blender/blenkernel/intern/image.c36
-rw-r--r--source/blender/blenkernel/intern/key.c200
-rw-r--r--source/blender/blenkernel/intern/lamp.c5
-rw-r--r--source/blender/blenkernel/intern/lattice.c22
-rw-r--r--source/blender/blenkernel/intern/library.c4
-rw-r--r--source/blender/blenkernel/intern/linestyle.c6
-rw-r--r--source/blender/blenkernel/intern/mask.c12
-rw-r--r--source/blender/blenkernel/intern/mask_evaluate.c2
-rw-r--r--source/blender/blenkernel/intern/material.c30
-rw-r--r--source/blender/blenkernel/intern/mball.c8
-rw-r--r--source/blender/blenkernel/intern/mesh.c4
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c7
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c377
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c1988
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c2
-rw-r--r--source/blender/blenkernel/intern/modifier.c10
-rw-r--r--source/blender/blenkernel/intern/movieclip.c29
-rw-r--r--source/blender/blenkernel/intern/nla.c74
-rw-r--r--source/blender/blenkernel/intern/node.c37
-rw-r--r--source/blender/blenkernel/intern/object.c140
-rw-r--r--source/blender/blenkernel/intern/object_deform.c544
-rw-r--r--source/blender/blenkernel/intern/paint.c74
-rw-r--r--source/blender/blenkernel/intern/particle.c21
-rw-r--r--source/blender/blenkernel/intern/particle_system.c4
-rw-r--r--source/blender/blenkernel/intern/pbvh.c6
-rw-r--r--source/blender/blenkernel/intern/pointcache.c15
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c26
-rw-r--r--source/blender/blenkernel/intern/screen.c17
-rw-r--r--source/blender/blenkernel/intern/seqcache.c8
-rw-r--r--source/blender/blenkernel/intern/sequencer.c139
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c1
-rw-r--r--source/blender/blenkernel/intern/smoke.c11
-rw-r--r--source/blender/blenkernel/intern/sound.c64
-rw-r--r--source/blender/blenkernel/intern/speaker.c4
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c167
-rw-r--r--source/blender/blenkernel/intern/text.c69
-rw-r--r--source/blender/blenkernel/intern/texture.c21
-rw-r--r--source/blender/blenkernel/intern/tracking.c29
-rw-r--r--source/blender/blenkernel/intern/tracking_auto.c48
-rw-r--r--source/blender/blenkernel/intern/tracking_detect.c1
-rw-r--r--source/blender/blenkernel/intern/tracking_region_tracker.c5
-rw-r--r--source/blender/blenkernel/intern/tracking_solver.c7
-rw-r--r--source/blender/blenkernel/intern/tracking_util.c3
-rw-r--r--source/blender/blenkernel/intern/world.c15
-rw-r--r--source/blender/blenkernel/intern/writeavi.c4
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c17
-rw-r--r--source/blender/blenlib/BLI_astar.h98
-rw-r--r--source/blender/blenlib/BLI_bitmap.h15
-rw-r--r--source/blender/blenlib/BLI_callbacks.h1
-rw-r--r--source/blender/blenlib/BLI_compiler_typecheck.h19
-rw-r--r--source/blender/blenlib/BLI_edgehash.h4
-rw-r--r--source/blender/blenlib/BLI_fileops.h9
-rw-r--r--source/blender/blenlib/BLI_ghash.h8
-rw-r--r--source/blender/blenlib/BLI_heap.h1
-rw-r--r--source/blender/blenlib/BLI_linklist_stack.h32
-rw-r--r--source/blender/blenlib/BLI_math_base.h11
-rw-r--r--source/blender/blenlib/BLI_math_geom.h12
-rw-r--r--source/blender/blenlib/BLI_math_vector.h1
-rw-r--r--source/blender/blenlib/BLI_path_util.h47
-rw-r--r--source/blender/blenlib/BLI_polyfill2d.h3
-rw-r--r--source/blender/blenlib/BLI_polyfill2d_beautify.h42
-rw-r--r--source/blender/blenlib/BLI_rand.h3
-rw-r--r--source/blender/blenlib/BLI_smallhash.h15
-rw-r--r--source/blender/blenlib/BLI_string.h7
-rw-r--r--source/blender/blenlib/BLI_string_utf8.h1
-rw-r--r--source/blender/blenlib/BLI_system.h5
-rw-r--r--source/blender/blenlib/BLI_task.h5
-rw-r--r--source/blender/blenlib/BLI_utildefines.h109
-rw-r--r--source/blender/blenlib/CMakeLists.txt13
-rw-r--r--source/blender/blenlib/SConscript6
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c3
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c31
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c4
-rw-r--r--source/blender/blenlib/intern/BLI_linklist.c8
-rw-r--r--source/blender/blenlib/intern/astar.c294
-rw-r--r--source/blender/blenlib/intern/boxpack2d.c4
-rw-r--r--source/blender/blenlib/intern/convexhull2d.c4
-rw-r--r--source/blender/blenlib/intern/easing.c2
-rw-r--r--source/blender/blenlib/intern/edgehash.c99
-rw-r--r--source/blender/blenlib/intern/fileops.c12
-rw-r--r--source/blender/blenlib/intern/graph.c8
-rw-r--r--source/blender/blenlib/intern/hash_md5.c2
-rw-r--r--source/blender/blenlib/intern/hash_mm2a.c2
-rw-r--r--source/blender/blenlib/intern/lasso.c1
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c13
-rw-r--r--source/blender/blenlib/intern/math_geom.c435
-rw-r--r--source/blender/blenlib/intern/math_geom_inline.c6
-rw-r--r--source/blender/blenlib/intern/math_matrix.c33
-rw-r--r--source/blender/blenlib/intern/math_rotation.c2
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c12
-rw-r--r--source/blender/blenlib/intern/path_util.c789
-rw-r--r--source/blender/blenlib/intern/polyfill2d.c4
-rw-r--r--source/blender/blenlib/intern/polyfill2d_beautify.c490
-rw-r--r--source/blender/blenlib/intern/rand.c25
-rw-r--r--source/blender/blenlib/intern/scanfill.c28
-rw-r--r--source/blender/blenlib/intern/scanfill_utils.c12
-rw-r--r--source/blender/blenlib/intern/smallhash.c59
-rw-r--r--source/blender/blenlib/intern/storage.c48
-rw-r--r--source/blender/blenlib/intern/string.c121
-rw-r--r--source/blender/blenlib/intern/string_utf8.c22
-rw-r--r--source/blender/blenlib/intern/system.c75
-rw-r--r--source/blender/blenlib/intern/task.c64
-rw-r--r--source/blender/blenlib/intern/winstuff_dir.c10
-rw-r--r--source/blender/blenloader/intern/readblenentry.c8
-rw-r--r--source/blender/blenloader/intern/readfile.c110
-rw-r--r--source/blender/blenloader/intern/readfile.h3
-rw-r--r--source/blender/blenloader/intern/runtime.c1
-rw-r--r--source/blender/blenloader/intern/undofile.c1
-rw-r--r--source/blender/blenloader/intern/versioning_250.c8
-rw-r--r--source/blender/blenloader/intern/versioning_260.c2
-rw-r--r--source/blender/blenloader/intern/versioning_270.c27
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c10
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c101
-rw-r--r--source/blender/blenloader/intern/writefile.c12
-rw-r--r--source/blender/bmesh/bmesh_class.h6
-rw-r--r--source/blender/bmesh/intern/bmesh_callback_generic.c5
-rw-r--r--source/blender/bmesh/intern/bmesh_callback_generic.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h28
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c154
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h18
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c56
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h16
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_impl.c1
-rw-r--r--source/blender/bmesh/operators/bmo_bridge.c32
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c20
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c2
-rw-r--r--source/blender/bmesh/operators/bmo_hull.c4
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c102
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c2
-rw-r--r--source/blender/bmesh/operators/bmo_similar.c7
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c2
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c29
-rw-r--r--source/blender/bmesh/operators/bmo_wireframe.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c123
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.h14
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c24
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c4
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.c70
-rw-r--r--source/blender/collada/ArmatureImporter.cpp336
-rw-r--r--source/blender/collada/ArmatureImporter.h44
-rw-r--r--source/blender/collada/DocumentImporter.cpp2
-rw-r--r--source/blender/collada/ErrorHandler.cpp18
-rw-r--r--source/blender/collada/ImageExporter.cpp2
-rw-r--r--source/blender/collada/ImportSettings.h4
-rw-r--r--source/blender/collada/SkinInfo.cpp9
-rw-r--r--source/blender/collada/TransformWriter.cpp2
-rw-r--r--source/blender/collada/collada.cpp13
-rw-r--r--source/blender/collada/collada.h5
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.h2
-rw-r--r--source/blender/compositor/intern/COM_Debug.cpp2
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_CompositorNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_MixNode.cpp4
-rw-r--r--source/blender/compositor/nodes/COM_ViewerNode.cpp2
-rw-r--r--source/blender/compositor/operations/COM_OpenCLKernels.cl12
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.cpp92
-rw-r--r--source/blender/datatoc/datatoc_icon.c3
-rwxr-xr-xsource/blender/datatoc/datatoc_icon.py11
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c133
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c256
-rw-r--r--source/blender/editors/animation/anim_deps.c2
-rw-r--r--source/blender/editors/animation/anim_draw.c1
-rw-r--r--source/blender/editors/animation/anim_filter.c122
-rw-r--r--source/blender/editors/animation/anim_ops.c69
-rw-r--r--source/blender/editors/animation/drivers.c6
-rw-r--r--source/blender/editors/animation/keyframes_draw.c35
-rw-r--r--source/blender/editors/animation/keyframes_edit.c42
-rw-r--r--source/blender/editors/animation/keyframes_general.c124
-rw-r--r--source/blender/editors/animation/keyframing.c56
-rw-r--r--source/blender/editors/armature/armature_ops.c2
-rw-r--r--source/blender/editors/armature/armature_skinning.c12
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c2
-rw-r--r--source/blender/editors/armature/pose_group.c4
-rw-r--r--source/blender/editors/armature/pose_lib.c2
-rw-r--r--source/blender/editors/armature/pose_utils.c2
-rw-r--r--source/blender/editors/curve/curve_ops.c4
-rw-r--r--source/blender/editors/curve/editcurve.c3
-rw-r--r--source/blender/editors/curve/editfont.c10
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt3
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c851
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c59
-rw-r--r--source/blender/editors/gpencil/gpencil_buttons.c378
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c1259
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h93
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c198
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c242
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c943
-rw-r--r--source/blender/editors/gpencil/gpencil_undo.c57
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c166
-rw-r--r--source/blender/editors/include/BIF_gl.h10
-rw-r--r--source/blender/editors/include/ED_anim_api.h3
-rw-r--r--source/blender/editors/include/ED_gpencil.h29
-rw-r--r--source/blender/editors/include/ED_image.h2
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h9
-rw-r--r--source/blender/editors/include/ED_keyframes_edit.h11
-rw-r--r--source/blender/editors/include/ED_keyframing.h2
-rw-r--r--source/blender/editors/include/ED_mesh.h8
-rw-r--r--source/blender/editors/include/ED_object.h6
-rw-r--r--source/blender/editors/include/ED_render.h6
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/include/ED_sculpt.h3
-rw-r--r--source/blender/editors/include/ED_sequencer.h6
-rw-r--r--source/blender/editors/include/ED_text.h3
-rw-r--r--source/blender/editors/include/ED_transform.h2
-rw-r--r--source/blender/editors/include/ED_uvedit.h2
-rw-r--r--source/blender/editors/include/ED_view3d.h2
-rw-r--r--source/blender/editors/include/UI_icons.h4
-rw-r--r--source/blender/editors/include/UI_interface.h56
-rw-r--r--source/blender/editors/include/UI_interface_icons.h4
-rw-r--r--source/blender/editors/include/UI_resources.h16
-rw-r--r--source/blender/editors/interface/CMakeLists.txt6
-rw-r--r--source/blender/editors/interface/SConscript4
-rw-r--r--source/blender/editors/interface/interface.c56
-rw-r--r--source/blender/editors/interface/interface_anim.c2
-rw-r--r--source/blender/editors/interface/interface_draw.c6
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c371
-rw-r--r--source/blender/editors/interface/interface_handlers.c181
-rw-r--r--source/blender/editors/interface/interface_icons.c46
-rw-r--r--source/blender/editors/interface/interface_intern.h9
-rw-r--r--source/blender/editors/interface/interface_layout.c34
-rw-r--r--source/blender/editors/interface/interface_ops.c2
-rw-r--r--source/blender/editors/interface/interface_panel.c12
-rw-r--r--source/blender/editors/interface/interface_regions.c6
-rw-r--r--source/blender/editors/interface/interface_style.c4
-rw-r--r--source/blender/editors/interface/interface_templates.c29
-rw-r--r--source/blender/editors/interface/interface_utils.c35
-rw-r--r--source/blender/editors/interface/interface_widgets.c114
-rw-r--r--source/blender/editors/interface/resources.c87
-rw-r--r--source/blender/editors/interface/view2d.c4
-rw-r--r--source/blender/editors/io/io_collada.c57
-rw-r--r--source/blender/editors/io/io_ops.c13
-rw-r--r--source/blender/editors/mask/mask_ops.c4
-rw-r--r--source/blender/editors/mask/mask_relationships.c1
-rw-r--r--source/blender/editors/mesh/editface.c2
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c225
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c3
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c435
-rw-r--r--source/blender/editors/mesh/editmesh_path.c5
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c2
-rw-r--r--source/blender/editors/mesh/editmesh_rip_edge.c7
-rw-r--r--source/blender/editors/mesh/editmesh_select.c13
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c2
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c2
-rw-r--r--source/blender/editors/mesh/mesh_data.c22
-rw-r--r--source/blender/editors/metaball/mball_edit.c1
-rw-r--r--source/blender/editors/metaball/mball_ops.c4
-rw-r--r--source/blender/editors/object/CMakeLists.txt1
-rw-r--r--source/blender/editors/object/object_add.c89
-rw-r--r--source/blender/editors/object/object_bake.c3
-rw-r--r--source/blender/editors/object/object_bake_api.c7
-rw-r--r--source/blender/editors/object/object_data_transfer.c675
-rw-r--r--source/blender/editors/object/object_intern.h16
-rw-r--r--source/blender/editors/object/object_lod.c8
-rw-r--r--source/blender/editors/object/object_modifier.c15
-rw-r--r--source/blender/editors/object/object_ops.c9
-rw-r--r--source/blender/editors/object/object_relations.c1
-rw-r--r--source/blender/editors/object/object_shapekey.c7
-rw-r--r--source/blender/editors/object/object_transform.c3
-rw-r--r--source/blender/editors/object/object_vgroup.c1058
-rw-r--r--source/blender/editors/object/object_warp.c1
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c5
-rw-r--r--source/blender/editors/physics/physics_fluid.c2
-rw-r--r--source/blender/editors/physics/physics_ops.c4
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c2
-rw-r--r--source/blender/editors/physics/rigidbody_object.c5
-rw-r--r--source/blender/editors/physics/rigidbody_world.c6
-rw-r--r--source/blender/editors/render/render_internal.c28
-rw-r--r--source/blender/editors/render/render_opengl.c13
-rw-r--r--source/blender/editors/render/render_preview.c37
-rw-r--r--source/blender/editors/render/render_shading.c9
-rw-r--r--source/blender/editors/render/render_update.c41
-rw-r--r--source/blender/editors/screen/area.c19
-rw-r--r--source/blender/editors/screen/glutil.c1
-rw-r--r--source/blender/editors/screen/screen_context.c117
-rw-r--r--source/blender/editors/screen/screen_edit.c31
-rw-r--r--source/blender/editors/screen/screen_ops.c20
-rw-r--r--source/blender/editors/screen/screendump.c3
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c16
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c21
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c7
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c215
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c50
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c25
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c26
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c68
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c9
-rw-r--r--source/blender/editors/sound/sound_ops.c9
-rw-r--r--source/blender/editors/space_action/action_edit.c74
-rw-r--r--source/blender/editors/space_action/action_ops.c6
-rw-r--r--source/blender/editors/space_api/spacetypes.c7
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c6
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c5
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c19
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c1
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_ops.c1
-rw-r--r--source/blender/editors/space_clip/clip_draw.c3
-rw-r--r--source/blender/editors/space_clip/clip_editor.c1
-rw-r--r--source/blender/editors/space_clip/clip_graph_draw.c1
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c2
-rw-r--r--source/blender/editors/space_clip/clip_ops.c11
-rw-r--r--source/blender/editors/space_clip/clip_utils.c4
-rw-r--r--source/blender/editors/space_clip/space_clip.c7
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c3
-rw-r--r--source/blender/editors/space_clip/tracking_select.c8
-rw-r--r--source/blender/editors/space_console/console_draw.c1
-rw-r--r--source/blender/editors/space_file/file_draw.c65
-rw-r--r--source/blender/editors/space_file/file_ops.c59
-rw-r--r--source/blender/editors/space_file/filelist.c966
-rw-r--r--source/blender/editors/space_file/filelist.h60
-rw-r--r--source/blender/editors/space_file/filesel.c36
-rw-r--r--source/blender/editors/space_file/fsmenu.c2
-rw-r--r--source/blender/editors/space_file/space_file.c63
-rw-r--r--source/blender/editors/space_graph/graph_edit.c15
-rw-r--r--source/blender/editors/space_graph/graph_intern.h1
-rw-r--r--source/blender/editors/space_graph/graph_ops.c205
-rw-r--r--source/blender/editors/space_graph/graph_select.c85
-rw-r--r--source/blender/editors/space_graph/graph_utils.c1
-rw-r--r--source/blender/editors/space_image/image_buttons.c14
-rw-r--r--source/blender/editors/space_image/image_draw.c15
-rw-r--r--source/blender/editors/space_image/image_ops.c44
-rw-r--r--source/blender/editors/space_image/space_image.c12
-rw-r--r--source/blender/editors/space_info/info_draw.c3
-rw-r--r--source/blender/editors/space_info/textview.c2
-rw-r--r--source/blender/editors/space_logic/logic_buttons.c1
-rw-r--r--source/blender/editors/space_logic/logic_window.c6
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c1
-rw-r--r--source/blender/editors/space_nla/nla_channels.c1
-rw-r--r--source/blender/editors/space_nla/nla_draw.c3
-rw-r--r--source/blender/editors/space_nla/nla_edit.c19
-rw-r--r--source/blender/editors/space_nla/nla_intern.h2
-rw-r--r--source/blender/editors/space_nla/nla_ops.c4
-rw-r--r--source/blender/editors/space_nla/space_nla.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c4
-rw-r--r--source/blender/editors/space_node/node_add.c61
-rw-r--r--source/blender/editors/space_node/node_buttons.c11
-rw-r--r--source/blender/editors/space_node/node_draw.c8
-rw-r--r--source/blender/editors/space_node/node_edit.c46
-rw-r--r--source/blender/editors/space_node/node_group.c12
-rw-r--r--source/blender/editors/space_node/node_relationships.c14
-rw-r--r--source/blender/editors/space_node/node_templates.c2
-rw-r--r--source/blender/editors/space_node/node_toolbar.c9
-rw-r--r--source/blender/editors/space_node/space_node.c15
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c1
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c64
-rw-r--r--source/blender/editors/space_script/script_edit.c3
-rw-r--r--source/blender/editors/space_script/script_ops.c13
-rw-r--r--source/blender/editors/space_script/space_script.c2
-rw-r--r--source/blender/editors/space_sequencer/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_buttons.c7
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c430
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c163
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h21
-rw-r--r--source/blender/editors/space_sequencer/sequencer_modifier.c12
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_preview.c172
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c32
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c9
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c14
-rw-r--r--source/blender/editors/space_text/text_draw.c51
-rw-r--r--source/blender/editors/space_text/text_header.c1
-rw-r--r--source/blender/editors/space_text/text_intern.h4
-rw-r--r--source/blender/editors/space_text/text_ops.c91
-rw-r--r--source/blender/editors/space_time/space_time.c15
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c2
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c1
-rw-r--r--source/blender/editors/space_view3d/drawanimviz.c1
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c1
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c109
-rw-r--r--source/blender/editors/space_view3d/drawobject.c34
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c5
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c24
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c14
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c420
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c181
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h4
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c34
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c2
-rw-r--r--source/blender/editors/transform/transform.c54
-rw-r--r--source/blender/editors/transform/transform.h10
-rw-r--r--source/blender/editors/transform/transform_conversions.c391
-rw-r--r--source/blender/editors/transform/transform_generics.c28
-rw-r--r--source/blender/editors/transform/transform_ops.c25
-rw-r--r--source/blender/editors/transform/transform_orientations.c7
-rw-r--r--source/blender/editors/transform/transform_snap.c35
-rw-r--r--source/blender/editors/util/ed_util.c2
-rw-r--r--source/blender/editors/util/editmode_undo.c2
-rw-r--r--source/blender/editors/util/undo.c12
-rw-r--r--source/blender/editors/uvedit/uvedit_buttons.c1
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c1
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h1
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c13
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c16
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c13
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c8
-rw-r--r--source/blender/freestyle/CMakeLists.txt2
-rw-r--r--source/blender/freestyle/intern/application/AppConfig.cpp4
-rw-r--r--source/blender/freestyle/intern/application/Controller.cpp37
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp502
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h19
-rw-r--r--source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp9
-rw-r--r--source/blender/freestyle/intern/python/BPy_Convert.cpp11
-rw-r--r--source/blender/freestyle/intern/python/BPy_Convert.h1
-rw-r--r--source/blender/freestyle/intern/python/BPy_Freestyle.cpp7
-rw-r--r--source/blender/freestyle/intern/python/BPy_Operators.cpp3
-rw-r--r--source/blender/freestyle/intern/python/BPy_SShape.cpp10
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewShape.cpp23
-rw-r--r--source/blender/freestyle/intern/python/Director.cpp6
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp18
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp16
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeCamera.h2
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp35
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h64
-rw-r--r--source/blender/freestyle/intern/scene_graph/SceneHash.cpp42
-rw-r--r--source/blender/freestyle/intern/scene_graph/SceneHash.h25
-rw-r--r--source/blender/freestyle/intern/scene_graph/SceneVisitor.h2
-rw-r--r--source/blender/freestyle/intern/stroke/Curve.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.cpp25
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.h1
-rw-r--r--source/blender/freestyle/intern/system/StringUtils.h3
-rw-r--r--source/blender/freestyle/intern/winged_edge/Curvature.cpp2
-rw-r--r--source/blender/gpu/CMakeLists.txt1
-rw-r--r--source/blender/gpu/GPU_buffers.h11
-rw-r--r--source/blender/gpu/GPU_extensions.h9
-rw-r--r--source/blender/gpu/GPU_material.h11
-rw-r--r--source/blender/gpu/SConscript1
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c181
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c32
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h2
-rw-r--r--source/blender/gpu/intern/gpu_draw.c43
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c218
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c1
-rw-r--r--source/blender/gpu/intern/gpu_material.c191
-rw-r--r--source/blender/gpu/intern/gpu_select.c4
-rw-r--r--source/blender/gpu/intern/gpu_simple_shader.c3
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl82
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex_world.glsl13
-rw-r--r--source/blender/ikplugin/intern/ikplugin_api.c7
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c2
-rw-r--r--source/blender/imbuf/intern/anim_movie.c5
-rw-r--r--source/blender/imbuf/intern/bmp.c1
-rw-r--r--source/blender/imbuf/intern/cache.c3
-rw-r--r--source/blender/imbuf/intern/cineon/cineonlib.c2
-rw-r--r--source/blender/imbuf/intern/cineon/dpxlib.c4
-rw-r--r--source/blender/imbuf/intern/colormanagement.c12
-rw-r--r--source/blender/imbuf/intern/dds/Stream.cpp15
-rw-r--r--source/blender/imbuf/intern/divers.c1
-rw-r--r--source/blender/imbuf/intern/filetype.c2
-rw-r--r--source/blender/imbuf/intern/indexer.c8
-rw-r--r--source/blender/imbuf/intern/iris.c1
-rw-r--r--source/blender/imbuf/intern/jp2.c3
-rw-r--r--source/blender/imbuf/intern/moviecache.c15
-rw-r--r--source/blender/imbuf/intern/png.c2
-rw-r--r--source/blender/imbuf/intern/radiance_hdr.c62
-rw-r--r--source/blender/imbuf/intern/rectop.c2
-rw-r--r--source/blender/imbuf/intern/rotate.c2
-rw-r--r--source/blender/imbuf/intern/scaling.c2
-rw-r--r--source/blender/imbuf/intern/targa.c1
-rw-r--r--source/blender/imbuf/intern/thumbs_blend.c2
-rw-r--r--source/blender/imbuf/intern/tiff.c2
-rw-r--r--source/blender/imbuf/intern/writeimage.c2
-rw-r--r--source/blender/makesdna/DNA_ID.h132
-rw-r--r--source/blender/makesdna/DNA_action_types.h10
-rw-r--r--source/blender/makesdna/DNA_brush_types.h8
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h24
-rw-r--r--source/blender/makesdna/DNA_curve_types.h203
-rw-r--r--source/blender/makesdna/DNA_dynamicpaint_types.h166
-rw-r--r--source/blender/makesdna/DNA_freestyle_types.h96
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h110
-rw-r--r--source/blender/makesdna/DNA_key_types.h6
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h2
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h46
-rw-r--r--source/blender/makesdna/DNA_scene_types.h40
-rw-r--r--source/blender/makesdna/DNA_screen_types.h45
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h10
-rw-r--r--source/blender/makesdna/DNA_sound_types.h9
-rw-r--r--source/blender/makesdna/DNA_space_types.h52
-rw-r--r--source/blender/makesdna/DNA_texture_types.h11
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h8
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h37
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h15
-rw-r--r--source/blender/makesdna/DNA_world_types.h1
-rw-r--r--source/blender/makesdna/intern/makesdna.c2
-rw-r--r--source/blender/makesrna/RNA_access.h2
-rw-r--r--source/blender/makesrna/RNA_enum_types.h8
-rw-r--r--source/blender/makesrna/RNA_types.h6
-rw-r--r--source/blender/makesrna/intern/makesrna.c15
-rw-r--r--source/blender/makesrna/intern/rna_ID.c35
-rw-r--r--source/blender/makesrna/intern/rna_access.c6
-rw-r--r--source/blender/makesrna/intern/rna_action.c6
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c4
-rw-r--r--source/blender/makesrna/intern/rna_brush.c98
-rw-r--r--source/blender/makesrna/intern/rna_color.c4
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c38
-rw-r--r--source/blender/makesrna/intern/rna_define.c2
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c282
-rw-r--r--source/blender/makesrna/intern/rna_image.c20
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_internal.h1
-rw-r--r--source/blender/makesrna/intern/rna_key.c7
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c2
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c660
-rw-r--r--source/blender/makesrna/intern/rna_movieclip.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c14
-rw-r--r--source/blender/makesrna/intern/rna_object.c37
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c56
-rw-r--r--source/blender/makesrna/intern/rna_pose.c2
-rw-r--r--source/blender/makesrna/intern/rna_render.c6
-rw-r--r--source/blender/makesrna/intern/rna_rigidbody.c3
-rw-r--r--source/blender/makesrna/intern/rna_scene.c25
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c25
-rw-r--r--source/blender/makesrna/intern/rna_screen.c4
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c38
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c5
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c1
-rw-r--r--source/blender/makesrna/intern/rna_sound.c5
-rw-r--r--source/blender/makesrna/intern/rna_space.c91
-rw-r--r--source/blender/makesrna/intern/rna_space_api.c31
-rw-r--r--source/blender/makesrna/intern/rna_texture.c5
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c2
-rw-r--r--source/blender/makesrna/intern/rna_ui.c1
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c4
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c63
-rw-r--r--source/blender/makesrna/intern/rna_world.c2
-rw-r--r--source/blender/modifiers/CMakeLists.txt1
-rw-r--r--source/blender/modifiers/MOD_modifiertypes.h1
-rw-r--r--source/blender/modifiers/intern/MOD_array.c6
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c4
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.c25
-rw-r--r--source/blender/modifiers/intern/MOD_build.c6
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c3
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c2
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c221
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c5
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c3
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c3
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim.c1
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c2
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c3
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c1
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c2
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache.c2
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_pc2.c1
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c15
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c2
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c3
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c2
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c2
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c7
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c1
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c2
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c7
-rw-r--r--source/blender/modifiers/intern/MOD_smoke.c3
-rw-r--r--source/blender/modifiers/intern/MOD_triangulate.c1
-rw-r--r--source/blender/modifiers/intern/MOD_util.c6
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weightvg_util.c5
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c1
-rw-r--r--source/blender/modifiers/intern/MOD_wireframe.c6
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c10
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_boxmask.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_colorbalance.c3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_common.c1
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_composite.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_defocus.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_keying.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_keyingscreen.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mask.c4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_movieclip.c3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_moviedistortion.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_outputFile.c3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_stabilize2d.c3
-rw-r--r--source/blender/nodes/intern/node_common.c4
-rw-r--r--source/blender/nodes/intern/node_socket.c1
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_background.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bump.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_gamma.c15
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_world.c13
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_script.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_coord.c16
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c21
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_texture.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vectMath.c3
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c3
-rw-r--r--source/blender/pointcache/util/util_path.cpp3
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops.c5
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops_call.c18
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c24
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.h21
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.c10
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.c17
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_select.c10
-rw-r--r--source/blender/python/bmesh/bmesh_py_utils.c12
-rw-r--r--source/blender/python/generic/blf_py_api.c8
-rw-r--r--source/blender/python/generic/bpy_internal_import.c2
-rw-r--r--source/blender/python/generic/idprop_py_api.c30
-rw-r--r--source/blender/python/generic/py_capi_utils.c18
-rw-r--r--source/blender/python/generic/py_capi_utils.h1
-rw-r--r--source/blender/python/generic/python_utildefines.h60
-rw-r--r--source/blender/python/intern/bpy.c29
-rw-r--r--source/blender/python/intern/bpy_app.c11
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c42
-rw-r--r--source/blender/python/intern/bpy_app_translations.c28
-rw-r--r--source/blender/python/intern/bpy_interface.c5
-rw-r--r--source/blender/python/intern/bpy_library.c15
-rw-r--r--source/blender/python/intern/bpy_operator.c6
-rw-r--r--source/blender/python/intern/bpy_props.c1
-rw-r--r--source/blender/python/intern/bpy_rna.c88
-rw-r--r--source/blender/python/intern/bpy_rna_anim.c7
-rw-r--r--source/blender/python/intern/bpy_utils_units.c2
-rw-r--r--source/blender/python/intern/gpu.c1
-rw-r--r--source/blender/python/mathutils/mathutils.c39
-rw-r--r--source/blender/python/mathutils/mathutils.h25
-rw-r--r--source/blender/python/mathutils/mathutils_Color.c95
-rw-r--r--source/blender/python/mathutils/mathutils_Color.h15
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.c88
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.h15
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c191
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.h21
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c108
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.h15
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c144
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.h22
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c818
-rw-r--r--source/blender/python/mathutils/mathutils_kdtree.c14
-rw-r--r--source/blender/python/mathutils/mathutils_noise.c14
-rw-r--r--source/blender/render/SConscript1
-rw-r--r--source/blender/render/extern/include/RE_engine.h1
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h2
-rw-r--r--source/blender/render/intern/include/rayintersection.h2
-rw-r--r--source/blender/render/intern/source/bake.c6
-rw-r--r--source/blender/render/intern/source/convertblender.c28
-rw-r--r--source/blender/render/intern/source/envmap.c4
-rw-r--r--source/blender/render/intern/source/external_engine.c16
-rw-r--r--source/blender/render/intern/source/imagetexture.c2
-rw-r--r--source/blender/render/intern/source/initrender.c10
-rw-r--r--source/blender/render/intern/source/occlusion.c2
-rw-r--r--source/blender/render/intern/source/pipeline.c20
-rw-r--r--source/blender/render/intern/source/pixelblending.c1
-rw-r--r--source/blender/render/intern/source/pixelshading.c5
-rw-r--r--source/blender/render/intern/source/pointdensity.c1
-rw-r--r--source/blender/render/intern/source/rayshade.c10
-rw-r--r--source/blender/render/intern/source/render_result.c10
-rw-r--r--source/blender/render/intern/source/render_texture.c5
-rw-r--r--source/blender/render/intern/source/rendercore.c10
-rw-r--r--source/blender/render/intern/source/renderdatabase.c3
-rw-r--r--source/blender/render/intern/source/shadbuf.c1
-rw-r--r--source/blender/render/intern/source/shadeinput.c2
-rw-r--r--source/blender/render/intern/source/shadeoutput.c2
-rw-r--r--source/blender/render/intern/source/sss.c5
-rw-r--r--source/blender/render/intern/source/strand.c3
-rw-r--r--source/blender/render/intern/source/sunsky.c3
-rw-r--r--source/blender/render/intern/source/texture_ocean.c2
-rw-r--r--source/blender/render/intern/source/voxeldata.c1
-rw-r--r--source/blender/render/intern/source/zbuf.c4
-rw-r--r--source/blender/windowmanager/CMakeLists.txt8
-rw-r--r--source/blender/windowmanager/SConscript5
-rw-r--r--source/blender/windowmanager/WM_api.h6
-rw-r--r--source/blender/windowmanager/WM_types.h27
-rw-r--r--source/blender/windowmanager/intern/wm.c3
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c4
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c108
-rw-r--r--source/blender/windowmanager/intern/wm_files.c27
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c1
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c17
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c27
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c1
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c507
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c2
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c1
-rw-r--r--source/blender/windowmanager/intern/wm_window.c18
-rw-r--r--source/blender/windowmanager/wm_event_types.h7
-rw-r--r--source/blender/windowmanager/wm_window.h5
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c15
-rw-r--r--source/creator/CMakeLists.txt63
-rw-r--r--source/creator/creator.c108
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp4
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp11
-rw-r--r--source/gameengine/Converter/BL_ArmatureChannel.cpp2
-rw-r--r--source/gameengine/Converter/BL_ModifierDeformer.cpp1
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp23
-rw-r--r--source/gameengine/Expressions/ListValue.cpp2
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.cpp6
-rw-r--r--source/gameengine/Expressions/Value.cpp2
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp14
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp6
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.cpp1
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp2
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp19
-rw-r--r--source/gameengine/Ketsji/KXNetwork/CMakeLists.txt1
-rw-r--r--source/gameengine/Ketsji/KXNetwork/SConscript1
-rw-r--r--source/gameengine/Ketsji/KX_Camera.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_Dome.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp99
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h15
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp44
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.h1
-rw-r--r--source/gameengine/Ketsji/KX_MouseActuator.cpp49
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_PyMath.cpp12
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp28
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h2
-rw-r--r--source/gameengine/Network/CMakeLists.txt1
-rw-r--r--source/gameengine/Network/SConscript1
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp43
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h7
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp4
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.h6
-rw-r--r--source/gameengine/VideoTexture/ImageRender.cpp2
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.cpp7
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.h3
-rw-r--r--tests/gtests/blenlib/BLI_path_util_test.cc1
-rw-r--r--tests/gtests/blenlib/BLI_polyfill2d_test.cc26
-rw-r--r--tests/gtests/testing/testing_main.cc2
1296 files changed, 36132 insertions, 14189 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c07af704adf..f232a005ce6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -178,6 +178,15 @@ if(UNIX AND NOT APPLE)
set(_init_GAMEENGINE OFF)
endif()
+
+#-----------------------------------------------------------------------------
+# Options
+
+# First platform spesific non-cached vars
+if(UNIX AND NOT APPLE)
+ set(WITH_X11 ON)
+endif()
+
# Blender internal features
option(WITH_BLENDER "Build blender (disable to build only the blender player)" ON)
mark_as_advanced(WITH_BLENDER)
@@ -233,10 +242,6 @@ mark_as_advanced(WITH_AUDASPACE)
option(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" ON)
-if(UNIX AND NOT APPLE)
- set(WITH_X11 ON)
-endif()
-
if(WITH_X11)
option(WITH_X11_XINPUT "Enable X11 Xinput (tablet support and unicode input)" ON)
option(WITH_X11_XF86VMODE "Enable X11 video mode switching" ON)
@@ -317,6 +322,9 @@ mark_as_advanced(WITH_LIBMV_SCHUR_SPECIALIZATIONS)
option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON)
# Misc
+if(WIN32)
+ option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON)
+endif()
option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ${_init_INPUT_NDOF})
option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON)
option(WITH_OPENNL "Enable use of Open Numerical Library" ON)
@@ -350,7 +358,7 @@ option(WITH_CYCLES_CUDA_BINARIES "Build cycles CUDA binaries" OFF)
set(CYCLES_CUDA_BINARIES_ARCH sm_20 sm_21 sm_30 sm_35 sm_50 CACHE STRING "CUDA architectures to build binaries for")
mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH)
unset(PLATFORM_DEFAULT)
-option(WITH_CYCLES_LOGGING "Build cycles with logging support" OFF)
+option(WITH_CYCLES_LOGGING "Build cycles with logging support" ON)
option(WITH_CYCLES_DEBUG "Build cycles with extra debug capabilities" OFF)
mark_as_advanced(WITH_CYCLES_LOGGING)
mark_as_advanced(WITH_CYCLES_DEBUG)
@@ -965,6 +973,12 @@ if(UNIX AND NOT APPLE)
if(WITH_OPENIMAGEIO)
find_package_wrapper(OpenImageIO)
+ if(NOT OPENIMAGEIO_PUGIXML_FOUND AND WITH_CYCLES_STANDALONE)
+ find_package_wrapper(PugiXML)
+ else()
+ set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR/OpenImageIO}")
+ set(PUGIXML_LIBRARIES "")
+ endif()
set(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARIES} ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${ZLIB_LIBRARIES} ${BOOST_LIBRARIES})
set(OPENIMAGEIO_LIBPATH) # TODO, remove and reference the absolute path everywhere
@@ -1078,16 +1092,14 @@ if(UNIX AND NOT APPLE)
# Note: --whole-archive is needed to force loading of all symbols in liboslexec,
# otherwise LLVM is missing the osl_allocate_closure_component function
list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -Wl,--whole-archive ${OSL_LIB_EXEC} -Wl,--no-whole-archive ${OSL_LIB_QUERY})
- find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
+ find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
- if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER)
+ if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER)
set(OSL_FOUND TRUE)
- message(STATUS "OSL includes = ${OSL_INCLUDES}")
- message(STATUS "OSL library = ${OSL_LIBRARIES}")
- message(STATUS "OSL compiler = ${OSL_COMPILER}")
else()
message(STATUS "OSL not found")
+ set(WITH_CYCLES_OSL OFF)
endif()
endif()
@@ -1105,6 +1117,8 @@ if(UNIX AND NOT APPLE)
find_package(Threads REQUIRED)
list(APPEND PLATFORM_LINKLIBS ${CMAKE_THREAD_LIBS_INIT})
+ # used by other platforms
+ set(PTHREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
if(CMAKE_DL_LIBS)
list(APPEND PLATFORM_LINKLIBS ${CMAKE_DL_LIBS})
@@ -1167,6 +1181,10 @@ elseif(WIN32)
list(APPEND PLATFORM_LINKLIBS ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid psapi)
+ if(WITH_INPUT_IME)
+ list(APPEND PLATFORM_LINKLIBS imm32)
+ endif()
+
add_definitions(
-D_CRT_NONSTDC_NO_DEPRECATE
-D_CRT_SECURE_NO_DEPRECATE
@@ -1522,6 +1540,11 @@ elseif(WIN32)
endif()
list(APPEND PLATFORM_LINKLIBS -lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32 -lz -lstdc++ -lole32 -luuid -lwsock32 -lpsapi)
+
+ if(WITH_INPUT_IME)
+ list(APPEND PLATFORM_LINKLIBS -limm32)
+ endif()
+
set(PLATFORM_CFLAGS "-pipe -funsigned-char -fno-strict-aliasing")
if(WITH_MINGW64)
@@ -1764,13 +1787,14 @@ elseif(WIN32)
find_library(OSL_LIB_COMP_DEBUG NAMES oslcomp_d PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_QUERY_DEBUG NAMES oslquery_d PATHS ${CYCLES_OSL}/lib)
list(APPEND OSL_LIBRARIES optimized ${OSL_LIB_COMP} optimized ${OSL_LIB_EXEC} optimized ${OSL_LIB_QUERY} debug ${OSL_LIB_EXEC_DEBUG} debug ${OSL_LIB_COMP_DEBUG} debug ${OSL_LIB_QUERY_DEBUG})
- find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
+ find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
- if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER)
+ if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER)
set(OSL_FOUND TRUE)
else()
message(STATUS "OSL not found")
+ set(WITH_CYCLES_OSL OFF)
endif()
endif()
@@ -1954,8 +1978,9 @@ elseif(APPLE)
if(WITH_SDL)
set(SDL ${LIBDIR}/sdl)
set(SDL_INCLUDE_DIR ${SDL}/include)
- set(SDL_LIBRARY SDL)
+ set(SDL_LIBRARY SDL2)
set(SDL_LIBPATH ${SDL}/lib)
+ set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -lazy_framework ForceFeedback")
endif()
set(PNG "${LIBDIR}/png")
@@ -2056,13 +2081,14 @@ elseif(APPLE)
find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib)
# WARNING! depends on correct order of OSL libs linking
list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -force_load ${OSL_LIB_EXEC} ${OSL_LIB_QUERY})
- find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
+ find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
- if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER)
+ if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER)
set(OSL_FOUND TRUE)
else()
message(STATUS "OSL not found")
+ set(WITH_CYCLES_OSL OFF)
endif()
endif()
@@ -2636,7 +2662,7 @@ mark_as_advanced(
OSL_COMPILER
OSL_LIB_COMP
OSL_LIB_QUERY
- OSL_INCLUDES
+ OSL_INCLUDE_DIR
)
mark_as_advanced(
diff --git a/GNUmakefile b/GNUmakefile
index 36c05965c55..775d0ae532b 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -113,7 +113,7 @@ endif
# -----------------------------------------------------------------------------
# Build Blender
-all:
+all: FORCE
@echo
@echo Configuring Blender ...
@@ -142,13 +142,13 @@ bpy: all
# -----------------------------------------------------------------------------
# Configuration (save some cd'ing around)
-config:
+config: FORCE
$(CMAKE_CONFIG_TOOL) "$(BUILD_DIR)"
# -----------------------------------------------------------------------------
# Help for build targets
-help:
+help: FORCE
@echo ""
@echo "Convenience targets provided for building blender, (multiple at once can be used)"
@echo " * debug - build a debug binary"
@@ -214,13 +214,13 @@ help:
# -----------------------------------------------------------------------------
# Packages
#
-package_debian:
+package_debian: FORCE
cd build_files/package_spec ; DEB_BUILD_OPTIONS="parallel=$(NPROCS)" sh ./build_debian.sh
-package_pacman:
+package_pacman: FORCE
cd build_files/package_spec/pacman ; MAKEFLAGS="-j$(NPROCS)" makepkg --asroot
-package_archive:
+package_archive: FORCE
make -C "$(BUILD_DIR)" -s package_archive
@echo archive in "$(BUILD_DIR)/release"
@@ -228,24 +228,24 @@ package_archive:
# -----------------------------------------------------------------------------
# Tests
#
-test:
+test: FORCE
cd $(BUILD_DIR) ; ctest . --output-on-failure
# run pep8 check check on scripts we distribute.
-test_pep8:
+test_pep8: FORCE
python3 tests/python/pep8.py > test_pep8.log 2>&1
@echo "written: test_pep8.log"
# run some checks on our cmakefiles.
-test_cmake:
+test_cmake: FORCE
python3 build_files/cmake/cmake_consistency_check.py > test_cmake_consistency.log 2>&1
@echo "written: test_cmake_consistency.log"
# run deprecation tests, see if we have anything to remove.
-test_deprecated:
+test_deprecated: FORCE
python3 tests/check_deprecated.py
-test_style_c:
+test_style_c: FORCE
# run our own checks on C/C++ style
PYTHONIOENCODING=utf_8 python3 \
"$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
@@ -253,7 +253,7 @@ test_style_c:
"$(BLENDER_DIR)/source/creator" \
--no-length-check
-test_style_c_qtc:
+test_style_c_qtc: FORCE
# run our own checks on C/C++ style
USE_QTC_TASK=1 \
PYTHONIOENCODING=utf_8 python3 \
@@ -266,7 +266,7 @@ test_style_c_qtc:
@echo "written: test_style.tasks"
-test_style_osl:
+test_style_osl: FORCE
# run our own checks on C/C++ style
PYTHONIOENCODING=utf_8 python3 \
"$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
@@ -274,7 +274,7 @@ test_style_osl:
"$(BLENDER_DIR)/release/scripts/templates_osl"
-test_style_osl_qtc:
+test_style_osl_qtc: FORCE
# run our own checks on C/C++ style
USE_QTC_TASK=1 \
PYTHONIOENCODING=utf_8 python3 \
@@ -289,13 +289,13 @@ test_style_osl_qtc:
# Project Files
#
-project_qtcreator:
+project_qtcreator: FORCE
python3 build_files/cmake/cmake_qtcreator_project.py "$(BUILD_DIR)"
-project_netbeans:
+project_netbeans: FORCE
python3 build_files/cmake/cmake_netbeans_project.py "$(BUILD_DIR)"
-project_eclipse:
+project_eclipse: FORCE
cmake -G"Eclipse CDT4 - Unix Makefiles" -H"$(BLENDER_DIR)" -B"$(BUILD_DIR)"
@@ -303,40 +303,40 @@ project_eclipse:
# Static Checking
#
-check_cppcheck:
+check_cppcheck: FORCE
$(CMAKE_CONFIG)
cd "$(BUILD_DIR)" ; \
python3 "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py" 2> \
"$(BLENDER_DIR)/check_cppcheck.txt"
@echo "written: check_cppcheck.txt"
-check_clang_array:
+check_clang_array: FORCE
$(CMAKE_CONFIG)
cd "$(BUILD_DIR)" ; \
python3 "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_clang_array.py"
-check_splint:
+check_splint: FORCE
$(CMAKE_CONFIG)
cd "$(BUILD_DIR)" ; \
python3 "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_splint.py"
-check_sparse:
+check_sparse: FORCE
$(CMAKE_CONFIG)
cd "$(BUILD_DIR)" ; \
python3 "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_sparse.py"
-check_smatch:
+check_smatch: FORCE
$(CMAKE_CONFIG)
cd "$(BUILD_DIR)" ; \
python3 "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py"
-check_spelling_py:
+check_spelling_py: FORCE
cd "$(BUILD_DIR)" ; \
PYTHONIOENCODING=utf_8 python3 \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
"$(BLENDER_DIR)/release/scripts"
-check_spelling_c:
+check_spelling_c: FORCE
cd "$(BUILD_DIR)" ; \
PYTHONIOENCODING=utf_8 python3 \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
@@ -345,7 +345,7 @@ check_spelling_c:
"$(BLENDER_DIR)/intern/guardedalloc" \
"$(BLENDER_DIR)/intern/ghost" \
-check_spelling_c_qtc:
+check_spelling_c_qtc: FORCE
cd "$(BUILD_DIR)" ; USE_QTC_TASK=1 \
PYTHONIOENCODING=utf_8 python3 \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
@@ -356,13 +356,13 @@ check_spelling_c_qtc:
> \
"$(BLENDER_DIR)/check_spelling_c.tasks"
-check_spelling_osl:
+check_spelling_osl: FORCE
cd "$(BUILD_DIR)" ;\
PYTHONIOENCODING=utf_8 python3 \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
"$(BLENDER_DIR)/intern/cycles/kernel/shaders"
-check_descriptions:
+check_descriptions: FORCE
"$(BUILD_DIR)/bin/blender" --background -noaudio --factory-startup --python \
"$(BLENDER_DIR)/source/tools/check_source/check_descriptions.py"
@@ -370,14 +370,14 @@ check_descriptions:
# Utilities
#
-tgz:
+tgz: FORCE
./build_files/utils/build_tgz.sh
-icons:
+icons: FORCE
"$(BLENDER_DIR)/release/datafiles/blender_icons_update.py"
"$(BLENDER_DIR)/release/datafiles/prvicons_update.py"
-update:
+update: FORCE
if [ -d "../lib" ]; then \
svn update ../lib/* ; \
fi
@@ -390,23 +390,23 @@ update:
#
# Simple version of ./doc/python_api/sphinx_doc_gen.sh with no PDF generation.
-doc_py:
+doc_py: FORCE
"$(BUILD_DIR)/bin/blender" --background -noaudio --factory-startup --python doc/python_api/sphinx_doc_gen.py
cd doc/python_api ; sphinx-build -b html sphinx-in sphinx-out
@echo "docs written into: '$(BLENDER_DIR)/doc/python_api/sphinx-out/contents.html'"
-doc_doxy:
+doc_doxy: FORCE
cd doc/doxygen; doxygen Doxyfile
@echo "docs written into: '$(BLENDER_DIR)/doc/doxygen/html/index.html'"
-doc_dna:
+doc_dna: FORCE
"$(BUILD_DIR)/bin/blender" --background -noaudio --factory-startup --python doc/blender_file_format/BlendFileDnaExporter_25.py
@echo "docs written into: '$(BLENDER_DIR)/doc/blender_file_format/dna.html'"
-doc_man:
+doc_man: FORCE
python3 doc/manpage/blender.1.py "$(BUILD_DIR)/bin/blender"
-help_features:
+help_features: FORCE
@python3 -c \
"import re; \
print('\n'.join([ \
@@ -417,7 +417,9 @@ help_features:
if w.startswith('WITH_')]))" | uniq
-clean:
+clean: FORCE
$(MAKE) -C "$(BUILD_DIR)" clean
.PHONY: all
+
+FORCE:
diff --git a/SConstruct b/SConstruct
index dc60400eb21..4dacf89fcb0 100644
--- a/SConstruct
+++ b/SConstruct
@@ -266,6 +266,7 @@ if 'blenderlite' in B.targets:
target_env_defs['WITH_BF_BOOLEAN'] = False
target_env_defs['WITH_BF_REMESH'] = False
target_env_defs['WITH_BF_PYTHON'] = False
+ target_env_defs['WITH_BF_IME'] = False
target_env_defs['WITH_BF_3DMOUSE'] = False
target_env_defs['WITH_BF_LIBMV'] = False
target_env_defs['WITH_BF_FREESTYLE'] = False
@@ -422,6 +423,9 @@ if env['OURPLATFORM']=='darwin':
env.Append(LINKFLAGS=['-F/Library/Frameworks','-Xlinker','-weak_framework','-Xlinker','Jackmp'])
print B.bc.OKGREEN + "Using Jack"
+ if env['WITH_BF_SDL']:
+ env.Append(LINKFLAGS=['-lazy_framework','ForceFeedback'])
+
if env['WITH_BF_QUICKTIME'] == 1:
env['PLATFORM_LINKFLAGS'] = env['PLATFORM_LINKFLAGS']+['-framework','QTKit']
@@ -754,6 +758,7 @@ if B.targets != ['cudakernels']:
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex_world.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl")
data_to_c_simple("intern/opencolorio/gpu_shader_display_transform.glsl")
@@ -857,9 +862,11 @@ if B.targets != ['cudakernels']:
from FindUnorderedMap import FindUnorderedMap
conf = Configure(env)
+ old_linkflags = conf.env['LINKFLAGS']
conf.env.Append(LINKFLAGS=env['PLATFORM_LINKFLAGS'])
FindSharedPtr(conf)
FindUnorderedMap(conf)
+ conf.env['LINKFLAGS'] = old_linkflags
env = conf.Finish()
# End of auto configuration
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index c3c13187e4c..ca9832b6abb 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -518,8 +518,12 @@ LLVM_SOURCE=( "http://llvm.org/releases/$LLVM_VERSION/llvm-$LLVM_VERSION.src.tar
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/imageworks/OpenShadingLanguage.git" )
-OSL_SOURCE=( "https://github.com/mont29/OpenShadingLanguage.git" )
-OSL_REPO_UID="85179714e1bc69cd25ecb6bb711c1a156685d395"
+#OSL_SOURCE=( "https://github.com/mont29/OpenShadingLanguage.git" )
+#OSL_REPO_UID="85179714e1bc69cd25ecb6bb711c1a156685d395"
+#OSL_REPO_BRANCH="master"
+OSL_SOURCE=( "https://github.com/Nazg-Gul/OpenShadingLanguage.git" )
+OSL_REPO_UID="22ee5ea298fd215430dfbd160b5aefd507f06db0"
+OSL_REPO_BRANCH="blender-fixes"
OPENCOLLADA_SOURCE=( "https://github.com/KhronosGroup/OpenCOLLADA.git" )
OPENCOLLADA_REPO_UID="18da7f4109a8eafaa290a33f5550501cc4c8bae8"
@@ -1429,12 +1433,13 @@ clean_OSL() {
compile_OSL() {
# To be changed each time we make edits that would modify the compiled result!
- osl_magic=15
+ osl_magic=16
_init_osl
# Clean install if needed!
magic_compile_check osl-$OSL_VERSION $osl_magic
if [ $? -eq 1 -o $OSL_FORCE_REBUILD == true ]; then
+ rm -Rf $_src # XXX Radical, but not easy to change remote repo fully automatically
clean_OSL
fi
@@ -1458,10 +1463,10 @@ compile_OSL() {
cd $_src
- git remote set-url origin $OSL_SOURCE
+ git remote set-url origin ${OSL_SOURCE[0]}
# XXX For now, always update from latest repo...
- git pull -X theirs origin master
+ git pull --no-edit -X theirs origin $OSL_GIT_BRANCH
# Stick to same rev as windows' libs...
git checkout $OSL_REPO_UID
diff --git a/build_files/buildbot/config/user-config-cuda-glibc211-i686.py b/build_files/buildbot/config/user-config-cuda-glibc211-i686.py
index 854f535398b..ae5cbac8cc7 100644
--- a/build_files/buildbot/config/user-config-cuda-glibc211-i686.py
+++ b/build_files/buildbot/config/user-config-cuda-glibc211-i686.py
@@ -2,4 +2,4 @@ BF_BUILDDIR = '../blender-build/linux-glibc211-i686'
BF_INSTALLDIR = '../blender-install/linux-glibc211-i686'
BF_NUMJOBS = 1
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
diff --git a/build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py b/build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py
index 7e928948762..29b1b9f1ad7 100644
--- a/build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py
+++ b/build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py
@@ -2,4 +2,4 @@ BF_BUILDDIR = '../blender-build/linux-glibc211-x86_64'
BF_INSTALLDIR = '../blender-install/linux-glibc211-x86_64'
BF_NUMJOBS = 1
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
diff --git a/build_files/buildbot/config/user-config-glibc211-i686.py b/build_files/buildbot/config/user-config-glibc211-i686.py
index 0971735f641..59a11072f2b 100644
--- a/build_files/buildbot/config/user-config-glibc211-i686.py
+++ b/build_files/buildbot/config/user-config-glibc211-i686.py
@@ -79,6 +79,8 @@ WITH_BF_STATICZLIB = True
BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
WITH_BF_SDL = True
+WITH_BF_SDL_DYNLOAD = True
+
WITH_BF_OGG = True
WITH_BF_OPENMP = True
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 748d1004850..a0ae6122944 100644
--- a/build_files/buildbot/config/user-config-glibc211-x86_64.py
+++ b/build_files/buildbot/config/user-config-glibc211-x86_64.py
@@ -79,6 +79,8 @@ WITH_BF_STATICZLIB = True
BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
WITH_BF_SDL = True
+WITH_BF_SDL_DYNLOAD = True
+
WITH_BF_OGG = True
WITH_BF_OPENMP = True
diff --git a/build_files/buildbot/config/user-config-player-glibc211-i686.py b/build_files/buildbot/config/user-config-player-glibc211-i686.py
index 384da4070eb..b3c26ebb310 100644
--- a/build_files/buildbot/config/user-config-player-glibc211-i686.py
+++ b/build_files/buildbot/config/user-config-player-glibc211-i686.py
@@ -64,6 +64,8 @@ WITH_BF_STATICZLIB = True
BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
WITH_BF_SDL = True
+WITH_BF_SDL_DYNLOAD = True
+
WITH_BF_OGG = False
WITH_BF_OPENMP = True
diff --git a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py
index 5176d59d5a0..173e15b08ca 100644
--- a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py
+++ b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py
@@ -64,6 +64,8 @@ WITH_BF_STATICZLIB = True
BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
WITH_BF_SDL = True
+WITH_BF_SDL_DYNLOAD = True
+
WITH_BF_OGG = False
WITH_BF_OPENMP = True
diff --git a/build_files/cmake/Modules/FindOpenColorIO.cmake b/build_files/cmake/Modules/FindOpenColorIO.cmake
index ac486a13a6d..bd1ecac0a39 100644
--- a/build_files/cmake/Modules/FindOpenColorIO.cmake
+++ b/build_files/cmake/Modules/FindOpenColorIO.cmake
@@ -83,6 +83,9 @@ ENDIF(OPENCOLORIO_FOUND)
MARK_AS_ADVANCED(
OPENCOLORIO_INCLUDE_DIR
OPENCOLORIO_LIBRARY
+ OPENCOLORIO_OPENCOLORIO_LIBRARY
+ OPENCOLORIO_TINYXML_LIBRARY
+ OPENCOLORIO_YAML-CPP_LIBRARY
)
UNSET(COMPONENT)
diff --git a/build_files/cmake/Modules/FindOpenImageIO.cmake b/build_files/cmake/Modules/FindOpenImageIO.cmake
index 39049981385..f8d66124ae6 100644
--- a/build_files/cmake/Modules/FindOpenImageIO.cmake
+++ b/build_files/cmake/Modules/FindOpenImageIO.cmake
@@ -7,6 +7,7 @@
# OPENIMAGEIO_ROOT_DIR, The base directory to search for OpenImageIO.
# This can also be an environment variable.
# OPENIMAGEIO_FOUND, If false, do not try to use OpenImageIO.
+# OPENIMAGEIO_PUGIXML_FOUND, Indicates whether OIIO has biltin PuguXML parser.
#
# also defined, but not for general use are
# OPENIMAGEIO_LIBRARY, where to find the OpenImageIO library.
@@ -63,7 +64,12 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenImageIO DEFAULT_MSG
IF(OPENIMAGEIO_FOUND)
SET(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARY})
SET(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO_INCLUDE_DIR})
-ENDIF(OPENIMAGEIO_FOUND)
+ IF(EXISTS ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO/pugixml.hpp)
+ SET(OPENIMAGEIO_PUGIXML_FOUND TRUE)
+ ENDIF()
+ELSE()
+ SET(OPENIMAGEIO_PUGIXML_FOUND FALSE)
+ENDIF()
MARK_AS_ADVANCED(
OPENIMAGEIO_INCLUDE_DIR
diff --git a/build_files/cmake/Modules/FindPugiXML.cmake b/build_files/cmake/Modules/FindPugiXML.cmake
new file mode 100644
index 00000000000..b1ed45fd257
--- /dev/null
+++ b/build_files/cmake/Modules/FindPugiXML.cmake
@@ -0,0 +1,73 @@
+# - Find PugiXML library
+# Find the native PugiXML includes and library
+# This module defines
+# PUGIXML_INCLUDE_DIRS, where to find pugixml.h, Set when
+# PugiXML is found.
+# PUGIXML_LIBRARIES, libraries to link against to use PugiiXML.
+# PUGIXML_ROOT_DIR, The base directory to search for PugiXML.
+# This can also be an environment variable.
+# PUGIXML_FOUND, If false, do not try to use PugiXML.
+#
+# also defined, but not for general use are
+# PUGIXML_LIBRARY, where to find the PugiXML library.
+
+#=============================================================================
+# Copyright 2014 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+# If PUGIXML_ROOT_DIR was defined in the environment, use it.
+IF(NOT PUGIXML_ROOT_DIR AND NOT $ENV{PUGIXML_ROOT_DIR} STREQUAL "")
+ SET(PUGIXML_ROOT_DIR $ENV{PUGIXML_ROOT_DIR})
+ENDIF()
+
+SET(_pugixml_SEARCH_DIRS
+ ${PUGIXML_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt/lib/oiio
+)
+
+FIND_PATH(PUGIXML_INCLUDE_DIR
+ NAMES
+ pugixml.h
+ HINTS
+ ${_pugixml_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include
+)
+
+FIND_LIBRARY(PUGIXML_LIBRARY
+ NAMES
+ pugixml
+ HINTS
+ ${_pugixml_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+ )
+
+# handle the QUIETLY and REQUIRED arguments and set PUGIXML_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(PUGIXML DEFAULT_MSG
+ PUGIXML_LIBRARY PUGIXML_INCLUDE_DIR)
+
+IF(PUGIXML_FOUND)
+ SET(PUGIXML_LIBRARIES ${PUGIXML_LIBRARY})
+ SET(PUGIXML_INCLUDE_DIRS ${PUGIXML_INCLUDE_DIR})
+ELSE()
+ SET(PUGIXML_PUGIXML_FOUND FALSE)
+ENDIF()
+
+MARK_AS_ADVANCED(
+ PUGIXML_INCLUDE_DIR
+ PUGIXML_LIBRARY
+)
diff --git a/build_files/cmake/Modules/GTestTesting.cmake b/build_files/cmake/Modules/GTestTesting.cmake
index fd0379b8f78..6a9cae22f33 100644
--- a/build_files/cmake/Modules/GTestTesting.cmake
+++ b/build_files/cmake/Modules/GTestTesting.cmake
@@ -32,6 +32,8 @@ macro(BLENDER_SRC_GTEST NAME SRC EXTRA_LIBS)
bf_testing_main
bf_intern_guardedalloc
extern_gtest
+ # needed for glog
+ ${PTHREADS_LIBRARIES}
extern_glog)
set_target_properties(${NAME}_test PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${TESTS_OUTPUT_DIR}"
diff --git a/build_files/cmake/cmake_qtcreator_project.py b/build_files/cmake/cmake_qtcreator_project.py
index 59b8c7e5c4c..1676d634cf2 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 .~/blender-git/blender/build_files/cmake/cmake_qtcreator_project.py ~/blender-git/cmake
+ python ~/blender-git/blender/build_files/cmake/cmake_qtcreator_project.py ~/blender-git/cmake
"""
from project_info import (SIMPLE_PROJECTFILE,
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index bf5c4f9e103..3a702014bae 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -44,6 +44,7 @@ set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE)
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE)
+set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
set(WITH_OPENNL OFF CACHE BOOL "" FORCE)
set(WITH_PYTHON_INSTALL OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index ee3c872f693..a97f6328948 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -118,6 +118,19 @@ macro(target_link_libraries_debug TARGET LIBS)
unset(_LIB)
endmacro()
+macro(target_link_libraries_decoupled target libraries_var)
+ if(NOT MSVC)
+ target_link_libraries(${target} ${${libraries_var}})
+ else()
+ # For MSVC we link to different libraries depending whether
+ # release or debug target is being built.
+ file_list_suffix(_libraries_debug "${${libraries_var}}" "_d")
+ target_link_libraries_debug(${target} "${_libraries_debug}")
+ target_link_libraries_optimized(${target} "${${libraries_var}}")
+ unset(_libraries_debug)
+ endif()
+endmacro()
+
# Nicer makefiles with -I/1/foo/ instead of -I/1/2/3/../../foo/
# use it instead of include_directories()
macro(blender_include_dirs
@@ -284,7 +297,6 @@ macro(setup_liblinks
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}")
target_link_libraries(${target}
- ${BLENDER_GL_LIBRARIES}
${PNG_LIBRARIES}
${ZLIB_LIBRARIES}
${FREETYPE_LIBRARY})
@@ -357,14 +369,6 @@ macro(setup_liblinks
target_link_libraries(${target} ${OPENJPEG_LIBRARIES})
endif()
if(WITH_CODEC_FFMPEG)
-
- # Strange! Without this ffmpeg gives linking errors (on linux),
- # even though it's linked above.
- # XXX: Does FFMPEG depend on GLU?
- if(WITH_GLU)
- target_link_libraries(${target} ${OPENGL_glu_LIBRARY})
- endif()
-
target_link_libraries(${target} ${FFMPEG_LIBRARIES})
endif()
if(WITH_OPENCOLLADA)
@@ -418,13 +422,17 @@ macro(setup_liblinks
target_link_libraries(${target} ${PTHREADS_LIBRARIES})
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()
+
+ #system libraries with no dependencies such as platform link libs or opengl should go last
+ target_link_libraries(${target}
+ ${BLENDER_GL_LIBRARIES})
+
+ target_link_libraries(${target} ${PLATFORM_LINKLIBS} ${CMAKE_DL_LIBS})
endmacro()
macro(SETUP_BLENDER_SORTED_LIBS)
diff --git a/build_files/package_spec/pacman/PKGBUILD b/build_files/package_spec/pacman/PKGBUILD
index e59d1cf31d7..cc5198a88e3 100644
--- a/build_files/package_spec/pacman/PKGBUILD
+++ b/build_files/package_spec/pacman/PKGBUILD
@@ -17,7 +17,7 @@ else
blender_version_full=${blender_version}
fi
-blender_ver_string=$blender_version+svn$blender_version_full
+blender_ver_string=$blender_version+git$blender_version_full
pkgname=blender-snapshot
pkgver=$blender_ver_string
@@ -27,8 +27,8 @@ arch=('i686' 'x86_64')
url="www.blender.org"
license=('GPL')
groups=()
-depends=('libjpeg' 'libpng' 'openjpeg' 'libtiff' 'openexr' 'python>=3.2' 'gettext' 'libxi' 'libxmu' 'mesa' 'freetype2' 'openal' 'sdl' 'libsndfile' 'ffmpeg')
-makedepends=('cmake' 'svn')
+depends=('libjpeg' 'libpng' 'openjpeg' 'libtiff' 'openexr' 'python>=3.4' 'gettext' 'libxi' 'libxmu' 'mesa' 'freetype2' 'openal' 'sdl' 'libsndfile' 'ffmpeg')
+makedepends=('cmake' 'git')
optdepends=()
provides=()
conflicts=('blender')
@@ -36,7 +36,7 @@ replaces=('blender')
backup=()
options=()
install=blender.install
-# use current svn to make the package.
+# use current git to make the package.
# source=(http://download.blender.org/source/$pkgname-$pkgver.tar.gz)
# md5sums=('27edb80c82c25252d43d6a01980d953a') #generate with 'makepkg -g'
source=()
@@ -51,11 +51,7 @@ build() {
-DCMAKE_BUILD_TYPE:STRING=Release \
-DWITH_INSTALL_PORTABLE:BOOL=OFF \
-DWITH_PYTHON_INSTALL:BOOL=OFF \
- -DWITH_OPENCOLLADA:BOOL=OFF \
- -DPYTHON_VERSION:STRING=3.2 \
- -DPYTHON_LIBPATH:STRING=/usr/lib \
- -DPYTHON_LIBRARY:STRING=python3.2mu \
- -DPYTHON_INCLUDE_DIRS:STRING=/usr/include/python3.2mu
+ -DWITH_OPENCOLLADA:BOOL=OFF
make $MAKEFLAGS
}
diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py
index 338065e5e88..1fb6d649ae9 100644
--- a/build_files/scons/config/darwin-config.py
+++ b/build_files/scons/config/darwin-config.py
@@ -68,7 +68,7 @@ BF_SNDFILE_LIBPATH = '${BF_SNDFILE}/lib ${BF_FFMPEG}/lib' #ogg libs are stored i
WITH_BF_SDL = True
BF_SDL = LIBDIR + '/sdl' #$(shell sdl-config --prefix)
BF_SDL_INC = '${BF_SDL}/include' #$(shell $(BF_SDL)/bin/sdl-config --cflags)
-BF_SDL_LIB = 'SDL' #BF_SDL #$(shell $(BF_SDL)/bin/sdl-config --libs) -lSDL_mixer
+BF_SDL_LIB = 'SDL2' #BF_SDL #$(shell $(BF_SDL)/bin/sdl-config --libs) -lSDL_mixer
BF_SDL_LIBPATH = '${BF_SDL}/lib'
WITH_BF_OPENEXR = True
@@ -205,7 +205,7 @@ BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
WITH_BF_CYCLES_CUDA_BINARIES = False
BF_CYCLES_CUDA_NVCC = '/usr/local/cuda/bin/nvcc'
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
#Freestyle
WITH_BF_FREESTYLE = True
diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py
index 85aa72af19c..0fb84bfa4a5 100644
--- a/build_files/scons/config/win32-mingw-config.py
+++ b/build_files/scons/config/win32-mingw-config.py
@@ -170,6 +170,8 @@ BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse']
+WITH_BF_IME = True
+
WITH_BF_OPENMP = True
#CUDA
@@ -198,6 +200,9 @@ CC_WARN = [ '-Wall' ]
LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid', '-lwsock32', '-lpsapi']
+if WITH_BF_IME:
+ LLIBS.append('-limm32')
+
PLATFORM_LINKFLAGS = ['-Xlinker', '--stack=2097152']
## DISABLED, causes linking errors!
diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py
index 48a40cf6719..d447a1ec08e 100644
--- a/build_files/scons/config/win32-vc-config.py
+++ b/build_files/scons/config/win32-vc-config.py
@@ -151,6 +151,8 @@ BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include/opencollada'
BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml pcre buffer ftoa'
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib/opencollada'
+WITH_BF_IME = True
+
WITH_BF_3DMOUSE = True
WITH_BF_OPENMP = True
@@ -197,7 +199,7 @@ BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
#CUDA
WITH_BF_CYCLES_CUDA_BINARIES = False
#BF_CYCLES_CUDA_NVCC = "" # Path to the nvidia compiler
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
@@ -237,6 +239,9 @@ CXX_WARN = []
LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi']
+if WITH_BF_IME:
+ LLIBS.append('imm32')
+
PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:IX86','/STACK:2097152','/INCREMENTAL:NO', '/LARGEADDRESSAWARE', '/NODEFAULTLIB:msvcrt.lib', '/NODEFAULTLIB:msvcmrt.lib', '/NODEFAULTLIB:msvcurt.lib', '/NODEFAULTLIB:msvcrtd.lib']
# # Todo
diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py
index 92dcd6db455..60a9c9f84cd 100644
--- a/build_files/scons/config/win64-mingw-config.py
+++ b/build_files/scons/config/win64-mingw-config.py
@@ -169,6 +169,8 @@ BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-mmmx', '-msse', '-msse2']
+WITH_BF_IME = True
+
WITH_BF_OPENMP = True
#Freestyle
@@ -192,6 +194,9 @@ CC_WARN = [ '-Wall' ]
LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid', '-lwsock32', '-lpsapi', '-lpthread']
+if WITH_BF_IME:
+ LLIBS.append('-limm32')
+
PLATFORM_LINKFLAGS = ['-Xlinker', '--stack=2097152']
## DISABLED, causes linking errors!
diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py
index 285e9ac9867..b8e4f3d70fe 100644
--- a/build_files/scons/config/win64-vc-config.py
+++ b/build_files/scons/config/win64-vc-config.py
@@ -154,6 +154,8 @@ BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include/opencollada'
BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml pcre buffer ftoa'
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib/opencollada'
+WITH_BF_IME = True
+
WITH_BF_3DMOUSE = True
WITH_BF_OPENMP = True
@@ -200,7 +202,7 @@ BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
#CUDA
WITH_BF_CYCLES_CUDA_BINARIES = False
#BF_CYCLES_CUDA_NVCC = "" # Path to the nvidia compiler
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
@@ -244,6 +246,9 @@ CXX_WARN = []
LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi']
+if WITH_BF_IME:
+ LLIBS.append('imm32')
+
PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:X64','/STACK:2097152','/OPT:NOREF','/INCREMENTAL:NO', '/NODEFAULTLIB:msvcrt.lib', '/NODEFAULTLIB:msvcmrt.lib', '/NODEFAULTLIB:msvcurt.lib', '/NODEFAULTLIB:msvcrtd.lib']
BF_CYCLES_CUDA_ENV="C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd"
diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py
index d9e80a1fcd5..1ab363532c6 100755..100644
--- a/build_files/scons/tools/Blender.py
+++ b/build_files/scons/tools/Blender.py
@@ -405,6 +405,10 @@ def creator(env):
incs.append('#/extern/libmv')
defs.append('WITH_LIBMV')
+ if env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_LOGGING']:
+ incs.append('#/intern/cycles/blender')
+ defs.append('WITH_CYCLES_LOGGING')
+
if env['WITH_BF_FFMPEG']:
defs.append('WITH_FFMPEG')
@@ -665,7 +669,7 @@ def WinPyBundle(target=None, source=None, env=None):
# Extract Numpy
if env['WITH_BF_PYTHON_INSTALL_NUMPY']:
py_tar = env.subst(env['LCGDIR']).lstrip("#")
- py_tar += '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '_numpy_1.8.tar.gz'
+ py_tar += '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '_numpy_1.9.tar.gz'
py_target = env.subst(env['BF_INSTALLDIR']).lstrip("#")
py_target = os.path.join(py_target, VERSION, 'python', 'lib', 'site-packages')
diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py
index 085cc052a07..20a20503c09 100644
--- a/build_files/scons/tools/btools.py
+++ b/build_files/scons/tools/btools.py
@@ -174,6 +174,7 @@ def validate_arguments(args, bc):
'WITH_BF_CXX_GUARDEDALLOC',
'WITH_BF_JEMALLOC', 'WITH_BF_STATICJEMALLOC', 'BF_JEMALLOC', 'BF_JEMALLOC_INC', 'BF_JEMALLOC_LIBPATH', 'BF_JEMALLOC_LIB', 'BF_JEMALLOC_LIB_STATIC',
'BUILDBOT_BRANCH',
+ 'WITH_BF_IME',
'WITH_BF_3DMOUSE', 'WITH_BF_STATIC3DMOUSE', 'BF_3DMOUSE', 'BF_3DMOUSE_INC', 'BF_3DMOUSE_LIB', 'BF_3DMOUSE_LIBPATH', 'BF_3DMOUSE_LIB_STATIC',
'WITH_BF_CYCLES', 'WITH_BF_CYCLES_CUDA_BINARIES', 'BF_CYCLES_CUDA_NVCC', 'BF_CYCLES_CUDA_NVCC', 'WITH_BF_CYCLES_CUDA_THREADED_COMPILE', 'BF_CYCLES_CUDA_ENV',
'WITH_BF_OIIO', 'WITH_BF_STATICOIIO', 'BF_OIIO', 'BF_OIIO_INC', 'BF_OIIO_LIB', 'BF_OIIO_LIB_STATIC', 'BF_OIIO_LIBPATH',
@@ -197,7 +198,7 @@ def validate_arguments(args, bc):
'C_WARN', 'CC_WARN', 'CXX_WARN',
'LLIBS', 'PLATFORM_LINKFLAGS', 'MACOSX_ARCHITECTURE', 'MACOSX_SDK', 'XCODE_CUR_VER', 'C_COMPILER_ID',
'BF_CYCLES_CUDA_BINARIES_ARCH', 'BF_PROGRAM_LINKFLAGS', 'MACOSX_DEPLOYMENT_TARGET',
- 'WITH_BF_CYCLES_DEBUG'
+ 'WITH_BF_CYCLES_DEBUG', 'WITH_BF_CYCLES_LOGGING'
]
@@ -507,6 +508,8 @@ def read_opts(env, cfg, args):
(BoolVariable('WITH_BF_PLAYER', 'Build blenderplayer if true', False)),
(BoolVariable('WITH_BF_NOBLENDER', 'Do not build blender if true', False)),
+ (BoolVariable('WITH_BF_IME', 'Enable Input Method Editor (IME) for complex Asian character input', False)),
+
(BoolVariable('WITH_BF_3DMOUSE', 'Build blender with support of 3D mouses', False)),
(BoolVariable('WITH_BF_STATIC3DMOUSE', 'Staticly link to 3d mouse library', False)),
('BF_3DMOUSE', '3d mouse library base path', ''),
@@ -616,6 +619,7 @@ def read_opts(env, cfg, args):
('BF_CYCLES_CUDA_ENV', 'preset environement nvcc will execute in', ''),
('BF_CYCLES_CUDA_BINARIES_ARCH', 'CUDA architectures to compile binaries for', []),
(BoolVariable('WITH_BF_CYCLES_DEBUG', 'Build Cycles engine with extra debugging capabilities', False)),
+ (BoolVariable('WITH_BF_CYCLES_LOGGING', 'Build Cycles engine with logging support', True)),
(BoolVariable('WITH_BF_OIIO', 'Build with OpenImageIO', False)),
(BoolVariable('WITH_BF_STATICOIIO', 'Statically link to OpenImageIO', False)),
diff --git a/build_files/utils/build_tgz.sh b/build_files/utils/build_tgz.sh
index 16899fd34b2..3c921081c29 100755
--- a/build_files/utils/build_tgz.sh
+++ b/build_files/utils/build_tgz.sh
@@ -25,7 +25,16 @@ TARBALL="blender-$VERSION.tar.gz"
cd "$blender_srcdir"
# not so nice, but works
-FILTER_FILES_PY="import os, sys; [print(l[:-1]) for l in sys.stdin.readlines() if os.path.isfile(l[:-1])]"
+FILTER_FILES_PY=\
+"import os, sys; "\
+"[print(l[:-1]) for l in sys.stdin.readlines() "\
+"if os.path.isfile(l[:-1]) "\
+"if os.path.basename(l[:-1]) not in {"\
+"'.gitignore', "\
+"'.gitmodules', "\
+"'.arcconfig', "\
+"}"\
+"]"
# Build master list
echo -n "Building manifest of files: \"$BASE_DIR/$MANIFEST\" ..."
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 a6d03dee1a1..09f48fb17d5 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
@@ -78,6 +78,27 @@ base class --- :class:`SCA_IObject`
The object must have a physics controller for the mass to be applied, otherwise the mass value will be returned as 0.0.
+ .. attribute:: linearDamping
+
+ The object's linear damping, also known as translational damping. Can be set simultaneously with angular damping using the :py:meth:`setDamping` method.
+
+ :type: float between 0 and 1 inclusive.
+
+ .. note::
+
+ The object must have a physics controller for the linear damping to be applied, otherwise the value will be returned as 0.0.
+
+ .. attribute:: angularDamping
+
+ The object's angular damping, also known as rotationation damping. Can be set simultaneously with linear damping using the :py:meth:`setDamping` method.
+
+ :type: float between 0 and 1 inclusive.
+
+ .. note::
+
+ The object must have a physics controller for the angular damping to be applied, otherwise the value will be returned as 0.0.
+
+
.. attribute:: linVelocityMin
Enforces the object keeps moving at a minimum velocity.
@@ -580,6 +601,15 @@ base class --- :class:`SCA_IObject`
* True: you get the "local" impulse ie: relative to local coordinates with object orientation.
:type local: boolean
+ .. method:: setDamping(linear_damping, angular_damping)
+
+ Sets both the :py:attr:`linearDamping` and :py:attr:`angularDamping` simultaneously. This is more efficient than setting both properties individually.
+
+ :arg linear_damping: Linear ("translational") damping factor.
+ :type linear_damping: float ∈ [0, 1]
+ :arg angular_damping: Angular ("rotational") damping factor.
+ :type angular_damping: float ∈ [0, 1]
+
.. method:: suspendDynamics()
Suspends physics for this object.
diff --git a/doc/python_api/rst/info_quickstart.rst b/doc/python_api/rst/info_quickstart.rst
index a1052bf4208..dc1bba01f00 100644
--- a/doc/python_api/rst/info_quickstart.rst
+++ b/doc/python_api/rst/info_quickstart.rst
@@ -11,32 +11,22 @@ This API is generally stable but some areas are still being added and improved.
The Blender/Python API can do the following:
-* Edit any data the user interface can (Scenes, Meshes, Particles etc.)
-
-* Modify user preferences, keymaps and themes
-
-* Run tools with own settings
-
-* Create user interface elements such as menus, headers and panels
-
-* Create new tools
-
-* Create interactive tools
-
-* Create new rendering engines that integrate with Blender
-
-* Define new settings in existing Blender data
-
-* Draw in the 3D view using OpenGL commands from Python
+- Edit any data the user interface can (Scenes, Meshes, Particles etc.)
+- Modify user preferences, keymaps and themes
+- Run tools with own settings
+- Create user interface elements such as menus, headers and panels
+- Create new tools
+- Create interactive tools
+- Create new rendering engines that integrate with Blender
+- Define new settings in existing Blender data
+- Draw in the 3D view using OpenGL commands from Python
The Blender/Python API **can't** (yet)...
-* Create new space types.
-
-* Assign custom properties to every type.
-
-* Define callbacks or listeners to be notified when data is changed.
+- Create new space types.
+- Assign custom properties to every type.
+- Define callbacks or listeners to be notified when data is changed.
Before Starting
@@ -47,23 +37,21 @@ This document isn't intended to fully cover each topic. Rather, its purpose is t
A quick list of helpful things to know before starting:
-* Blender uses Python 3.x; some 3rd party extensions are not available yet.
-
-* The interactive console is great for testing one-liners, It also has autocompletion so you can inspect the api quickly.
-
-* Button tool tips show Python attributes and operator names.
-
-* Right clicking on buttons and menu items directly links to API documentation.
-
-* For more examples, the text menu has a templates section where some example operators can be found.
+- Blender uses Python 3.x; some online documentation still assumes 2.x.
+- The interactive console is great for testing one-liners, It also has autocompletion so you can inspect the API quickly.
+- Button tool tips show Python attributes and operator names.
+- Right clicking on buttons and menu items directly links to API documentation.
+- For more examples, the text menu has a templates section where some example operators can be found.
+- To examine further scripts distributed with Blender, see:
-* To examine further scripts distributed with Blender, see ``~/.blender/scripts/startup/bl_ui`` for the user interface and ``~/.blender/scripts/startup/bl_op`` for operators.
+ | ``~/.blender/scripts/startup/bl_ui`` for the user interface,
+ | ``~/.blender/scripts/startup/bl_op`` for operators.
Running Scripts
---------------
-The two most common ways to execute python scripts are using the built-in text editor or entering commands in the python console.
+The two most common ways to execute Python scripts are using the built-in text editor or entering commands in the Python console.
Both the **Text Editor** and **Python Console** are space types you can select from the view header.
@@ -82,7 +70,7 @@ Key Concepts
Data Access
-----------
-Accessing datablocks
+Accessing DataBlocks
^^^^^^^^^^^^^^^^^^^^
Python accesses Blender's data in the same way as the animation system and user interface; this implies that any setting that can be changed via a button can also be changed from Python.
@@ -116,7 +104,7 @@ Unlike Python's dictionaries, both methods are acceptable; however, the index of
bpy.data.objects["Cube"]
-Accessing attributes
+Accessing Attributes
^^^^^^^^^^^^^^^^^^^^
Once you have a data block, such as a material, object, groups etc., its attributes can be accessed much like you would change a setting using the graphical interface. In fact, the tooltip for each button also displays the Python attribute which can help in finding what settings to change in a script.
@@ -144,7 +132,7 @@ Example of a data path that can be quickly found via the console:
Data Creation/Removal
^^^^^^^^^^^^^^^^^^^^^
-Those of you familiar with other python api's may be surprised that new datablocks in the bpy api can't be created by calling the class:
+Those of you familiar with other Python API's may be surprised that new datablocks in the bpy API can't be created by calling the class:
>>> bpy.types.Mesh()
Traceback (most recent call last):
@@ -153,9 +141,9 @@ Those of you familiar with other python api's may be surprised that new databloc
This is an intentional part of the API design.
-The blender/python api can't create blender data that exists outside the main blender database (accessed through bpy.data), because this data is managed by blender (save/load/undo/append... etc).
+The Blender/Python API can't create Blender data that exists outside the main Blender database (accessed through :mod:`bpy.data`), because this data is managed by Blender (save/load/undo/append... etc).
-Data is added and removed via methods on the collections in bpy.data, eg:
+Data is added and removed via methods on the collections in :mod:`bpy.data`, eg:
>>> mesh = bpy.data.meshes.new(name="MyMesh")
>>> print(mesh)
@@ -167,7 +155,8 @@ Data is added and removed via methods on the collections in bpy.data, eg:
Custom Properties
^^^^^^^^^^^^^^^^^
-Python can access properties on any datablock that has an ID (data that can be linked in and accessed from :mod:`bpy.data`. When assigning a property, you can make up your own names, these will be created when needed or overwritten if they exist.
+Python can access properties on any datablock that has an ID (data that can be linked in and accessed from :mod:`bpy.data`.
+When assigning a property, you can make up your own names, these will be created when needed or overwritten if they exist.
This data is saved with the blend file and copied with objects.
@@ -180,7 +169,7 @@ Example:
if "SomeProp" in bpy.context.object:
print("Property found")
- # Use the get function like a python dictionary
+ # Use the get function like a Python dictionary
# which can have a fallback value.
value = bpy.data.scenes["Scene"].get("test_prop", "fallback value")
@@ -193,11 +182,9 @@ Example:
Note that these properties can only be assigned basic Python types.
-* int, float, string
-
-* array of ints/floats
-
-* dictionary (only string keys are supported, values must be basic types too)
+- int, float, string
+- array of ints/floats
+- dictionary (only string keys are supported, values must be basic types too)
These properties are valid outside of Python. They can be animated by curves or used in driver paths.
@@ -205,7 +192,8 @@ These properties are valid outside of Python. They can be animated by curves or
Context
-------
-While it's useful to be able to access data directly by name or as a list, it's more common to operate on the user's selection. The context is always available from '''bpy.context''' and can be used to get the active object, scene, tool settings along with many other attributes.
+While it's useful to be able to access data directly by name or as a list, it's more common to operate on the user's selection.
+The context is always available from ``bpy.context`` and can be used to get the active object, scene, tool settings along with many other attributes.
Common-use cases:
@@ -220,9 +208,10 @@ So ``bpy.context.object = obj`` will raise an error.
But ``bpy.context.scene.objects.active = obj`` will work as expected.
-The context attributes change depending on where they are accessed. The 3D view has different context members than the console, so take care when accessing context attributes that the user state is known.
+The context attributes change depending on where they are accessed.
+The 3D view has different context members than the console, so take care when accessing context attributes that the user state is known.
-See :mod:`bpy.context` API reference
+See :mod:`bpy.context` API reference.
Operators (Tools)
@@ -241,16 +230,17 @@ Examples:
.. note::
- The menu item: Help -> Operator Cheat Sheet" gives a list of all operators and their default values in Python syntax, along with the generated docs. This is a good way to get an overview of all blender's operators.
+ The menu item: :menuselection:`Help --> Operator Cheat Sheet` gives a list of all operators and their default values in Python syntax, along with the generated docs.
+ This is a good way to get an overview of all Blender's operators.
Operator Poll()
^^^^^^^^^^^^^^^
Many operators have a "poll" function which may check that the mouse is in a valid area or that the object is in the correct mode (Edit Mode, Weight Paint etc).
-When an operator's poll function fails within python, an exception is raised.
+When an operator's poll function fails within Python, an exception is raised.
-For example, calling bpy.ops.view3d.render_border() from the console raises the following error:
+For example, calling ``bpy.ops.view3d.render_border()`` from the console raises the following error:
.. code-block:: python
@@ -271,13 +261,10 @@ Integration
Python scripts can integrate with Blender in the following ways:
-* By defining a rendering engine.
-
-* By defining operators.
-
-* By defining menus, headers and panels.
-
-* By inserting new buttons into existing menus, headers and panels
+- By defining a rendering engine.
+- By defining operators.
+- By defining menus, headers and panels.
+- By inserting new buttons into existing menus, headers and panels
In Python, this is done by defining a class, which is a subclass of an existing type.
@@ -292,24 +279,17 @@ Once this script runs, ``SimpleOperator`` is registered with Blender and can be
To run the script:
-#. Highlight the above code then press Ctrl+C to copy it.
-
+#. Highlight the above code then press :kbd:`Ctrl-C` to copy it.
#. Start Blender
-
-#. Press Ctrl+Right twice to change to the Scripting layout.
-
+#. Press :kbd:`Ctrl-Right` twice to change to the Scripting layout.
#. Click the button labeled ``New`` and the confirmation pop up in order to create a new text block.
-
-#. Press Ctrl+V to paste the code into the text panel (the upper left frame).
-
+#. Press :kbd:`Ctrl-V` to paste the code into the text panel (the upper left frame).
#. Click on the button **Run Script**.
-
#. Move your mouse into the 3D view, press spacebar for the operator search menu, and type "Simple".
-
#. Click on the "Simple Operator" item found in search.
-.. seealso:: The class members with the **bl_** prefix are documented in the API
+.. seealso:: The class members with the ``bl_`` prefix are documented in the API
reference :class:`bpy.types.Operator`
.. note:: The output from the ``main`` function is sent to the terminal; in order to see this, be sure to :ref:`use the terminal <use_the_terminal>`.
@@ -317,33 +297,25 @@ To run the script:
Example Panel
-------------
-Panels register themselves as a class, like an operator. Notice the extra **bl_** variables used to set the context they display in.
+Panels register themselves as a class, like an operator. Notice the extra ``bl_`` variables used to set the context they display in.
.. literalinclude:: ../../../release/scripts/templates_py/ui_panel_simple.py
To run the script:
-#. Highlight the above code then press Ctrl+C to copy it
-
+#. Highlight the above code then press :kbd:`Ctrl-C` to copy it
#. Start Blender
-
-#. Press Ctrl+Right twice to change to the Scripting layout
-
+#. Press :kbd:`Ctrl-Right` twice to change to the Scripting layout
#. Click the button labeled ``New`` and the confirmation pop up in order to create a new text block.
-
-#. Press Ctrl+V to paste the code into the text panel (the upper left frame)
-
+#. Press :kbd:`Ctrl-V` to paste the code into the text panel (the upper left frame)
#. Click on the button **Run Script**.
To view the results:
#. Select the the default cube.
-
#. Click on the Object properties icon in the buttons panel (far right; appears as a tiny cube).
-
#. Scroll down to see a panel named **Hello World Panel**.
-
#. Changing the object name also updates **Hello World Panel's** Name: field.
Note the row distribution and the label and properties that are available through the code.
@@ -362,16 +334,14 @@ Blender's Python API can be split up into 3 categories.
Native Types
------------
-In simple cases returning a number or a string as a custom type would be cumbersome, so these are accessed as normal python types.
+In simple cases returning a number or a string as a custom type would be cumbersome, so these are accessed as normal Python types.
-* blender float/int/boolean -> float/int/boolean
-
-* blender enumerator -> string
+- Blender float/int/boolean -> float/int/boolean
+- Blender enumerator -> string
>>> C.object.rotation_mode = 'AXIS_ANGLE'
-
-* blender enumerator (multiple) -> set of strings
+- Blender enumerator (multiple) -> set of strings
.. code-block:: python
@@ -389,7 +359,7 @@ Used for Blender datablocks and collections: :class:`bpy.types.bpy_struct`
For data that contains its own attributes groups/meshes/bones/scenes... etc.
-There are 2 main types that wrap Blenders data, one for datablocks (known internally as bpy_struct), another for properties.
+There are 2 main types that wrap Blenders data, one for datablocks (known internally as ``bpy_struct``), another for properties.
>>> bpy.context.object
bpy.data.objects['Cube']
diff --git a/doc/python_api/rst/info_tutorial_addon.rst b/doc/python_api/rst/info_tutorial_addon.rst
index 436f74bc441..659b80df632 100644
--- a/doc/python_api/rst/info_tutorial_addon.rst
+++ b/doc/python_api/rst/info_tutorial_addon.rst
@@ -19,21 +19,17 @@ Prerequisites
Before going through the tutorial you should...
-* Familiarity with the basics of working in Blender.
-
-* Know how to run a script in Blender's text editor (as documented in the quick-start)
-
-* Have an understanding of Python primitive types (int, boolean, string, list, tuple, dictionary, and set).
-
-* Be familiar with the concept of Python modules.
-
-* Basic understanding of classes (object orientation) in Python.
+- Familiarity with the basics of working in Blender.
+- Know how to run a script in Blender's text editor (as documented in the quick-start)
+- Have an understanding of Python primitive types (int, boolean, string, list, tuple, dictionary, and set).
+- Be familiar with the concept of Python modules.
+- Basic understanding of classes (object orientation) in Python.
Suggested reading before starting this tutorial.
-* `Dive Into Python <http://getpython3.com/diveintopython3/index.html>`_ sections (1, 2, 3, 4, and 7).
-* :ref:`Blender API Quickstart <info_quickstart>`
+- `Dive Into Python <http://getpython3.com/diveintopython3/index.html>`_ sections (1, 2, 3, 4, and 7).
+- :ref:`Blender API Quickstart <info_quickstart>`
to help become familiar with Blender/Python basics.
@@ -45,13 +41,11 @@ Documentation Links
While going through the tutorial you may want to look into our reference documentation.
-* :ref:`Blender API Overview <info_overview>`. -
+- :ref:`Blender API Overview <info_overview>`. -
*This document is rather detailed but helpful if you want to know more on a topic.*
-
-* :mod:`bpy.context` api reference. -
+- :mod:`bpy.context` api reference. -
*Handy to have a list of available items your script may operate on.*
-
-* :class:`bpy.types.Operator`. -
+- :class:`bpy.types.Operator`. -
*The following addons define operators, these docs give details and more examples of operators.*
@@ -78,11 +72,11 @@ To give an example, here is the simplest possible addon.
print("Goodbye World")
-* ``bl_info`` is a dictionary containing addon meta-data such as the title, version and author to be displayed in the
+- ``bl_info`` is a dictionary containing addon meta-data such as the title, version and author to be displayed in the
user preferences addon list.
-* ``register`` is a function which only runs when enabling the addon, this means the module can be loaded without
+- ``register`` is a function which only runs when enabling the addon, this means the module can be loaded without
activating the addon.
-* ``unregister`` is a function to unload anything setup by ``register``, this is called when the addon is disabled.
+- ``unregister`` is a function to unload anything setup by ``register``, this is called when the addon is disabled.
@@ -184,12 +178,15 @@ This addon takes the body of the script above, and adds them to an operator's ``
register()
-.. note:: ``bl_info`` is split across multiple lines, this is just a style convention used to more easily add items.
+.. note::
-.. note:: Rather than using ``bpy.context.scene``, we use the ``context.scene`` argument passed to ``execute()``.
- In most cases these will be the same however in some cases operators will be passed a custom context
- so script authors should prefer the ``context`` argument passed to operators.
-
+ ``bl_info`` is split across multiple lines, this is just a style convention used to more easily add items.
+
+.. note::
+
+ Rather than using ``bpy.context.scene``, we use the ``context.scene`` argument passed to ``execute()``.
+ In most cases these will be the same however in some cases operators will be passed a custom context
+ so script authors should prefer the ``context`` argument passed to operators.
To test the script you can copy and paste this into Blender text editor and run it, this will execute the script
directly and call register immediately.
@@ -202,8 +199,8 @@ However running the script wont move any objects, for this you need to execute t
:height: 574px
:alt: Spacebar
-Do this by pressing ``SpaceBar`` to bring up the operator search dialog and type in "Move X by One" (the ``bl_label``),
-then press ``Enter``.
+Do this by pressing :kbd:`Spacebar` to bring up the operator search dialog and type in
+"Move X by One" (the ``bl_label``), then :kbd:`Enter`.
@@ -214,8 +211,8 @@ The objects should move as before.
Install The Addon
-----------------
-Once you have your addon within in Blender's text editor, you will want to be able to install it so it can be enabled in
-the user preferences to load on startup.
+Once you have your addon within in Blender's text editor,
+you will want to be able to install it so it can be enabled in the user preferences to load on startup.
Even though the addon above is a test, lets go through the steps anyway so you know how to do it for later.
@@ -633,15 +630,12 @@ you want to see example code for, this is a good place to start.
Here are some sites you might like to check on after completing this tutorial.
-* :ref:`Blender/Python API Overview <info_overview>` -
+- :ref:`Blender/Python API Overview <info_overview>` -
*For more background details on Blender/Python integration.*
-
-* `How to Think Like a Computer Scientist <http://interactivepython.org/courselib/static/thinkcspy/index.html>`_ -
+- `How to Think Like a Computer Scientist <http://interactivepython.org/courselib/static/thinkcspy/index.html>`_ -
*Great info for those who are still learning Python.*
-
-* `Blender Development (Wiki) <http://wiki.blender.org/index.php/Dev:Contents>`_ -
+- `Blender Development (Wiki) <http://wiki.blender.org/index.php/Dev:Contents>`_ -
*Blender Development, general information and helpful links.*
-
-* `Blender Artists (Coding Section) <http://blenderartists.org/forum/forumdisplay.php?47-Coding>`_ -
+- `Blender Artists (Coding Section) <http://blenderartists.org/forum/forumdisplay.php?47-Coding>`_ -
*forum where people ask Python development questions*
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index 0b9a4e6a37b..7ffb4483593 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -971,10 +971,12 @@ def pymodule2sphinx(basepath, module_name, module, title):
context_type_map = {
"active_base": ("ObjectBase", False),
"active_bone": ("EditBone", False),
+ "active_gpencil_frame": ("GreasePencilLayer", True),
+ "active_gpencil_layer": ("GPencilLayer", True),
+ "active_node": ("Node", False),
"active_object": ("Object", False),
"active_operator": ("Operator", False),
"active_pose_bone": ("PoseBone", False),
- "active_node": ("Node", False),
"armature": ("Armature", False),
"bone": ("Bone", False),
"brush": ("Brush", False),
@@ -990,7 +992,11 @@ context_type_map = {
"edit_object": ("Object", False),
"edit_text": ("Text", False),
"editable_bones": ("EditBone", True),
+ "editable_gpencil_layers": ("GPencilLayer", True),
+ "editable_gpencil_strokes": ("GPencilStroke", True),
"fluid": ("FluidSimulationModifier", False),
+ "gpencil_data": ("GreasePencel", False),
+ "gpencil_data_owner": ("ID", False),
"image_paint_object": ("Object", False),
"lamp": ("Lamp", False),
"lattice": ("Lattice", False),
@@ -1030,6 +1036,7 @@ context_type_map = {
"vertex_paint_object": ("Object", False),
"visible_bases": ("ObjectBase", True),
"visible_bones": ("EditBone", True),
+ "visible_gpencil_layers": ("GPencilLayer", True),
"visible_objects": ("Object", True),
"visible_pose_bones": ("PoseBone", True),
"weight_paint_object": ("Object", False),
diff --git a/doc/python_api/sphinx_doc_gen.sh b/doc/python_api/sphinx_doc_gen.sh
index 3e01293588a..01de3e2c2ea 100755
--- a/doc/python_api/sphinx_doc_gen.sh
+++ b/doc/python_api/sphinx_doc_gen.sh
@@ -3,6 +3,10 @@
# bash doc/python_api/sphinx_doc_gen.sh
# ssh upload means you need an account on the server
+if [ "$1" == "" ] ; then
+ echo "Expected a single argument for the username on blender.org, aborting"
+ exit 1
+fi
# ----------------------------------------------------------------------------
# Upload vars
@@ -16,7 +20,7 @@ DO_OUT_PDF=false
BLENDER="./blender.bin"
-SSH_USER="ideasman42"
+SSH_USER=$1
SSH_HOST=$SSH_USER"@blender.org"
SSH_UPLOAD="/data/www/vhosts/www.blender.org/api" # blender_python_api_VERSION, added after
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
index aff9f27f594..aff9f27f594 100755..100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
index 57ebb47d8e7..57ebb47d8e7 100755..100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt
index 10d99a2a316..80e64046534 100644
--- a/extern/libmv/CMakeLists.txt
+++ b/extern/libmv/CMakeLists.txt
@@ -37,13 +37,42 @@ set(SRC
libmv-capi.h
)
-if(WITH_LIBMV)
+if(WITH_LIBMV OR WITH_GTESTS OR (WITH_CYCLES AND WITH_CYCLES_LOGGING))
+ list(APPEND INC
+ third_party/gflags
+ third_party/gflags/gflags
+ third_party/glog/src
+ third_party/ceres/include
+ third_party/ceres/config
+ ../../intern/guardedalloc
+ )
+
+ list(APPEND INC_SYS
+ ../Eigen3
+ ${PNG_INCLUDE_DIRS}
+ ${ZLIB_INCLUDE_DIRS}
+ )
+
+ if(WIN32)
+ list(APPEND INC
+ third_party/glog/src/windows
+ )
+
+ if(NOT MINGW)
+ list(APPEND INC
+ third_party/msinttypes
+ )
+ endif()
+ endif()
+
add_definitions(
-DWITH_LIBMV_GUARDED_ALLOC
-DGOOGLE_GLOG_DLL_DECL=
-DLIBMV_NO_FAST_DETECTOR=
)
+endif()
+if(WITH_LIBMV)
TEST_SHARED_PTR_SUPPORT()
if(SHARED_PTR_FOUND)
if(SHARED_PTR_TR1_MEMORY_HEADER)
@@ -56,20 +85,6 @@ if(WITH_LIBMV)
message(FATAL_ERROR "Unable to find shared_ptr.")
endif()
- list(APPEND INC
- third_party/gflags
- third_party/glog/src
- third_party/ceres/include
- third_party/ceres/config
- ../../intern/guardedalloc
- )
-
- list(APPEND INC_SYS
- ../Eigen3
- ${PNG_INCLUDE_DIRS}
- ${ZLIB_INCLUDE_DIRS}
- )
-
list(APPEND SRC
intern/autotrack.cc
intern/camera_intrinsics.cc
@@ -202,17 +217,6 @@ if(WITH_LIBMV)
third_party/msinttypes/stdint.h
)
- if(WIN32)
- list(APPEND INC
- third_party/glog/src/windows
- )
-
- if(NOT MINGW)
- list(APPEND INC
- third_party/msinttypes
- )
- endif()
- endif()
if(WITH_GTESTS)
blender_add_lib(libmv_test_dataset "./libmv/multiview/test_data_sets.cc" "" "")
@@ -262,7 +266,7 @@ if(WITH_LIBMV)
endif()
# make GLog a separate target, so it can be used for gtest as well.
-if(WITH_LIBMV OR WITH_GTESTS OR WITH_CYCLES_LOGGING)
+if(WITH_LIBMV OR WITH_GTESTS OR (WITH_CYCLES AND WITH_CYCLES_LOGGING))
# We compile GLog together with GFlag so we don't worry about
# adding extra lib to linker.
set(GLOG_SRC
@@ -303,6 +307,9 @@ if(WITH_LIBMV OR WITH_GTESTS OR WITH_CYCLES_LOGGING)
third_party/glog/src/windows/glog/log_severity.h
third_party/glog/src/windows/port.h
third_party/glog/src/windows/config.h
+
+ third_party/gflags/windows_port.cc
+ third_party/gflags/windows_port.h
)
else()
list(APPEND GLOG_SRC
@@ -338,13 +345,5 @@ if(WITH_LIBMV OR WITH_GTESTS OR WITH_CYCLES_LOGGING)
)
endif()
- set(GLOG_INC
- third_party/gflags
- third_party/glog/src
- )
-
- set(GLOG_INC_SYS
- )
-
- blender_add_lib(extern_glog "${GLOG_SRC}" "${GLOG_INC}" "${GLOG_INC_SYS}")
+ blender_add_lib(extern_glog "${GLOG_SRC}" "${INC}" "${INC_SYS}")
endif()
diff --git a/extern/libmv/ChangeLog b/extern/libmv/ChangeLog
index 5c2129b6b1a..0bb340b2491 100644
--- a/extern/libmv/ChangeLog
+++ b/extern/libmv/ChangeLog
@@ -1,3 +1,42 @@
+commit 7d6020d2ec42c6cb2749bc891186b4880d26d40b
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed Dec 31 15:32:07 2014 +0500
+
+ Update GLog to latest upstream revision 143
+
+ Mainly to solve compilation error with demangle.cc.
+
+commit 5dc746700eaf85cb674f0fb73ff3c1b49a7f6315
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Fri Dec 12 14:59:55 2014 +0500
+
+ Update GFlags to latest release 2.1.1
+
+ Main purpose of this (andsome of upcoming) update is to check if the
+ upstream sources are useable without any modifications for us. And if
+ not, then we'll need to consider moving some changes into upstream.
+
+ This commit contains an one-to-one copy of the upstream GFlags library
+ and also changes namespace usage since it's changed in the upstream.
+
+commit 6fe6d75f7e90e161b44643b953f058a3829a5247
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Sat Nov 1 02:53:36 2014 +0500
+
+ Libmv: Code cleanup, mixed class/struct in declaration/definition
+
+commit d2a5f7953812d2d09765431b59c6c4ac72faf35b
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Thu Oct 30 23:13:53 2014 +0500
+
+ Libmv: Support disabled color channels in tracking settings
+
+ This was never ported to a new tracking pipeline and now it's done using
+ FrameAccessor::Transform routines. Quite striaghtforward, but i've changed
+ order of grayscale conversion in blender side with call of transform callback.
+
+ This way it's much easier to perform rescaling in libmv side.
+
commit d976e034cdf74b34860e0632d7b29713f47c5756
Author: Keir Mierle <mierle@gmail.com>
Date: Sat Aug 23 00:38:01 2014 -0700
@@ -666,37 +705,3 @@ Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Tue Feb 18 19:38:22 2014 +0600
Remove .orig file which was added by accident
-
-commit 62597e3cf0f266a2fefec415c89759e502793e06
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Thu Jan 2 16:02:08 2014 +0600
-
- Upgrade glog to latest svn r139
-
- The intention of this upgrade is to get rid of custom patches
- we've been having to support compilation on different platforms
- and compilers.
-
-commit 2452d5d42b390c7ab853e6fe60e58bdd7a01a004
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Tue Feb 18 18:46:08 2014 +0600
-
- Tweak Ceres CMake to detect uninstall target properly on Windows
-
-commit 98a281d58ce2301f3dd239a97a448e53f48d0258
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 14 00:36:44 2014 +0600
-
- Fix order of third party libs compilation and options used by them
-
- WITH_FAST_DETECTOR was defined too late and third_party folder
- didn't see this option.
-
-commit 4962bccd643ec0f2aed3035170d5f20e8f6efc85
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Thu Feb 13 23:55:03 2014 +0600
-
- Disable Ceres unit tests and examples by default
-
- Actually we're to switch to external Ceres rather than
- bundled one, would make life much easier actually.
diff --git a/extern/libmv/SConscript b/extern/libmv/SConscript
index 96282f3c3c2..251e5835d64 100644
--- a/extern/libmv/SConscript
+++ b/extern/libmv/SConscript
@@ -12,6 +12,22 @@ Import('env')
defs = []
incs = '.'
+if env['WITH_BF_LIBMV'] or (env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_LOGGING']):
+ defs.append('GOOGLE_GLOG_DLL_DECL=')
+ defs.append('WITH_LIBMV_GUARDED_ALLOC')
+ defs.append('LIBMV_NO_FAST_DETECTOR')
+
+ incs += ' ../Eigen3 third_party/gflags third_party/gflags/gflags third_party/glog/src third_party/ceres/include third_party/ceres/config ../../intern/guardedalloc'
+ incs += ' ' + env['BF_PNG_INC']
+ incs += ' ' + env['BF_ZLIB_INC']
+
+ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ incs += ' ./third_party/glog/src/windows ./third_party/glog/src/windows/glog'
+ if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
+ incs += ' ./third_party/msinttypes'
+ else:
+ incs += ' ./third_party/glog/src'
+
if env['WITH_BF_LIBMV']:
if not env['WITH_SHARED_PTR_SUPPORT']:
print("-- Unable to find shared_ptr which is required for compilation.")
@@ -22,10 +38,6 @@ if env['WITH_BF_LIBMV']:
if env['SHARED_PTR_NAMESPACE'] == 'std::tr1':
defs.append('CERES_TR1_SHARED_PTR')
- defs.append('GOOGLE_GLOG_DLL_DECL=')
- defs.append('WITH_LIBMV_GUARDED_ALLOC')
- defs.append('LIBMV_NO_FAST_DETECTOR')
-
src = env.Glob('intern/*.cc')
src.remove('intern' + os.sep + 'stub.cc')
src += env.Glob('libmv/autotrack/*.cc')
@@ -35,28 +47,24 @@ if env['WITH_BF_LIBMV']:
src += env.Glob('libmv/numeric/*.cc')
src += env.Glob('libmv/simple_pipeline/*.cc')
src += env.Glob('libmv/tracking/*.cc')
- src += env.Glob('third_party/gflags/*.cc')
-
- incs += ' ../Eigen3 third_party/gflags third_party/glog/src third_party/ceres/include third_party/ceres/config ../../intern/guardedalloc'
- incs += ' ' + env['BF_PNG_INC']
- incs += ' ' + env['BF_ZLIB_INC']
-
- if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
- incs += ' ./third_party/glog/src/windows ./third_party/glog/src/windows/glog'
- if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
- incs += ' ./third_party/msinttypes'
-
- src += ['./third_party/glog/src/logging.cc', './third_party/glog/src/raw_logging.cc', './third_party/glog/src/utilities.cc', './third_party/glog/src/vlog_is_on.cc']
- src += ['./third_party/glog/src/windows/port.cc']
- else:
- src += env.Glob("third_party/glog/src/*.cc")
- incs += ' ./third_party/glog/src'
else:
src = env.Glob("intern/stub.cc")
src = [src for src in src if src.find('_test.cc') == -1]
-env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137] )
+env.BlenderLib(libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137])
+
+if env['WITH_BF_LIBMV'] or (env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_LOGGING']):
+ glog_src = []
+ glog_src += env.Glob("third_party/gflags/*.cc")
+ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ glog_src += ['./third_party/glog/src/logging.cc', './third_party/glog/src/raw_logging.cc', './third_party/glog/src/utilities.cc', './third_party/glog/src/vlog_is_on.cc']
+ glog_src += ['./third_party/glog/src/windows/port.cc']
+ else:
+ glog_src.remove('third_party/gflags/windows_port.cc')
+ glog_src += env.Glob("third_party/glog/src/*.cc")
+
+ env.BlenderLib(libname = 'extern_glog', sources=glog_src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137])
if env['WITH_BF_LIBMV']:
SConscript(['third_party/SConscript'])
diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh
index 45b0e27f126..c10a5fbbad2 100755
--- a/extern/libmv/bundle.sh
+++ b/extern/libmv/bundle.sh
@@ -75,7 +75,7 @@ for x in $src_dir $src_third_dir; do
fi
fi
- if test `echo $x | grep -c windows ` -eq 0; then
+ if test `echo $x | grep -c "windows\|gflags" ` -eq 0; then
if [ -z "$src" ]; then
src=$t
else
@@ -130,13 +130,42 @@ set(SRC
libmv-capi.h
)
-if(WITH_LIBMV)
+if(WITH_LIBMV OR WITH_GTESTS OR (WITH_CYCLES AND WITH_CYCLES_LOGGING))
+ list(APPEND INC
+ third_party/gflags
+ third_party/gflags/gflags
+ third_party/glog/src
+ third_party/ceres/include
+ third_party/ceres/config
+ ../../intern/guardedalloc
+ )
+
+ list(APPEND INC_SYS
+ ../Eigen3
+ \${PNG_INCLUDE_DIRS}
+ \${ZLIB_INCLUDE_DIRS}
+ )
+
+ if(WIN32)
+ list(APPEND INC
+ third_party/glog/src/windows
+ )
+
+ if(NOT MINGW)
+ list(APPEND INC
+ third_party/msinttypes
+ )
+ endif()
+ endif()
+
add_definitions(
-DWITH_LIBMV_GUARDED_ALLOC
-DGOOGLE_GLOG_DLL_DECL=
-DLIBMV_NO_FAST_DETECTOR=
)
+endif()
+if(WITH_LIBMV)
TEST_SHARED_PTR_SUPPORT()
if(SHARED_PTR_FOUND)
if(SHARED_PTR_TR1_MEMORY_HEADER)
@@ -149,20 +178,6 @@ if(WITH_LIBMV)
message(FATAL_ERROR "Unable to find shared_ptr.")
endif()
- list(APPEND INC
- third_party/gflags
- third_party/glog/src
- third_party/ceres/include
- third_party/ceres/config
- ../../intern/guardedalloc
- )
-
- list(APPEND INC_SYS
- ../Eigen3
- \${PNG_INCLUDE_DIRS}
- \${ZLIB_INCLUDE_DIRS}
- )
-
list(APPEND SRC
intern/autotrack.cc
intern/camera_intrinsics.cc
@@ -194,17 +209,6 @@ ${headers}
${third_headers}
)
- if(WIN32)
- list(APPEND INC
- third_party/glog/src/windows
- )
-
- if(NOT MINGW)
- list(APPEND INC
- third_party/msinttypes
- )
- endif()
- endif()
if(WITH_GTESTS)
blender_add_lib(libmv_test_dataset "./libmv/multiview/test_data_sets.cc" "${INC}" "${INC_SYS}")
@@ -213,7 +217,7 @@ ${tests}
endif()
else()
list(APPEND SRC
- libmv-capi_stub.cc
+ intern/stub.cc
)
endif()
@@ -224,7 +228,7 @@ if(WITH_LIBMV)
endif()
# make GLog a separate target, so it can be used for gtest as well.
-if(WITH_LIBMV OR WITH_GTESTS OR WITH_CYCLES_LOGGING)
+if(WITH_LIBMV OR WITH_GTESTS OR (WITH_CYCLES AND WITH_CYCLES_LOGGING))
# We compile GLog together with GFlag so we don't worry about
# adding extra lib to linker.
set(GLOG_SRC
@@ -258,6 +262,9 @@ ${third_gflags_headers}
third_party/glog/src/windows/glog/log_severity.h
third_party/glog/src/windows/port.h
third_party/glog/src/windows/config.h
+
+ third_party/gflags/windows_port.cc
+ third_party/gflags/windows_port.h
)
else()
list(APPEND GLOG_SRC
@@ -267,15 +274,7 @@ ${third_glog_headers}
)
endif()
- set(GLOG_INC
- third_party/gflags
- third_party/glog/src
- )
-
- set(GLOG_INC_SYS
- )
-
- blender_add_lib(extern_glog "\${GLOG_SRC}" "\${GLOG_INC}" "\${GLOG_INC_SYS}")
+ blender_add_lib(extern_glog "\${GLOG_SRC}" "\${INC}" "\${INC_SYS}")
endif()
EOF
@@ -294,25 +293,12 @@ Import('env')
defs = []
incs = '.'
-if env['WITH_BF_LIBMV']:
- if not env['WITH_SHARED_PTR_SUPPORT']:
- print("-- Unable to find shared_ptr which is required for compilation.")
- exit(1)
-
- if env['SHARED_PTR_HEADER'] == 'tr1/memory':
- defs.append('CERES_TR1_MEMORY_HEADER')
- if env['SHARED_PTR_NAMESPACE'] == 'std::tr1':
- defs.append('CERES_TR1_SHARED_PTR')
-
+if env['WITH_BF_LIBMV'] or (env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_LOGGING']):
defs.append('GOOGLE_GLOG_DLL_DECL=')
defs.append('WITH_LIBMV_GUARDED_ALLOC')
defs.append('LIBMV_NO_FAST_DETECTOR')
- src = env.Glob('intern/*.cc')
- src.remove('intern' + os.sep + 'stub.cc')
-$src
-
- incs += ' ../Eigen3 third_party/gflags third_party/glog/src third_party/ceres/include third_party/ceres/config ../../intern/guardedalloc'
+ incs += ' ../Eigen3 third_party/gflags third_party/gflags/gflags third_party/glog/src third_party/ceres/include third_party/ceres/config ../../intern/guardedalloc'
incs += ' ' + env['BF_PNG_INC']
incs += ' ' + env['BF_ZLIB_INC']
@@ -320,18 +306,40 @@ $src
incs += ' ./third_party/glog/src/windows ./third_party/glog/src/windows/glog'
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
incs += ' ./third_party/msinttypes'
-${win_src}
- src += ['./third_party/glog/src/logging.cc', './third_party/glog/src/raw_logging.cc', './third_party/glog/src/utilities.cc', './third_party/glog/src/vlog_is_on.cc']
- src += ['./third_party/glog/src/windows/port.cc']
else:
- src += env.Glob("third_party/glog/src/*.cc")
incs += ' ./third_party/glog/src'
+
+if env['WITH_BF_LIBMV']:
+ if not env['WITH_SHARED_PTR_SUPPORT']:
+ print("-- Unable to find shared_ptr which is required for compilation.")
+ exit(1)
+
+ if env['SHARED_PTR_HEADER'] == 'tr1/memory':
+ defs.append('CERES_TR1_MEMORY_HEADER')
+ if env['SHARED_PTR_NAMESPACE'] == 'std::tr1':
+ defs.append('CERES_TR1_SHARED_PTR')
+
+ src = env.Glob('intern/*.cc')
+ src.remove('intern' + os.sep + 'stub.cc')
+$src
else:
src = env.Glob("intern/stub.cc")
src = [src for src in src if src.find('_test.cc') == -1]
-env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137] )
+env.BlenderLib(libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137])
+
+if env['WITH_BF_LIBMV'] or (env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_LOGGING']):
+ glog_src = []
+ glog_src += env.Glob("third_party/gflags/*.cc")
+ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ glog_src += ['./third_party/glog/src/logging.cc', './third_party/glog/src/raw_logging.cc', './third_party/glog/src/utilities.cc', './third_party/glog/src/vlog_is_on.cc']
+ glog_src += ['./third_party/glog/src/windows/port.cc']
+ else:
+ glog_src.remove('third_party/gflags/windows_port.cc')
+ glog_src += env.Glob("third_party/glog/src/*.cc")
+
+ env.BlenderLib(libname = 'extern_glog', sources=glog_src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137])
if env['WITH_BF_LIBMV']:
SConscript(['third_party/SConscript'])
diff --git a/extern/libmv/files.txt b/extern/libmv/files.txt
index a206ffe1edd..11f8ef24781 100644
--- a/extern/libmv/files.txt
+++ b/extern/libmv/files.txt
@@ -133,10 +133,10 @@ libmv/tracking/track_region.cc
libmv/tracking/track_region.h
libmv/tracking/trklt_region_tracker.cc
libmv/tracking/trklt_region_tracker.h
-third_party/gflags/AUTHORS
-third_party/gflags/ChangeLog
+third_party/gflags/AUTHORS.txt
+third_party/gflags/ChangeLog.txt
third_party/gflags/config.h
-third_party/gflags/COPYING
+third_party/gflags/COPYING.txt
third_party/gflags/gflags.cc
third_party/gflags/gflags_completions.cc
third_party/gflags/gflags/gflags_completions.h
@@ -144,9 +144,11 @@ third_party/gflags/gflags/gflags_declare.h
third_party/gflags/gflags/gflags.h
third_party/gflags/gflags_reporting.cc
third_party/gflags/mutex.h
-third_party/gflags/NEWS
+third_party/gflags/NEWS.txt
third_party/gflags/README.libmv
third_party/gflags/util.h
+third_party/gflags/windows_port.cc
+third_party/gflags/windows_port.h
third_party/glog/AUTHORS
third_party/glog/ChangeLog
third_party/glog/COPYING
diff --git a/extern/libmv/intern/logging.cc b/extern/libmv/intern/logging.cc
index 4ab2d91c8b4..77b56ef4df3 100644
--- a/extern/libmv/intern/logging.cc
+++ b/extern/libmv/intern/logging.cc
@@ -35,21 +35,21 @@ void libmv_initLogging(const char* argv0) {
google::GLOG_FATAL);
google::InitGoogleLogging(argv0);
- google::SetCommandLineOption("logtostderr", "1");
- google::SetCommandLineOption("v", "0");
- google::SetCommandLineOption("stderrthreshold", severity_fatal);
- google::SetCommandLineOption("minloglevel", severity_fatal);
+ gflags::SetCommandLineOption("logtostderr", "1");
+ gflags::SetCommandLineOption("v", "0");
+ gflags::SetCommandLineOption("stderrthreshold", severity_fatal);
+ gflags::SetCommandLineOption("minloglevel", severity_fatal);
}
void libmv_startDebugLogging(void) {
- google::SetCommandLineOption("logtostderr", "1");
- google::SetCommandLineOption("v", "2");
- google::SetCommandLineOption("stderrthreshold", "1");
- google::SetCommandLineOption("minloglevel", "0");
+ gflags::SetCommandLineOption("logtostderr", "1");
+ gflags::SetCommandLineOption("v", "2");
+ gflags::SetCommandLineOption("stderrthreshold", "1");
+ gflags::SetCommandLineOption("minloglevel", "0");
}
void libmv_setLoggingVerbosity(int verbosity) {
char val[10];
snprintf(val, sizeof(val), "%d", verbosity);
- google::SetCommandLineOption("v", val);
+ gflags::SetCommandLineOption("v", val);
}
diff --git a/extern/libmv/intern/reconstruction.cc b/extern/libmv/intern/reconstruction.cc
index f89efd8e8ca..046671e467f 100644
--- a/extern/libmv/intern/reconstruction.cc
+++ b/extern/libmv/intern/reconstruction.cc
@@ -61,6 +61,7 @@ struct libmv_Reconstruction {
CameraIntrinsics *intrinsics;
double error;
+ bool is_valid;
};
namespace {
@@ -289,6 +290,12 @@ libmv_Reconstruction *libmv_solveReconstruction(
LG << "number of markers for init: " << keyframe_markers.size();
+ if (keyframe_markers.size() < 8) {
+ LG << "No enough markers to initialize from";
+ libmv_reconstruction->is_valid = false;
+ return libmv_reconstruction;
+ }
+
update_callback.invoke(0, "Initial reconstruction");
EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction);
@@ -319,6 +326,7 @@ libmv_Reconstruction *libmv_solveReconstruction(
progress_update_callback,
callback_customdata);
+ libmv_reconstruction->is_valid = true;
return (libmv_Reconstruction *) libmv_reconstruction;
}
@@ -377,9 +385,14 @@ libmv_Reconstruction *libmv_solveModal(
progress_update_callback,
callback_customdata);
+ libmv_reconstruction->is_valid = true;
return (libmv_Reconstruction *) libmv_reconstruction;
}
+int libmv_reconstructionIsValid(libmv_Reconstruction *libmv_reconstruction) {
+ return libmv_reconstruction->is_valid;
+}
+
void libmv_reconstructionDestroy(libmv_Reconstruction *libmv_reconstruction) {
LIBMV_OBJECT_DELETE(libmv_reconstruction->intrinsics, CameraIntrinsics);
LIBMV_OBJECT_DELETE(libmv_reconstruction, libmv_Reconstruction);
diff --git a/extern/libmv/intern/reconstruction.h b/extern/libmv/intern/reconstruction.h
index 88e810b54aa..8b6b34a6142 100644
--- a/extern/libmv/intern/reconstruction.h
+++ b/extern/libmv/intern/reconstruction.h
@@ -68,6 +68,8 @@ libmv_Reconstruction* libmv_solveModal(
reconstruct_progress_update_cb progress_update_callback,
void* callback_customdata);
+int libmv_reconstructionIsValid(libmv_Reconstruction *libmv_reconstruction);
+
void libmv_reconstructionDestroy(libmv_Reconstruction* libmv_reconstruction);
int libmv_reprojectionPointForTrack(
diff --git a/extern/libmv/intern/stub.cc b/extern/libmv/intern/stub.cc
index f307d831475..f02509de90a 100644
--- a/extern/libmv/intern/stub.cc
+++ b/extern/libmv/intern/stub.cc
@@ -138,6 +138,10 @@ libmv_Reconstruction *libmv_solveModal(
return NULL;
}
+int libmv_reconstructionIsValid(libmv_Reconstruction * /*libmv_reconstruction*/) {
+ return 0;
+}
+
int libmv_reprojectionPointForTrack(
const libmv_Reconstruction * /*libmv_reconstruction*/,
int /*track*/,
diff --git a/extern/libmv/third_party/gflags/AUTHORS b/extern/libmv/third_party/gflags/AUTHORS.txt
index 887918bd00e..887918bd00e 100644
--- a/extern/libmv/third_party/gflags/AUTHORS
+++ b/extern/libmv/third_party/gflags/AUTHORS.txt
diff --git a/extern/libmv/third_party/gflags/COPYING b/extern/libmv/third_party/gflags/COPYING.txt
index d15b0c24134..d15b0c24134 100644
--- a/extern/libmv/third_party/gflags/COPYING
+++ b/extern/libmv/third_party/gflags/COPYING.txt
diff --git a/extern/libmv/third_party/gflags/ChangeLog b/extern/libmv/third_party/gflags/ChangeLog
deleted file mode 100644
index f9ef9350984..00000000000
--- a/extern/libmv/third_party/gflags/ChangeLog
+++ /dev/null
@@ -1,195 +0,0 @@
-Wed Jan 25 15:09:14 2012 Google Inc. <google-gflags@googlegroups.com>
-
- * gflags: version 2.0
- * Changed the 'official' gflags email in setup.py/etc
- * Renamed google-gflags.sln to gflags.sln
- * Changed copyright text to reflect Google's relinquished ownership
-
-Tue Dec 20 19:48:57 2011 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.7
- * Add CommandLineFlagInfo::flag_ptr pointing to current storage (musji)
- * PORTING: flush after writing to stderr, needed on cygwin
- * PORTING: Clean up the GFLAGS_DLL_DECL stuff better
- * Fix a bug in StringPrintf() that affected large strings (csilvers)
- * Die at configure-time when g++ isn't installed
-
-Fri Jul 29 19:05:21 2011 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.6
- * BUGFIX: Fix a bug where we were leaving out a required $(top_srcdir)
- * Fix definition of clstring (jyrki)
- * Split up flag declares into its own file (jyrki)
- * Add --version support (csilvers)
- * Update the README for gflags with static libs
- * Update acx_pthread.m4 for nostdlib
- * Change ReparseCommandLineFlags to return void (csilvers)
- * Some doc typofixes and example augmentation (various)
-
-Mon Jan 24 16:11:35 2011 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.5
- * Better reporting of current vs default value (handler)
- * Add API for cleaning up of memory at program-exit (jmarantz)
- * Fix macros to work inside namespaces (csilvers)
- * Use our own string typedef in case string is redefined (csilvers)
- * Updated to autoconf 2.65
-
-Wed Oct 13 17:40:12 2010 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.4
- * Add a check to prevent passing 0 to DEFINE_string (jorg)
- * Reduce compile (.o) size (jyrki)
- * Some small changes to quiet debug compiles (alexk)
- * PORTING: better support static linking on windows (csilvers)
- * DOCUMENTATION: change default values, use validators, etc.
- * Update the NEWS file to be non-empty
- * Add pkg-config (.pc) files for libgflags and libgflags_nothreads
-
-Mon Jan 4 18:09:30 2010 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.3
- * PORTABILITY: can now build and run tests under MSVC (csilvers)
- * Remove the python gflags code, which is now its own package (tansell)
- * Clarify that "last flag wins" in the docs (csilvers)
- * Comment danger of using GetAllFlags in validators (wojtekm)
- * PORTABILITY: Some fixes necessary for c++0x (mboerger)
- * Makefile fix: $(srcdir) -> $(top_srcdir) in one place (csilvres)
- * INSTALL: autotools to autoconf v2.64 + automake v1.11 (csilvers)
-
-Thu Sep 10 12:53:04 2009 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.2
- * PORTABILITY: can now build and run tests under mingw (csilvers)
- * Using a string arg for a bool flag is a compile-time error (rbayardo)
- * Add --helpxml to gflags.py (salcianu)
- * Protect against a hypothetical global d'tor mutex problem (csilvers)
- * BUGFIX: can now define a flag after 'using namespace google' (hamaji)
-
-Tue Apr 14 12:35:25 2009 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.1
- * Add both foo and nofoo for boolean flags, with --undefok (andychu)
- * Better document how validators work (wojtekm)
- * Improve binary-detection for bash-completion (mtamsky)
- * Python: Add a concept of "key flags", used with --help (salcianu)
- * Python: Robustify flag_values (salcianu)
- * Python: Add a new DEFINE_bool alias (keir, andrewliu)
- * Python: Do module introspection based on module name (dsturtevant)
- * Fix autoconf a bit better, especially on windows and solaris (ajenjo)
- * BUG FIX: gflags_nothreads was linking against the wrong lib (ajenjo)
- * BUG FIX: threads-detection failed on FreeBSD; replace it (ajenjo)
- * PORTABILITY: Quiet an internal compiler error with SUSE 10 (csilvers)
- * PORTABILITY: Update deb.sh for more recenty debuilds (csilvers)
- * PORTABILITY: #include more headers to satify new gcc's (csilvers)
- * INSTALL: Updated to autoconf 2.61 and libtool 1.5.26 (csilvers)
-
-Fri Oct 3 15:16:46 2008 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.0
- * Add a missing newline to an error string (bcmills)
- * (otherwise exactly the same as gflags 1.0rc2)
-
-Thu Sep 18 12:58:05 2008 Google Inc. <opensource@google.com>
-
- * google-gflags: version 1.0rc2
- * Report current flag values in --helpxml (hdn)
- * Fix compilation troubles with gcc 4.3.3 (simonb)
- * BUG FIX: I was missing a std:: in DECLARE_string (csilvers)
- * BUG FIX: Clarify in docs how to specify --bool flags (csilvers)
- * BUG FIX: Fix --helpshort for source files not in a subdir (csilvers)
- * BUG FIX: Fix python unittest for 64-bit builds (bcmills)
-
-Tue Aug 19 16:15:48 2008
-
- * google-gflags: version 1.0rc1
- * Move #include files from google/ to gflags/ (csilvers)
- * Small optimizations to reduce binary (library) size (jyrki)
- * BUGFIX: forgot a std:: in one of the .h files (csilvers)
- * Speed up locking by making sure calls are inlined (ajenjo)
- * 64-BIT COMPATIBILITY: Use %PRId64 instead of %lld (csilvers)
- * PORTABILITY: fix Makefile to work with Cygwin (ajenjo)
- * PORTABILITY: fix code to compile under Visual Studio (ajenjo)
- * PORTABILITY: fix code to compile under Solaris 10 with CC (csilvers)
-
-Mon Jul 21 23:01:38 2008 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.9
- * Add the ability to validate a command-line flag (csilvers)
- * Add completion support for commandline flags in bash (daven)
- * Add -W compile flags to Makefile, when using gcc (csilvers)
- * Allow helpstring to be NULL (cristianoc)
- * Improved documentation of classes in the .cc file (csilvers)
- * Fix python bug with AppendFlagValues + shortnames (jjtswan)
- * Use bool instead of int for boolean flags in gflags.py (bcmills)
- * Simplify the way we declare flags, now more foolproof (csilvers)
- * Better error messages when bool flags collide (colohan)
- * Only evaluate DEFINE_foo macro args once (csilvers)
-
-Wed Mar 26 15:20:18 2008 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.8
- * Export DescribeOneFlag() in the API
- * Add support for automatic line wrapping at 80 cols for gflags.py
- * Bugfix: do not treat an isolated "-" the same as an isolated "--"
- * Update rpm spec to point to Google Code rather than sourceforge (!)
- * Improve documentation (including documenting thread-safety)
- * Improve #include hygiene
- * Improve testing
-
-Thu Oct 18 11:33:20 2007 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.7
- * Deal even more correctly with libpthread not linked in (csilvers)
- * Add STRIP_LOG, an improved DO_NOT_SHOW_COMMANDLINE_HELP (sioffe)
- * Be more accurate printing default flag values in --help (dsturtevant)
- * Reduce .o file size a bit by using shorter namespace names (jeff)
- * Use relative install path, so 'setup.py --home' works (csilvers)
- * Notice when a boolean flag has a non-boolean default (bnmouli)
- * Broaden --helpshort to match foo-main.cc and foo_main.cc (hendrie)
- * Fix "no modules match" message for --helpshort, etc (hendrie)
-
-Wed Aug 15 07:35:51 2007 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.6
- * Deal correctly with case that libpthread is not linked in (csilvers)
- * Update Makefile/tests so we pass "make distcheck" (csilvers)
- * Document and test that last assignment to a flag wins (wan)
-
-Tue Jun 12 15:23:42 2007 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.5
- * Include all m4 macros in the distribution (csilvers)
- * Python: Fix broken data_files field in setup.py (sidlon)
- * Python: better string serliaizing and unparsing (abo, csimmons)
- * Fix checks for NaN and inf to work with Mac OS X (csilvers)
-
-Thu Apr 19 15:15:07 2007 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.4
- * Remove is_default from GetCommandLineFlagInfo (csilvers)
- * Portability fixes: includes, strtoll, gcc4.3 errors (csilvers)
- * A few doc typo cleanups (csilvers)
-
-Wed Mar 28 12:15:56 2007 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.3
- * python portability fix: use popen instead of subprocess (csilvers)
- * Add is_default to CommandLineFlagInfo (pchien)
- * Make docs a bit prettier (csilvers)
- * Actually include the python files in the distribution! :-/ (csilvers)
-
-Mon Jan 22 15:33:06 2007 Google Inc. <opensource@google.com>
-
- * google-gflags: version 0.2
- * added support for python commandlineflags, as well as c++
- * gflags2man, a script to turn flags into a man page (dchristian)
-
-Wed Dec 13 12:37:19 2006 Google Inc. <opensource@google.com>
-
- * google-gflags: initial release:
- The gflags package contains a library that implements commandline
- flags processing. As such it's a replacement for getopt(). It
- has increased flexibility, including built-in support for C++
- types like string, and the ability to define flags in the source
- file in which they're used.
diff --git a/extern/libmv/third_party/gflags/ChangeLog.txt b/extern/libmv/third_party/gflags/ChangeLog.txt
new file mode 100644
index 00000000000..e14d88e35f2
--- /dev/null
+++ b/extern/libmv/third_party/gflags/ChangeLog.txt
@@ -0,0 +1,208 @@
+* Sun Mar 20 2014 - Andreas Schuh <google-gflags@googlegroups.com>
+
+- gflags: version 2.1.1
+- Fixed issue 77: GFLAGS_IS_A_DLL expands to empty string in gflags_declare.h
+- Fixed issue 79: GFLAGS_NAMESPACE not expanded to actual namespace in gflags_declare.h
+- Fixed issue 80: Allow include path to differ from GFLAGS_NAMESPACE
+
+* Thu Mar 20 2014 - Andreas Schuh <google-gflags@googlegroups.com>
+
+- gflags: version 2.1.0
+- Build system configuration using CMake instead of autotools
+- CPack packaging support for Debian/Ubuntu, Red Hat, and Mac OS X
+- Fixed issue 54: Fix "invalid suffix on literal" (C++11)
+- Fixed issue 57: Use _strdup instead of strdup on Windows
+- Fixed issue 62: Change all preprocessor include guards to start with GFLAGS_
+- Fixed issue 64: Add DEFINE_validator macro
+- Fixed issue 73: Warnings in Visual Studio 2010 and unable to compile unit test
+
+* Wed Jan 25 2012 - Google Inc. <google-gflags@googlegroups.com>
+
+- gflags: version 2.0
+- Changed the 'official' gflags email in setup.py/etc
+- Renamed google-gflags.sln to gflags.sln
+- Changed copyright text to reflect Google's relinquished ownership
+
+* Tue Dec 20 2011 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.7
+- Add CommandLineFlagInfo::flag_ptr pointing to current storage (musji)
+- PORTING: flush after writing to stderr, needed on cygwin
+- PORTING: Clean up the GFLAGS_DLL_DECL stuff better
+- Fix a bug in StringPrintf() that affected large strings (csilvers)
+- Die at configure-time when g++ isn't installed
+
+* Fri Jul 29 2011 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.6
+- BUGFIX: Fix a bug where we were leaving out a required $(top_srcdir)
+- Fix definition of clstring (jyrki)
+- Split up flag declares into its own file (jyrki)
+- Add --version support (csilvers)
+- Update the README for gflags with static libs
+- Update acx_pthread.m4 for nostdlib
+- Change ReparseCommandLineFlags to return void (csilvers)
+- Some doc typofixes and example augmentation (various)
+
+* Mon Jan 24 2011 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.5
+- Better reporting of current vs default value (handler)
+- Add API for cleaning up of memory at program-exit (jmarantz)
+- Fix macros to work inside namespaces (csilvers)
+- Use our own string typedef in case string is redefined (csilvers)
+- Updated to autoconf 2.65
+
+* Wed Oct 13 2010 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.4
+- Add a check to prevent passing 0 to DEFINE_string (jorg)
+- Reduce compile (.o) size (jyrki)
+- Some small changes to quiet debug compiles (alexk)
+- PORTING: better support static linking on windows (csilvers)
+- DOCUMENTATION: change default values, use validators, etc.
+- Update the NEWS file to be non-empty
+- Add pkg-config (.pc) files for libgflags and libgflags_nothreads
+
+* Mon Jan 4 2010 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.3
+- PORTABILITY: can now build and run tests under MSVC (csilvers)
+- Remove the python gflags code, which is now its own package (tansell)
+- Clarify that "last flag wins" in the docs (csilvers)
+- Comment danger of using GetAllFlags in validators (wojtekm)
+- PORTABILITY: Some fixes necessary for c++0x (mboerger)
+- Makefile fix: $(srcdir) -> $(top_srcdir) in one place (csilvres)
+- INSTALL: autotools to autoconf v2.64 + automake v1.11 (csilvers)
+
+* Thu Sep 10 2009 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.2
+- PORTABILITY: can now build and run tests under mingw (csilvers)
+- Using a string arg for a bool flag is a compile-time error (rbayardo)
+- Add --helpxml to gflags.py (salcianu)
+- Protect against a hypothetical global d'tor mutex problem (csilvers)
+- BUGFIX: can now define a flag after 'using namespace google' (hamaji)
+
+* Tue Apr 14 2009 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.1
+- Add both foo and nofoo for boolean flags, with --undefok (andychu)
+- Better document how validators work (wojtekm)
+- Improve binary-detection for bash-completion (mtamsky)
+- Python: Add a concept of "key flags", used with --help (salcianu)
+- Python: Robustify flag_values (salcianu)
+- Python: Add a new DEFINE_bool alias (keir, andrewliu)
+- Python: Do module introspection based on module name (dsturtevant)
+- Fix autoconf a bit better, especially on windows and solaris (ajenjo)
+- BUG FIX: gflags_nothreads was linking against the wrong lib (ajenjo)
+- BUG FIX: threads-detection failed on FreeBSD; replace it (ajenjo)
+- PORTABILITY: Quiet an internal compiler error with SUSE 10 (csilvers)
+- PORTABILITY: Update deb.sh for more recenty debuilds (csilvers)
+- PORTABILITY: #include more headers to satify new gcc's (csilvers)
+- INSTALL: Updated to autoconf 2.61 and libtool 1.5.26 (csilvers)
+
+* Fri Oct 3 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.0
+- Add a missing newline to an error string (bcmills)
+- (otherwise exactly the same as gflags 1.0rc2)
+
+* Thu Sep 18 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.0rc2
+- Report current flag values in --helpxml (hdn)
+- Fix compilation troubles with gcc 4.3.3 (simonb)
+- BUG FIX: I was missing a std:: in DECLARE_string (csilvers)
+- BUG FIX: Clarify in docs how to specify --bool flags (csilvers)
+- BUG FIX: Fix --helpshort for source files not in a subdir (csilvers)
+- BUG FIX: Fix python unittest for 64-bit builds (bcmills)
+
+* Tue Aug 19 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.0rc1
+- Move #include files from google/ to gflags/ (csilvers)
+- Small optimizations to reduce binary (library) size (jyrki)
+- BUGFIX: forgot a std:: in one of the .h files (csilvers)
+- Speed up locking by making sure calls are inlined (ajenjo)
+- 64-BIT COMPATIBILITY: Use %PRId64 instead of %lld (csilvers)
+- PORTABILITY: fix Makefile to work with Cygwin (ajenjo)
+- PORTABILITY: fix code to compile under Visual Studio (ajenjo)
+- PORTABILITY: fix code to compile under Solaris 10 with CC (csilvers)
+
+* Mon Jul 21 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.9
+- Add the ability to validate a command-line flag (csilvers)
+- Add completion support for commandline flags in bash (daven)
+- Add -W compile flags to Makefile, when using gcc (csilvers)
+- Allow helpstring to be NULL (cristianoc)
+- Improved documentation of classes in the .cc file (csilvers)
+- Fix python bug with AppendFlagValues + shortnames (jjtswan)
+- Use bool instead of int for boolean flags in gflags.py (bcmills)
+- Simplify the way we declare flags, now more foolproof (csilvers)
+- Better error messages when bool flags collide (colohan)
+- Only evaluate DEFINE_foo macro args once (csilvers)
+
+* Wed Mar 26 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.8
+- Export DescribeOneFlag() in the API
+- Add support for automatic line wrapping at 80 cols for gflags.py
+- Bugfix: do not treat an isolated "-" the same as an isolated "--"
+- Update rpm spec to point to Google Code rather than sourceforge (!)
+- Improve documentation (including documenting thread-safety)
+- Improve #include hygiene
+- Improve testing
+
+* Thu Oct 18 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.7
+- Deal even more correctly with libpthread not linked in (csilvers)
+- Add STRIP_LOG, an improved DO_NOT_SHOW_COMMANDLINE_HELP (sioffe)
+- Be more accurate printing default flag values in --help (dsturtevant)
+- Reduce .o file size a bit by using shorter namespace names (jeff)
+- Use relative install path, so 'setup.py --home' works (csilvers)
+- Notice when a boolean flag has a non-boolean default (bnmouli)
+- Broaden --helpshort to match foo-main.cc and foo_main.cc (hendrie)
+- Fix "no modules match" message for --helpshort, etc (hendrie)
+
+* Wed Aug 15 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.6
+- Deal correctly with case that libpthread is not linked in (csilvers)
+- Update Makefile/tests so we pass "make distcheck" (csilvers)
+- Document and test that last assignment to a flag wins (wan)
+
+* Tue Jun 12 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.5
+- Include all m4 macros in the distribution (csilvers)
+- Python: Fix broken data_files field in setup.py (sidlon)
+- Python: better string serliaizing and unparsing (abo, csimmons)
+- Fix checks for NaN and inf to work with Mac OS X (csilvers)
+
+* Thu Apr 19 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.4
+- Remove is_default from GetCommandLineFlagInfo (csilvers)
+- Portability fixes: includes, strtoll, gcc4.3 errors (csilvers)
+- A few doc typo cleanups (csilvers)
+
+* Wed Mar 28 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.3
+- python portability fix: use popen instead of subprocess (csilvers)
+- Add is_default to CommandLineFlagInfo (pchien)
+- Make docs a bit prettier (csilvers)
+- Actually include the python files in the distribution! :-/ (csilvers)
+
+* Mon Jan 22 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.2
+- added support for python commandlineflags, as well as c++
+- gflags2man, a script to turn flags into a man page (dchristian)
+
+* Wed Dec 13 2006 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.1
diff --git a/extern/libmv/third_party/gflags/NEWS b/extern/libmv/third_party/gflags/NEWS.txt
index ffc0127d91e..74186071129 100644
--- a/extern/libmv/third_party/gflags/NEWS
+++ b/extern/libmv/third_party/gflags/NEWS.txt
@@ -1,4 +1,86 @@
-== 25 January 2012 ==
+=== 30 March 2014 ===
+
+I've just released gflags 2.1.1.
+
+This release fixes a few bugs in the configuration of gflags_declare.h
+and adds a separate GFLAGS_INCLUDE_DIR CMake variable to the build configuration.
+Setting GFLAGS_NAMESPACE to "google" no longer changes also the include
+path of the public header files. This allows the use of the library with
+other Google projects such as glog which still use the deprecated "google"
+namespace for the gflags library, but include it as "gflags/gflags.h".
+
+=== 20 March 2014 ===
+
+I've just released gflags 2.1.
+
+The major changes are the use of CMake for the build configuration instead
+of the autotools and packaging support through CPack. The default namespace
+of all C++ symbols is now "gflags" instead of "google". This can be
+configured via the GFLAGS_NAMESPACE variable.
+
+This release compiles with all major compilers without warnings and passed
+the unit tests on Ubuntu 12.04, Windows 7 (Visual Studio 2008 and 2010,
+Cygwin, MinGW), and Mac OS X (Xcode 5.1).
+
+The SVN repository on Google Code is now frozen and replaced by a Git
+repository such that it can be used as Git submodule by projects. The main
+hosting of this project remains at Google Code. Thanks to the distributed
+character of Git, I can push (and pull) changes from both GitHub and Google Code
+in order to keep the two public repositories in sync.
+When fixing an issue for a pull request through either of these hosting
+platforms, please reference the issue number as
+[https://code.google.com/p/support/wiki/IssueTracker#Integration_with_version_control described here].
+For the further development, I am following the
+[http://nvie.com/posts/a-successful-git-branching-model/ Git branching model]
+with feature branch names prefixed by "feature/" and bugfix branch names
+prefixed by "bugfix/", respectively.
+
+Binary and source [https://github.com/schuhschuh/gflags/releases packages] are available on GitHub.
+
+
+=== 14 January 2013 ===
+
+The migration of the build system to CMake is almost complete.
+What remains to be done is rewriting the tests in Python such they can be
+executed on non-Unix platforms and splitting them up into separate CTest tests.
+Though merging these changes into the master branch yet remains to be done,
+it is recommended to already start using the
+[https://github.com/schuhschuh/gflags/tree/cmake-migration cmake-migration] branch.
+
+
+=== 20 April 2013 ===
+
+More than a year has past since I (Andreas) took over the maintenance for
+`gflags`. Only few minor changes have been made since then, much to my regret.
+To get more involved and stimulate participation in the further
+development of the library, I moved the project source code today to
+[https://github.com/schuhschuh/gflags GitHub].
+I believe that the strengths of [http://git-scm.com/ Git] will allow for better community collaboration
+as well as ease the integration of changes made by others. I encourage everyone
+who would like to contribute to send me pull requests.
+Git's lightweight feature branches will also provide the right tool for more
+radical changes which should only be merged back into the master branch
+after these are complete and implement the desired behavior.
+
+The SVN repository remains accessible at Google Code and I will keep the
+master branch of the Git repository hosted at GitHub and the trunk of the
+Subversion repository synchronized. Initially, I was going to simply switch the
+Google Code project to Git, but in this case the SVN repository would be
+frozen and force everyone who would like the latest development changes to
+use Git as well. Therefore I decided to host the public Git repository at GitHub
+instead.
+
+Please continue to report any issues with gflags on Google Code. The GitHub project will
+only be used to host the Git repository.
+
+One major change of the project structure I have in mind for the next weeks
+is the migration from autotools to [http://www.cmake.org/ CMake].
+Check out the (unstable!)
+[https://github.com/schuhschuh/gflags/tree/cmake-migration cmake-migration]
+branch on GitHub for details.
+
+
+=== 25 January 2012 ===
I've just released gflags 2.0.
@@ -128,7 +210,7 @@ If you've tried to install a .rpm or .deb and it doesn't work for you,
let me know. I'm excited to finally have 64-bit package files, but
there may still be some wrinkles in the new system to iron out.
-===1 October 2008===
+=== 1 October 2008 ===
gflags 1.0rc2 was out for a few weeks without any issues, so gflags
1.0 is now released. This is much like gflags 0.9. The major change
diff --git a/extern/libmv/third_party/gflags/README.libmv b/extern/libmv/third_party/gflags/README.libmv
index b310c57ac34..f4310b39bbb 100644
--- a/extern/libmv/third_party/gflags/README.libmv
+++ b/extern/libmv/third_party/gflags/README.libmv
@@ -1,16 +1,18 @@
Project: Google Flags
URL: http://code.google.com/p/google-gflags/
License: New BSD
-Upstream version: 2.0
+Upstream version: 2.1.1
Local modifications:
-- Flattened the tree and only included files needed for libmv. This involved
- changing some of the includes to point to the current directory instead of a
- nested gflags directory.
+- Flattened the tree and only included files needed for libmv.
-- Added a poor-man's version of upstream's port.cc/h to make gflags compile on
- windows. This isn't sufficient but is a stopgap for now.
+- config.h was originally generated on linux machine with some
+ further tweaks:
-- Added -fPIC flag, so shared libraries from Ceres could be linked against static glog
+ * OS_WINDOWS need to be conditinally defined from inside #ifdef WIN32
+ * Same applies yo HAVE_SHLWAPI_H
+ * Disabeld HAVE_FNMATCH_H
+
+- Removed attribute(unused) from FlagSaver.
TODO(keir): Import and use gflags for Windows from upstream.
diff --git a/extern/libmv/third_party/gflags/config.h b/extern/libmv/third_party/gflags/config.h
index 03ed03ca99b..858510835c1 100644
--- a/extern/libmv/third_party/gflags/config.h
+++ b/extern/libmv/third_party/gflags/config.h
@@ -1,101 +1,117 @@
-/* src/config.h. Generated from config.h.in by configure. */
-/* src/config.h.in. Generated from configure.ac by autoheader. */
+/* Generated from config.h.in during build configuration using CMake. */
-/* Always the empty-string on non-windows systems. On windows, should be
- "__declspec(dllexport)". This way, when we compile the dll, we export our
- functions/classes. It's safe to define this here because config.h is only
- used internally, to compile the DLL, and every DLL source file #includes
- "config.h" before anything else. */
-#define GFLAGS_DLL_DECL /**/
+// Note: This header file is only used internally. It is not part of public interface!
-/* Namespace for Google classes */
-#define GOOGLE_NAMESPACE ::google
+// ---------------------------------------------------------------------------
+// System checks
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
+// Define if you build this library for a MS Windows OS.
+#ifdef WIN32
+# define OS_WINDOWS
+#endif
-/* Define to 1 if you have the <fnmatch.h> header file. */
-/* #ubdef HAVE_FNMATCH_H 1 */
+// Define if you have the <stdint.h> header file.
+#define HAVE_STDINT_H
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
+// Define if you have the <sys/types.h> header file.
+#define HAVE_SYS_TYPES_H
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
+// Define if you have the <inttypes.h> header file.
+#define HAVE_INTTYPES_H
-/* define if the compiler implements namespaces */
-#define HAVE_NAMESPACES 1
+// Define if you have the <sys/stat.h> header file.
+#define HAVE_SYS_STAT_H
-/* Define if you have POSIX threads libraries and header files. */
-#define HAVE_PTHREAD 1
+// Define if you have the <unistd.h> header file.
+#define HAVE_UNISTD_H
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
+// Define if you have the <fnmatch.h> header file.
+/* #undef HAVE_FNMATCH_H */
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
+// Define if you have the <shlwapi.h> header file (Windows 2000/XP).
+#undef HAVE_SHLWAPI_H
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
+// Define if you have the strtoll function.
+#define HAVE_STRTOLL
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
+// Define if you have the strtoq function.
+/* #undef HAVE_STRTOQ */
-/* Define to 1 if you have the `strtoll' function. */
-#define HAVE_STRTOLL 1
+// Define if you have the <pthread.h> header file.
+#define HAVE_PTHREAD
-/* Define to 1 if you have the `strtoq' function. */
-#define HAVE_STRTOQ 1
+// Define if your pthread library defines the type pthread_rwlock_t
+#define HAVE_RWLOCK
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
+// gcc requires this to get PRId64, etc.
+#if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS)
+# define __STDC_FORMAT_MACROS 1
+#endif
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
+// ---------------------------------------------------------------------------
+// Package information
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
+// Name of package.
+#define PACKAGE gflags
-/* define if your compiler has __attribute__ */
-#define HAVE___ATTRIBUTE__ 1
+// Define to the full name of this package.
+#define PACKAGE_NAME gflags
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#define LT_OBJDIR ".libs/"
+// Define to the full name and version of this package.
+#define PACKAGE_STRING gflags 2.1.1
-/* Name of package */
-#define PACKAGE "gflags"
+// Define to the one symbol short name of this package.
+#define PACKAGE_TARNAME gflags-2.1.1
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "google-gflags@googlegroups.com"
+// Define to the version of this package.
+#define PACKAGE_VERSION 2.1.1
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "gflags"
+// Version number of package.
+#define VERSION PACKAGE_VERSION
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "gflags 2.0"
+// Define to the address where bug reports for this package should be sent.
+#define PACKAGE_BUGREPORT https://code.google.com/p/gflags/issues/
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "gflags"
+// Namespace of gflags library symbols.
+#define GFLAGS_NAMESPACE gflags
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.0"
+// ---------------------------------------------------------------------------
+// Path separator
+#ifndef PATH_SEPARATOR
+# ifdef OS_WINDOWS
+# define PATH_SEPARATOR '\\'
+# else
+# define PATH_SEPARATOR '/'
+# endif
+#endif
-/* Define to necessary symbol if this constant uses a non-standard name on
- your system. */
-/* #undef PTHREAD_CREATE_JOINABLE */
+// ---------------------------------------------------------------------------
+// Windows
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
+// Whether gflags library is a DLL.
+#ifndef GFLAGS_IS_A_DLL
+# define GFLAGS_IS_A_DLL 0
+#endif
-/* the namespace where STL code like vector<> is defined */
-#define STL_NAMESPACE std
-
-/* Version number of package */
-#define VERSION "2.0"
-
-/* Stops putting the code inside the Google namespace */
-#define _END_GOOGLE_NAMESPACE_ }
-
-/* Puts following code inside the Google namespace */
-#define _START_GOOGLE_NAMESPACE_ namespace google {
+// Always export symbols when compiling a shared library as this file is only
+// included by internal modules when building the gflags library itself.
+// The gflags_declare.h header file will set it to import these symbols otherwise.
+#ifndef GFLAGS_DLL_DECL
+# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
+# define GFLAGS_DLL_DECL __declspec(dllexport)
+# else
+# define GFLAGS_DLL_DECL
+# endif
+#endif
+// Flags defined by the gflags library itself must be exported
+#ifndef GFLAGS_DLL_DEFINE_FLAG
+# define GFLAGS_DLL_DEFINE_FLAG GFLAGS_DLL_DECL
+#endif
+
+#ifdef OS_WINDOWS
+// The unittests import the symbols of the shared gflags library
+# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
+# define GFLAGS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
+# endif
+# include "windows_port.h"
+#endif
diff --git a/extern/libmv/third_party/gflags/gflags.cc b/extern/libmv/third_party/gflags/gflags.cc
index 4ba2b6f393c..285050fe9ec 100644
--- a/extern/libmv/third_party/gflags/gflags.cc
+++ b/extern/libmv/third_party/gflags/gflags.cc
@@ -87,18 +87,16 @@
// other hand, hooks into CommandLineFlagParser. Other API functions
// are, similarly, mostly hooks into the functionality described above.
-// This comes first to ensure we define __STDC_FORMAT_MACROS in time.
#include "config.h"
-#if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS)
-# define __STDC_FORMAT_MACROS 1 // gcc requires this to get PRId64, etc.
-#endif
+#include "gflags.h"
-#include "gflags/gflags.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
-#ifdef HAVE_FNMATCH_H
-# include <fnmatch.h>
+#if defined(HAVE_FNMATCH_H)
+# include <fnmatch.h>
+#elif defined(HAVE_SHLWAPI_H)
+# include <shlwapi.h>
#endif
#include <stdarg.h> // For va_list and related operations
#include <stdio.h>
@@ -109,31 +107,23 @@
#include <string>
#include <utility> // for pair<>
#include <vector>
+
#include "mutex.h"
#include "util.h"
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR '/'
-#endif
-
-
// Special flags, type 1: the 'recursive' flags. They set another flag's val.
-DEFINE_string(flagfile, "",
- "load flags from file");
-DEFINE_string(fromenv, "",
- "set flags from the environment"
- " [use 'export FLAGS_flag1=value']");
-DEFINE_string(tryfromenv, "",
- "set flags from the environment if present");
+DEFINE_string(flagfile, "", "load flags from file");
+DEFINE_string(fromenv, "", "set flags from the environment"
+ " [use 'export FLAGS_flag1=value']");
+DEFINE_string(tryfromenv, "", "set flags from the environment if present");
// Special flags, type 2: the 'parsing' flags. They modify how we parse.
-DEFINE_string(undefok, "",
- "comma-separated list of flag names that it is okay to specify "
- "on the command line even if the program does not define a flag "
- "with that name. IMPORTANT: flags in this list that have "
- "arguments MUST use the flag=value format");
+DEFINE_string(undefok, "", "comma-separated list of flag names that it is okay to specify "
+ "on the command line even if the program does not define a flag "
+ "with that name. IMPORTANT: flags in this list that have "
+ "arguments MUST use the flag=value format");
-_START_GOOGLE_NAMESPACE_
+namespace GFLAGS_NAMESPACE {
using std::map;
using std::pair;
@@ -206,7 +196,7 @@ class FlagValue {
private:
friend class CommandLineFlag; // for many things, including Validate()
- friend class GOOGLE_NAMESPACE::FlagSaverImpl; // calls New()
+ friend class GFLAGS_NAMESPACE::FlagSaverImpl; // calls New()
friend class FlagRegistry; // checks value_buffer_ for flags_by_ptr_ map
template <typename T> friend T GetFromEnv(const char*, const char*, T);
friend bool TryParseLocked(const CommandLineFlag*, FlagValue*,
@@ -348,13 +338,13 @@ string FlagValue::ToString() const {
case FV_BOOL:
return VALUE_AS(bool) ? "true" : "false";
case FV_INT32:
- snprintf(intbuf, sizeof(intbuf), "%"PRId32, VALUE_AS(int32));
+ snprintf(intbuf, sizeof(intbuf), "%" PRId32, VALUE_AS(int32));
return intbuf;
case FV_INT64:
- snprintf(intbuf, sizeof(intbuf), "%"PRId64, VALUE_AS(int64));
+ snprintf(intbuf, sizeof(intbuf), "%" PRId64, VALUE_AS(int64));
return intbuf;
case FV_UINT64:
- snprintf(intbuf, sizeof(intbuf), "%"PRIu64, VALUE_AS(uint64));
+ snprintf(intbuf, sizeof(intbuf), "%" PRIu64, VALUE_AS(uint64));
return intbuf;
case FV_DOUBLE:
snprintf(intbuf, sizeof(intbuf), "%.17g", VALUE_AS(double));
@@ -406,8 +396,7 @@ const char* FlagValue::TypeName() const {
assert(false);
return "";
}
- // Directly indexing the strigns in the 'types' string, each of them
- // is 7 bytes long.
+ // Directly indexing the strings in the 'types' string, each of them is 7 bytes long.
return &types[type_ * 7];
}
@@ -504,7 +493,7 @@ class CommandLineFlag {
private:
// for SetFlagLocked() and setting flags_by_ptr_
friend class FlagRegistry;
- friend class GOOGLE_NAMESPACE::FlagSaverImpl; // for cloning the values
+ friend class GFLAGS_NAMESPACE::FlagSaverImpl; // for cloning the values
// set validate_fn
friend bool AddFlagValidator(const void*, ValidateFnProto);
@@ -671,9 +660,9 @@ class FlagRegistry {
static FlagRegistry* GlobalRegistry(); // returns a singleton registry
private:
- friend class GOOGLE_NAMESPACE::FlagSaverImpl; // reads all the flags in order to copy them
+ friend class GFLAGS_NAMESPACE::FlagSaverImpl; // reads all the flags in order to copy them
friend class CommandLineFlagParser; // for ValidateAllFlags
- friend void GOOGLE_NAMESPACE::GetAllFlags(vector<CommandLineFlagInfo>*);
+ friend void GFLAGS_NAMESPACE::GetAllFlags(vector<CommandLineFlagInfo>*);
// The map from name to flag, for FindFlagLocked().
typedef map<const char*, CommandLineFlag*, StringCmp> FlagMap;
@@ -1003,8 +992,8 @@ static string ReadFileIntoString(const char* filename) {
const int kBufSize = 8092;
char buffer[kBufSize];
string s;
- FILE* fp = fopen(filename, "r");
- if (!fp) PFATAL(filename);
+ FILE* fp;
+ if ((errno = SafeFOpen(&fp, filename, "r")) != 0) PFATAL(filename);
size_t n;
while ( (n=fread(buffer, 1, kBufSize, fp)) > 0 ) {
if (ferror(fp)) PFATAL(filename);
@@ -1148,8 +1137,8 @@ string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
}
const string envname = string("FLAGS_") + string(flagname);
- const char* envval = getenv(envname.c_str());
- if (!envval) {
+ string envval;
+ if (!SafeGetEnv(envname.c_str(), envval)) {
if (errors_are_fatal) {
error_flags_[flagname] = (string(kError) + envname +
" not found in environment\n");
@@ -1158,15 +1147,14 @@ string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
}
// Avoid infinite recursion.
- if ((strcmp(envval, "fromenv") == 0) ||
- (strcmp(envval, "tryfromenv") == 0)) {
+ if (envval == "fromenv" || envval == "tryfromenv") {
error_flags_[flagname] =
StringPrintf("%sinfinite recursion on environment flag '%s'\n",
- kError, envval);
+ kError, envval.c_str());
continue;
}
- msg += ProcessSingleOptionLocked(flag, envval, set_mode);
+ msg += ProcessSingleOptionLocked(flag, envval.c_str(), set_mode);
}
return msg;
}
@@ -1318,13 +1306,12 @@ string CommandLineFlagParser::ProcessOptionsFromStringLocked(
// We try matching both against the full argv0 and basename(argv0)
if (glob == ProgramInvocationName() // small optimization
|| glob == ProgramInvocationShortName()
-#ifdef HAVE_FNMATCH_H
- || fnmatch(glob.c_str(),
- ProgramInvocationName(),
- FNM_PATHNAME) == 0
- || fnmatch(glob.c_str(),
- ProgramInvocationShortName(),
- FNM_PATHNAME) == 0
+#if defined(HAVE_FNMATCH_H)
+ || fnmatch(glob.c_str(), ProgramInvocationName(), FNM_PATHNAME) == 0
+ || fnmatch(glob.c_str(), ProgramInvocationShortName(), FNM_PATHNAME) == 0
+#elif defined(HAVE_SHLWAPI_H)
+ || PathMatchSpec(glob.c_str(), ProgramInvocationName())
+ || PathMatchSpec(glob.c_str(), ProgramInvocationShortName())
#endif
) {
flags_are_relevant = true;
@@ -1346,14 +1333,15 @@ string CommandLineFlagParser::ProcessOptionsFromStringLocked(
template<typename T>
T GetFromEnv(const char *varname, const char* type, T dflt) {
- const char* const valstr = getenv(varname);
- if (!valstr)
- return dflt;
- FlagValue ifv(new T, type, true);
- if (!ifv.ParseFrom(valstr))
- ReportError(DIE, "ERROR: error parsing env variable '%s' with value '%s'\n",
- varname, valstr);
- return OTHER_VALUE_AS(ifv, T);
+ std::string valstr;
+ if (SafeGetEnv(varname, valstr)) {
+ FlagValue ifv(new T, type, true);
+ if (!ifv.ParseFrom(valstr.c_str())) {
+ ReportError(DIE, "ERROR: error parsing env variable '%s' with value '%s'\n",
+ varname, valstr.c_str());
+ }
+ return OTHER_VALUE_AS(ifv, T);
+ } else return dflt;
}
bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) {
@@ -1765,8 +1753,8 @@ bool ReadFlagsFromString(const string& flagfilecontents,
// TODO(csilvers): nix prog_name in favor of ProgramInvocationShortName()
bool AppendFlagsIntoFile(const string& filename, const char *prog_name) {
- FILE *fp = fopen(filename.c_str(), "a");
- if (!fp) {
+ FILE *fp;
+ if (SafeFOpen(&fp, filename.c_str(), "a") != 0) {
return false;
}
@@ -1824,10 +1812,18 @@ uint64 Uint64FromEnv(const char *v, uint64 dflt) {
double DoubleFromEnv(const char *v, double dflt) {
return GetFromEnv(v, "double", dflt);
}
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996) // ignore getenv security warning
+#endif
const char *StringFromEnv(const char *varname, const char *dflt) {
const char* const val = getenv(varname);
return val ? val : dflt;
}
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
// --------------------------------------------------------------------
@@ -1957,4 +1953,5 @@ void ShutDownCommandLineFlags() {
FlagRegistry::DeleteGlobalRegistry();
}
-_END_GOOGLE_NAMESPACE_
+
+} // namespace GFLAGS_NAMESPACE
diff --git a/extern/libmv/third_party/gflags/gflags/gflags.h b/extern/libmv/third_party/gflags/gflags/gflags.h
index e69812c8c38..797a54cac52 100644
--- a/extern/libmv/third_party/gflags/gflags/gflags.h
+++ b/extern/libmv/third_party/gflags/gflags/gflags.h
@@ -75,21 +75,26 @@
// other thread is writing to the variable or calling non-const
// methods of this class.
-#ifndef BASE_COMMANDLINEFLAGS_H_
-#define BASE_COMMANDLINEFLAGS_H_
+#ifndef GFLAGS_GFLAGS_H_
+#define GFLAGS_GFLAGS_H_
#include <string>
#include <vector>
-#include "gflags_declare.h" // IWYU pragma: export
-namespace google {
-//
-// NOTE: all functions below MUST have an explicit 'extern' before
-// them. Our automated opensourcing tools use this as a signal to do
-// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
-//
-#define GFLAGS_DLL_DECL /* rewritten to be non-empty in windows dir */
-#define GFLAGS_DLL_DEFINE_FLAG /* rewritten to be non-empty in windows dir */
+#include "gflags_declare.h" // IWYU pragma: export
+
+
+// We always want to export variables defined in user code
+#ifndef GFLAGS_DLL_DEFINE_FLAG
+# if 0 && defined(_MSC_VER)
+# define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport)
+# else
+# define GFLAGS_DLL_DEFINE_FLAG
+# endif
+#endif
+
+
+namespace gflags {
// --------------------------------------------------------------------
@@ -121,19 +126,17 @@ namespace google {
// Returns true if successfully registered, false if not (because the
// first argument doesn't point to a command-line flag, or because a
// validator is already registered for this flag).
-extern bool RegisterFlagValidator(const bool* flag,
- bool (*validate_fn)(const char*, bool));
-extern bool RegisterFlagValidator(const int32* flag,
- bool (*validate_fn)(const char*, int32));
-extern bool RegisterFlagValidator(const int64* flag,
- bool (*validate_fn)(const char*, int64));
-extern bool RegisterFlagValidator(const uint64* flag,
- bool (*validate_fn)(const char*, uint64));
-extern bool RegisterFlagValidator(const double* flag,
- bool (*validate_fn)(const char*, double));
-extern bool RegisterFlagValidator(const std::string* flag,
- bool (*validate_fn)(const char*,
- const std::string&));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const bool* flag, bool (*validate_fn)(const char*, bool));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int32* flag, bool (*validate_fn)(const char*, int32));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int64* flag, bool (*validate_fn)(const char*, int64));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint64* flag, bool (*validate_fn)(const char*, uint64));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const double* flag, bool (*validate_fn)(const char*, double));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const std::string* flag, bool (*validate_fn)(const char*, const std::string&));
+
+// Convenience macro for the registration of a flag validator
+#define DEFINE_validator(name, validator) \
+ static const bool name##_validator_registered = \
+ gflags::RegisterFlagValidator(&FLAGS_##name, validator)
// --------------------------------------------------------------------
@@ -146,19 +149,20 @@ extern bool RegisterFlagValidator(const std::string* flag,
// In addition to accessing flags, you can also access argv[0] (the program
// name) and argv (the entire commandline), which we sock away a copy of.
// These variables are static, so you should only set them once.
-
-struct GFLAGS_DLL_DECL CommandLineFlagInfo {
+//
+// No need to export this data only structure from DLL, avoiding VS warning 4251.
+struct CommandLineFlagInfo {
std::string name; // the name of the flag
std::string type; // the type of the flag: int32, etc
std::string description; // the "help text" associated with the flag
std::string current_value; // the current value, as a string
std::string default_value; // the default value, as a string
std::string filename; // 'cleaned' version of filename holding the flag
- bool has_validator_fn; // true if RegisterFlagValidator called on this flag
- bool is_default; // true if the flag has the default value and
- // has not been set explicitly from the cmdline
- // or via SetCommandLineOption
- const void* flag_ptr; // pointer to the flag's current value (i.e. FLAGS_foo)
+ bool has_validator_fn; // true if RegisterFlagValidator called on this flag
+ bool is_default; // true if the flag has the default value and
+ // has not been set explicitly from the cmdline
+ // or via SetCommandLineOption
+ const void* flag_ptr; // pointer to the flag's current value (i.e. FLAGS_foo)
};
// Using this inside of a validator is a recipe for a deadlock.
@@ -166,34 +170,34 @@ struct GFLAGS_DLL_DECL CommandLineFlagInfo {
// call validators during ParseAllFlags.
// Also make sure then to uncomment the corresponding unit test in
// gflags_unittest.sh
-extern void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
+extern GFLAGS_DLL_DECL void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
// These two are actually defined in gflags_reporting.cc.
-extern void ShowUsageWithFlags(const char *argv0); // what --help does
-extern void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
+extern GFLAGS_DLL_DECL void ShowUsageWithFlags(const char *argv0); // what --help does
+extern GFLAGS_DLL_DECL void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
// Create a descriptive string for a flag.
// Goes to some trouble to make pretty line breaks.
-extern std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
+extern GFLAGS_DLL_DECL std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
// Thread-hostile; meant to be called before any threads are spawned.
-extern void SetArgv(int argc, const char** argv);
+extern GFLAGS_DLL_DECL void SetArgv(int argc, const char** argv);
// The following functions are thread-safe as long as SetArgv() is
// only called before any threads start.
-extern const std::vector<std::string>& GetArgvs();
-extern const char* GetArgv(); // all of argv as a string
-extern const char* GetArgv0(); // only argv0
-extern uint32 GetArgvSum(); // simple checksum of argv
-extern const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
-extern const char* ProgramInvocationShortName(); // basename(argv0)
+extern GFLAGS_DLL_DECL const std::vector<std::string>& GetArgvs();
+extern GFLAGS_DLL_DECL const char* GetArgv(); // all of argv as a string
+extern GFLAGS_DLL_DECL const char* GetArgv0(); // only argv0
+extern GFLAGS_DLL_DECL uint32 GetArgvSum(); // simple checksum of argv
+extern GFLAGS_DLL_DECL const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
+extern GFLAGS_DLL_DECL const char* ProgramInvocationShortName(); // basename(argv0)
// ProgramUsage() is thread-safe as long as SetUsageMessage() is only
// called before any threads start.
-extern const char* ProgramUsage(); // string set by SetUsageMessage()
+extern GFLAGS_DLL_DECL const char* ProgramUsage(); // string set by SetUsageMessage()
// VersionString() is thread-safe as long as SetVersionString() is only
// called before any threads start.
-extern const char* VersionString(); // string set by SetVersionString()
+extern GFLAGS_DLL_DECL const char* VersionString(); // string set by SetVersionString()
@@ -207,17 +211,16 @@ extern const char* VersionString(); // string set by SetVersionString()
// Return true iff the flagname was found.
// OUTPUT is set to the flag's value, or unchanged if we return false.
-extern bool GetCommandLineOption(const char* name, std::string* OUTPUT);
+extern GFLAGS_DLL_DECL bool GetCommandLineOption(const char* name, std::string* OUTPUT);
// Return true iff the flagname was found. OUTPUT is set to the flag's
// CommandLineFlagInfo or unchanged if we return false.
-extern bool GetCommandLineFlagInfo(const char* name,
- CommandLineFlagInfo* OUTPUT);
+extern GFLAGS_DLL_DECL bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT);
// Return the CommandLineFlagInfo of the flagname. exit() if name not found.
// Example usage, to check if a flag's value is currently the default value:
// if (GetCommandLineFlagInfoOrDie("foo").is_default) ...
-extern CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name);
+extern GFLAGS_DLL_DECL CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name);
enum GFLAGS_DLL_DECL FlagSettingMode {
// update the flag's value (can call this multiple times).
@@ -239,9 +242,8 @@ enum GFLAGS_DLL_DECL FlagSettingMode {
// non-empty else.
// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case)
-extern std::string SetCommandLineOption(const char* name, const char* value);
-extern std::string SetCommandLineOptionWithMode(const char* name, const char* value,
- FlagSettingMode set_mode);
+extern GFLAGS_DLL_DECL std::string SetCommandLineOption (const char* name, const char* value);
+extern GFLAGS_DLL_DECL std::string SetCommandLineOptionWithMode(const char* name, const char* value, FlagSettingMode set_mode);
// --------------------------------------------------------------------
@@ -262,8 +264,8 @@ extern std::string SetCommandLineOptionWithMode(const char* name, const char* va
// // without worrying about restoring the FLAG values.
// }
//
-// Note: This class is marked with ATTRIBUTE_UNUSED because all the
-// work is done in the constructor and destructor, so in the standard
+// Note: This class is marked with GFLAGS_ATTRIBUTE_UNUSED because all
+// the work is done in the constructor and destructor, so in the standard
// usage example above, the compiler would complain that it's an
// unused variable.
//
@@ -282,27 +284,23 @@ class GFLAGS_DLL_DECL FlagSaver {
FlagSaver(const FlagSaver&); // no copying!
void operator=(const FlagSaver&);
-}
-#ifndef _MSC_VER
-__attribute__ ((unused))
-#endif
-;
+};
// --------------------------------------------------------------------
// Some deprecated or hopefully-soon-to-be-deprecated functions.
// This is often used for logging. TODO(csilvers): figure out a better way
-extern std::string CommandlineFlagsIntoString();
+extern GFLAGS_DLL_DECL std::string CommandlineFlagsIntoString();
// Usually where this is used, a FlagSaver should be used instead.
-extern bool ReadFlagsFromString(const std::string& flagfilecontents,
- const char* prog_name,
- bool errors_are_fatal); // uses SET_FLAGS_VALUE
+extern GFLAGS_DLL_DECL
+bool ReadFlagsFromString(const std::string& flagfilecontents,
+ const char* prog_name,
+ bool errors_are_fatal); // uses SET_FLAGS_VALUE
// These let you manually implement --flagfile functionality.
// DEPRECATED.
-extern bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
-extern bool ReadFromFlagsFile(const std::string& filename, const char* prog_name,
- bool errors_are_fatal); // uses SET_FLAGS_VALUE
+extern GFLAGS_DLL_DECL bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
+extern GFLAGS_DLL_DECL bool ReadFromFlagsFile(const std::string& filename, const char* prog_name, bool errors_are_fatal); // uses SET_FLAGS_VALUE
// --------------------------------------------------------------------
@@ -313,12 +311,12 @@ extern bool ReadFromFlagsFile(const std::string& filename, const char* prog_name
// Otherwise, return the value. NOTE: for booleans, for true use
// 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'.
-extern bool BoolFromEnv(const char *varname, bool defval);
-extern int32 Int32FromEnv(const char *varname, int32 defval);
-extern int64 Int64FromEnv(const char *varname, int64 defval);
-extern uint64 Uint64FromEnv(const char *varname, uint64 defval);
-extern double DoubleFromEnv(const char *varname, double defval);
-extern const char *StringFromEnv(const char *varname, const char *defval);
+extern GFLAGS_DLL_DECL bool BoolFromEnv(const char *varname, bool defval);
+extern GFLAGS_DLL_DECL int32 Int32FromEnv(const char *varname, int32 defval);
+extern GFLAGS_DLL_DECL int64 Int64FromEnv(const char *varname, int64 defval);
+extern GFLAGS_DLL_DECL uint64 Uint64FromEnv(const char *varname, uint64 defval);
+extern GFLAGS_DLL_DECL double DoubleFromEnv(const char *varname, double defval);
+extern GFLAGS_DLL_DECL const char *StringFromEnv(const char *varname, const char *defval);
// --------------------------------------------------------------------
@@ -330,12 +328,12 @@ extern const char *StringFromEnv(const char *varname, const char *defval);
// SetUsageMessage(usage);
// Do not include commandline flags in the usage: we do that for you!
// Thread-hostile; meant to be called before any threads are spawned.
-extern void SetUsageMessage(const std::string& usage);
+extern GFLAGS_DLL_DECL void SetUsageMessage(const std::string& usage);
// Sets the version string, which is emitted with --version.
// For instance: SetVersionString("1.3");
// Thread-hostile; meant to be called before any threads are spawned.
-extern void SetVersionString(const std::string& version);
+extern GFLAGS_DLL_DECL void SetVersionString(const std::string& version);
// Looks for flags in argv and parses them. Rearranges argv to put
@@ -345,7 +343,7 @@ extern void SetVersionString(const std::string& version);
// of the first non-flag argument.
// See top-of-file for more details on this function.
#ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead.
-extern uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
+extern GFLAGS_DLL_DECL uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
#endif
@@ -359,18 +357,18 @@ extern uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
// defined more than once in the command line or flag file, the last
// definition is used. Returns the index (into argv) of the first
// non-flag argument. (If remove_flags is true, will always return 1.)
-extern uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv,
- bool remove_flags);
+extern GFLAGS_DLL_DECL uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv, bool remove_flags);
+
// This is actually defined in gflags_reporting.cc.
// This function is misnamed (it also handles --version, etc.), but
// it's too late to change that now. :-(
-extern void HandleCommandLineHelpFlags(); // in gflags_reporting.cc
+extern GFLAGS_DLL_DECL void HandleCommandLineHelpFlags(); // in gflags_reporting.cc
// Allow command line reparsing. Disables the error normally
// generated when an unknown flag is found, since it may be found in a
// later parse. Thread-hostile; meant to be called before any threads
// are spawned.
-extern void AllowCommandLineReparsing();
+extern GFLAGS_DLL_DECL void AllowCommandLineReparsing();
// Reparse the flags that have not yet been recognized. Only flags
// registered since the last parse will be recognized. Any flag value
@@ -378,7 +376,7 @@ extern void AllowCommandLineReparsing();
// separate command line argument that follows the flag argument.
// Intended for handling flags from dynamically loaded libraries,
// since their flags are not registered until they are loaded.
-extern void ReparseCommandLineNonHelpFlags();
+extern GFLAGS_DLL_DECL void ReparseCommandLineNonHelpFlags();
// Clean up memory allocated by flags. This is only needed to reduce
// the quantity of "potentially leaked" reports emitted by memory
@@ -389,7 +387,7 @@ extern void ReparseCommandLineNonHelpFlags();
// called will have unexpected consequences. This is not safe to run
// when multiple threads might be running: the function is
// thread-hostile.
-extern void ShutDownCommandLineFlags();
+extern GFLAGS_DLL_DECL void ShutDownCommandLineFlags();
// --------------------------------------------------------------------
@@ -420,7 +418,7 @@ extern void ShutDownCommandLineFlags();
// directly. The idea is that DEFINE puts the flag in the weird
// namespace, and DECLARE imports the flag from there into the current
// namespace. The net result is to force people to use DECLARE to get
-// access to a flag, rather than saying "extern bool FLAGS_whatever;"
+// access to a flag, rather than saying "extern GFLAGS_DLL_DECL bool FLAGS_whatever;"
// or some such instead. We want this so we can put extra
// functionality (like sanity-checking) in DECLARE if we want, and
// make sure it is picked up everywhere.
@@ -441,16 +439,18 @@ class GFLAGS_DLL_DECL FlagRegisterer {
// binary file. This can reduce the size of the resulting binary
// somewhat, and may also be useful for security reasons.
-extern const char kStrippedFlagHelp[];
+extern GFLAGS_DLL_DECL const char kStrippedFlagHelp[];
+
+
+} // namespace gflags
-}
#ifndef SWIG // In swig, ignore the main flag declarations
#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
// Need this construct to avoid the 'defined but not used' warning.
#define MAYBE_STRIPPED_HELP(txt) \
- (false ? (txt) : ::google::kStrippedFlagHelp)
+ (false ? (txt) : gflags::kStrippedFlagHelp)
#else
#define MAYBE_STRIPPED_HELP(txt) txt
#endif
@@ -472,7 +472,7 @@ extern const char kStrippedFlagHelp[];
/* We always want to export defined variables, dll or no */ \
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \
type FLAGS_no##name = FLAGS_nono##name; \
- static ::google::FlagRegisterer o_##name( \
+ static gflags::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
@@ -505,15 +505,15 @@ GFLAGS_DLL_DECL bool IsBoolFlag(bool from);
DEFINE_VARIABLE(bool, B, name, val, txt)
#define DEFINE_int32(name, val, txt) \
- DEFINE_VARIABLE(::google::int32, I, \
+ DEFINE_VARIABLE(gflags::int32, I, \
name, val, txt)
#define DEFINE_int64(name, val, txt) \
- DEFINE_VARIABLE(::google::int64, I64, \
+ DEFINE_VARIABLE(gflags::int64, I64, \
name, val, txt)
#define DEFINE_uint64(name,val, txt) \
- DEFINE_VARIABLE(::google::uint64, U64, \
+ DEFINE_VARIABLE(gflags::uint64, U64, \
name, val, txt)
#define DEFINE_double(name, val, txt) \
@@ -554,7 +554,7 @@ inline clstring* dont_pass0toDEFINE_string(char *stringspot,
clstring* const FLAGS_no##name = ::fLS:: \
dont_pass0toDEFINE_string(s_##name[0].s, \
val); \
- static ::google::FlagRegisterer o_##name( \
+ static gflags::FlagRegisterer o_##name( \
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \
@@ -565,4 +565,4 @@ inline clstring* dont_pass0toDEFINE_string(char *stringspot,
#endif // SWIG
-#endif // BASE_COMMANDLINEFLAGS_H_
+#endif // GFLAGS_GFLAGS_H_
diff --git a/extern/libmv/third_party/gflags/gflags/gflags_completions.h b/extern/libmv/third_party/gflags/gflags/gflags_completions.h
index 37f5b0ec2cf..2fa0db6d48a 100644
--- a/extern/libmv/third_party/gflags/gflags/gflags_completions.h
+++ b/extern/libmv/third_party/gflags/gflags/gflags_completions.h
@@ -109,22 +109,13 @@ $ complete -o bashdefault -o default -o nospace -C \
// produce the expected completion output.
-#ifndef BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
-#define BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
+#ifndef GFLAGS_COMPLETIONS_H_
+#define GFLAGS_COMPLETIONS_H_
-// Annoying stuff for windows -- makes sure clients can import these functions
-//
-// NOTE: all functions below MUST have an explicit 'extern' before
-// them. Our automated opensourcing tools use this as a signal to do
-// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
-//
-#define GFLAGS_DLL_DECL /* rewritten to be non-empty in windows dir */
-
-
-namespace google {
+namespace gflags {
extern void HandleCommandLineCompletions(void);
}
-#endif // BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
+#endif // GFLAGS_COMPLETIONS_H_
diff --git a/extern/libmv/third_party/gflags/gflags/gflags_declare.h b/extern/libmv/third_party/gflags/gflags/gflags_declare.h
index 503b686657f..335c389b610 100644
--- a/extern/libmv/third_party/gflags/gflags/gflags_declare.h
+++ b/extern/libmv/third_party/gflags/gflags/gflags_declare.h
@@ -34,43 +34,64 @@
// This is the file that should be included by any file which declares
// command line flag.
-#ifndef BASE_COMMANDLINEFLAGS_DECLARE_H_
-#define BASE_COMMANDLINEFLAGS_DECLARE_H_
-
-#include <string>
-#if 1
-#include <stdint.h> // the normal place uint16_t is defined
+#ifndef GFLAGS_DECLARE_H_
+#define GFLAGS_DECLARE_H_
+
+// ---------------------------------------------------------------------------
+// Windows DLL import/export.
+
+// We always want to import the symbols of the gflags library
+#ifndef GFLAGS_DLL_DECL
+# if 0 && defined(_MSC_VER)
+# define GFLAGS_DLL_DECL __declspec(dllimport)
+# else
+# define GFLAGS_DLL_DECL
+# endif
#endif
-#if 1
-#include <sys/types.h> // the normal place u_int16_t is defined
+
+// We always want to import variables declared in user code
+#ifndef GFLAGS_DLL_DECLARE_FLAG
+# if 0 && defined(_MSC_VER)
+# define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport)
+# else
+# define GFLAGS_DLL_DECLARE_FLAG
+# endif
#endif
+
+// ---------------------------------------------------------------------------
+// Flag types
+#include <string>
#if 1
-#include <inttypes.h> // a third place for uint16_t or u_int16_t
+# include <stdint.h> // the normal place uint32_t is defined
+#elif 1
+# include <sys/types.h> // the normal place u_int32_t is defined
+#elif 1
+# include <inttypes.h> // a third place for uint32_t or u_int32_t
#endif
-namespace google {
-#if defined(__GNUC__) || defined(__MINGW32__) // the C99 format
-typedef int32_t int32;
-typedef uint32_t uint32;
-typedef int64_t int64;
-typedef uint64_t uint64;
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) // the BSD format
-typedef int32_t int32;
-typedef u_int32_t uint32;
-typedef int64_t int64;
-typedef u_int64_t uint64;
-#elif defined(_MSC_VER) // the windows (vc7) format
-typedef __int32 int32;
+namespace gflags {
+
+#if 1 // C99
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
+#elif 0 // BSD
+typedef int32_t int32;
+typedef u_int32_t uint32;
+typedef int64_t int64;
+typedef u_int64_t uint64;
+#elif 0 // Windows
+typedef __int32 int32;
typedef unsigned __int32 uint32;
-typedef __int64 int64;
+typedef __int64 int64;
typedef unsigned __int64 uint64;
#else
-#error Do not know how to define a 32-bit integer quantity on your system
+# error Do not know how to define a 32-bit integer quantity on your system
#endif
-}
+} // namespace gflags
-#define GFLAGS_DLL_DECLARE_FLAG /* rewritten to be non-empty in windows dir */
namespace fLS {
@@ -80,7 +101,8 @@ namespace fLS {
// included). Save the current meaning now and use it in the macros.
typedef std::string clstring;
-}
+} // namespace fLS
+
#define DECLARE_VARIABLE(type, shorttype, name) \
/* We always want to import declared variables, dll or no */ \
@@ -91,22 +113,24 @@ typedef std::string clstring;
DECLARE_VARIABLE(bool, B, name)
#define DECLARE_int32(name) \
- DECLARE_VARIABLE(::google::int32, I, name)
+ DECLARE_VARIABLE(::gflags::int32, I, name)
#define DECLARE_int64(name) \
- DECLARE_VARIABLE(::google::int64, I64, name)
+ DECLARE_VARIABLE(::gflags::int64, I64, name)
#define DECLARE_uint64(name) \
- DECLARE_VARIABLE(::google::uint64, U64, name)
+ DECLARE_VARIABLE(::gflags::uint64, U64, name)
#define DECLARE_double(name) \
DECLARE_VARIABLE(double, D, name)
#define DECLARE_string(name) \
- namespace fLS { \
- using ::fLS::clstring; \
+ /* We always want to import declared variables, dll or no */ \
+ namespace fLS { \
+ using ::fLS::clstring; \
extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \
- } \
+ } \
using fLS::FLAGS_##name
-#endif // BASE_COMMANDLINEFLAGS_DECLARE_H_
+
+#endif // GFLAGS_DECLARE_H_
diff --git a/extern/libmv/third_party/gflags/gflags_completions.cc b/extern/libmv/third_party/gflags/gflags_completions.cc
index f46a2e0814e..3a476230ff9 100644
--- a/extern/libmv/third_party/gflags/gflags_completions.cc
+++ b/extern/libmv/third_party/gflags/gflags_completions.cc
@@ -48,6 +48,7 @@
#include "config.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // for strlen
@@ -57,17 +58,13 @@
#include <utility>
#include <vector>
-#include "gflags/gflags_completions.h"
-#include "gflags/gflags.h"
+#include "gflags.h"
#include "util.h"
using std::set;
using std::string;
using std::vector;
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR '/'
-#endif
DEFINE_string(tab_completion_word, "",
"If non-empty, HandleCommandLineCompletions() will hijack the "
@@ -76,7 +73,9 @@ DEFINE_string(tab_completion_word, "",
DEFINE_int32(tab_completion_columns, 80,
"Number of columns to use in output for tab completion");
-_START_GOOGLE_NAMESPACE_
+
+namespace GFLAGS_NAMESPACE {
+
namespace {
// Function prototypes and Type forward declarations. Code may be
@@ -766,4 +765,5 @@ void HandleCommandLineCompletions(void) {
gflags_exitfunc(0);
}
-_END_GOOGLE_NAMESPACE_
+
+} // namespace GFLAGS_NAMESPACE
diff --git a/extern/libmv/third_party/gflags/gflags_reporting.cc b/extern/libmv/third_party/gflags/gflags_reporting.cc
index c74bcc8d762..9cc41a7488c 100644
--- a/extern/libmv/third_party/gflags/gflags_reporting.cc
+++ b/extern/libmv/third_party/gflags/gflags_reporting.cc
@@ -48,40 +48,32 @@
// called after all flag-values have been assigned, that is, after
// parsing the command-line.
-#include "config.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <string>
#include <vector>
-#include "gflags/gflags.h"
-#include "gflags/gflags_completions.h"
+
+#include "config.h"
+#include "gflags.h"
+#include "gflags_completions.h"
#include "util.h"
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR '/'
-#endif
// The 'reporting' flags. They all call gflags_exitfunc().
-DEFINE_bool(help, false,
- "show help on all flags [tip: all flags can have two dashes]");
-DEFINE_bool(helpfull, false,
- "show help on all flags -- same as -help");
-DEFINE_bool(helpshort, false,
- "show help on only the main module for this program");
-DEFINE_string(helpon, "",
- "show help on the modules named by this flag value");
-DEFINE_string(helpmatch, "",
- "show help on modules whose name contains the specified substr");
-DEFINE_bool(helppackage, false,
- "show help on all modules in the main package");
-DEFINE_bool(helpxml, false,
- "produce an xml version of help");
-DEFINE_bool(version, false,
- "show version and build info and exit");
-
-_START_GOOGLE_NAMESPACE_
+DEFINE_bool (help, false, "show help on all flags [tip: all flags can have two dashes]");
+DEFINE_bool (helpfull, false, "show help on all flags -- same as -help");
+DEFINE_bool (helpshort, false, "show help on only the main module for this program");
+DEFINE_string(helpon, "", "show help on the modules named by this flag value");
+DEFINE_string(helpmatch, "", "show help on modules whose name contains the specified substr");
+DEFINE_bool (helppackage, false, "show help on all modules in the main package");
+DEFINE_bool (helpxml, false, "produce an xml version of help");
+DEFINE_bool (version, false, "show version and build info and exit");
+
+
+namespace GFLAGS_NAMESPACE {
+
using std::string;
using std::vector;
@@ -254,7 +246,7 @@ static bool FileMatchesSubstring(const string& filename,
// the string to be at the beginning of a directory component.
// That should match the first directory component as well, so
// we allow '/foo' to match a filename of 'foo'.
- if (!target->empty() && (*target)[0] == '/' &&
+ if (!target->empty() && (*target)[0] == PATH_SEPARATOR &&
strncmp(filename.c_str(), target->c_str() + 1,
strlen(target->c_str() + 1)) == 0)
return true;
@@ -360,7 +352,8 @@ static void ShowVersion() {
static void AppendPrognameStrings(vector<string>* substrings,
const char* progname) {
- string r("/");
+ string r("");
+ r += PATH_SEPARATOR;
r += progname;
substrings->push_back(r + ".");
substrings->push_back(r + "-main.");
@@ -395,7 +388,7 @@ void HandleCommandLineHelpFlags() {
gflags_exitfunc(1);
} else if (!FLAGS_helpon.empty()) {
- string restrict = "/" + FLAGS_helpon + ".";
+ string restrict = PATH_SEPARATOR + FLAGS_helpon + ".";
ShowUsageWithFlagsRestrict(progname, restrict.c_str());
gflags_exitfunc(1);
@@ -417,7 +410,7 @@ void HandleCommandLineHelpFlags() {
++flag) {
if (!FileMatchesSubstring(flag->filename, substrings))
continue;
- const string package = Dirname(flag->filename) + "/";
+ const string package = Dirname(flag->filename) + PATH_SEPARATOR;
if (package != last_package) {
ShowUsageWithFlagsRestrict(progname, package.c_str());
VLOG(7) << "Found package: " << package;
@@ -444,4 +437,5 @@ void HandleCommandLineHelpFlags() {
}
}
-_END_GOOGLE_NAMESPACE_
+
+} // namespace GFLAGS_NAMESPACE
diff --git a/extern/libmv/third_party/gflags/mutex.h b/extern/libmv/third_party/gflags/mutex.h
index 7c3c060a043..0bdd9d5f2a5 100644
--- a/extern/libmv/third_party/gflags/mutex.h
+++ b/extern/libmv/third_party/gflags/mutex.h
@@ -32,11 +32,6 @@
// A simple mutex wrapper, supporting locks and read-write locks.
// You should assume the locks are *not* re-entrant.
//
-// To use: you should define the following macros in your configure.ac:
-// ACX_PTHREAD
-// AC_RWLOCK
-// The latter is defined in ../autoconf.
-//
// This class is meant to be internal-only and should be wrapped by an
// internal namespace. Before you use this module, please give the
// name of your internal namespace for this module. Or, if you want
@@ -108,14 +103,14 @@
// weird to a Mutex's memory after it is destroyed, but for a
// static global variable, that's pretty safe.
-#ifndef GOOGLE_MUTEX_H_
-#define GOOGLE_MUTEX_H_
+#ifndef GFLAGS_MUTEX_H_
+#define GFLAGS_MUTEX_H_
-#include "config.h" // to figure out pthreads support
+#include "gflags_declare.h" // to figure out pthreads support
#if defined(NO_THREADS)
- typedef int MutexType; // to keep a lock-count
-#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
+ typedef int MutexType; // to keep a lock-count
+#elif defined(OS_WINDOWS)
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
# endif
@@ -232,7 +227,7 @@ bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; }
void Mutex::ReaderLock() { assert(++mutex_ > 0); }
void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
-#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
+#elif defined(OS_WINDOWS)
Mutex::Mutex() : destroy_(true) {
InitializeCriticalSection(&mutex_);
@@ -353,4 +348,4 @@ using namespace MUTEX_NAMESPACE;
#undef MUTEX_NAMESPACE
-#endif /* #define GOOGLE_MUTEX_H__ */
+#endif /* #define GFLAGS_MUTEX_H__ */
diff --git a/extern/libmv/third_party/gflags/util.h b/extern/libmv/third_party/gflags/util.h
index 8e2b1b89525..366e1be22e2 100644
--- a/extern/libmv/third_party/gflags/util.h
+++ b/extern/libmv/third_party/gflags/util.h
@@ -34,48 +34,53 @@
#ifndef GFLAGS_UTIL_H_
#define GFLAGS_UTIL_H_
-#include <assert.h>
#include "config.h"
+
+#include <assert.h>
+#include <config.h>
#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
+# include <inttypes.h>
#endif
#include <stdarg.h> // for va_*
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
+#include <errno.h>
#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif // for mkdir()
+# include <sys/stat.h> // for mkdir
+#endif
+
+
+namespace GFLAGS_NAMESPACE {
-_START_GOOGLE_NAMESPACE_
// This is used for unittests for death-testing. It is defined in gflags.cc.
extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int);
-// Work properly if either strtoll or strtoq is on this system
-#ifdef HAVE_STRTOLL
-# define strto64 strtoll
-# define strtou64 strtoull
-#elif HAVE_STRTOQ
-# define strto64 strtoq
-# define strtou64 strtouq
-#else
+// Work properly if either strtoll or strtoq is on this system.
+#if defined(strtoll) || defined(HAVE_STRTOLL)
+# define strto64 strtoll
+# define strtou64 strtoull
+#elif defined(HAVE_STRTOQ)
+# define strto64 strtoq
+# define strtou64 strtouq
// Neither strtoll nor strtoq are defined. I hope strtol works!
-# define strto64 strtol
-# define strtou64 strtoul
+#else
+# define strto64 strtol
+# define strtou64 strtoul
#endif
-// If we have inttypes.h, it will have defined PRId32/etc for us. If
-// not, take our best guess.
+// If we have inttypes.h, it will have defined PRId32/etc for us.
+// If not, take our best guess.
#ifndef PRId32
-# define PRId32 "d"
+# define PRId32 "d"
#endif
#ifndef PRId64
-# define PRId64 "lld"
+# define PRId64 "lld"
#endif
#ifndef PRIu64
-# define PRIu64 "llu"
+# define PRIu64 "llu"
#endif
typedef signed char int8;
@@ -230,37 +235,36 @@ class Test {};
#if defined(__MINGW32__)
#include <io.h>
inline void MakeTmpdir(std::string* path) {
+ if (!path->empty()) {
+ path->append("/gflags_unittest_testdir");
+ int err = mkdir(path->c_str());
+ if (err == 0 || errno == EEXIST) return;
+ }
// I had trouble creating a directory in /tmp from mingw
- *path = "./gflags_unittest_testdir";
- mkdir(path->c_str()); // mingw has a weird one-arg mkdir
+ *path = "./gflags_unittest";
+ mkdir(path->c_str());
}
#elif defined(_MSC_VER)
#include <direct.h>
-#include <windows.h>
inline void MakeTmpdir(std::string* path) {
+ if (!path->empty()) {
+ int err = _mkdir(path->c_str());
+ if (err == 0 || errno == EEXIST) return;
+ }
char tmppath_buffer[1024];
int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it
- *path = std::string(tmppath_buffer) + "gflags_unittest_testdir";
+ *path = std::string(tmppath_buffer) + "gflags_unittest";
_mkdir(path->c_str());
}
-// Windows is missing random bits like strcasecmp, strtoll, strtoull, and
-// snprintf in the usual locations. Put them somewhere sensible.
-//
-// TODO(keir): Get the upstream Windows port and use that instead.
-#define snprintf _snprintf
-#undef strtoint64
-#define strtoint64 _strtoi64
-#undef strtouint64
-#define strtouint64 _strtoui64
-#define strcasecmp _stricmp
-#define va_copy(dst, src) ((dst) = (src))
-#define strto64 _strtoi64
-#define strtou64 _strtoui64
#else
inline void MakeTmpdir(std::string* path) {
- mkdir(path->c_str(), 0755);
+ if (!path->empty()) {
+ int err = mkdir(path->c_str(), 0755);
+ if (err == 0 || errno == EEXIST) return;
+ }
+ mkdir("/tmp/gflags_unittest", 0755);
}
#endif
@@ -278,7 +282,7 @@ inline void InternalStringPrintf(std::string* output, const char* format,
int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap);
va_end(backup_ap);
- if ((bytes_written >= 0) && (bytes_written < sizeof(space))) {
+ if ((bytes_written >= 0) && (static_cast<size_t>(bytes_written) < sizeof(space))) {
output->append(space, bytes_written);
return;
}
@@ -334,6 +338,36 @@ inline std::string StringPrintf(const char* format, ...) {
return output;
}
-_END_GOOGLE_NAMESPACE_
+inline bool SafeGetEnv(const char *varname, std::string &valstr)
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ char *val;
+ size_t sz;
+ if (_dupenv_s(&val, &sz, varname) != 0 || !val) return false;
+ valstr = val;
+ free(val);
+#else
+ const char * const val = getenv(varname);
+ if (!val) return false;
+ valstr = val;
+#endif
+ return true;
+}
+
+inline int SafeFOpen(FILE **fp, const char* fname, const char *mode)
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ return fopen_s(fp, fname, mode);
+#else
+ assert(fp != NULL);
+ *fp = fopen(fname, mode);
+ // errno only guaranteed to be set on failure
+ return ((*fp == NULL) ? errno : 0);
+#endif
+}
+
+
+} // namespace GFLAGS_NAMESPACE
+
#endif // GFLAGS_UTIL_H_
diff --git a/extern/libmv/third_party/gflags/windows_port.cc b/extern/libmv/third_party/gflags/windows_port.cc
new file mode 100644
index 00000000000..1f40458e888
--- /dev/null
+++ b/extern/libmv/third_party/gflags/windows_port.cc
@@ -0,0 +1,71 @@
+/* Copyright (c) 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Craig Silverstein
+ */
+
+#ifndef _WIN32
+# error You should only be including windows/port.cc in a windows environment!
+#endif
+
+#include <string.h> // for strlen(), memset(), memcmp()
+#include <assert.h>
+#include <stdarg.h> // for va_list, va_start, va_end
+#include <windows.h>
+
+#include "windows_port.h"
+
+// These call the windows _vsnprintf, but always NUL-terminate.
+#if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996) // ignore _vsnprintf security warning
+#endif
+int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ if (size == 0) // not even room for a \0?
+ return -1; // not what C99 says to do, but what windows does
+ str[size-1] = '\0';
+ return _vsnprintf(str, size-1, format, ap);
+}
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+int snprintf(char *str, size_t size, const char *format, ...) {
+ int r;
+ va_list ap;
+ va_start(ap, format);
+ r = vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return r;
+}
+
+#endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
diff --git a/extern/libmv/third_party/gflags/windows_port.h b/extern/libmv/third_party/gflags/windows_port.h
new file mode 100644
index 00000000000..c8ff24f8f00
--- /dev/null
+++ b/extern/libmv/third_party/gflags/windows_port.h
@@ -0,0 +1,127 @@
+/* Copyright (c) 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Craig Silverstein
+ *
+ * These are some portability typedefs and defines to make it a bit
+ * easier to compile this code under VC++.
+ *
+ * Several of these are taken from glib:
+ * http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
+ */
+
+#ifndef GFLAGS_WINDOWS_PORT_H_
+#define GFLAGS_WINDOWS_PORT_H_
+
+#include "config.h"
+
+// This must be defined before the windows.h is included.
+// It's needed for mutex.h, to give access to the TryLock method.
+# if !defined(_WIN32_WINNT) && !(defined( __MINGW32__) || defined(__MINGW64__))
+# define _WIN32_WINNT 0x0400
+# endif
+// We always want minimal includes
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <direct.h> /* for mkdir */
+#include <stdlib.h> /* for _putenv, getenv */
+#include <stdio.h> /* need this to override stdio's snprintf, also defines _unlink used by unit tests */
+#include <stdarg.h> /* util.h uses va_copy */
+#include <string.h> /* for _stricmp and _strdup */
+
+/* We can't just use _vsnprintf and _snprintf as drop-in-replacements,
+ * because they don't always NUL-terminate. :-( We also can't use the
+ * name vsnprintf, since windows defines that (but not snprintf (!)).
+ */
+#if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */
+extern GFLAGS_DLL_DECL int snprintf(char *str, size_t size,
+ const char *format, ...);
+extern int GFLAGS_DLL_DECL safe_vsnprintf(char *str, size_t size,
+ const char *format, va_list ap);
+#define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap)
+#define va_copy(dst, src) (dst) = (src)
+#endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996) // ignore getenv security warning
+#endif
+inline void setenv(const char* name, const char* value, int) {
+ // In windows, it's impossible to set a variable to the empty string.
+ // We handle this by setting it to "0" and the NUL-ing out the \0.
+ // That is, we putenv("FOO=0") and then find out where in memory the
+ // putenv wrote "FOO=0", and change it in-place to "FOO=\0".
+ // c.f. http://svn.apache.org/viewvc/stdcxx/trunk/tests/src/environ.cpp?r1=611451&r2=637508&pathrev=637508
+ static const char* const kFakeZero = "0";
+ if (*value == '\0')
+ value = kFakeZero;
+ // Apparently the semantics of putenv() is that the input
+ // must live forever, so we leak memory here. :-(
+ const size_t nameval_len = strlen(name) + 1 + strlen(value) + 1;
+ char* nameval = reinterpret_cast<char*>(malloc(nameval_len));
+ snprintf(nameval, nameval_len, "%s=%s", name, value);
+ _putenv(nameval);
+ if (value == kFakeZero) {
+ nameval[nameval_len - 2] = '\0'; // works when putenv() makes no copy
+ if (*getenv(name) != '\0')
+ *getenv(name) = '\0'; // works when putenv() copies nameval
+ }
+}
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#define strcasecmp _stricmp
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+#define strdup _strdup
+#define unlink _unlink
+#endif
+
+#define PRId32 "d"
+#define PRIu32 "u"
+#define PRId64 "I64d"
+#define PRIu64 "I64u"
+
+#if !defined(__MINGW32__) && !defined(__MINGW64__)
+#define strtoq _strtoi64
+#define strtouq _strtoui64
+#define strtoll _strtoi64
+#define strtoull _strtoui64
+#define atoll _atoi64
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#endif /* GFLAGS_WINDOWS_PORT_H_ */
diff --git a/extern/libmv/third_party/glog/README.libmv b/extern/libmv/third_party/glog/README.libmv
index eb4b2ea3379..10e51fa6df4 100644
--- a/extern/libmv/third_party/glog/README.libmv
+++ b/extern/libmv/third_party/glog/README.libmv
@@ -1,7 +1,7 @@
Project: Google Logging
URL: http://code.google.com/p/google-glog/
License: New BSD
-Upstream version: 0.3.3, r139
+Upstream version: 0.3.3, r143
Local modifications:
* Added per-platform config.h files so no configuration-time
checks for functions and so are needed.
diff --git a/extern/libmv/third_party/glog/src/demangle.cc b/extern/libmv/third_party/glog/src/demangle.cc
index 0daf30893b3..e858181a68f 100644
--- a/extern/libmv/third_party/glog/src/demangle.cc
+++ b/extern/libmv/third_party/glog/src/demangle.cc
@@ -167,7 +167,7 @@ static size_t StrLen(const char *str) {
// Returns true if "str" has at least "n" characters remaining.
static bool AtLeastNumCharsRemaining(const char *str, int n) {
for (int i = 0; i < n; ++i) {
- if (str == '\0') {
+ if (str[i] == '\0') {
return false;
}
}
@@ -223,9 +223,6 @@ static bool ParseTwoCharToken(State *state, const char *two_char_token) {
// Returns true and advances "mangled_cur" if we find any character in
// "char_class" at "mangled_cur" position.
static bool ParseCharClass(State *state, const char *char_class) {
- if (state->mangled_cur == '\0') {
- return false;
- }
const char *p = char_class;
for (; *p != '\0'; ++p) {
if (state->mangled_cur[0] == *p) {
diff --git a/extern/libmv/third_party/glog/src/logging.cc b/extern/libmv/third_party/glog/src/logging.cc
index 5e2ce61c9c9..75047353535 100644
--- a/extern/libmv/third_party/glog/src/logging.cc
+++ b/extern/libmv/third_party/glog/src/logging.cc
@@ -31,6 +31,7 @@
#include "utilities.h"
+#include <algorithm>
#include <assert.h>
#include <iomanip>
#include <string>
@@ -181,6 +182,10 @@ GLOG_DEFINE_string(log_backtrace_at, "",
#define PATH_SEPARATOR '/'
#ifndef HAVE_PREAD
+#if defined(OS_WINDOWS)
+#include <BaseTsd.h>
+#define ssize_t SSIZE_T
+#endif
static ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
off_t orig_offset = lseek(fd, 0, SEEK_CUR);
if (orig_offset == (off_t)-1)
diff --git a/extern/libmv/third_party/glog/src/symbolize.cc b/extern/libmv/third_party/glog/src/symbolize.cc
index 18bbccf3072..b25f7479d0d 100644
--- a/extern/libmv/third_party/glog/src/symbolize.cc
+++ b/extern/libmv/third_party/glog/src/symbolize.cc
@@ -45,6 +45,12 @@
// some functions which are not guaranteed to be so, such as memchr()
// and memmove(). We assume they are async-signal-safe.
//
+// Additional header can be specified by the GLOG_BUILD_CONFIG_INCLUDE
+// macro to add platform specific defines (e.g. OS_OPENBSD).
+
+#ifdef GLOG_BUILD_CONFIG_INCLUDE
+#include GLOG_BUILD_CONFIG_INCLUDE
+#endif // GLOG_BUILD_CONFIG_INCLUDE
#include "utilities.h"
@@ -74,6 +80,13 @@ void InstallSymbolizeCallback(SymbolizeCallback callback) {
g_symbolize_callback = callback;
}
+static SymbolizeOpenObjectFileCallback g_symbolize_open_object_file_callback =
+ NULL;
+void InstallSymbolizeOpenObjectFileCallback(
+ SymbolizeOpenObjectFileCallback callback) {
+ g_symbolize_open_object_file_callback = callback;
+}
+
// This function wraps the Demangle function to provide an interface
// where the input symbol is demangled in-place.
// To keep stack consumption low, we would like this function to not
@@ -95,11 +108,14 @@ _END_GOOGLE_NAMESPACE_
#if defined(__ELF__)
#include <dlfcn.h>
+#if defined(OS_OPENBSD)
+#include <sys/exec_elf.h>
+#else
#include <elf.h>
+#endif
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#include <link.h> // For ElfW() macro.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -123,7 +139,7 @@ _START_GOOGLE_NAMESPACE_
// success, return the number of bytes read. Otherwise, return -1.
static ssize_t ReadPersistent(const int fd, void *buf, const size_t count) {
SAFE_ASSERT(fd >= 0);
- SAFE_ASSERT(count >= 0 && count <= std::numeric_limits<ssize_t>::max());
+ SAFE_ASSERT(count <= std::numeric_limits<ssize_t>::max());
char *buf0 = reinterpret_cast<char *>(buf);
ssize_t num_bytes = 0;
while (num_bytes < count) {
@@ -326,31 +342,29 @@ static bool GetSymbolFromObjectFile(const int fd, uint64_t pc,
ElfW(Shdr) symtab, strtab;
// Consult a regular symbol table first.
- if (!GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
- SHT_SYMTAB, &symtab)) {
- return false;
- }
- if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
- symtab.sh_link * sizeof(symtab))) {
- return false;
- }
- if (FindSymbol(pc, fd, out, out_size, symbol_offset,
- &strtab, &symtab)) {
- return true; // Found the symbol in a regular symbol table.
+ if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
+ SHT_SYMTAB, &symtab)) {
+ if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
+ symtab.sh_link * sizeof(symtab))) {
+ return false;
+ }
+ if (FindSymbol(pc, fd, out, out_size, symbol_offset,
+ &strtab, &symtab)) {
+ return true; // Found the symbol in a regular symbol table.
+ }
}
// If the symbol is not found, then consult a dynamic symbol table.
- if (!GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
- SHT_DYNSYM, &symtab)) {
- return false;
- }
- if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
- symtab.sh_link * sizeof(symtab))) {
- return false;
- }
- if (FindSymbol(pc, fd, out, out_size, symbol_offset,
- &strtab, &symtab)) {
- return true; // Found the symbol in a dynamic symbol table.
+ if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
+ SHT_DYNSYM, &symtab)) {
+ if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
+ symtab.sh_link * sizeof(symtab))) {
+ return false;
+ }
+ if (FindSymbol(pc, fd, out, out_size, symbol_offset,
+ &strtab, &symtab)) {
+ return true; // Found the symbol in a dynamic symbol table.
+ }
}
return false;
@@ -481,13 +495,20 @@ static char *GetHex(const char *start, const char *end, uint64_t *hex) {
return const_cast<char *>(p);
}
-// Search for the object file (from /proc/self/maps) that contains
-// the specified pc. If found, open this file and return the file handle,
-// and also set start_address to the start address of where this object
-// file is mapped to in memory. Otherwise, return -1.
+// Searches for the object file (from /proc/self/maps) that contains
+// the specified pc. If found, sets |start_address| to the start address
+// of where this object file is mapped in memory, sets the module base
+// address into |base_address|, copies the object file name into
+// |out_file_name|, and attempts to open the object file. If the object
+// file is opened successfully, returns the file descriptor. Otherwise,
+// returns -1. |out_file_name_size| is the size of the file name buffer
+// (including the null-terminator).
static ATTRIBUTE_NOINLINE int
OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
- uint64_t &start_address) {
+ uint64_t &start_address,
+ uint64_t &base_address,
+ char *out_file_name,
+ int out_file_name_size) {
int object_fd;
// Open /proc/self/maps.
@@ -501,8 +522,10 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
// Iterate over maps and look for the map containing the pc. Then
// look into the symbol tables inside.
char buf[1024]; // Big enough for line of sane /proc/self/maps
+ int num_maps = 0;
LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf));
while (true) {
+ num_maps++;
const char *cursor;
const char *eol;
if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line.
@@ -552,14 +575,35 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
}
++cursor; // Skip ' '.
- // Skip to file name. "cursor" now points to file offset. We need to
- // skip at least three spaces for file offset, dev, and inode.
+ // Read file offset.
+ uint64_t file_offset;
+ cursor = GetHex(cursor, eol, &file_offset);
+ if (cursor == eol || *cursor != ' ') {
+ return -1; // Malformed line.
+ }
+ ++cursor; // Skip ' '.
+
+ // Don't subtract 'start_address' from the first entry:
+ // * If a binary is compiled w/o -pie, then the first entry in
+ // process maps is likely the binary itself (all dynamic libs
+ // are mapped higher in address space). For such a binary,
+ // instruction offset in binary coincides with the actual
+ // instruction address in virtual memory (as code section
+ // is mapped to a fixed memory range).
+ // * If a binary is compiled with -pie, all the modules are
+ // mapped high at address space (in particular, higher than
+ // shadow memory of the tool), so the module can't be the
+ // first entry.
+ base_address = ((num_maps == 1) ? 0U : start_address) - file_offset;
+
+ // Skip to file name. "cursor" now points to dev. We need to
+ // skip at least two spaces for dev and inode.
int num_spaces = 0;
while (cursor < eol) {
if (*cursor == ' ') {
++num_spaces;
- } else if (num_spaces >= 3) {
- // The first non-space character after skipping three spaces
+ } else if (num_spaces >= 2) {
+ // The first non-space character after skipping two spaces
// is the beginning of the file name.
break;
}
@@ -572,12 +616,105 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
// Finally, "cursor" now points to file name of our interest.
NO_INTR(object_fd = open(cursor, O_RDONLY));
if (object_fd < 0) {
+ // Failed to open object file. Copy the object file name to
+ // |out_file_name|.
+ strncpy(out_file_name, cursor, out_file_name_size);
+ // Making sure |out_file_name| is always null-terminated.
+ out_file_name[out_file_name_size - 1] = '\0';
return -1;
}
return object_fd;
}
}
+// POSIX doesn't define any async-signal safe function for converting
+// an integer to ASCII. We'll have to define our own version.
+// itoa_r() converts a (signed) integer to ASCII. It returns "buf", if the
+// conversion was successful or NULL otherwise. It never writes more than "sz"
+// bytes. Output will be truncated as needed, and a NUL character is always
+// appended.
+// NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
+char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) {
+ // Make sure we can write at least one NUL byte.
+ size_t n = 1;
+ if (n > sz)
+ return NULL;
+
+ if (base < 2 || base > 16) {
+ buf[0] = '\000';
+ return NULL;
+ }
+
+ char *start = buf;
+
+ uintptr_t j = i;
+
+ // Handle negative numbers (only for base 10).
+ if (i < 0 && base == 10) {
+ j = -i;
+
+ // Make sure we can write the '-' character.
+ if (++n > sz) {
+ buf[0] = '\000';
+ return NULL;
+ }
+ *start++ = '-';
+ }
+
+ // Loop until we have converted the entire number. Output at least one
+ // character (i.e. '0').
+ char *ptr = start;
+ do {
+ // Make sure there is still enough space left in our output buffer.
+ if (++n > sz) {
+ buf[0] = '\000';
+ return NULL;
+ }
+
+ // Output the next digit.
+ *ptr++ = "0123456789abcdef"[j % base];
+ j /= base;
+
+ if (padding > 0)
+ padding--;
+ } while (j > 0 || padding > 0);
+
+ // Terminate the output with a NUL character.
+ *ptr = '\000';
+
+ // Conversion to ASCII actually resulted in the digits being in reverse
+ // order. We can't easily generate them in forward order, as we can't tell
+ // the number of characters needed until we are done converting.
+ // So, now, we reverse the string (except for the possible "-" sign).
+ while (--ptr > start) {
+ char ch = *ptr;
+ *ptr = *start;
+ *start++ = ch;
+ }
+ return buf;
+}
+
+// Safely appends string |source| to string |dest|. Never writes past the
+// buffer size |dest_size| and guarantees that |dest| is null-terminated.
+void SafeAppendString(const char* source, char* dest, int dest_size) {
+ int dest_string_length = strlen(dest);
+ SAFE_ASSERT(dest_string_length < dest_size);
+ dest += dest_string_length;
+ dest_size -= dest_string_length;
+ strncpy(dest, source, dest_size);
+ // Making sure |dest| is always null-terminated.
+ dest[dest_size - 1] = '\0';
+}
+
+// Converts a 64-bit value into a hex string, and safely appends it to |dest|.
+// Never writes past the buffer size |dest_size| and guarantees that |dest| is
+// null-terminated.
+void SafeAppendHexNumber(uint64_t value, char* dest, int dest_size) {
+ // 64-bit numbers in hex can have up to 16 digits.
+ char buf[17] = {'\0'};
+ SafeAppendString(itoa_r(value, buf, sizeof(buf), 16, 0), dest, dest_size);
+}
+
// The implementation of our symbolization routine. If it
// successfully finds the symbol containing "pc" and obtains the
// symbol name, returns true and write the symbol name to "out".
@@ -590,10 +727,40 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
int out_size) {
uint64_t pc0 = reinterpret_cast<uintptr_t>(pc);
uint64_t start_address = 0;
+ uint64_t base_address = 0;
+ int object_fd = -1;
- int object_fd = OpenObjectFileContainingPcAndGetStartAddress(pc0,
- start_address);
- if (object_fd == -1) {
+ if (out_size < 1) {
+ return false;
+ }
+ out[0] = '\0';
+ SafeAppendString("(", out, out_size);
+
+ if (g_symbolize_open_object_file_callback) {
+ object_fd = g_symbolize_open_object_file_callback(pc0, start_address,
+ base_address, out + 1,
+ out_size - 1);
+ } else {
+ object_fd = OpenObjectFileContainingPcAndGetStartAddress(pc0, start_address,
+ base_address,
+ out + 1,
+ out_size - 1);
+ }
+
+ // Check whether a file name was returned.
+ if (object_fd < 0) {
+ if (out[1]) {
+ // The object file containing PC was determined successfully however the
+ // object file was not opened successfully. This is still considered
+ // success because the object file name and offset are known and tools
+ // like asan_symbolize.py can be used for the symbolization.
+ out[out_size - 1] = '\0'; // Making sure |out| is always null-terminated.
+ SafeAppendString("+0x", out, out_size);
+ SafeAppendHexNumber(pc0 - base_address, out, out_size);
+ SafeAppendString(")", out, out_size);
+ return true;
+ }
+ // Failed to determine the object file containing PC. Bail out.
return false;
}
FileDescriptor wrapped_object_fd(object_fd);
diff --git a/extern/libmv/third_party/glog/src/symbolize.h b/extern/libmv/third_party/glog/src/symbolize.h
index 1ebe4dd94a2..f617184249c 100644
--- a/extern/libmv/third_party/glog/src/symbolize.h
+++ b/extern/libmv/third_party/glog/src/symbolize.h
@@ -60,9 +60,26 @@
#ifdef HAVE_SYMBOLIZE
-#if defined(__ELF__) // defined by gcc on Linux
+#if defined(__ELF__) // defined by gcc
+#if defined(__OpenBSD__)
+#include <sys/exec_elf.h>
+#else
#include <elf.h>
+#endif
+
+#if !defined(ANDROID)
#include <link.h> // For ElfW() macro.
+#endif
+
+// For systems where SIZEOF_VOID_P is not defined, determine it
+// based on __LP64__ (defined by gcc on 64-bit systems)
+#if !defined(SIZEOF_VOID_P)
+# if defined(__LP64__)
+# define SIZEOF_VOID_P 8
+# else
+# define SIZEOF_VOID_P 4
+# endif
+#endif
// If there is no ElfW macro, let's define it by ourself.
#ifndef ElfW
@@ -88,6 +105,10 @@ _END_GOOGLE_NAMESPACE_
_START_GOOGLE_NAMESPACE_
+// Restrictions on the callbacks that follow:
+// - The callbacks must not use heaps but only use stacks.
+// - The callbacks must be async-signal-safe.
+
// Installs a callback function, which will be called right before a symbol name
// is printed. The callback is intended to be used for showing a file name and a
// line number preceding a symbol name.
@@ -99,6 +120,24 @@ typedef int (*SymbolizeCallback)(int fd, void *pc, char *out, size_t out_size,
uint64 relocation);
void InstallSymbolizeCallback(SymbolizeCallback callback);
+// Installs a callback function, which will be called instead of
+// OpenObjectFileContainingPcAndGetStartAddress. The callback is expected
+// to searches for the object file (from /proc/self/maps) that contains
+// the specified pc. If found, sets |start_address| to the start address
+// of where this object file is mapped in memory, sets the module base
+// address into |base_address|, copies the object file name into
+// |out_file_name|, and attempts to open the object file. If the object
+// file is opened successfully, returns the file descriptor. Otherwise,
+// returns -1. |out_file_name_size| is the size of the file name buffer
+// (including the null-terminator).
+typedef int (*SymbolizeOpenObjectFileCallback)(uint64_t pc,
+ uint64_t &start_address,
+ uint64_t &base_address,
+ char *out_file_name,
+ int out_file_name_size);
+void InstallSymbolizeOpenObjectFileCallback(
+ SymbolizeOpenObjectFileCallback callback);
+
_END_GOOGLE_NAMESPACE_
#endif
diff --git a/extern/sdlew/src/sdlew.c b/extern/sdlew/src/sdlew.c
index 6444e6b6081..3b19f0cef47 100644
--- a/extern/sdlew/src/sdlew.c
+++ b/extern/sdlew/src/sdlew.c
@@ -565,16 +565,20 @@ int sdlewInit(void) {
/* Library paths. */
#ifdef _WIN32
/* Expected in c:/windows/system or similar, no path needed. */
- const char *path = "SDL2.dll";
+ const char *paths[] = {"SDL2.dll", NULL};
#elif defined(__APPLE__)
/* Default installation path. */
- const char *path = "/usr/local/cuda/lib/libSDL2.dylib";
+ const char *paths[] = {"/usr/local/cuda/lib/libSDL2.dylib", NULL};
#else
- const char *path = "libSDL2.so";
+ const char *paths[] = {"libSDL2.so",
+ "libSDL2-2.0.so.0",
+ "libSDL.so",
+ NULL};
#endif
static int initialized = 0;
static int result = 0;
- int error;
+ int a, error;
+ SDL_version version;
if (initialized) {
return result;
@@ -589,7 +593,9 @@ int sdlewInit(void) {
}
/* Load library. */
- lib = dynamic_library_open(path);
+ for (a = 0; paths[a] != NULL && lib == NULL; ++a) {
+ lib = dynamic_library_open(paths[a]);
+ }
if (lib == NULL) {
result = SDLEW_ERROR_OPEN_FAILED;
@@ -1089,7 +1095,18 @@ int sdlewInit(void) {
SDL_LIBRARY_FIND(SDL_HasClipboardText);
SDL_LIBRARY_FIND(SDL_GetWindowWMInfo);
- result = SDLEW_SUCCESS;
+ if (SDL_GetVersion == NULL) {
+ result = SDLEW_ERROR_VERSION;
+ }
+ else {
+ SDL_GetVersion(&version);
+ if(version.major < 2) {
+ result = SDLEW_ERROR_VERSION;
+ }
+ else {
+ result = SDLEW_SUCCESS;
+ }
+ }
return result;
}
diff --git a/intern/atomic/atomic_ops.h b/intern/atomic/atomic_ops.h
index f63ff630c40..06a5c8d834e 100644
--- a/intern/atomic/atomic_ops.h
+++ b/intern/atomic/atomic_ops.h
@@ -34,6 +34,11 @@
#if defined (__APPLE__)
# include <libkern/OSAtomic.h>
#elif defined(_MSC_VER)
+# define NOGDI
+# ifndef NOMINMAX
+# define NOMINMAX
+# endif
+# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#elif defined(__arm__)
/* Attempt to fix compilation error on Debian armel kernel.
@@ -97,13 +102,13 @@ atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new)
ATOMIC_INLINE uint64_t
atomic_add_uint64(uint64_t *p, uint64_t x)
{
- return InterlockedExchangeAdd64(p, x);
+ return InterlockedExchangeAdd64((int64_t *)p, (int64_t)x);
}
ATOMIC_INLINE uint64_t
atomic_sub_uint64(uint64_t *p, uint64_t x)
{
- return InterlockedExchangeAdd64(p, -((int64_t)x));
+ return InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x));
}
ATOMIC_INLINE uint64_t
diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp
index d2a934740d6..45d72ccb50e 100644
--- a/intern/audaspace/intern/AUD_C-API.cpp
+++ b/intern/audaspace/intern/AUD_C-API.cpp
@@ -46,6 +46,7 @@
#include <cstring>
#include <cmath>
#include <sstream>
+#include <iostream>
#include "AUD_NULLDevice.h"
#include "AUD_I3DDevice.h"
@@ -317,8 +318,9 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound *sound)
info.length = reader->getLength() / (float) info.specs.rate;
}
}
- catch(AUD_Exception&)
+ catch(AUD_Exception &ae)
{
+ std::cout << ae.str << std::endl;
}
return info;
@@ -1084,7 +1086,7 @@ int AUD_doesPlayback()
return -1;
}
-int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second)
+int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second, short *interrupt)
{
AUD_DeviceSpecs specs;
sample_t *buf;
@@ -1107,6 +1109,9 @@ int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_pe
for (int i = 0; i < length; i++) {
len = floor(samplejump * (i+1)) - floor(samplejump * i);
+ if (*interrupt) {
+ return 0;
+ }
aBuffer.assureSize(len * AUD_SAMPLE_SIZE(specs));
buf = aBuffer.getBuffer();
diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h
index 64a3d06bd5f..657d4e6fd02 100644
--- a/intern/audaspace/intern/AUD_C-API.h
+++ b/intern/audaspace/intern/AUD_C-API.h
@@ -646,7 +646,7 @@ extern int AUD_doesPlayback(void);
* \param samples_per_second How many samples to read per second of the sound.
* \return How many samples really have been read. Always <= length.
*/
-extern int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second);
+extern int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second, short *interrupt);
/**
* Copies a sound.
diff --git a/intern/audaspace/intern/AUD_SequencerHandle.cpp b/intern/audaspace/intern/AUD_SequencerHandle.cpp
index 135c960471c..56cfa0de683 100644
--- a/intern/audaspace/intern/AUD_SequencerHandle.cpp
+++ b/intern/audaspace/intern/AUD_SequencerHandle.cpp
@@ -31,18 +31,92 @@
#include "AUD_ReadDevice.h"
#include "AUD_MutexLock.h"
+#define KEEP_TIME 10
+
+void AUD_SequencerHandle::start()
+{
+ // we already tried to start, aborting
+ if(!m_valid)
+ return;
+
+ // in case the sound is playing, we need to stop first
+ stop();
+
+ AUD_MutexLock lock(*m_entry);
+
+ // let's try playing
+ if(m_entry->m_sound.get())
+ {
+ m_handle = m_device.play(m_entry->m_sound, true);
+ m_3dhandle = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle);
+
+ // after starting we have to set the properties, so let's ensure that
+ m_status--;
+ }
+
+ // if the sound could not be played, we invalidate
+ m_valid = m_handle.get();
+}
+
+bool AUD_SequencerHandle::updatePosition(float position)
+{
+ AUD_MutexLock lock(*m_entry);
+
+ if(m_handle.get())
+ {
+ // we currently have a handle, let's check where we are
+ if(position >= m_entry->m_end)
+ {
+ if(position >= m_entry->m_end + KEEP_TIME)
+ // far end, stopping
+ stop();
+ else
+ {
+ // close end, just pausing
+ m_handle->pause();
+ return true;
+ }
+ }
+ else if(position >= m_entry->m_begin)
+ {
+ // inside, resuming
+ m_handle->resume();
+ return true;
+ }
+ else
+ {
+ if(position < m_entry->m_begin - KEEP_TIME)
+ // far beginning, stopping
+ stop();
+ else
+ {
+ // close beginning, just pausing
+ m_handle->pause();
+ return true;
+ }
+ }
+ }
+ else
+ {
+ // we don't have a handle, let's start if we should be playing
+ if(position >= m_entry->m_begin && position <= m_entry->m_end)
+ {
+ start();
+ return m_valid;
+ }
+ }
+
+ return false;
+}
+
AUD_SequencerHandle::AUD_SequencerHandle(boost::shared_ptr<AUD_SequencerEntry> entry, AUD_ReadDevice& device) :
m_entry(entry),
+ m_valid(true),
m_status(0),
m_pos_status(0),
m_sound_status(0),
m_device(device)
{
- if(entry->m_sound.get())
- {
- m_handle = device.play(entry->m_sound, true);
- m_3dhandle = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle);
- }
}
AUD_SequencerHandle::~AUD_SequencerHandle()
@@ -63,101 +137,116 @@ void AUD_SequencerHandle::stop()
{
if(m_handle.get())
m_handle->stop();
+ m_handle = boost::shared_ptr<AUD_IHandle>();
+ m_3dhandle = boost::shared_ptr<AUD_I3DHandle>();
}
void AUD_SequencerHandle::update(float position, float frame, float fps)
{
- if(m_handle.get())
+ if(m_sound_status != m_entry->m_sound_status)
{
- AUD_MutexLock lock(*m_entry);
- if(position >= m_entry->m_end)
- m_handle->pause();
- else if(position >= m_entry->m_begin)
- m_handle->resume();
-
- if(m_sound_status != m_entry->m_sound_status)
- {
- if(m_handle.get())
- m_handle->stop();
+ // if a new sound has been set, it's possible to get valid again!
+ m_sound_status = m_entry->m_sound_status;
+ m_valid = true;
- if(m_entry->m_sound.get())
- {
- m_handle = m_device.play(m_entry->m_sound, true);
- m_3dhandle = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle);
- }
+ // stop whatever sound has been playing
+ stop();
- m_sound_status = m_entry->m_sound_status;
- m_pos_status--;
- m_status--;
- }
+ // seek starts and seeks to the correct position
+ if(!seek(position))
+ // no handle, aborting
+ return;
+ }
+ else
+ {
+ if(!m_valid)
+ // invalid, aborting
+ return;
- if(m_pos_status != m_entry->m_pos_status)
+ if(m_handle.get())
{
- seek(position);
-
- m_pos_status = m_entry->m_pos_status;
+ // we have a handle, let's update the position
+ if(!updatePosition(position))
+ // lost handle, aborting
+ return;
}
-
- if(m_status != m_entry->m_status)
+ else
{
- m_3dhandle->setRelative(m_entry->m_relative);
- m_3dhandle->setVolumeMaximum(m_entry->m_volume_max);
- m_3dhandle->setVolumeMinimum(m_entry->m_volume_min);
- m_3dhandle->setDistanceMaximum(m_entry->m_distance_max);
- m_3dhandle->setDistanceReference(m_entry->m_distance_reference);
- m_3dhandle->setAttenuation(m_entry->m_attenuation);
- m_3dhandle->setConeAngleOuter(m_entry->m_cone_angle_outer);
- m_3dhandle->setConeAngleInner(m_entry->m_cone_angle_inner);
- m_3dhandle->setConeVolumeOuter(m_entry->m_cone_volume_outer);
-
- m_status = m_entry->m_status;
+ // we don't have a handle, let's see if we can start
+ if(!seek(position))
+ return;
}
+ }
- float value;
-
- m_entry->m_volume.read(frame, &value);
- m_handle->setVolume(value);
- m_entry->m_pitch.read(frame, &value);
- m_handle->setPitch(value);
- m_entry->m_panning.read(frame, &value);
- AUD_SoftwareDevice::setPanning(m_handle.get(), value);
+ AUD_MutexLock lock(*m_entry);
+ if(m_pos_status != m_entry->m_pos_status)
+ {
+ m_pos_status = m_entry->m_pos_status;
- AUD_Vector3 v, v2;
- AUD_Quaternion q;
+ // position changed, need to seek
+ if(!seek(position))
+ // lost handle, aborting
+ return;
+ }
- m_entry->m_orientation.read(frame, q.get());
- m_3dhandle->setSourceOrientation(q);
- m_entry->m_location.read(frame, v.get());
- m_3dhandle->setSourceLocation(v);
- m_entry->m_location.read(frame + 1, v2.get());
- v2 -= v;
- m_3dhandle->setSourceVelocity(v2 * fps);
+ // so far everything alright and handle is there, let's keep going
- if(m_entry->m_muted)
- m_handle->setVolume(0);
+ if(m_status != m_entry->m_status)
+ {
+ m_status = m_entry->m_status;
+
+ m_3dhandle->setRelative(m_entry->m_relative);
+ m_3dhandle->setVolumeMaximum(m_entry->m_volume_max);
+ m_3dhandle->setVolumeMinimum(m_entry->m_volume_min);
+ m_3dhandle->setDistanceMaximum(m_entry->m_distance_max);
+ m_3dhandle->setDistanceReference(m_entry->m_distance_reference);
+ m_3dhandle->setAttenuation(m_entry->m_attenuation);
+ m_3dhandle->setConeAngleOuter(m_entry->m_cone_angle_outer);
+ m_3dhandle->setConeAngleInner(m_entry->m_cone_angle_inner);
+ m_3dhandle->setConeVolumeOuter(m_entry->m_cone_volume_outer);
}
+
+ float value;
+
+ m_entry->m_volume.read(frame, &value);
+ m_handle->setVolume(value);
+ m_entry->m_pitch.read(frame, &value);
+ m_handle->setPitch(value);
+ m_entry->m_panning.read(frame, &value);
+ AUD_SoftwareDevice::setPanning(m_handle.get(), value);
+
+ AUD_Vector3 v, v2;
+ AUD_Quaternion q;
+
+ m_entry->m_orientation.read(frame, q.get());
+ m_3dhandle->setSourceOrientation(q);
+ m_entry->m_location.read(frame, v.get());
+ m_3dhandle->setSourceLocation(v);
+ m_entry->m_location.read(frame + 1, v2.get());
+ v2 -= v;
+ m_3dhandle->setSourceVelocity(v2 * fps);
+
+ if(m_entry->m_muted)
+ m_handle->setVolume(0);
}
-void AUD_SequencerHandle::seek(float position)
+bool AUD_SequencerHandle::seek(float position)
{
- if(m_handle.get())
- {
- AUD_MutexLock lock(*m_entry);
- if(position >= m_entry->m_end)
- {
- m_handle->pause();
- return;
- }
-
- float seekpos = position - m_entry->m_begin;
- if(seekpos < 0)
- seekpos = 0;
- seekpos += m_entry->m_skip;
- m_handle->setPitch(1.0f);
- m_handle->seek(seekpos);
- if(position < m_entry->m_begin)
- m_handle->pause();
- else
- m_handle->resume();
- }
+ if(!m_valid)
+ // sound not valid, aborting
+ return false;
+
+ if(!updatePosition(position))
+ // no handle, aborting
+ return false;
+
+ AUD_MutexLock lock(*m_entry);
+ float seekpos = position - m_entry->m_begin;
+ if(seekpos < 0)
+ seekpos = 0;
+ seekpos += m_entry->m_skip;
+ m_handle->setPitch(1.0f);
+ m_handle->seek(seekpos);
+
+ return true;
}
diff --git a/intern/audaspace/intern/AUD_SequencerHandle.h b/intern/audaspace/intern/AUD_SequencerHandle.h
index 881bbdd43dc..306df4a84b9 100644
--- a/intern/audaspace/intern/AUD_SequencerHandle.h
+++ b/intern/audaspace/intern/AUD_SequencerHandle.h
@@ -51,6 +51,9 @@ private:
/// The 3D handle in the read device.
boost::shared_ptr<AUD_I3DHandle> m_3dhandle;
+ /// Whether the sound is playable.
+ bool m_valid;
+
/// The last read status from the entry.
int m_status;
@@ -63,6 +66,18 @@ private:
/// The read device this handle is played on.
AUD_ReadDevice& m_device;
+ /**
+ * Starts playing back the handle.
+ */
+ void start();
+
+ /**
+ * Updates the handle state depending on position.
+ * \param position Current playback position in seconds.
+ * \return Whether the handle is valid.
+ */
+ bool updatePosition(float position);
+
public:
/**
* Creates a new sequenced handle.
@@ -99,8 +114,9 @@ public:
/**
* Seeks the handle to a specific time position.
* \param position The time to seek to.
+ * \return Whether the handle is valid.
*/
- void seek(float position);
+ bool seek(float position);
};
#endif //__AUD_SEQUENCERHANDLE_H__
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 7de1182282d..2ba6af48d0d 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -16,8 +16,12 @@ include(cmake/external_libs.cmake)
if(NOT WITH_CPU_SSE)
set(CXX_HAS_SSE FALSE)
+ set(CXX_HAS_AVX FALSE)
+ set(CXX_HAS_AVX2 FALSE)
elseif(WIN32 AND MSVC)
set(CXX_HAS_SSE TRUE)
+ set(CXX_HAS_AVX TRUE)
+ set(CXX_HAS_AVX2 TRUE)
# /arch:AVX for VC2012 and above
if(NOT MSVC_VERSION LESS 1700)
@@ -49,21 +53,33 @@ elseif(WIN32 AND MSVC)
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /Ox")
elseif(CMAKE_COMPILER_IS_GNUCC)
check_cxx_compiler_flag(-msse CXX_HAS_SSE)
+ check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
+ check_cxx_compiler_flag(-mavx2 CXX_HAS_AVX2)
if(CXX_HAS_SSE)
set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2 -mfpmath=sse")
set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse")
set(CYCLES_SSE41_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mfpmath=sse")
+ endif()
+ if(CXX_HAS_AVX)
set(CYCLES_AVX_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mfpmath=sse")
+ endif()
+ if(CXX_HAS_AVX2)
set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mfpmath=sse")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
check_cxx_compiler_flag(-msse CXX_HAS_SSE)
+ check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
+ check_cxx_compiler_flag(-mavx2 CXX_HAS_AVX2)
if(CXX_HAS_SSE)
set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2")
set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3")
set(CYCLES_SSE41_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1")
+ endif()
+ if(CXX_HAS_AVX)
set(CYCLES_AVX_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx")
+ endif()
+ if(CXX_HAS_AVX2)
set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math")
@@ -74,11 +90,17 @@ if(CXX_HAS_SSE)
-DWITH_KERNEL_SSE2
-DWITH_KERNEL_SSE3
-DWITH_KERNEL_SSE41
- -DWITH_KERNEL_AVX
- -DWITH_KERNEL_AVX2
)
endif()
+if(CXX_HAS_AVX)
+ add_definitions(-DWITH_KERNEL_AVX)
+endif()
+
+if(CXX_HAS_AVX2)
+ add_definitions(-DWITH_KERNEL_AVX2)
+endif()
+
if(WITH_CYCLES_OSL)
if(WIN32 AND MSVC)
set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
@@ -120,7 +142,7 @@ if(WITH_CYCLES_OSL)
add_definitions(-DOSL_STATIC_LIBRARY)
include_directories(
SYSTEM
- ${OSL_INCLUDES}
+ ${OSL_INCLUDE_DIR}
)
endif()
@@ -134,19 +156,12 @@ add_definitions(
if(WITH_CYCLES_LOGGING)
add_definitions(-DWITH_CYCLES_LOGGING)
add_definitions(-DGOOGLE_GLOG_DLL_DECL=)
- if(WIN32)
- include_directories(
- SYSTEM
- ../../extern/libmv/third_party/glog/src/windows
- ../../extern/libmv/third_party/gflags
- )
- else()
- include_directories(
- SYSTEM
- ../../extern/libmv/third_party/glog/src
- ../../extern/libmv/third_party/gflags
- )
- endif()
+ add_definitions(-DCYCLES_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
+ include_directories(
+ SYSTEM
+ ${GLOG_INCLUDE_DIRS}
+ ${GFLAGS_INCLUDE_DIRS}
+ )
endif()
# Debugging capabilities (debug passes etc).
@@ -161,8 +176,14 @@ include_directories(
${OPENIMAGEIO_INCLUDE_DIRS}/OpenImageIO
${OPENEXR_INCLUDE_DIR}
${OPENEXR_INCLUDE_DIRS}
+ ${PUGIXML_INCLUDE_DIR}
)
+if(CYCLES_STANDALONE_REPOSITORY)
+ include_directories(../third_party/atomic)
+else()
+ include_directories(../atomic)
+endif()
# Warnings
if(CMAKE_COMPILER_IS_GNUCXX)
diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript
index b399844534d..9cbdb93ce85 100644
--- a/intern/cycles/SConscript
+++ b/intern/cycles/SConscript
@@ -62,12 +62,24 @@ if env['WITH_BF_CYCLES_OSL']:
if env['WITH_BF_CYCLES_DEBUG']:
defs.append('WITH_CYCLES_DEBUG')
+if env['WITH_BF_CYCLES_LOGGING']:
+ defs.append('WITH_CYCLES_LOGGING')
+ defs.append('GOOGLE_GLOG_DLL_DECL=')
+ defs.append('CYCLES_GFLAGS_NAMESPACE=gflags')
+ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ incs.append('#extern/libmv/third_party/glog/src/windows')
+ incs.append('#extern/libmv/third_party/gflags')
+ else:
+ incs.append('#extern/libmv/third_party/glog/src')
+ incs.append('#extern/libmv/third_party/gflags')
+
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.append(env['BF_GLEW_INC'])
incs.append('#/intern/glew-mx')
+incs.append('#/intern/atomic')
incs.append('#intern/mikktspace')
incs.extend('#extern/glew/include #extern/clew/include #extern/cuew/include #intern/mikktspace'.split())
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index c8464899725..f6a6f96280f 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -12,6 +12,8 @@ set(INC
set(INC_SYS
)
+# NOTE: LIBRARIES contains all the libraries which are common
+# across release and debug build types, stored in a linking order.
set(LIBRARIES
cycles_device
cycles_kernel
@@ -19,39 +21,83 @@ set(LIBRARIES
cycles_bvh
cycles_subd
cycles_util
- ${BOOST_LIBRARIES}
- ${OPENEXR_LIBRARIES}
${BLENDER_GL_LIBRARIES}
- bf_intern_glew_mx
${CYCLES_APP_GLEW_LIBRARY}
- ${OPENIMAGEIO_LIBRARIES}
${PNG_LIBRARIES}
${JPEG_LIBRARIES}
${ZLIB_LIBRARIES}
${TIFF_LIBRARY}
+ ${PTHREADS_LIBRARIES}
extern_clew
extern_cuew
)
-add_definitions(${GL_DEFINITIONS})
-
-if(WIN32)
- list(APPEND LIBRARIES ${PTHREADS_LIBRARIES})
+if(WITH_CYCLES_OSL)
+ list(APPEND LIBRARIES cycles_kernel_osl)
endif()
-link_directories(${OPENIMAGEIO_LIBPATH} ${BOOST_LIBPATH} ${PNG_LIBPATH} ${JPEG_LIBPATH} ${ZLIB_LIBPATH} ${TIFF_LIBPATH})
+if(CYCLES_STANDALONE_REPOSITORY)
+ if(WITH_CYCLES_LOGGING)
+ list(APPEND LIBRARIES
+ ${GLOG_LIBRARIES}
+ ${GFLAGS_LIBRARIES}
+ )
+ endif()
+else()
+ list(APPEND LIBRARIES bf_intern_glew_mx)
+ list(APPEND LIBRARIES extern_glog)
+endif()
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
list(APPEND LIBRARIES ${GLUT_LIBRARIES})
endif()
-if(WITH_CYCLES_OSL)
- list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES} ${LLVM_LIBRARY})
-endif()
+# Common configuration.
+
+link_directories(${OPENIMAGEIO_LIBPATH}
+ ${BOOST_LIBPATH}
+ ${PNG_LIBPATH}
+ ${JPEG_LIBPATH}
+ ${ZLIB_LIBPATH}
+ ${TIFF_LIBPATH}
+ ${OPENEXR_LIBPATH})
+
+add_definitions(${GL_DEFINITIONS})
include_directories(${INC})
include_directories(SYSTEM ${INC_SYS})
+# Make sure given target is linked against proper libraries
+# which varies across debug and release build types.
+#
+# This will also make sure dependencies of that libraries
+# are sent to the linker after them.
+#
+# TODO(sergey): Think of a better place for this?
+macro(cycles_target_link_libraries target)
+ target_link_libraries(${target} ${LIBRARIES})
+ if(WITH_CYCLES_OSL)
+ target_link_libraries_decoupled(${target} OSL_LIBRARIES)
+ if(MSVC)
+ target_link_libraries_debug(${target} "${LLVM_LIBRARIES_DEBUG}")
+ target_link_libraries_optimized(${target} "${LLVM_LIBRARIES}")
+ else()
+ target_link_libraries(${target} ${LLVM_LIBRARIES})
+ endif()
+ endif()
+ target_link_libraries_decoupled(${target} OPENIMAGEIO_LIBRARIES)
+ target_link_libraries_decoupled(${target} OPENEXR_LIBRARIES)
+ target_link_libraries(
+ ${target}
+ ${PUGIXML_LIBRARIES}
+ ${BOOST_LIBRARIES}
+ ${CMAKE_DL_LIBS}
+ ${PLATFORM_LINKLIBS}
+ )
+endmacro()
+
+# Application build targets
+
if(WITH_CYCLES_STANDALONE)
set(SRC
cycles_standalone.cpp
@@ -59,8 +105,7 @@ if(WITH_CYCLES_STANDALONE)
cycles_xml.h
)
add_executable(cycles ${SRC})
- list(APPEND LIBRARIES ${PLATFORM_LINKLIBS})
- target_link_libraries(cycles ${LIBRARIES} ${CMAKE_DL_LIBS})
+ cycles_target_link_libraries(cycles)
if(UNIX AND NOT APPLE)
set_target_properties(cycles PROPERTIES INSTALL_RPATH $ORIGIN/lib)
@@ -73,11 +118,10 @@ if(WITH_CYCLES_NETWORK)
cycles_server.cpp
)
add_executable(cycles_server ${SRC})
- target_link_libraries(cycles_server ${LIBRARIES} ${CMAKE_DL_LIBS})
+ cycles_target_link_libraries(cycles_server)
if(UNIX AND NOT APPLE)
set_target_properties(cycles_server PROPERTIES INSTALL_RPATH $ORIGIN/lib)
endif()
unset(SRC)
endif()
-
diff --git a/intern/cycles/app/cycles_server.cpp b/intern/cycles/app/cycles_server.cpp
index f4cacb2d001..3d5b237eec1 100644
--- a/intern/cycles/app/cycles_server.cpp
+++ b/intern/cycles/app/cycles_server.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdio.h>
@@ -29,13 +29,14 @@ using namespace ccl;
int main(int argc, const char **argv)
{
+ util_logging_init(argv[0]);
path_init();
/* device types */
string devicelist = "";
string devicename = "cpu";
- bool list = false;
- int threads = 0;
+ bool list = false, debug = false;
+ int threads = 0, verbosity = 1;
vector<DeviceType>& types = Device::available_types();
@@ -53,6 +54,10 @@ int main(int argc, const char **argv)
"--device %s", &devicename, ("Devices to use: " + devicelist).c_str(),
"--list-devices", &list, "List information about all available devices",
"--threads %d", &threads, "Number of threads to use for CPU device",
+#ifdef WITH_CYCLES_LOGGING
+ "--debug", &debug, "Enable debug logging",
+ "--verbose %d", &verbosity, "Set verbosity of the logger",
+#endif
NULL);
if(ap.parse(argc, argv) < 0) {
@@ -60,7 +65,13 @@ int main(int argc, const char **argv)
ap.usage();
exit(EXIT_FAILURE);
}
- else if(list) {
+
+ if (debug) {
+ util_logging_start();
+ util_logging_verbosity_set(verbosity);
+ }
+
+ if(list) {
vector<DeviceInfo>& devices = Device::available_devices();
printf("Devices:\n");
diff --git a/intern/cycles/app/cycles_standalone.cpp b/intern/cycles/app/cycles_standalone.cpp
index 90333eb3fc5..42c339f56e5 100644
--- a/intern/cycles/app/cycles_standalone.cpp
+++ b/intern/cycles/app/cycles_standalone.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdio.h>
@@ -25,6 +25,7 @@
#include "util_args.h"
#include "util_foreach.h"
#include "util_function.h"
+#include "util_logging.h"
#include "util_path.h"
#include "util_progress.h"
#include "util_string.h"
@@ -70,12 +71,12 @@ static void session_print(const string& str)
static void session_print_status()
{
int sample, tile;
- double total_time, sample_time;
+ double total_time, sample_time, render_time;
string status, substatus;
/* get status */
sample = options.session->progress.get_sample();
- options.session->progress.get_tile(tile, total_time, sample_time);
+ options.session->progress.get_tile(tile, total_time, sample_time, render_time);
options.session->progress.get_status(status, substatus);
if(substatus != "")
@@ -165,11 +166,11 @@ static void display_info(Progress& progress)
last = elapsed;
int sample, tile;
- double total_time, sample_time;
+ double total_time, sample_time, render_time;
string status, substatus;
sample = progress.get_sample();
- progress.get_tile(tile, total_time, sample_time);
+ progress.get_tile(tile, total_time, sample_time, render_time);
progress.get_status(status, substatus);
if(substatus != "")
@@ -319,6 +320,11 @@ static void options_parse(int argc, const char **argv)
vector<DeviceType>& types = Device::available_types();
+ /* TODO(sergey): Here's a feedback loop happens: on the one hand we want
+ * the device list to be printed in help message, on the other hand logging
+ * is not initialized yet so we wouldn't have debug log happening in the
+ * device initialization.
+ */
foreach(DeviceType type, types) {
if(device_names != "")
device_names += ", ";
@@ -331,7 +337,8 @@ static void options_parse(int argc, const char **argv)
/* parse options */
ArgParse ap;
- bool help = false;
+ bool help = false, debug = false;
+ int verbosity = 1;
ap.options ("Usage: cycles [options] file.xml",
"%*", files_parse, "",
@@ -347,6 +354,10 @@ static void options_parse(int argc, const char **argv)
"--width %d", &options.width, "Window width in pixel",
"--height %d", &options.height, "Window height in pixel",
"--list-devices", &list, "List information about all available devices",
+#ifdef WITH_CYCLES_LOGGING
+ "--debug", &debug, "Enable debug logging",
+ "--verbose %d", &verbosity, "Set verbosity of the logger",
+#endif
"--help", &help, "Print help message",
NULL);
@@ -355,7 +366,13 @@ static void options_parse(int argc, const char **argv)
ap.usage();
exit(EXIT_FAILURE);
}
- else if(list) {
+
+ if (debug) {
+ util_logging_start();
+ util_logging_verbosity_set(verbosity);
+ }
+
+ if(list) {
vector<DeviceInfo>& devices = Device::available_devices();
printf("Devices:\n");
@@ -435,6 +452,7 @@ using namespace ccl;
int main(int argc, const char **argv)
{
+ util_logging_init(argv[0]);
path_init();
options_parse(argc, argv);
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 6123f35ae0c..05e34387eb7 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdio.h>
@@ -825,6 +825,14 @@ static void xml_read_background(const XMLReadState& state, pugi::xml_node node)
Shader *shader = state.scene->shaders[state.scene->default_background];
xml_read_bool(&shader->heterogeneous_volume, node, "heterogeneous_volume");
+ xml_read_int(&shader->volume_interpolation_method, node, "volume_interpolation_method");
+
+ if(xml_equal_string(node, "volume_sampling_method", "distance"))
+ shader->volume_sampling_method = VOLUME_SAMPLING_DISTANCE;
+ else if(xml_equal_string(node, "volume_sampling_method", "equiangular"))
+ shader->volume_sampling_method = VOLUME_SAMPLING_EQUIANGULAR;
+ else if(xml_equal_string(node, "volume_sampling_method", "multiple_importance"))
+ shader->volume_sampling_method = VOLUME_SAMPLING_MULTIPLE_IMPORTANCE;
xml_read_shader_graph(state, shader, node);
}
diff --git a/intern/cycles/app/cycles_xml.h b/intern/cycles/app/cycles_xml.h
index 96bc79c35d8..6a48980d8ea 100644
--- a/intern/cycles/app/cycles_xml.h
+++ b/intern/cycles/app/cycles_xml.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __CYCLES_XML_H__
diff --git a/intern/cycles/app/io_export_cycles_xml.py b/intern/cycles/app/io_export_cycles_xml.py
index ad8fb9d3dd3..7d6d85f88af 100644
--- a/intern/cycles/app/io_export_cycles_xml.py
+++ b/intern/cycles/app/io_export_cycles_xml.py
@@ -11,7 +11,7 @@
# 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
+# limitations under the License.
#
# XML exporter for generating test files, not intended for end users
diff --git a/intern/cycles/blender/CCL_api.h b/intern/cycles/blender/CCL_api.h
index cfd0c3ef264..d3a68c4db4f 100644
--- a/intern/cycles/blender/CCL_api.h
+++ b/intern/cycles/blender/CCL_api.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __CCL_API_H__
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index e1d592d32b4..fff9ed20bba 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -17,7 +17,7 @@ set(INC
set(INC_SYS
${PYTHON_INCLUDE_DIRS}
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_DIR}
)
set(SRC
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 8c60ea31053..64e4a8391d1 100644
--- a/intern/cycles/blender/addon/__init__.py
+++ b/intern/cycles/blender/addon/__init__.py
@@ -11,7 +11,7 @@
# 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
+# limitations under the License.
#
# <pep8 compliant>
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 18235eca790..a0ad044f24c 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -11,7 +11,7 @@
# 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
+# limitations under the License.
#
# <pep8 compliant>
@@ -100,3 +100,7 @@ def with_osl():
def with_network():
import _cycles
return _cycles.with_network
+
+def system_info():
+ import _cycles
+ return _cycles.system_info()
diff --git a/intern/cycles/blender/addon/osl.py b/intern/cycles/blender/addon/osl.py
index c5f9d93013e..f4aaaab5eab 100644
--- a/intern/cycles/blender/addon/osl.py
+++ b/intern/cycles/blender/addon/osl.py
@@ -11,7 +11,7 @@
# 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
+# limitations under the License.
#
# <pep8 compliant>
diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py
index 2ec65d7183a..f97b51b629d 100644
--- a/intern/cycles/blender/addon/presets.py
+++ b/intern/cycles/blender/addon/presets.py
@@ -11,7 +11,7 @@
# 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
+# limitations under the License.
#
# <pep8 compliant>
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 9459b750bd1..5f8a55d3de8 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -11,7 +11,7 @@
# 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
+# limitations under the License.
#
# <pep8 compliant>
@@ -582,6 +582,34 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
min=0.01, soft_max=15.0, max=100.0,
default=10.5,
)
+ cls.latitude_min = FloatProperty(
+ name="Min Latitude",
+ description="Minimum latitude (vertical angle) for the equirectangular lens",
+ min=-0.5 * math.pi, max=0.5 * math.pi,
+ subtype='ANGLE',
+ default=-0.5 * math.pi,
+ )
+ cls.latitude_max = FloatProperty(
+ name="Max Latitude",
+ description="Maximum latitude (vertical angle) for the equirectangular lens",
+ min=-0.5 * math.pi, max=0.5 * math.pi,
+ subtype='ANGLE',
+ default=0.5 * math.pi,
+ )
+ cls.longitude_min = FloatProperty(
+ name="Min Longitude",
+ description="Minimum longitude (horizontal angle) for the equirectangular lens",
+ min=-math.pi, max=math.pi,
+ subtype='ANGLE',
+ default=-math.pi,
+ )
+ cls.longitude_max = FloatProperty(
+ name="Max Longitude",
+ description="Maximum longitude (horizontal angle) for the equirectangular lens",
+ min=-math.pi, max=math.pi,
+ subtype='ANGLE',
+ default=math.pi,
+ )
@classmethod
def unregister(cls):
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index e4f34f3a5aa..8fd09c3bc19 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -11,7 +11,7 @@
# 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
+# limitations under the License.
#
# <pep8 compliant>
@@ -733,7 +733,7 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
col = split.column()
col.prop(clamp, "cast_shadow")
- col.prop(clamp, "use_multiple_importance_sampling")
+ col.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
if lamp.type == 'HEMI':
layout.label(text="Not supported, interpreted as sun lamp")
@@ -1020,17 +1020,6 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
cmat = mat.cycles
split = layout.split()
-
- col = split.column(align=True)
- col.prop(mat, "diffuse_color", text="Viewport Color")
- col.prop(mat, "alpha")
-
- col = split.column(align=True)
- col.label()
- col.prop(mat, "pass_index")
-
- split = layout.split()
-
col = split.column()
col.label(text="Surface:")
col.prop(cmat, "sample_as_light", text="Multiple Importance")
@@ -1044,6 +1033,22 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
col.prop(cmat, "volume_interpolation", text="")
col.prop(cmat, "homogeneous_volume", text="Homogeneous")
+ layout.separator()
+ split = layout.split()
+
+ col = split.column(align=True)
+ col.label("Viewport Color:")
+ col.prop(mat, "diffuse_color", text="")
+ col.prop(mat, "alpha")
+
+ col.separator()
+ col.prop(mat, "pass_index")
+
+ col = split.column(align=True)
+ col.label("Viewport Specular:")
+ col.prop(mat, "specular_color", text="")
+ col.prop(mat, "specular_hardness", text="Hardness")
+
class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
bl_label = ""
diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py
index eaeec703ff5..84414123a8c 100644
--- a/intern/cycles/blender/addon/version_update.py
+++ b/intern/cycles/blender/addon/version_update.py
@@ -11,7 +11,7 @@
# 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
+# limitations under the License.
#
# <pep8 compliant>
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index ce8c64c4819..e5214fb5c30 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "camera.h"
@@ -20,6 +20,8 @@
#include "blender_sync.h"
#include "blender_util.h"
+#include "util_logging.h"
+
CCL_NAMESPACE_BEGIN
/* Blender Camera Intermediate: we first convert both the offline and 3d view
@@ -51,6 +53,10 @@ struct BlenderCamera {
PanoramaType panorama_type;
float fisheye_fov;
float fisheye_lens;
+ float latitude_min;
+ float latitude_max;
+ float longitude_min;
+ float longitude_max;
enum { AUTO, HORIZONTAL, VERTICAL } sensor_fit;
float sensor_width;
@@ -145,6 +151,10 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, boo
bcam->fisheye_fov = RNA_float_get(&ccamera, "fisheye_fov");
bcam->fisheye_lens = RNA_float_get(&ccamera, "fisheye_lens");
+ bcam->latitude_min = RNA_float_get(&ccamera, "latitude_min");
+ bcam->latitude_max = RNA_float_get(&ccamera, "latitude_max");
+ bcam->longitude_min = RNA_float_get(&ccamera, "longitude_min");
+ bcam->longitude_max = RNA_float_get(&ccamera, "longitude_max");
bcam->ortho_scale = b_camera.ortho_scale();
@@ -330,6 +340,11 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
cam->panorama_type = bcam->panorama_type;
cam->fisheye_fov = bcam->fisheye_fov;
cam->fisheye_lens = bcam->fisheye_lens;
+ cam->latitude_min = bcam->latitude_min;
+ cam->latitude_max = bcam->latitude_max;
+
+ cam->longitude_min = bcam->longitude_min;
+ cam->longitude_max = bcam->longitude_max;
/* anamorphic lens bokeh */
cam->aperture_ratio = bcam->aperture_ratio;
@@ -400,6 +415,7 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time)
tfm = blender_camera_matrix(tfm, cam->type);
if(tfm != cam->matrix) {
+ VLOG(1) << "Camera " << b_ob.name() << " motion detected.";
if(motion_time == -1.0f) {
cam->motion.pre = tfm;
cam->use_motion = true;
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 8cfaea59a06..a2f76bbe091 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "attribute.h"
@@ -25,6 +25,7 @@
#include "blender_util.h"
#include "util_foreach.h"
+#include "util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -577,6 +578,10 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
}
}
+ if (num_curves > 0) {
+ VLOG(1) << "Exporting curve segments for mesh " << mesh->name;
+ }
+
mesh->curve_keys.reserve(mesh->curve_keys.size() + num_keys);
mesh->curves.reserve(mesh->curves.size() + num_curves);
@@ -612,9 +617,9 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
}
}
- /* check allocation*/
+ /* check allocation */
if((mesh->curve_keys.size() != num_keys) || (mesh->curves.size() != num_curves)) {
- /* allocation failed -> clear data */
+ VLOG(1) << "Allocation failed, clearing data";
mesh->curve_keys.clear();
mesh->curves.clear();
mesh->curve_attributes.clear();
@@ -623,12 +628,16 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveData *CData, int time_index)
{
+ VLOG(1) << "Exporting curve motion segments for mesh " << mesh->name
+ << ", time index " << time_index;
+
/* find attribute */
Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
bool new_attribute = false;
/* add new attribute if it doesn't exist already */
if(!attr_mP) {
+ VLOG(1) << "Creating new motion vertex position attribute";
attr_mP = mesh->curve_attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
new_attribute = true;
}
@@ -675,9 +684,12 @@ static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveDat
if(new_attribute) {
if(i != numkeys || !have_motion) {
/* no motion, remove attributes again */
+ VLOG(1) << "No motion, removing attribute";
mesh->curve_attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
}
else if(time_index > 0) {
+ VLOG(1) << "Filling in new motion vertex position for time_index"
+ << time_index;
/* motion, fill up previous steps that we might have skipped because
* they had no motion, but we need them anyway now */
for(int step = 0; step < time_index; step++) {
diff --git a/intern/cycles/blender/blender_logging.cpp b/intern/cycles/blender/blender_logging.cpp
index d3f1accf099..f4f86929168 100644
--- a/intern/cycles/blender/blender_logging.cpp
+++ b/intern/cycles/blender/blender_logging.cpp
@@ -11,55 +11,23 @@
* 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
+ * limitations under the License.
*/
#include "CCL_api.h"
-
-#include <stdio.h>
-
#include "util_logging.h"
-#ifdef _MSC_VER
-# define snprintf _snprintf
-#endif
-
void CCL_init_logging(const char *argv0)
{
-#ifdef WITH_CYCLES_LOGGING
- /* Make it so FATAL messages are always print into console. */
- char severity_fatal[32];
- snprintf(severity_fatal, sizeof(severity_fatal), "%d",
- google::GLOG_FATAL);
-
- google::InitGoogleLogging(argv0);
- google::SetCommandLineOption("logtostderr", "1");
- google::SetCommandLineOption("v", "0");
- google::SetCommandLineOption("stderrthreshold", severity_fatal);
- google::SetCommandLineOption("minloglevel", severity_fatal);
-#else
- (void) argv0;
-#endif
+ ccl::util_logging_init(argv0);
}
void CCL_start_debug_logging(void)
{
-#ifdef WITH_CYCLES_LOGGING
- google::SetCommandLineOption("logtostderr", "1");
- google::SetCommandLineOption("v", "2");
- google::SetCommandLineOption("stderrthreshold", "1");
- google::SetCommandLineOption("minloglevel", "0");
-#endif
+ ccl::util_logging_start();
}
void CCL_logging_verbosity_set(int verbosity)
{
-#ifdef WITH_CYCLES_LOGGING
- char val[10];
- snprintf(val, sizeof(val), "%d", verbosity);
-
- google::SetCommandLineOption("v", val);
-#else
- (void) verbosity;
-#endif
+ ccl::util_logging_verbosity_set(verbosity);
}
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index a5e4b7bd2ae..88054436bc6 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
@@ -27,6 +27,7 @@
#include "subd_split.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "mikktspace.h"
@@ -761,11 +762,13 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion
if(new_attribute) {
if(i != numverts || memcmp(mP, &mesh->verts[0], sizeof(float3)*numverts) == 0) {
/* no motion, remove attributes again */
+ VLOG(1) << "No actual motion for mesh " << b_mesh.name();
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
if(attr_mN)
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL);
}
else if(time_index > 0) {
+ VLOG(1) << "Filling motion for mesh " << b_mesh.name();
/* motion, fill up previous steps that we might have skipped because
* they had no motion, but we need them anyway now */
float3 *P = &mesh->verts[0];
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 239e0c6cc64..e827d46223b 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "camera.h"
@@ -30,6 +30,7 @@
#include "util_foreach.h"
#include "util_hash.h"
+#include "util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -251,6 +252,7 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
if(object && (scene->need_motion() == Scene::MOTION_PASS || object_use_motion(b_ob))) {
/* object transformation */
if(tfm != object->tfm) {
+ VLOG(1) << "Object " << b_ob.name() << " motion detected.";
if(motion_time == -1.0f) {
object->motion.pre = tfm;
object->use_motion = true;
@@ -412,9 +414,17 @@ static bool object_render_hide(BL::Object b_ob, bool top_level, bool parent_hide
/* hide original object for duplis */
BL::Object parent = b_ob.parent();
- if(parent && object_render_hide_original(b_ob.type(), parent.dupli_type()))
- if(parent_hide)
- hide_as_dupli_child_original = true;
+ while(parent) {
+ if(object_render_hide_original(b_ob.type(),
+ parent.dupli_type()))
+ {
+ if(parent_hide) {
+ hide_as_dupli_child_original = true;
+ break;
+ }
+ }
+ parent = parent.parent();
+ }
hide_triangles = hide_emitter;
diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp
index 5b2782ec2ac..2785cfa9634 100644
--- a/intern/cycles/blender/blender_particles.cpp
+++ b/intern/cycles/blender/blender_particles.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "mesh.h"
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index dd45ae0865c..37191bb797a 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <Python.h>
@@ -105,7 +105,7 @@ static PyObject *create_func(PyObject *self, PyObject *args)
BL::UserPreferences userpref(userprefptr);
PointerRNA dataptr;
- RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pydata), &dataptr);
+ RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr);
BL::BlendData data(dataptr);
PointerRNA sceneptr;
@@ -113,15 +113,15 @@ static PyObject *create_func(PyObject *self, PyObject *args)
BL::Scene scene(sceneptr);
PointerRNA regionptr;
- RNA_id_pointer_create((ID*)pylong_as_voidptr_typesafe(pyregion), &regionptr);
+ RNA_pointer_create(NULL, &RNA_Region, pylong_as_voidptr_typesafe(pyregion), &regionptr);
BL::Region region(regionptr);
PointerRNA v3dptr;
- RNA_id_pointer_create((ID*)pylong_as_voidptr_typesafe(pyv3d), &v3dptr);
+ RNA_pointer_create(NULL, &RNA_SpaceView3D, pylong_as_voidptr_typesafe(pyv3d), &v3dptr);
BL::SpaceView3D v3d(v3dptr);
PointerRNA rv3dptr;
- RNA_id_pointer_create((ID*)pylong_as_voidptr_typesafe(pyrv3d), &rv3dptr);
+ RNA_pointer_create(NULL, &RNA_RegionView3D, pylong_as_voidptr_typesafe(pyrv3d), &rv3dptr);
BL::RegionView3D rv3d(rv3dptr);
/* create session */
@@ -196,7 +196,7 @@ static PyObject *bake_func(PyObject *self, PyObject *args)
void *b_result = PyLong_AsVoidPtr(pyresult);
PointerRNA bakepixelptr;
- RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pypixel_array), &bakepixelptr);
+ RNA_pointer_create(NULL, &RNA_BakePixel, PyLong_AsVoidPtr(pypixel_array), &bakepixelptr);
BL::BakePixel b_bake_pixel(bakepixelptr);
python_thread_state_save(&session->python_thread_state);
@@ -238,7 +238,7 @@ static PyObject *reset_func(PyObject *self, PyObject *args)
BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
PointerRNA dataptr;
- RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pydata), &dataptr);
+ RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr);
BL::BlendData b_data(dataptr);
PointerRNA sceneptr;
@@ -473,6 +473,12 @@ static PyObject *osl_compile_func(PyObject *self, PyObject *args)
}
#endif
+static PyObject *system_info_func(PyObject *self, PyObject *value)
+{
+ string system_info = Device::device_capabilities();
+ return PyUnicode_FromString(system_info.c_str());
+}
+
static PyMethodDef methods[] = {
{"init", init_func, METH_VARARGS, ""},
{"create", create_func, METH_VARARGS, ""},
@@ -487,6 +493,7 @@ static PyMethodDef methods[] = {
{"osl_compile", osl_compile_func, METH_VARARGS, ""},
#endif
{"available_devices", available_devices_func, METH_NOARGS, ""},
+ {"system_info", system_info_func, METH_NOARGS, ""},
{NULL, NULL, 0, NULL},
};
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 57ffea4b1a9..eb3f54ae90c 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdlib.h>
@@ -86,12 +86,14 @@ void BlenderSession::create()
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 is_cpu = session_params.device.type == DEVICE_CPU;
+ SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background, is_cpu);
bool session_pause = BlenderSync::get_session_pause(b_scene, background);
/* reset status/progress */
last_status = "";
+ last_error = "";
last_progress = -1.0f;
start_resize_time = 0.0;
@@ -111,7 +113,7 @@ void BlenderSession::create_session()
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);
+ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, is_cpu);
if(b_v3d) {
if(session_pause == false) {
@@ -141,8 +143,9 @@ void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
b_render = b_engine.render();
b_scene = b_scene_;
- SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
+ const bool is_cpu = session_params.device.type == DEVICE_CPU;
+ SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background, is_cpu);
width = render_resolution_x(b_render);
height = render_resolution_y(b_render);
@@ -173,7 +176,7 @@ void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
session->stats.mem_peak = session->stats.mem_used;
/* sync object should be re-created */
- sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, session_params.device.type == DEVICE_CPU);
+ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, is_cpu);
/* for final render we will do full data sync per render layer, only
* do some basic syncing here, no objects or materials for speed */
@@ -640,8 +643,9 @@ void BlenderSession::synchronize()
return;
/* 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);
+ const bool is_cpu = session_params.device.type == DEVICE_CPU;
+ SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background, is_cpu);
bool session_pause = BlenderSync::get_session_pause(b_scene, background);
if(session->params.modified(session_params) ||
@@ -774,19 +778,23 @@ void BlenderSession::get_status(string& status, string& substatus)
session->progress.get_status(status, substatus);
}
-void BlenderSession::get_progress(float& progress, double& total_time)
+void BlenderSession::get_progress(float& progress, double& total_time, double& render_time)
{
double tile_time;
int tile, sample, samples_per_tile;
int tile_total = session->tile_manager.state.num_tiles;
+ int samples = session->tile_manager.state.sample + 1;
+ int total_samples = session->tile_manager.num_samples;
- session->progress.get_tile(tile, total_time, tile_time);
+ session->progress.get_tile(tile, total_time, render_time, tile_time);
sample = session->progress.get_sample();
samples_per_tile = session->tile_manager.num_samples;
- if(samples_per_tile && tile_total)
+ if(background && samples_per_tile && tile_total)
progress = ((float)sample / (float)(tile_total * samples_per_tile));
+ else if(!background && samples > 0 && total_samples != USHRT_MAX)
+ progress = ((float)samples) / total_samples;
else
progress = 0.0;
}
@@ -816,22 +824,18 @@ void BlenderSession::update_status_progress()
string timestatus, status, substatus;
string scene = "";
float progress;
- double total_time, remaining_time = 0;
+ double total_time, remaining_time = 0, render_time;
char time_str[128];
float mem_used = (float)session->stats.mem_used / 1024.0f / 1024.0f;
float mem_peak = (float)session->stats.mem_peak / 1024.0f / 1024.0f;
- int samples = session->tile_manager.state.sample + 1;
- int total_samples = session->tile_manager.num_samples;
get_status(status, substatus);
- get_progress(progress, total_time);
+ get_progress(progress, total_time, render_time);
-
+ if(progress > 0)
+ remaining_time = (1.0 - (double)progress) * (render_time / (double)progress);
if(background) {
- if(progress>0)
- remaining_time = (1.0 - (double)progress) * (total_time / (double)progress);
-
scene += " | " + b_scene.name();
if(b_rlay_name != "")
scene += ", " + b_rlay_name;
@@ -839,16 +843,13 @@ void BlenderSession::update_status_progress()
else {
BLI_timestr(total_time, time_str, sizeof(time_str));
timestatus = "Time:" + string(time_str) + " | ";
-
- if(samples > 0 && total_samples != USHRT_MAX)
- remaining_time = (total_samples - samples) * (total_time / samples);
}
-
- if(remaining_time>0) {
+
+ if(remaining_time > 0) {
BLI_timestr(remaining_time, time_str, sizeof(time_str));
timestatus += "Remaining:" + string(time_str) + " | ";
}
-
+
timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", (double)mem_used, (double)mem_peak);
if(status.size() > 0)
@@ -865,6 +866,21 @@ void BlenderSession::update_status_progress()
b_engine.update_progress(progress);
last_progress = progress;
}
+
+ if (session->progress.get_error()) {
+ string error = session->progress.get_error_message();
+ if(error != last_error) {
+ /* TODO(sergey): Currently C++ RNA API doesn't let us to
+ * use mnemonic name for the variable. Would be nice to
+ * have this figured out.
+ *
+ * For until then, 1 << 5 means RPT_ERROR.
+ */
+ b_engine.report(1 << 5, error.c_str());
+ b_engine.error_set(error.c_str());
+ last_error = error;
+ }
+ }
}
void BlenderSession::tag_update()
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index ac685118b3d..33da3076b55 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __BLENDER_SESSION_H__
@@ -70,7 +70,7 @@ public:
void tag_redraw();
void tag_update();
void get_status(string& status, string& substatus);
- void get_progress(float& progress, double& total_time);
+ void get_progress(float& progress, double& total_time, double& render_time);
void test_cancel();
void update_status_progress();
void update_bake_progress();
@@ -91,6 +91,7 @@ public:
string b_rlay_name;
string last_status;
+ string last_error;
float last_progress;
int width, height;
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 27c2e9e9ae8..806eae72b23 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "background.h"
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index ee492dd00e4..97ceae7237b 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "background.h"
@@ -353,7 +353,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer)
/* Scene Parameters */
-SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background)
+SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background, bool is_cpu)
{
BL::RenderSettings r = b_scene.render();
SceneParams params;
@@ -378,6 +378,16 @@ SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background)
else
params.persistent_data = false;
+#if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
+ if(is_cpu) {
+ params.use_qbvh = system_cpu_support_sse2();
+ }
+ else
+#endif
+ {
+ params.use_qbvh = false;
+ }
+
return params;
}
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 9c4175ef690..8f851a14bfc 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __BLENDER_SYNC_H__
@@ -62,7 +62,7 @@ public:
int get_layer_bound_samples() { return render_layer.bound_samples; }
/* get parameters */
- static SceneParams get_scene_params(BL::Scene b_scene, bool background);
+ static SceneParams get_scene_params(BL::Scene b_scene, bool background, bool is_cpu);
static SessionParams get_session_params(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, BL::Scene b_scene, bool background);
static bool get_session_pause(BL::Scene b_scene, bool background);
static BufferParams get_buffer_params(BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height);
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 35e417d8069..3bc0a758433 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __BLENDER_UTIL_H__
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 15bd814b8d5..947f6fe67d8 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -275,68 +275,13 @@ void BVH::pack_triangle(int idx, float4 woop[3])
float3 v1 = vpos[vidx[1]];
float3 v2 = vpos[vidx[2]];
- float3 r0 = v0 - v2;
- float3 r1 = v1 - v2;
- float3 r2 = cross(r0, r1);
-
- if(is_zero(r0) || is_zero(r1) || is_zero(r2)) {
- /* degenerate */
- woop[0] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- woop[1] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- woop[2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- else {
- Transform t = make_transform(
- r0.x, r1.x, r2.x, v2.x,
- r0.y, r1.y, r2.y, v2.y,
- r0.z, r1.z, r2.z, v2.z,
- 0.0f, 0.0f, 0.0f, 1.0f);
-
- t = transform_inverse(t);
-
- woop[0] = make_float4(t.z.x, t.z.y, t.z.z, -t.z.w);
- woop[1] = make_float4(t.x.x, t.x.y, t.x.z, t.x.w);
- woop[2] = make_float4(t.y.x, t.y.y, t.y.z, t.y.w);
- }
+ woop[0] = float3_to_float4(v0);
+ woop[1] = float3_to_float4(v1);
+ woop[2] = float3_to_float4(v2);
}
/* Curves*/
-void BVH::pack_curve_segment(int idx, float4 woop[3])
-{
- int tob = pack.prim_object[idx];
- const Mesh *mesh = objects[tob]->mesh;
- int tidx = pack.prim_index[idx];
- int segment = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[idx]);
- int k0 = mesh->curves[tidx].first_key + segment;
- int k1 = mesh->curves[tidx].first_key + segment + 1;
- float3 v0 = float4_to_float3(mesh->curve_keys[k0]);
- float3 v1 = float4_to_float3(mesh->curve_keys[k1]);
-
- float3 d0 = v1 - v0;
- float l = len(d0);
-
- /*Plan
- *Transform tfm = make_transform(
- * location <3> , l,
- * extra curve data <3> , StrID,
- * nextkey, flags/tip?, 0, 0);
- */
- float3 tg0 = make_float3(1.0f, 0.0f, 0.0f);
- float3 tg1 = make_float3(1.0f, 0.0f, 0.0f);
-
- Transform tfm = make_transform(
- tg0.x, tg0.y, tg0.z, l,
- tg1.x, tg1.y, tg1.z, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 1);
-
- woop[0] = tfm.x;
- woop[1] = tfm.y;
- woop[2] = tfm.z;
-
-}
-
void BVH::pack_primitives()
{
int nsize = TRI_NODE_SIZE;
@@ -351,9 +296,7 @@ void BVH::pack_primitives()
if(pack.prim_index[i] != -1) {
float4 woop[3];
- if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
- pack_curve_segment(i, woop);
- else
+ if(pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE)
pack_triangle(i, woop);
memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3);
@@ -418,7 +361,7 @@ void BVH::pack_instances(size_t nodes_size)
if(mesh_map.find(mesh) == mesh_map.end()) {
prim_index_size += bvh->pack.prim_index.size();
tri_woop_size += bvh->pack.tri_woop.size();
- nodes_size += bvh->pack.nodes.size()*nsize;
+ nodes_size += bvh->pack.nodes.size();
mesh_map[mesh] = 1;
}
@@ -506,7 +449,10 @@ void BVH::pack_instances(size_t nodes_size)
/* merge nodes */
if(bvh->pack.nodes.size()) {
- size_t nsize_bbox = (use_qbvh)? nsize-2: nsize-1;
+ /* For QBVH we're packing a child bbox into 6 float4,
+ * and for regular BVH they're packed into 3 float4.
+ */
+ size_t nsize_bbox = (use_qbvh)? 6: 3;
int4 *bvh_nodes = &bvh->pack.nodes[0];
size_t bvh_nodes_size = bvh->pack.nodes.size();
int *bvh_is_leaf = (bvh->pack.is_leaf.size() != 0) ? &bvh->pack.is_leaf[0] : NULL;
@@ -533,8 +479,12 @@ void BVH::pack_instances(size_t nodes_size)
pack_nodes[pack_nodes_offset + nsize_bbox] = data;
- if(use_qbvh)
- pack_nodes[pack_nodes_offset + nsize_bbox+1] = bvh_nodes[i + nsize_bbox+1];
+ /* Usually this copies nothing, but we better
+ * be prepared for possible node size extension.
+ */
+ memcpy(&pack_nodes[pack_nodes_offset + nsize_bbox+1],
+ &bvh_nodes[i + nsize_bbox+1],
+ sizeof(int4) * (nsize - (nsize_bbox+1)));
pack_nodes_offset += nsize;
}
@@ -554,12 +504,20 @@ RegularBVH::RegularBVH(const BVHParams& params_, const vector<Object*>& objects_
void RegularBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
{
- if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1)
+ if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) {
/* object */
- pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0, leaf->m_visibility, leaf->m_visibility);
- else
- /* triangle */
- pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, leaf->m_lo, leaf->m_hi, leaf->m_visibility, leaf->m_visibility);
+ pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0,
+ leaf->m_visibility, leaf->m_visibility);
+ }
+ else {
+ int prim_type = leaf->num_triangles() ? pack.prim_type[leaf->m_lo] : 0;
+ /* Triangle/curve primitive leaf. */
+ pack_node(e.idx, leaf->m_bounds, leaf->m_bounds,
+ leaf->m_lo, leaf->m_hi,
+ leaf->m_visibility,
+ prim_type);
+ }
+
}
void RegularBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1)
@@ -636,7 +594,7 @@ void RegularBVH::refit_nodes()
void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
{
- int4 *data = &pack.nodes[idx*4];
+ int4 *data = &pack.nodes[idx*BVH_NODE_SIZE];
int c0 = data[3].x;
int c1 = data[3].y;
@@ -707,7 +665,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
visibility |= ob->visibility;
}
- pack_node(idx, bbox, bbox, c0, c1, visibility, visibility);
+ pack_node(idx, bbox, bbox, c0, c1, visibility, data[3].w);
}
else {
/* refit inner node, set bbox from children */
@@ -731,8 +689,6 @@ QBVH::QBVH(const BVHParams& params_, const vector<Object*>& objects_)
: BVH(params_, objects_)
{
params.use_qbvh = true;
-
- /* todo: use visibility */
}
void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
@@ -751,6 +707,10 @@ void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
data[6].x = __int_as_float(leaf->m_lo);
data[6].y = __int_as_float(leaf->m_hi);
}
+ data[6].z = __uint_as_float(leaf->m_visibility);
+ if(leaf->num_triangles() != 0) {
+ data[6].w = __uint_as_float(pack.prim_type[leaf->m_lo]);
+ }
memcpy(&pack.nodes[e.idx * BVH_QNODE_SIZE], data, sizeof(float4)*BVH_QNODE_SIZE);
}
@@ -771,20 +731,22 @@ void QBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num)
data[5][i] = bb_max.z;
data[6][i] = __int_as_float(en[i].encodeIdx());
- data[7][i] = 0.0f;
}
for(int i = num; i < 4; i++) {
- data[0][i] = 0.0f;
- data[1][i] = 0.0f;
- data[2][i] = 0.0f;
+ /* We store BB which would never be recorded as intersection
+ * so kernel might safely assume there are always 4 child nodes.
+ */
+ data[0][i] = FLT_MAX;
+ data[1][i] = -FLT_MAX;
- data[3][i] = 0.0f;
- data[4][i] = 0.0f;
- data[5][i] = 0.0f;
+ data[2][i] = FLT_MAX;
+ data[3][i] = -FLT_MAX;
+
+ data[4][i] = FLT_MAX;
+ data[5][i] = -FLT_MAX;
data[6][i] = __int_as_float(0);
- data[7][i] = 0.0f;
}
memcpy(&pack.nodes[e.idx * BVH_QNODE_SIZE], data, sizeof(float4)*BVH_QNODE_SIZE);
@@ -794,7 +756,7 @@ void QBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num)
void QBVH::pack_nodes(const array<int>& prims, const BVHNode *root)
{
- size_t node_size = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
+ size_t node_size = root->getSubtreeSize(BVH_STAT_QNODE_COUNT);
/* resize arrays */
pack.nodes.clear();
@@ -865,8 +827,138 @@ void QBVH::pack_nodes(const array<int>& prims, const BVHNode *root)
void QBVH::refit_nodes()
{
- assert(0); /* todo */
+ assert(!params.top_level);
+
+ BoundBox bbox = BoundBox::empty;
+ uint visibility = 0;
+ refit_node(0, (pack.is_leaf[0])? true: false, bbox, visibility);
}
-CCL_NAMESPACE_END
+void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
+{
+ int4 *data = &pack.nodes[idx*BVH_QNODE_SIZE];
+ int4 c = data[6];
+ if(leaf) {
+ /* Refit leaf node. */
+ for(int prim = c.x; prim < c.y; prim++) {
+ int pidx = pack.prim_index[prim];
+ int tob = pack.prim_object[prim];
+ Object *ob = objects[tob];
+
+ if(pidx == -1) {
+ /* Object instance. */
+ bbox.grow(ob->bounds);
+ }
+ else {
+ /* Primitives. */
+ const Mesh *mesh = ob->mesh;
+
+ if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
+ /* Curves. */
+ int str_offset = (params.top_level)? mesh->curve_offset: 0;
+ const Mesh::Curve& curve = mesh->curves[pidx - str_offset];
+ int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
+
+ curve.bounds_grow(k, &mesh->curve_keys[0], bbox);
+
+ visibility |= PATH_RAY_CURVE;
+
+ /* Motion curves. */
+ if(mesh->use_motion_blur) {
+ Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if(attr) {
+ size_t mesh_size = mesh->curve_keys.size();
+ size_t steps = mesh->motion_steps - 1;
+ float4 *key_steps = attr->data_float4();
+
+ for (size_t i = 0; i < steps; i++)
+ curve.bounds_grow(k, key_steps + i*mesh_size, bbox);
+ }
+ }
+ }
+ else {
+ /* Triangles. */
+ int tri_offset = (params.top_level)? mesh->tri_offset: 0;
+ const Mesh::Triangle& triangle = mesh->triangles[pidx - tri_offset];
+ const float3 *vpos = &mesh->verts[0];
+
+ triangle.bounds_grow(vpos, bbox);
+
+ /* Motion triangles. */
+ if(mesh->use_motion_blur) {
+ Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if(attr) {
+ size_t mesh_size = mesh->verts.size();
+ size_t steps = mesh->motion_steps - 1;
+ float3 *vert_steps = attr->data_float3();
+
+ for (size_t i = 0; i < steps; i++)
+ triangle.bounds_grow(vert_steps + i*mesh_size, bbox);
+ }
+ }
+ }
+ }
+
+ visibility |= ob->visibility;
+ }
+
+ /* TODO(sergey): This is actually a copy of pack_leaf(),
+ * but this chunk of code only knows actual data and has
+ * no idea about BVHNode.
+ *
+ * Would be nice to de-duplicate code, but trying to make
+ * making code more general ends up in much nastier code
+ * in my opinion so far.
+ *
+ * Same applies to the inner nodes case below.
+ */
+ float4 leaf_data[BVH_QNODE_SIZE];
+ memset(leaf_data, 0, sizeof(leaf_data));
+ leaf_data[6].x = __int_as_float(c.x);
+ leaf_data[6].y = __int_as_float(c.y);
+ leaf_data[6].z = __uint_as_float(visibility);
+ leaf_data[6].w = __uint_as_float(c.w);
+ memcpy(&pack.nodes[idx * BVH_QNODE_SIZE],
+ leaf_data,
+ sizeof(float4)*BVH_QNODE_SIZE);
+ }
+ else {
+ /* Refit inner node, set bbox from children. */
+ BoundBox child_bbox[4] = {BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty};
+ uint child_visibility[4] = {0};
+ int num_nodes = 0;
+
+ for(int i = 0; i < 4; ++i) {
+ if(c[i] != 0) {
+ refit_node((c[i] < 0)? -c[i]-1: c[i], (c[i] < 0),
+ child_bbox[i], child_visibility[i]);
+ ++num_nodes;
+ bbox.grow(child_bbox[i]);
+ visibility |= child_visibility[i];
+ }
+ }
+
+ float4 inner_data[BVH_QNODE_SIZE];
+ for(int i = 0; i < 4; ++i) {
+ float3 bb_min = child_bbox[i].min;
+ float3 bb_max = child_bbox[i].max;
+ inner_data[0][i] = bb_min.x;
+ inner_data[1][i] = bb_max.x;
+ inner_data[2][i] = bb_min.y;
+ inner_data[3][i] = bb_max.y;
+ inner_data[4][i] = bb_min.z;
+ inner_data[5][i] = bb_max.z;
+ inner_data[6][i] = __int_as_float(c[i]);
+ }
+ memcpy(&pack.nodes[idx * BVH_QNODE_SIZE],
+ inner_data,
+ sizeof(float4)*BVH_QNODE_SIZE);
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index 5fcaaaa988c..a4a12707768 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -36,7 +36,7 @@ class Object;
class Progress;
#define BVH_NODE_SIZE 4
-#define BVH_QNODE_SIZE 8
+#define BVH_QNODE_SIZE 7
#define BVH_ALIGN 4096
#define TRI_NODE_SIZE 3
@@ -106,7 +106,6 @@ protected:
/* triangles and strands*/
void pack_primitives();
void pack_triangle(int idx, float4 woop[3]);
- void pack_curve_segment(int idx, float4 woop[3]);
/* merge instance BVH's */
void pack_instances(size_t nodes_size);
@@ -154,6 +153,7 @@ protected:
/* refit */
void refit_nodes();
+ void refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index eb4cca92b6b..dde8e455781 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -28,11 +28,27 @@
#include "util_debug.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_progress.h"
#include "util_time.h"
CCL_NAMESPACE_BEGIN
+#if !defined(__KERNEL_SSE2__)
+/* TODO(sergey): Move to some generic header so all code
+ * can use bitscan on non-SSE processors.
+ */
+ccl_device_inline int bitscan(int value)
+{
+ assert(value != 0);
+ int bit = 0;
+ while (value >>= 1) {
+ ++bit;
+ }
+ return bit;
+}
+#endif
+
/* BVH Build Task */
class BVHBuildTask : public Task {
@@ -223,7 +239,8 @@ BVHNode* BVHBuild::run()
spatial_right_bounds.resize(max(root.size(), (int)BVHParams::NUM_SPATIAL_BINS) - 1);
/* init progress updates */
- progress_start_time = time_dt();
+ double build_start_time;
+ build_start_time = progress_start_time = time_dt();
progress_count = 0;
progress_total = references.size();
progress_original_total = progress_total;
@@ -258,6 +275,18 @@ BVHNode* BVHBuild::run()
}
}
+ VLOG(1) << "BVH built in "
+ << time_dt() - build_start_time
+ << " seconds.";
+
+ VLOG(1) << "BVH statistics:";
+ VLOG(1) << " Total number of nodes: "
+ << rootnode->getSubtreeSize(BVH_STAT_NODE_COUNT);
+ VLOG(1) << " Number of inner nodes: "
+ << rootnode->getSubtreeSize(BVH_STAT_INNER_COUNT);
+ VLOG(1) << " Number of leaf nodes: "
+ << rootnode->getSubtreeSize(BVH_STAT_LEAF_COUNT);
+
return rootnode;
}
@@ -308,17 +337,22 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange& range)
size_t num_triangles = 0;
size_t num_curves = 0;
+ size_t num_motion_curves = 0;
for(int i = 0; i < size; i++) {
BVHReference& ref = references[range.start() + i];
- if(ref.prim_type() & PRIMITIVE_ALL_CURVE)
+ if(ref.prim_type() & PRIMITIVE_CURVE)
num_curves++;
+ if(ref.prim_type() & PRIMITIVE_MOTION_CURVE)
+ num_motion_curves++;
else if(ref.prim_type() & PRIMITIVE_ALL_TRIANGLE)
num_triangles++;
}
- return (num_triangles < params.max_triangle_leaf_size) && (num_curves < params.max_curve_leaf_size);
+ return (num_triangles < params.max_triangle_leaf_size) &&
+ (num_curves < params.max_curve_leaf_size) &&
+ (num_motion_curves < params.max_curve_leaf_size);
}
/* multithreaded binning builder */
@@ -394,7 +428,7 @@ BVHNode* BVHBuild::build_node(const BVHRange& range, int level)
progress_total += left.size() + right.size() - range.size();
size_t total = progress_total;
- /* leaft node */
+ /* left node */
BVHNode *leftnode = build_node(left, level + 1);
/* right node (modify start for splits) */
@@ -443,61 +477,119 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
}
}
-BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
+BVHNode *BVHBuild::create_primitive_leaf_node(const int *p_type,
+ const int *p_index,
+ const int *p_object,
+ const BoundBox& bounds,
+ uint visibility,
+ int start,
+ int num)
{
- vector<int>& p_type = prim_type;
- vector<int>& p_index = prim_index;
- vector<int>& p_object = prim_object;
- BoundBox bounds = BoundBox::empty;
- int num = 0, ob_num = 0;
- uint visibility = 0;
+ for(int i = 0; i < num; ++i) {
+ if(start + i == prim_index.size()) {
+ assert(params.use_spatial_split);
+ prim_type.push_back(p_type[i]);
+ prim_index.push_back(p_index[i]);
+ prim_object.push_back(p_object[i]);
+ }
+ else {
+ prim_type[start + i] = p_type[i];
+ prim_index[start + i] = p_index[i];
+ prim_object[start + i] = p_object[i];
+ }
+ }
+ return new LeafNode(bounds, visibility, start, start + num);
+}
+BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
+{
+#define MAX_LEAF_SIZE 8
+ int p_num[PRIMITIVE_NUM_TOTAL] = {0};
+ int p_type[PRIMITIVE_NUM_TOTAL][MAX_LEAF_SIZE];
+ int p_index[PRIMITIVE_NUM_TOTAL][MAX_LEAF_SIZE];
+ int p_object[PRIMITIVE_NUM_TOTAL][MAX_LEAF_SIZE];
+ uint visibility[PRIMITIVE_NUM_TOTAL] = {0};
+ /* NOTE: Keep initializtion in sync with actual number of primitives. */
+ BoundBox bounds[PRIMITIVE_NUM_TOTAL] = {BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty};
+ int ob_num = 0;
+
+ /* Fill in per-type type/index array. */
for(int i = 0; i < range.size(); i++) {
BVHReference& ref = references[range.start() + i];
-
if(ref.prim_index() != -1) {
- if(range.start() + num == prim_index.size()) {
- assert(params.use_spatial_split);
-
- p_type.push_back(ref.prim_type());
- p_index.push_back(ref.prim_index());
- p_object.push_back(ref.prim_object());
- }
- else {
- p_type[range.start() + num] = ref.prim_type();
- p_index[range.start() + num] = ref.prim_index();
- p_object[range.start() + num] = ref.prim_object();
- }
-
- bounds.grow(ref.bounds());
- visibility |= objects[ref.prim_object()]->visibility;
- num++;
+ int type_index = bitscan(ref.prim_type() & PRIMITIVE_ALL);
+ int idx = p_num[type_index];
+ p_type[type_index][idx] = ref.prim_type();
+ p_index[type_index][idx] = ref.prim_index();
+ p_object[type_index][idx] = ref.prim_object();
+ ++p_num[type_index];
+
+ bounds[type_index].grow(ref.bounds());
+ visibility[type_index] |= objects[ref.prim_object()]->visibility;
}
else {
- if(ob_num < i)
+ if(ob_num < i) {
references[range.start() + ob_num] = ref;
+ }
ob_num++;
}
}
- BVHNode *leaf = NULL;
-
- if(num > 0) {
- leaf = new LeafNode(bounds, visibility, range.start(), range.start() + num);
+ /* Create leaf nodes for every existing primitive. */
+ BVHNode *leaves[PRIMITIVE_NUM_TOTAL + 1] = {NULL};
+ int num_leaves = 0;
+ int start = range.start();
+ for(int i = 0; i < PRIMITIVE_NUM_TOTAL; ++i) {
+ if(p_num[i] != 0) {
+ leaves[num_leaves] = create_primitive_leaf_node(p_type[i],
+ p_index[i],
+ p_object[i],
+ bounds[i],
+ visibility[i],
+ start,
+ p_num[i]);
+ ++num_leaves;
+ start += p_num[i];
+ }
+ }
- if(num == range.size())
- return leaf;
+ /* Create leaf node for object. */
+ if(num_leaves == 0 || ob_num) {
+ /* Only create object leaf nodes if there are objects or no other
+ * nodes created.
+ */
+ const BVHReference *ref = (ob_num)? &references[range.start()]: NULL;
+ leaves[num_leaves] = create_object_leaf_nodes(ref, start, ob_num);
+ ++num_leaves;
}
- /* while there may be multiple triangles in a leaf, for object primitives
- * we want there to be the only one, so we keep splitting */
- const BVHReference *ref = (ob_num)? &references[range.start()]: NULL;
- BVHNode *oleaf = create_object_leaf_nodes(ref, range.start() + num, ob_num);
-
- if(leaf)
- return new InnerNode(range.bounds(), leaf, oleaf);
- else
- return oleaf;
+ if(num_leaves == 1) {
+ /* Simplest case: single leaf, just return it.
+ * In all the rest cases we'll be creating intermediate inner node with
+ * an appropriate bounding box.
+ */
+ return leaves[0];
+ }
+ else if(num_leaves == 2) {
+ return new InnerNode(range.bounds(), leaves[0], leaves[1]);
+ }
+ else if(num_leaves == 3) {
+ BoundBox inner_bounds = merge(bounds[1], bounds[2]);
+ BVHNode *inner = new InnerNode(inner_bounds, leaves[1], leaves[2]);
+ return new InnerNode(range.bounds(), leaves[0], inner);
+ } else /*if(num_leaves == 4)*/ {
+ /* Shpuld be doing more branches if more primitive types added. */
+ assert(num_leaves == 4);
+ BoundBox inner_bounds_a = merge(bounds[0], bounds[1]);
+ BoundBox inner_bounds_b = merge(bounds[2], bounds[3]);
+ BVHNode *inner_a = new InnerNode(inner_bounds_a, leaves[0], leaves[1]);
+ BVHNode *inner_b = new InnerNode(inner_bounds_b, leaves[2], leaves[3]);
+ return new InnerNode(range.bounds(), inner_a, inner_b);
+ }
+#undef AMX_LEAF_SIZE
}
/* Tree Rotations */
@@ -582,4 +674,3 @@ void BVHBuild::rotate(BVHNode *node, int max_depth)
}
CCL_NAMESPACE_END
-
diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h
index a6b9916de9b..294c5a1758d 100644
--- a/intern/cycles/bvh/bvh_build.h
+++ b/intern/cycles/bvh/bvh_build.h
@@ -70,6 +70,15 @@ protected:
BVHNode *create_leaf_node(const BVHRange& range);
BVHNode *create_object_leaf_nodes(const BVHReference *ref, int start, int num);
+ /* Leaf node type splitting. */
+ BVHNode *create_primitive_leaf_node(const int *p_type,
+ const int *p_index,
+ const int *p_object,
+ const BoundBox& bounds,
+ uint visibility,
+ int start,
+ int nun);
+
bool range_within_max_leaf_size(const BVHRange& range);
/* threads */
@@ -116,4 +125,3 @@ protected:
CCL_NAMESPACE_END
#endif /* __BVH_BUILD_H__ */
-
diff --git a/intern/cycles/bvh/bvh_node.cpp b/intern/cycles/bvh/bvh_node.cpp
index 7cc9bd333b0..8294690da7d 100644
--- a/intern/cycles/bvh/bvh_node.cpp
+++ b/intern/cycles/bvh/bvh_node.cpp
@@ -47,6 +47,20 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const
case BVH_STAT_CHILDNODE_COUNT:
cnt = num_children();
break;
+ case BVH_STAT_QNODE_COUNT:
+ cnt = 1;
+ for(int i = 0; i < num_children(); i++) {
+ BVHNode *node = get_child(i);
+ if(node->is_leaf()) {
+ cnt += 1;
+ }
+ else {
+ for(int j = 0; j < node->num_children(); j++) {
+ cnt += node->get_child(j)->getSubtreeSize(stat);
+ }
+ }
+ }
+ return cnt;
default:
assert(0); /* unknown mode */
}
diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h
index a0d10a46bfc..1656bb367a4 100644
--- a/intern/cycles/bvh/bvh_node.h
+++ b/intern/cycles/bvh/bvh_node.h
@@ -30,7 +30,8 @@ enum BVH_STAT
BVH_STAT_INNER_COUNT,
BVH_STAT_LEAF_COUNT,
BVH_STAT_TRIANGLE_COUNT,
- BVH_STAT_CHILDNODE_COUNT
+ BVH_STAT_CHILDNODE_COUNT,
+ BVH_STAT_QNODE_COUNT,
};
class BVHParams;
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index e073b69472e..3fa6ebd75af 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -49,8 +49,6 @@ public:
/* QBVH */
int use_qbvh;
- int pad;
-
/* fixed parameters */
enum {
MAX_DEPTH = 64,
@@ -75,7 +73,6 @@ public:
top_level = false;
use_cache = false;
use_qbvh = false;
- pad = false;
}
/* SAH costs */
@@ -115,6 +112,11 @@ public:
__forceinline int prim_object() const { return __float_as_int(rbounds.max.w); }
__forceinline int prim_type() const { return type; }
+ BVHReference& operator=(const BVHReference &arg) {
+ memcpy(this, &arg, sizeof(BVHReference));
+ return *this;
+ }
+
protected:
BoundBox rbounds;
uint type;
diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake
index 4f02b93f04a..d7c59f42a5e 100644
--- a/intern/cycles/cmake/external_libs.cmake
+++ b/intern/cycles/cmake/external_libs.cmake
@@ -1,4 +1,13 @@
###########################################################################
+# Precompiled libraries tips and hints, for find_package().
+
+if(CYCLES_STANDALONE_REPOSITORY)
+ if(APPLE OR WIN32)
+ include(precompiled_libs)
+ endif()
+endif()
+
+###########################################################################
# GLUT
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
@@ -16,6 +25,11 @@ endif()
###########################################################################
# GLEW
+# Workaround for unconventional variable name use in Blender.
+if(NOT CYCLES_STANDALONE_REPOSITORY)
+ set(GLEW_INCLUDE_DIR "${GLEW_INCLUDE_PATH}")
+endif()
+
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
set(CYCLES_APP_GLEW_LIBRARY ${BLENDER_GLEW_LIBRARIES})
endif()
@@ -32,3 +46,96 @@ if(WITH_CYCLES_CUDA_BINARIES)
set(WITH_CYCLES_CUDA_BINARIES OFF)
endif()
endif()
+
+# Packages which are being found by Blender when building from inside Blender
+# source code. but which we need to take care of when building Cycles from a
+# standalone repository
+if(CYCLES_STANDALONE_REPOSITORY)
+ # PThreads
+ # TODO(sergey): Bloody exception, handled in precompiled_libs.cmake.
+ if(NOT WIN32)
+ set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+ find_package(Threads REQUIRED)
+ set(PTHREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+ endif()
+
+ ####
+ # OpenGL
+
+ # TODO(sergey): We currently re-use the same variable name as we use
+ # in Blender. Ideally we need to make it CYCLES_GL_LIBRARIES.
+ find_package(OpenGL REQUIRED)
+ find_package(GLEW REQUIRED)
+ list(APPEND BLENDER_GL_LIBRARIES
+ "${OPENGL_gl_LIBRARY}"
+ "${OPENGL_glu_LIBRARY}"
+ "${GLEW_LIBRARY}"
+ )
+
+ ####
+ # OpenImageIO
+ find_package(OpenImageIO REQUIRED)
+ if(OPENIMAGEIO_PUGIXML_FOUND)
+ set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR/OpenImageIO}")
+ set(PUGIXML_LIBRARIES "")
+ else()
+ find_package(PugiXML REQUIRED)
+ endif()
+
+ # OIIO usually depends on OpenEXR, so find this library
+ # but don't make it required.
+ find_package(OpenEXR)
+
+ ####
+ # Boost
+ set(__boost_packages filesystem regex system thread date_time)
+ if(WITH_CYCLES_NETWORK)
+ list(APPEND __boost_packages serialization)
+ endif()
+ if(WITH_CYCLES_OSL)
+ # TODO(sergey): This is because of the way how our precompiled
+ # libraries works, could be different for someone's else libs..
+ if(APPLE OR MSVC)
+ list(APPEND __boost_packages wave)
+ endif()
+ endif()
+ find_package(Boost 1.48 COMPONENTS ${__boost_packages} REQUIRED)
+ if(NOT Boost_FOUND)
+ # Try to find non-multithreaded if -mt not found, this flag
+ # doesn't matter for us, it has nothing to do with thread
+ # safety, but keep it to not disturb build setups.
+ set(Boost_USE_MULTITHREADED OFF)
+ find_package(Boost 1.48 COMPONENTS ${__boost_packages})
+ endif()
+ unset(__boost_packages)
+ set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
+ set(BOOST_LIBRARIES ${Boost_LIBRARIES})
+ set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
+ set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
+
+ ####
+ # OpenShadingLanguage
+ if(WITH_CYCLES_OSL)
+ find_package(OpenShadingLanguage REQUIRED)
+ find_package(LLVM REQUIRED)
+ endif()
+
+ ####
+ # Logging
+ if(WITH_CYCLES_LOGGING)
+ find_package(Glog REQUIRED)
+ find_package(Gflags REQUIRED)
+ endif()
+
+ unset(_lib_DIR)
+else()
+ if(WIN32)
+ set(GLOG_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/libmv/third_party/glog/src/windows)
+ set(GFLAGS_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/libmv/third_party/gflags)
+ else()
+ set(GLOG_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/libmv/third_party/glog/src)
+ set(GFLAGS_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/libmv/third_party/gflags)
+ endif()
+ set(GFLAGS_NAMESPACE "gflags")
+ set(LLVM_LIBRARIES ${LLVM_LIBRARY})
+endif()
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index 998b35351e3..b0fa283c1d8 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -10,7 +10,7 @@ set(INC
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_DIR}
../../../extern/cuew/include
../../../extern/clew/include
)
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index efdfa98cfb5..3a33b8fb68b 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdlib.h>
@@ -20,9 +20,6 @@
#include "device.h"
#include "device_intern.h"
-#include "cuew.h"
-#include "clew.h"
-
#include "util_debug.h"
#include "util_foreach.h"
#include "util_half.h"
@@ -268,5 +265,28 @@ vector<DeviceInfo>& Device::available_devices()
return devices;
}
-CCL_NAMESPACE_END
+string Device::device_capabilities()
+{
+ string capabilities = "CPU device capabilities: ";
+ capabilities += device_cpu_capabilities() + "\n";
+#ifdef WITH_CUDA
+ if(device_cuda_init()) {
+ capabilities += "\nCUDA device capabilities:\n";
+ capabilities += device_cuda_capabilities();
+ }
+#endif
+#ifdef WITH_OPENCL
+ /* TODO(sergey): Needs proper usable implementation. */
+ /*
+ if(device_opencl_init()) {
+ capabilities += "\nOpenCL device capabilities:\n";
+ capabilities += device_opencl_capabilities();
+ }
+ */
+#endif
+
+ return capabilities;
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 20ebfd391d6..7c17f7f4112 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __DEVICE_H__
@@ -148,6 +148,7 @@ public:
static string string_from_type(DeviceType type);
static vector<DeviceType>& available_types();
static vector<DeviceInfo>& available_devices();
+ static string device_capabilities();
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index e5242e7ee47..a993a5810f5 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdlib.h>
@@ -419,5 +419,17 @@ void device_cpu_info(vector<DeviceInfo>& devices)
devices.insert(devices.begin(), info);
}
-CCL_NAMESPACE_END
+string device_cpu_capabilities(void)
+{
+ string capabilities = "";
+ capabilities += system_cpu_support_sse2() ? "SSE2 " : "";
+ capabilities += system_cpu_support_sse3() ? "SSE3 " : "";
+ capabilities += system_cpu_support_sse41() ? "SSE41 " : "";
+ capabilities += system_cpu_support_avx() ? "AVX " : "";
+ capabilities += system_cpu_support_avx2() ? "AVX2" : "";
+ if(capabilities[capabilities.size() - 1] == ' ')
+ capabilities.resize(capabilities.size() - 1);
+ return capabilities;
+}
+CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index b3d4215e51b..7f2f141bd2f 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdio.h>
@@ -25,9 +25,11 @@
#include "cuew.h"
#include "util_debug.h"
+#include "util_logging.h"
#include "util_map.h"
#include "util_opengl.h"
#include "util_path.h"
+#include "util_string.h"
#include "util_system.h"
#include "util_types.h"
#include "util_time.h"
@@ -76,7 +78,7 @@ public:
{
if(first_error) {
fprintf(stderr, "\nRefer to the Cycles GPU rendering documentation for possible solutions:\n");
- fprintf(stderr, "http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/GPU_Rendering\n\n");
+ fprintf(stderr, "http://www.blender.org/manual/render/cycles/gpu_rendering.html\n\n");
first_error = false;
}
}
@@ -202,31 +204,18 @@ public:
/* compute cubin name */
int major, minor;
cuDeviceComputeCapability(&major, &minor, cuDevId);
-
string cubin;
- /* ToDo: We don't bundle sm_52 kernel yet */
- if(major == 5 && minor == 2) {
- 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))
- /* self build sm_52 kernel? Use it. */
- return cubin;
- else
- /* use 5.0 kernel as workaround */
- minor = 0;
- }
-
/* attempt to use kernel provided with blender */
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))
+ VLOG(1) << "Testing for pre-compiled kernel " << cubin;
+ if(path_exists(cubin)) {
+ VLOG(1) << "Using precompiled kernel";
return cubin;
+ }
/* not found, try to use locally compiled kernel */
string kernel_path = path_get("kernel");
@@ -237,10 +226,12 @@ public:
else
cubin = string_printf("cycles_kernel_sm%d%d_%s.cubin", major, minor, md5.c_str());
cubin = path_user_get(path_join("cache", cubin));
-
+ VLOG(1) << "Testing for locally compiled kernel " << cubin;
/* if exists already, use it */
- if(path_exists(cubin))
+ if(path_exists(cubin)) {
+ VLOG(1) << "Using locally compiled kernel";
return cubin;
+ }
#ifdef _WIN32
if(have_precompiled_kernels()) {
@@ -261,6 +252,7 @@ public:
}
int cuda_version = cuewCompilerVersion();
+ VLOG(1) << "Found nvcc " << nvcc << ", CUDA version " << cuda_version;
if(cuda_version == 0) {
cuda_error_message("CUDA nvcc compiler version could not be parsed.");
@@ -1042,15 +1034,30 @@ bool device_cuda_init(void)
return result;
initialized = true;
-
- if (cuewInit() == CUEW_SUCCESS) {
- if(CUDADevice::have_precompiled_kernels())
+ int cuew_result = cuewInit();
+ if (cuew_result == CUEW_SUCCESS) {
+ VLOG(1) << "CUEW initialization succeeded";
+ if(CUDADevice::have_precompiled_kernels()) {
+ VLOG(1) << "Found precompiled kernels";
result = true;
+ }
#ifndef _WIN32
- else if(cuewCompilerPath() != NULL)
+ else if(cuewCompilerPath() != NULL) {
+ VLOG(1) << "Found CUDA compiled " << cuewCompilerPath();
result = true;
+ }
+ else {
+ VLOG(1) << "Neither precompiled kernels nor CUDA compiler wad found,"
+ << " unable to use CUDA";
+ }
#endif
}
+ else {
+ VLOG(1) << "CUEW initialization failed: "
+ << ((cuew_result == CUEW_ERROR_ATEXIT_FAILED)
+ ? "Error setting up atexit() handler"
+ : "Error opening the library");
+ }
return result;
}
@@ -1113,5 +1120,135 @@ void device_cuda_info(vector<DeviceInfo>& devices)
devices.insert(devices.end(), display_devices.begin(), display_devices.end());
}
-CCL_NAMESPACE_END
+string device_cuda_capabilities(void)
+{
+ CUresult result = cuInit(0);
+ if(result != CUDA_SUCCESS) {
+ if(result != CUDA_ERROR_NO_DEVICE) {
+ return string("Error initializing CUDA: ") + cuewErrorString(result);
+ }
+ return "No CUDA device found";
+ }
+
+ int count;
+ result = cuDeviceGetCount(&count);
+ if(result != CUDA_SUCCESS) {
+ return string("Error getting devices: ") + cuewErrorString(result);
+ }
+
+ string capabilities = "";
+ for(int num = 0; num < count; num++) {
+ char name[256];
+ if(cuDeviceGetName(name, 256, num) != CUDA_SUCCESS) {
+ continue;
+ }
+ capabilities += string("\t") + name + "\n";
+ int value;
+#define GET_ATTR(attr) \
+ { \
+ if(cuDeviceGetAttribute(&value, \
+ CU_DEVICE_ATTRIBUTE_##attr, \
+ num) == CUDA_SUCCESS) \
+ { \
+ capabilities += string_printf("\t\tCU_DEVICE_ATTRIBUTE_" #attr "\t\t\t%d\n", \
+ value); \
+ } \
+ } (void)0
+ /* TODO(sergey): Strip all attributes which are not useful for us
+ * or does not depend on the driver.
+ */
+ GET_ATTR(MAX_THREADS_PER_BLOCK);
+ GET_ATTR(MAX_BLOCK_DIM_X);
+ GET_ATTR(MAX_BLOCK_DIM_Y);
+ GET_ATTR(MAX_BLOCK_DIM_Z);
+ GET_ATTR(MAX_GRID_DIM_X);
+ GET_ATTR(MAX_GRID_DIM_Y);
+ GET_ATTR(MAX_GRID_DIM_Z);
+ GET_ATTR(MAX_SHARED_MEMORY_PER_BLOCK);
+ GET_ATTR(SHARED_MEMORY_PER_BLOCK);
+ GET_ATTR(TOTAL_CONSTANT_MEMORY);
+ GET_ATTR(WARP_SIZE);
+ GET_ATTR(MAX_PITCH);
+ GET_ATTR(MAX_REGISTERS_PER_BLOCK);
+ GET_ATTR(REGISTERS_PER_BLOCK);
+ GET_ATTR(CLOCK_RATE);
+ GET_ATTR(TEXTURE_ALIGNMENT);
+ GET_ATTR(GPU_OVERLAP);
+ GET_ATTR(MULTIPROCESSOR_COUNT);
+ GET_ATTR(KERNEL_EXEC_TIMEOUT);
+ GET_ATTR(INTEGRATED);
+ GET_ATTR(CAN_MAP_HOST_MEMORY);
+ GET_ATTR(COMPUTE_MODE);
+ GET_ATTR(MAXIMUM_TEXTURE1D_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE3D_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE3D_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE3D_DEPTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LAYERED_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_TEXTURE2D_ARRAY_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_ARRAY_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE2D_ARRAY_NUMSLICES);
+ GET_ATTR(SURFACE_ALIGNMENT);
+ GET_ATTR(CONCURRENT_KERNELS);
+ GET_ATTR(ECC_ENABLED);
+ GET_ATTR(TCC_DRIVER);
+ GET_ATTR(MEMORY_CLOCK_RATE);
+ GET_ATTR(GLOBAL_MEMORY_BUS_WIDTH);
+ GET_ATTR(L2_CACHE_SIZE);
+ GET_ATTR(MAX_THREADS_PER_MULTIPROCESSOR);
+ GET_ATTR(ASYNC_ENGINE_COUNT);
+ GET_ATTR(UNIFIED_ADDRESSING);
+ GET_ATTR(MAXIMUM_TEXTURE1D_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE1D_LAYERED_LAYERS);
+ GET_ATTR(CAN_TEX2D_GATHER);
+ GET_ATTR(MAXIMUM_TEXTURE2D_GATHER_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_GATHER_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE3D_WIDTH_ALTERNATE);
+ GET_ATTR(MAXIMUM_TEXTURE3D_HEIGHT_ALTERNATE);
+ GET_ATTR(MAXIMUM_TEXTURE3D_DEPTH_ALTERNATE);
+ GET_ATTR(TEXTURE_PITCH_ALIGNMENT);
+ GET_ATTR(MAXIMUM_TEXTURECUBEMAP_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURECUBEMAP_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURECUBEMAP_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_SURFACE1D_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE2D_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE2D_HEIGHT);
+ GET_ATTR(MAXIMUM_SURFACE3D_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE3D_HEIGHT);
+ GET_ATTR(MAXIMUM_SURFACE3D_DEPTH);
+ GET_ATTR(MAXIMUM_SURFACE1D_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE1D_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_SURFACE2D_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE2D_LAYERED_HEIGHT);
+ GET_ATTR(MAXIMUM_SURFACE2D_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_SURFACECUBEMAP_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACECUBEMAP_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACECUBEMAP_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_TEXTURE1D_LINEAR_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LINEAR_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LINEAR_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LINEAR_PITCH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_MIPMAPPED_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_MIPMAPPED_HEIGHT);
+ GET_ATTR(COMPUTE_CAPABILITY_MAJOR);
+ GET_ATTR(COMPUTE_CAPABILITY_MINOR);
+ GET_ATTR(MAXIMUM_TEXTURE1D_MIPMAPPED_WIDTH);
+ GET_ATTR(STREAM_PRIORITIES_SUPPORTED);
+ GET_ATTR(GLOBAL_L1_CACHE_SUPPORTED);
+ GET_ATTR(LOCAL_L1_CACHE_SUPPORTED);
+ GET_ATTR(MAX_SHARED_MEMORY_PER_MULTIPROCESSOR);
+ GET_ATTR(MAX_REGISTERS_PER_MULTIPROCESSOR);
+ GET_ATTR(MANAGED_MEMORY);
+ GET_ATTR(MULTI_GPU_BOARD);
+ GET_ATTR(MULTI_GPU_BOARD_GROUP_ID);
+#undef GET_ATTR
+ capabilities += "\n";
+ }
+
+ return capabilities;
+}
+CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h
index 80f1e2441a5..47584ae6d22 100644
--- a/intern/cycles/device/device_intern.h
+++ b/intern/cycles/device/device_intern.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __DEVICE_INTERN_H__
@@ -35,6 +35,10 @@ void device_cuda_info(vector<DeviceInfo>& devices);
void device_network_info(vector<DeviceInfo>& devices);
void device_multi_info(vector<DeviceInfo>& devices);
+string device_cpu_capabilities(void);
+string device_opencl_capabilities(void);
+string device_cuda_capabilities(void);
+
CCL_NAMESPACE_END
#endif /* __DEVICE_INTERN_H__ */
diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h
index 07a6eb36a3c..7df2bc1a0c2 100644
--- a/intern/cycles/device/device_memory.h
+++ b/intern/cycles/device/device_memory.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __DEVICE_MEMORY_H__
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index 7f055c79491..9aac86daa1d 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdlib.h>
diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp
index dca9bf29e70..4733482bf4e 100644
--- a/intern/cycles/device/device_network.cpp
+++ b/intern/cycles/device/device_network.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "device.h"
diff --git a/intern/cycles/device/device_network.h b/intern/cycles/device/device_network.h
index 893841d1da7..2e751f6697f 100644
--- a/intern/cycles/device/device_network.h
+++ b/intern/cycles/device/device_network.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __DEVICE_NETWORK_H__
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index 58b2bcafb82..a5bf35a63c8 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifdef WITH_OPENCL
@@ -20,13 +20,13 @@
#include <stdlib.h>
#include <string.h>
+#include "clew.h"
+
#include "device.h"
#include "device_intern.h"
#include "buffers.h"
-#include "clew.h"
-
#include "util_foreach.h"
#include "util_map.h"
#include "util_math.h"
@@ -1195,7 +1195,12 @@ void device_opencl_info(vector<DeviceInfo>& devices)
}
}
+string device_opencl_capabilities(void)
+{
+ /* TODO(sergey): Not implemented yet. */
+ return "";
+}
+
CCL_NAMESPACE_END
#endif /* WITH_OPENCL */
-
diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp
index dc124f8cf37..2fe2f334176 100644
--- a/intern/cycles/device/device_task.cpp
+++ b/intern/cycles/device/device_task.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdlib.h>
diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h
index 50216adefe2..84945bcf9a5 100644
--- a/intern/cycles/device/device_task.h
+++ b/intern/cycles/device/device_task.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __DEVICE_TASK_H__
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 0ff227938ae..0b2a5436879 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -123,7 +123,13 @@ set(SRC_GEOM_HEADERS
geom/geom_motion_triangle.h
geom/geom_object.h
geom/geom_primitive.h
+ geom/geom_qbvh.h
+ geom/geom_qbvh_shadow.h
+ geom/geom_qbvh_subsurface.h
+ geom/geom_qbvh_traversal.h
+ geom/geom_qbvh_volume.h
geom/geom_triangle.h
+ geom/geom_triangle_intersect.h
geom/geom_volume.h
)
@@ -236,17 +242,26 @@ if(CXX_HAS_SSE)
kernel_sse2.cpp
kernel_sse3.cpp
kernel_sse41.cpp
- kernel_avx.cpp
- kernel_avx2.cpp
)
set_source_files_properties(kernel_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
set_source_files_properties(kernel_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
set_source_files_properties(kernel_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
+endif()
+
+if(CXX_HAS_AVX)
+ list(APPEND SRC
+ kernel_avx.cpp
+ )
set_source_files_properties(kernel_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
- set_source_files_properties(kernel_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
endif()
+if(CXX_HAS_AVX2)
+ list(APPEND SRC
+ kernel_avx2.cpp
+ )
+ set_source_files_properties(kernel_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
+endif()
add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_SVM_HEADERS} ${SRC_GEOM_HEADERS})
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 7d4783b0f3c..56cd52f69e6 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "../closure/bsdf_ashikhmin_velvet.h"
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
index 1a1c1af6f5d..acc477246d2 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __BSDF_ASHIKHMIN_SHIRLEY_H__
@@ -37,7 +37,7 @@ ccl_device int bsdf_ashikhmin_shirley_setup(ShaderClosure *sc)
sc->data1 = sc->data0;
sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_ashikhmin_shirley_aniso_setup(ShaderClosure *sc)
@@ -46,7 +46,7 @@ ccl_device int bsdf_ashikhmin_shirley_aniso_setup(ShaderClosure *sc)
sc->data1 = clamp(sc->data1, 1e-4f, 1.0f);
sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_ashikhmin_shirley_blur(ShaderClosure *sc, float roughness)
diff --git a/intern/cycles/kernel/closure/bsdf_hair.h b/intern/cycles/kernel/closure/bsdf_hair.h
index e0b5454592b..4f4fd5d26b8 100644
--- a/intern/cycles/kernel/closure/bsdf_hair.h
+++ b/intern/cycles/kernel/closure/bsdf_hair.h
@@ -49,7 +49,7 @@ ccl_device int bsdf_hair_reflection_setup(ShaderClosure *sc)
sc->type = CLOSURE_BSDF_HAIR_REFLECTION_ID;
sc->data0 = clamp(sc->data0, 0.001f, 1.0f);
sc->data1 = clamp(sc->data1, 0.001f, 1.0f);
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_hair_transmission_setup(ShaderClosure *sc)
@@ -57,7 +57,7 @@ ccl_device int bsdf_hair_transmission_setup(ShaderClosure *sc)
sc->type = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
sc->data0 = clamp(sc->data0, 0.001f, 1.0f);
sc->data1 = clamp(sc->data1, 0.001f, 1.0f);
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device float3 bsdf_hair_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 8737b0e2d94..9561885525f 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -305,7 +305,7 @@ ccl_device int bsdf_microfacet_ggx_setup(ShaderClosure *sc)
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_aniso_setup(ShaderClosure *sc)
@@ -315,7 +315,7 @@ ccl_device int bsdf_microfacet_ggx_aniso_setup(ShaderClosure *sc)
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc)
@@ -325,7 +325,7 @@ ccl_device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc)
sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
@@ -657,7 +657,7 @@ ccl_device int bsdf_microfacet_beckmann_setup(ShaderClosure *sc)
sc->data1 = sc->data0; /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_beckmann_aniso_setup(ShaderClosure *sc)
@@ -666,7 +666,7 @@ ccl_device int bsdf_microfacet_beckmann_aniso_setup(ShaderClosure *sc)
sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_beckmann_refraction_setup(ShaderClosure *sc)
@@ -675,7 +675,7 @@ ccl_device int bsdf_microfacet_beckmann_refraction_setup(ShaderClosure *sc)
sc->data1 = sc->data0; /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness)
diff --git a/intern/cycles/kernel/closure/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
index 6d3b915c24a..d18c3dd6142 100644
--- a/intern/cycles/kernel/closure/bsdf_oren_nayar.h
+++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __BSDF_OREN_NAYAR_H__
diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
index dfd093b676e..f9f263719e9 100644
--- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h
+++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
@@ -54,7 +54,7 @@ ccl_device int bsdf_phong_ramp_setup(ShaderClosure *sc)
sc->data0 = max(sc->data0, 0.0f);
sc->type = CLOSURE_BSDF_PHONG_RAMP_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_phong_ramp_blur(ShaderClosure *sc, float roughness)
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h
index 3849dedc3b6..b6de2da8c71 100644
--- a/intern/cycles/kernel/closure/bssrdf.h
+++ b/intern/cycles/kernel/closure/bssrdf.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __KERNEL_BSSRDF_H__
diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h
index 058c4b8408f..9f519e2e2b1 100644
--- a/intern/cycles/kernel/closure/volume.h
+++ b/intern/cycles/kernel/closure/volume.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __VOLUME_H__
diff --git a/intern/cycles/kernel/geom/geom.h b/intern/cycles/kernel/geom/geom.h
index 9495a2541f9..bf0d86e6206 100644
--- a/intern/cycles/kernel/geom/geom.h
+++ b/intern/cycles/kernel/geom/geom.h
@@ -20,7 +20,9 @@
/* 64 object BVH + 64 mesh BVH + 64 object node splitting */
#define BVH_STACK_SIZE 192
+#define BVH_QSTACK_SIZE 384
#define BVH_NODE_SIZE 4
+#define BVH_QNODE_SIZE 7
#define TRI_NODE_SIZE 3
/* silly workaround for float extended precision that happens when compiling
@@ -35,6 +37,7 @@
#include "geom_attribute.h"
#include "geom_object.h"
#include "geom_triangle.h"
+#include "geom_triangle_intersect.h"
#include "geom_motion_triangle.h"
#include "geom_motion_curve.h"
#include "geom_curve.h"
diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h
index 63ce31c492f..2ade0df768f 100644
--- a/intern/cycles/kernel/geom/geom_attribute.h
+++ b/intern/cycles/kernel/geom/geom_attribute.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/geom/geom_bvh.h b/intern/cycles/kernel/geom/geom_bvh.h
index c5336e086b7..c0eefcd9c7f 100644
--- a/intern/cycles/kernel/geom/geom_bvh.h
+++ b/intern/cycles/kernel/geom/geom_bvh.h
@@ -42,6 +42,17 @@ CCL_NAMESPACE_BEGIN
#define BVH_HAIR 4
#define BVH_HAIR_MINIMUM_WIDTH 8
+#define BVH_NAME_JOIN(x,y) x ## _ ## y
+#define BVH_NAME_EVAL(x,y) BVH_NAME_JOIN(x,y)
+#define BVH_FUNCTION_FULL_NAME(prefix) BVH_NAME_EVAL(prefix, BVH_FUNCTION_NAME)
+
+#define BVH_FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
+
+/* Common QBVH functions. */
+#ifdef __QBVH__
+#include "geom_qbvh.h"
+#endif
+
/* Regular BVH traversal */
#define BVH_FUNCTION_NAME bvh_intersect
@@ -168,6 +179,11 @@ CCL_NAMESPACE_BEGIN
#include "geom_bvh_volume.h"
#endif
+#undef BVH_FEATURE
+#undef BVH_NAME_JOIN
+#undef BVH_NAME_EVAL
+#undef BVH_FUNCTION_FULL_NAME
+
ccl_device_intersect bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect,
uint *lcg_state, float difl, float extmax)
{
diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/geom/geom_bvh_shadow.h
index aee4097d77e..193f49074a3 100644
--- a/intern/cycles/kernel/geom/geom_bvh_shadow.h
+++ b/intern/cycles/kernel/geom/geom_bvh_shadow.h
@@ -17,6 +17,10 @@
* limitations under the License.
*/
+#ifdef __QBVH__
+#include "geom_qbvh_shadow.h"
+#endif
+
/* This is a template BVH traversal function, where various features can be
* enabled/disabled. This way we can compile optimized versions for each case
* without new features slowing things down.
@@ -27,10 +31,11 @@
*
*/
-#define FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
-
-ccl_device bool BVH_FUNCTION_NAME
-(KernelGlobals *kg, const Ray *ray, Intersection *isect_array, const uint max_hits, uint *num_hits)
+ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ const uint max_hits,
+ uint *num_hits)
{
/* todo:
* - likely and unlikely for if() statements
@@ -53,11 +58,11 @@ ccl_device bool BVH_FUNCTION_NAME
int object = OBJECT_NONE;
float isect_t = tmax;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
Transform ob_tfm;
#endif
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
int num_hits_in_instance = 0;
#endif
@@ -81,6 +86,9 @@ ccl_device bool BVH_FUNCTION_NAME
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
/* traversal loop */
do {
do {
@@ -174,6 +182,7 @@ ccl_device bool BVH_FUNCTION_NAME
}
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = nodeAddrChild1;
}
else {
@@ -191,13 +200,15 @@ ccl_device bool BVH_FUNCTION_NAME
/* if node is leaf, fetch triangle list */
if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1));
+ float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+3);
int primAddr = __float_as_int(leaf.x);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
/* pop */
nodeAddr = traversalStack[stackPtr];
@@ -205,25 +216,26 @@ ccl_device bool BVH_FUNCTION_NAME
/* primitive intersection */
while(primAddr < primAddr2) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+
bool hit;
- uint type = kernel_tex_fetch(__prim_type, primAddr);
/* todo: specialized intersect functions which don't fill in
* isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
* might give a few % performance improvement */
- switch(type & PRIMITIVE_ALL) {
+ switch(p_type) {
case PRIMITIVE_TRIANGLE: {
- hit = triangle_intersect(kg, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr);
+ hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr);
break;
}
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, PATH_RAY_SHADOW, object, primAddr);
break;
}
#endif
-#if FEATURE(BVH_HAIR)
+#if BVH_FEATURE(BVH_HAIR)
case PRIMITIVE_CURVE:
case PRIMITIVE_MOTION_CURVE: {
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
@@ -274,7 +286,7 @@ ccl_device bool BVH_FUNCTION_NAME
/* move on to next entry in intersections array */
isect_array++;
(*num_hits)++;
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
num_hits_in_instance++;
#endif
@@ -284,52 +296,55 @@ ccl_device bool BVH_FUNCTION_NAME
primAddr++;
}
}
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
else {
/* instance push */
object = kernel_tex_fetch(__prim_object, -primAddr-1);
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
#else
bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
num_hits_in_instance = 0;
+ isect_array->t = isect_t;
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
Psplat[1] = ssef(P.y);
Psplat[2] = ssef(P.z);
- isect_array->t = isect_t;
tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
-
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
nodeAddr = kernel_tex_fetch(__object_node, object);
}
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(stackPtr >= 0) {
kernel_assert(object != OBJECT_NONE);
if(num_hits_in_instance) {
float t_fac;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_tfm);
#else
bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
/* scale isect->t to adjust for instancing */
for(int i = 0; i < num_hits_in_instance; i++)
(isect_array-i-1)->t *= t_fac;
@@ -337,22 +352,23 @@ ccl_device bool BVH_FUNCTION_NAME
else {
float ignore_t = FLT_MAX;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_tfm);
#else
bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
}
+ isect_t = tmax;
+ isect_array->t = isect_t;
+
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
Psplat[1] = ssef(P.y);
Psplat[2] = ssef(P.z);
- isect_t = tmax;
- isect_array->t = isect_t;
tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
-
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
@@ -360,13 +376,37 @@ ccl_device bool BVH_FUNCTION_NAME
nodeAddr = traversalStack[stackPtr];
--stackPtr;
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
return false;
}
-#undef FEATURE
+ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ const uint max_hits,
+ uint *num_hits)
+{
+#ifdef __QBVH__
+ if(kernel_data.bvh.use_qbvh) {
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+ ray,
+ isect_array,
+ max_hits,
+ num_hits);
+ }
+ else
+#endif
+ {
+ kernel_assert(kernel_data.bvh.use_qbvh == false);
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+ ray,
+ isect_array,
+ max_hits,
+ num_hits);
+ }
+}
+
#undef BVH_FUNCTION_NAME
#undef BVH_FUNCTION_FEATURES
-
diff --git a/intern/cycles/kernel/geom/geom_bvh_subsurface.h b/intern/cycles/kernel/geom/geom_bvh_subsurface.h
index a8f57cffa78..290297ef5c5 100644
--- a/intern/cycles/kernel/geom/geom_bvh_subsurface.h
+++ b/intern/cycles/kernel/geom/geom_bvh_subsurface.h
@@ -17,6 +17,10 @@
* limitations under the License.
*/
+#ifdef __QBVH__
+#include "geom_qbvh_subsurface.h"
+#endif
+
/* This is a template BVH traversal function for subsurface scattering, where
* various features can be enabled/disabled. This way we can compile optimized
* versions for each case without new features slowing things down.
@@ -26,10 +30,12 @@
*
*/
-#define FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
-
-ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersection *isect_array,
- int subsurface_object, uint *lcg_state, int max_hits)
+ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ int subsurface_object,
+ uint *lcg_state,
+ int max_hits)
{
/* todo:
* - test if pushing distance on the stack helps (for non shadow rays)
@@ -54,10 +60,9 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
int object = OBJECT_NONE;
float isect_t = ray->t;
- const uint visibility = PATH_RAY_ALL_VISIBILITY;
uint num_hits = 0;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
Transform ob_tfm;
#endif
@@ -78,6 +83,9 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
/* traversal loop */
do {
do
@@ -118,14 +126,8 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
/* decide which nodes to traverse next */
-#ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- traverseChild0 = (c0max >= c0min) && (__float_as_uint(cnodes.z) & visibility);
- traverseChild1 = (c1max >= c1min) && (__float_as_uint(cnodes.w) & visibility);
-#else
traverseChild0 = (c0max >= c0min);
traverseChild1 = (c1max >= c1min);
-#endif
#else // __KERNEL_SSE2__
/* Intersect two child bounding boxes, SSE3 version adapted from Embree */
@@ -145,14 +147,8 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax);
/* decide which nodes to traverse next */
-#ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- traverseChild0 = (movemask(lrhit) & 1) && (__float_as_uint(cnodes.z) & visibility);
- traverseChild1 = (movemask(lrhit) & 2) && (__float_as_uint(cnodes.w) & visibility);
-#else
traverseChild0 = (movemask(lrhit) & 1);
traverseChild1 = (movemask(lrhit) & 2);
-#endif
#endif // __KERNEL_SSE2__
nodeAddr = __float_as_int(cnodes.x);
@@ -173,6 +169,7 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
}
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = nodeAddrChild1;
}
else {
@@ -190,57 +187,64 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
/* if node is leaf, fetch triangle list */
if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1));
+ float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+3);
int primAddr = __float_as_int(leaf.x);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* pop */
nodeAddr = traversalStack[stackPtr];
--stackPtr;
/* primitive intersection */
- for(; primAddr < primAddr2; primAddr++) {
- /* only primitives from the same object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
-
- if(tri_object != subsurface_object)
- continue;
-
- /* intersect ray against primitive */
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- triangle_intersect_subsurface(kg, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
- break;
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from the same object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object)
+ continue;
+ triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
}
-#if FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from the same object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object)
+ continue;
motion_triangle_intersect_subsurface(kg, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
- break;
}
+ break;
+ }
#endif
- default: {
- break;
- }
+ default: {
+ break;
}
}
}
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
else {
/* instance push */
if(subsurface_object == kernel_tex_fetch(__prim_object, -primAddr-1)) {
object = subsurface_object;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
#else
bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
@@ -253,6 +257,7 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
#endif
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
nodeAddr = kernel_tex_fetch(__object_node, object);
@@ -264,20 +269,22 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
}
}
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(stackPtr >= 0) {
kernel_assert(object != OBJECT_NONE);
/* instance pop */
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
#else
bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect_t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
Psplat[1] = ssef(P.y);
@@ -292,13 +299,40 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
nodeAddr = traversalStack[stackPtr];
--stackPtr;
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
return num_hits;
}
-#undef FEATURE
+ccl_device_inline uint BVH_FUNCTION_NAME(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ int subsurface_object,
+ uint *lcg_state,
+ int max_hits)
+{
+#ifdef __QBVH__
+ if(kernel_data.bvh.use_qbvh) {
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+ ray,
+ isect_array,
+ subsurface_object,
+ lcg_state,
+ max_hits);
+ }
+ else
+#endif
+ {
+ kernel_assert(kernel_data.bvh.use_qbvh == false);
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+ ray,
+ isect_array,
+ subsurface_object,
+ lcg_state,
+ max_hits);
+ }
+}
+
#undef BVH_FUNCTION_NAME
#undef BVH_FUNCTION_FEATURES
-
diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h
index 114d30a479d..0298e687de2 100644
--- a/intern/cycles/kernel/geom/geom_bvh_traversal.h
+++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h
@@ -17,6 +17,10 @@
* limitations under the License.
*/
+#ifdef __QBVH__
+#include "geom_qbvh_traversal.h"
+#endif
+
/* This is a template BVH traversal function, where various features can be
* enabled/disabled. This way we can compile optimized versions for each case
* without new features slowing things down.
@@ -28,14 +32,16 @@
*
*/
-#define FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
-
-ccl_device bool BVH_FUNCTION_NAME
-(KernelGlobals *kg, const Ray *ray, Intersection *isect, const uint visibility
-#if FEATURE(BVH_HAIR_MINIMUM_WIDTH)
-, uint *lcg_state, float difl, float extmax
+ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ const uint visibility
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ , uint *lcg_state,
+ float difl,
+ float extmax
#endif
-)
+ )
{
/* todo:
* - test if pushing distance on the stack helps (for non shadow rays)
@@ -58,7 +64,7 @@ ccl_device bool BVH_FUNCTION_NAME
float3 idir = bvh_inverse_direction(dir);
int object = OBJECT_NONE;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
Transform ob_tfm;
#endif
@@ -89,6 +95,9 @@ ccl_device bool BVH_FUNCTION_NAME
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
/* traversal loop */
do {
do {
@@ -126,7 +135,7 @@ ccl_device bool BVH_FUNCTION_NAME
NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
-#if FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
if(difl != 0.0f) {
float hdiff = 1.0f + difl;
float ldiff = 1.0f - difl;
@@ -167,7 +176,7 @@ ccl_device bool BVH_FUNCTION_NAME
ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat));
const ssef tminmax = minmax ^ pn;
-#if FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
if(difl != 0.0f) {
float4 *tminmaxview = (float4*)&tminmax;
float &c0min = tminmaxview->x, &c1min = tminmaxview->y;
@@ -217,6 +226,7 @@ ccl_device bool BVH_FUNCTION_NAME
}
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = nodeAddrChild1;
}
else {
@@ -238,80 +248,104 @@ ccl_device bool BVH_FUNCTION_NAME
/* if node is leaf, fetch triangle list */
if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1));
+ float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+3);
int primAddr = __float_as_int(leaf.x);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* pop */
nodeAddr = traversalStack[stackPtr];
--stackPtr;
/* primitive intersection */
- while(primAddr < primAddr2) {
- bool hit;
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- hit = triangle_intersect(kg, isect, P, dir, visibility, object, primAddr);
- break;
- }
-#if FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- hit = motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
- break;
- }
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
#endif
-#if FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
- hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
- else
- hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
- break;
- }
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr)) {
+ /* shadow ray early termination */
+#if defined(__KERNEL_SSE2__)
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+#else
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
#endif
- default: {
- hit = false;
- break;
+ }
}
+ break;
}
-
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
+ isect->num_traversal_steps++;
#endif
-
- /* shadow ray early termination */
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
+ /* shadow ray early termination */
#if defined(__KERNEL_SSE2__)
- if(hit) {
- if(visibility == PATH_RAY_SHADOW_OPAQUE)
- return true;
-
- tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+#else
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+#endif
+ }
+ }
+ break;
}
+#endif /* BVH_FEATURE(BVH_MOTION) */
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ bool hit;
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
+ else
+ hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
+ if(hit) {
+ /* shadow ray early termination */
+#if defined(__KERNEL_SSE2__)
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
#else
- if(hit && visibility == PATH_RAY_SHADOW_OPAQUE)
- return true;
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
#endif
-
- primAddr++;
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_HAIR) */
}
}
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
else {
/* instance push */
object = kernel_tex_fetch(__prim_object, -primAddr-1);
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
#else
bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
@@ -324,24 +358,26 @@ ccl_device bool BVH_FUNCTION_NAME
#endif
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
nodeAddr = kernel_tex_fetch(__object_node, object);
}
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(stackPtr >= 0) {
kernel_assert(object != OBJECT_NONE);
/* instance pop */
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
#else
bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
@@ -357,13 +393,52 @@ ccl_device bool BVH_FUNCTION_NAME
nodeAddr = traversalStack[stackPtr];
--stackPtr;
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
return (isect->prim != PRIM_NONE);
}
-#undef FEATURE
+ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ const uint visibility
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ , uint *lcg_state,
+ float difl,
+ float extmax
+#endif
+ )
+{
+#ifdef __QBVH__
+ if(kernel_data.bvh.use_qbvh) {
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+ ray,
+ isect,
+ visibility
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ , lcg_state,
+ difl,
+ extmax
+#endif
+ );
+ }
+ else
+#endif
+ {
+ kernel_assert(kernel_data.bvh.use_qbvh == false);
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+ ray,
+ isect,
+ visibility
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ , lcg_state,
+ difl,
+ extmax
+#endif
+ );
+ }
+}
+
#undef BVH_FUNCTION_NAME
#undef BVH_FUNCTION_FEATURES
-
diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/geom/geom_bvh_volume.h
index 16c16beee39..0862812a170 100644
--- a/intern/cycles/kernel/geom/geom_bvh_volume.h
+++ b/intern/cycles/kernel/geom/geom_bvh_volume.h
@@ -17,6 +17,10 @@
* limitations under the License.
*/
+#ifdef __QBVH__
+#include "geom_qbvh_volume.h"
+#endif
+
/* This is a template BVH traversal function for volumes, where
* various features can be enabled/disabled. This way we can compile optimized
* versions for each case without new features slowing things down.
@@ -27,11 +31,9 @@
*
*/
-#define FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
-
-ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
- const Ray *ray,
- Intersection *isect)
+ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect)
{
/* todo:
* - test if pushing distance on the stack helps (for non shadow rays)
@@ -56,7 +58,7 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
const uint visibility = PATH_RAY_ALL_VISIBILITY;
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
Transform ob_tfm;
#endif
@@ -83,6 +85,9 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
/* traversal loop */
do {
do {
@@ -121,14 +126,8 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
/* decide which nodes to traverse next */
-#ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- traverseChild0 = (c0max >= c0min) && (__float_as_uint(cnodes.z) & visibility);
- traverseChild1 = (c1max >= c1min) && (__float_as_uint(cnodes.w) & visibility);
-#else
traverseChild0 = (c0max >= c0min);
traverseChild1 = (c1max >= c1min);
-#endif
#else // __KERNEL_SSE2__
/* Intersect two child bounding boxes, SSE3 version adapted from Embree */
@@ -149,14 +148,8 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax);
/* decide which nodes to traverse next */
-#ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- traverseChild0 = (movemask(lrhit) & 1) && (__float_as_uint(cnodes.z) & visibility);
- traverseChild1 = (movemask(lrhit) & 2) && (__float_as_uint(cnodes.w) & visibility);
-#else
traverseChild0 = (movemask(lrhit) & 1);
traverseChild1 = (movemask(lrhit) & 2);
-#endif
#endif // __KERNEL_SSE2__
nodeAddr = __float_as_int(cnodes.x);
@@ -177,6 +170,7 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
}
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = nodeAddrChild1;
}
else {
@@ -194,59 +188,77 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
/* if node is leaf, fetch triangle list */
if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1));
+ float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+3);
int primAddr = __float_as_int(leaf.x);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* pop */
nodeAddr = traversalStack[stackPtr];
--stackPtr;
/* primitive intersection */
- for(; primAddr < primAddr2; primAddr++) {
- /* only primitives from volume object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
-
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
-
- /* intersect ray against primitive */
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- triangle_intersect(kg, isect, P, dir, visibility, object, primAddr);
- break;
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
}
-#if FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
- break;
}
+ break;
+ }
#endif
-#if FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
else
bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
- break;
}
+ break;
+ }
#endif
- default: {
- break;
- }
+ default: {
+ break;
}
}
}
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
else {
/* instance push */
object = kernel_tex_fetch(__prim_object, -primAddr-1);
@@ -254,12 +266,14 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
if(object_flag & SD_OBJECT_HAS_VOLUME) {
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
#else
bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
Psplat[1] = ssef(P.y);
@@ -271,6 +285,7 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
#endif
++stackPtr;
+ kernel_assert(stackPtr < BVH_STACK_SIZE);
traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
nodeAddr = kernel_tex_fetch(__object_node, object);
@@ -283,20 +298,22 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
}
}
}
-#endif
+#endif /* FEATURE(BVH_INSTANCING) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
-#if FEATURE(BVH_INSTANCING)
+#if BVH_FEATURE(BVH_INSTANCING)
if(stackPtr >= 0) {
kernel_assert(object != OBJECT_NONE);
/* instance pop */
-#if FEATURE(BVH_MOTION)
+#if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
#else
bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
#if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
Psplat[1] = ssef(P.y);
@@ -311,13 +328,31 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
nodeAddr = traversalStack[stackPtr];
--stackPtr;
}
-#endif
+#endif /* FEATURE(BVH_MOTION) */
} while(nodeAddr != ENTRYPOINT_SENTINEL);
return (isect->prim != PRIM_NONE);
}
-#undef FEATURE
+ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect)
+{
+#ifdef __QBVH__
+ if(kernel_data.bvh.use_qbvh) {
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+ ray,
+ isect);
+ }
+ else
+#endif
+ {
+ kernel_assert(kernel_data.bvh.use_qbvh == false);
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+ ray,
+ isect);
+ }
+}
+
#undef BVH_FUNCTION_NAME
#undef BVH_FUNCTION_FEATURES
-
diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h
index 91edd5863ac..79a56683454 100644
--- a/intern/cycles/kernel/geom/geom_object.h
+++ b/intern/cycles/kernel/geom/geom_object.h
@@ -391,6 +391,38 @@ ccl_device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ra
*t *= len;
}
+#ifdef __QBVH__
+/* Same as above, but optimized for QBVH scene intersection,
+ * which needs to modify two max distances.
+ *
+ * TODO(sergey): Investigate if passing NULL instead of t1 gets optimized
+ * so we can avoid having this duplication.
+ */
+ccl_device_inline void qbvh_instance_push(KernelGlobals *kg,
+ int object,
+ const Ray *ray,
+ float3 *P,
+ float3 *dir,
+ float3 *idir,
+ float *t,
+ float *t1)
+{
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+
+ *P = transform_point(&tfm, ray->P);
+
+ float len;
+ *dir = bvh_clamp_direction(normalize_len(transform_direction(&tfm, ray->D), &len));
+ *idir = bvh_inverse_direction(*dir);
+
+ if(*t != FLT_MAX)
+ *t *= len;
+
+ if(*t1 != -FLT_MAX)
+ *t1 *= len;
+}
+#endif
+
/* Transorm ray to exit static object in BVH */
ccl_device_inline void bvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t)
@@ -436,6 +468,33 @@ ccl_device_inline void bvh_instance_motion_push(KernelGlobals *kg, int object, c
*t *= len;
}
+#ifdef __QBVH__
+/* Same as above, but optimized for QBVH scene intersection,
+ * which needs to modify two max distances.
+ *
+ * TODO(sergey): Investigate if passing NULL instead of t1 gets optimized
+ * so we can avoid having this duplication.
+ */
+ccl_device_inline void qbvh_instance_motion_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t, float *t1, Transform *tfm)
+{
+ Transform itfm;
+ *tfm = object_fetch_transform_motion_test(kg, object, ray->time, &itfm);
+
+ *P = transform_point(&itfm, ray->P);
+
+ float len;
+ *dir = bvh_clamp_direction(normalize_len(transform_direction(&itfm, ray->D), &len));
+ *idir = bvh_inverse_direction(*dir);
+
+
+ if(*t != FLT_MAX)
+ *t *= len;
+
+ if(*t1 != -FLT_MAX)
+ *t1 *= len;
+}
+#endif
+
/* Transorm ray to exit motion blurred object in BVH */
ccl_device_inline void bvh_instance_motion_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t, Transform *tfm)
diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h
index 5df6c75df86..b52ec7ef1b2 100644
--- a/intern/cycles/kernel/geom/geom_primitive.h
+++ b/intern/cycles/kernel/geom/geom_primitive.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* Primitive Utilities
@@ -144,7 +144,8 @@ ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
float3 center;
#ifdef __HAIR__
- if(sd->type & PRIMITIVE_ALL_CURVE) {
+ bool is_curve_primitive = sd->type & PRIMITIVE_ALL_CURVE;
+ if(is_curve_primitive) {
center = curve_motion_center_location(kg, sd);
if(!(sd->flag & SD_TRANSFORM_APPLIED))
@@ -170,6 +171,13 @@ ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
motion_pre = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
motion_post = primitive_attribute_float3(kg, sd, elem, offset_next, NULL, NULL);
+
+#ifdef __HAIR__
+ if(is_curve_primitive && (sd->flag & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {
+ object_position_transform(kg, sd, &motion_pre);
+ object_position_transform(kg, sd, &motion_post);
+ }
+#endif
}
/* object motion. note that depending on the mesh having motion vectors, this
diff --git a/intern/cycles/kernel/geom/geom_qbvh.h b/intern/cycles/kernel/geom/geom_qbvh.h
new file mode 100644
index 00000000000..37deaac0800
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_qbvh.h
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+struct QBVHStackItem {
+ int addr;
+ float dist;
+};
+
+/* TOOD(sergey): Investigate if using instrinsics helps for both
+ * stack item swap and float comparison.
+ */
+ccl_device_inline void qbvh_item_swap(QBVHStackItem *__restrict a,
+ QBVHStackItem *__restrict b)
+{
+ QBVHStackItem tmp = *a;
+ *a = *b;
+ *b = tmp;
+}
+
+ccl_device_inline void qbvh_stack_sort(QBVHStackItem *__restrict s1,
+ QBVHStackItem *__restrict s2,
+ QBVHStackItem *__restrict s3)
+{
+ if(s2->dist < s1->dist) { qbvh_item_swap(s2, s1); }
+ if(s3->dist < s2->dist) { qbvh_item_swap(s3, s2); }
+ if(s2->dist < s1->dist) { qbvh_item_swap(s2, s1); }
+}
+
+ccl_device_inline void qbvh_stack_sort(QBVHStackItem *__restrict s1,
+ QBVHStackItem *__restrict s2,
+ QBVHStackItem *__restrict s3,
+ QBVHStackItem *__restrict s4)
+{
+ if(s2->dist < s1->dist) { qbvh_item_swap(s2, s1); }
+ if(s4->dist < s3->dist) { qbvh_item_swap(s4, s3); }
+ if(s3->dist < s1->dist) { qbvh_item_swap(s3, s1); }
+ if(s4->dist < s2->dist) { qbvh_item_swap(s4, s2); }
+ if(s3->dist < s2->dist) { qbvh_item_swap(s3, s2); }
+}
+
+ccl_device_inline int qbvh_node_intersect(KernelGlobals *__restrict kg,
+ const ssef& tnear,
+ const ssef& tfar,
+#ifdef __KERNEL_AVX2__
+ const sse3f& org_idir,
+#else
+ const sse3f& org,
+#endif
+ const sse3f& idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int nodeAddr,
+ ssef *__restrict dist)
+{
+ const int offset = nodeAddr*BVH_QNODE_SIZE;
+#ifdef __KERNEL_AVX2__
+ const ssef tnear_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x), idir.x, org_idir.x);
+ const ssef tnear_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y), idir.y, org_idir.y);
+ const ssef tnear_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_z), idir.z, org_idir.z);
+ const ssef tfar_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_x), idir.x, org_idir.x);
+ const ssef tfar_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_y), idir.y, org_idir.y);
+ const ssef tfar_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_z), idir.z, org_idir.z);
+#else
+ const ssef tnear_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x) - org.x) * idir.x;
+ const ssef tnear_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y) - org.y) * idir.y;
+ const ssef tnear_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_z) - org.z) * idir.z;
+ const ssef tfar_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_x) - org.x) * idir.x;
+ const ssef tfar_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_y) - org.y) * idir.y;
+ const ssef tfar_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_z) - org.z) * idir.z;
+#endif
+
+#ifdef __KERNEL_SSE41__
+ const ssef tNear = maxi(maxi(tnear_x, tnear_y), maxi(tnear_z, tnear));
+ const ssef tFar = mini(mini(tfar_x, tfar_y), mini(tfar_z, tfar));
+ const sseb vmask = cast(tNear) > cast(tFar);
+ int mask = (int)movemask(vmask)^0xf;
+#else
+ const ssef tNear = max4(tnear_x, tnear_y, tnear_z, tnear);
+ const ssef tFar = min4(tfar_x, tfar_y, tfar_z, tfar);
+ const sseb vmask = tNear <= tFar;
+ int mask = (int)movemask(vmask);
+#endif
+ *dist = tNear;
+ return mask;
+}
+
+ccl_device_inline int qbvh_node_intersect_robust(KernelGlobals *__restrict kg,
+ const ssef& tnear,
+ const ssef& tfar,
+#ifdef __KERNEL_AVX2__
+ const sse3f& P_idir,
+#else
+ const sse3f& P,
+#endif
+ const sse3f& idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int nodeAddr,
+ const float difl,
+ ssef *__restrict dist)
+{
+ const int offset = nodeAddr*BVH_QNODE_SIZE;
+#ifdef __KERNEL_AVX2__
+ const ssef tnear_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x), idir.x, P_idir.x);
+ const ssef tnear_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y), idir.y, P_idir.y);
+ const ssef tnear_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_z), idir.z, P_idir.z);
+ const ssef tfar_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_x), idir.x, P_idir.x);
+ const ssef tfar_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_y), idir.y, P_idir.y);
+ const ssef tfar_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_z), idir.z, P_idir.z);
+#else
+ const ssef tnear_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x) - P.x) * idir.x;
+ const ssef tnear_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y) - P.y) * idir.y;
+ const ssef tnear_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_z) - P.z) * idir.z;
+ const ssef tfar_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_x) - P.x) * idir.x;
+ const ssef tfar_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_y) - P.y) * idir.y;
+ const ssef tfar_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_z) - P.z) * idir.z;
+#endif
+
+ const float round_down = 1.0f - difl;
+ const float round_up = 1.0f + difl;
+ const ssef tNear = max4(tnear_x, tnear_y, tnear_z, tnear);
+ const ssef tFar = min4(tfar_x, tfar_y, tfar_z, tfar);
+ const sseb vmask = round_down*tNear <= round_up*tFar;
+ *dist = tNear;
+ return (int)movemask(vmask);
+}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_shadow.h b/intern/cycles/kernel/geom/geom_qbvh_shadow.h
new file mode 100644
index 00000000000..e77e220c919
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_qbvh_shadow.h
@@ -0,0 +1,397 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
+ * and code copyright 2009-2012 Intel Corporation
+ *
+ * Modifications 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.
+ */
+
+/* This is a template BVH traversal function, where various features can be
+ * enabled/disabled. This way we can compile optimized versions for each case
+ * without new features slowing things down.
+ *
+ * BVH_INSTANCING: object instancing
+ * BVH_HAIR: hair curve rendering
+ * BVH_MOTION: motion blur rendering
+ *
+ */
+
+ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ const uint max_hits,
+ uint *num_hits)
+{
+ /* TODO(sergey):
+ * - Likely and unlikely for if() statements.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
+ traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+
+ /* Traversal variables in registers. */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+
+ /* Ray parameters in registers. */
+ const float tmax = ray->t;
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = tmax;
+
+#if BVH_FEATURE(BVH_MOTION)
+ Transform ob_tfm;
+#endif
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ int num_hits_in_instance = 0;
+#endif
+
+ *num_hits = 0;
+ isect_array->t = tmax;
+
+ ssef tnear(0.0f), tfar(tmax);
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+
+#ifdef __KERNEL_AVX2__
+ float3 P_idir = P*idir;
+ sse3f P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ ssef dist;
+ int traverseChild = qbvh_node_intersect(kg,
+ tnear,
+ tfar,
+#ifdef __KERNEL_AVX2__
+ P_idir4,
+#else
+ org,
+#endif
+ idir4,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ nodeAddr,
+ &dist);
+
+ if(traverseChild != 0) {
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(traverseChild);
+ if(traverseChild == 0) {
+ nodeAddr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float*)&dist)[r];
+ r = __bscf(traverseChild);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ if(d1 < d0) {
+ nodeAddr = c1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+ continue;
+ }
+ else {
+ nodeAddr = c0;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = c1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = c0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2]);
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float*)&dist)[r];
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c3;
+ traversalStack[stackPtr].dist = d3;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2],
+ &traversalStack[stackPtr - 3]);
+ }
+
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_QNODE_SIZE+6);
+#ifdef __VISIBILITY_FLAG__
+ if((__float_as_uint(leaf.z) & PATH_RAY_SHADOW) == 0) {
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ continue;
+ }
+#endif
+
+ int primAddr = __float_as_int(leaf.x);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(primAddr >= 0) {
+#endif
+ int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
+
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+
+ /* Primitive intersection. */
+ while(primAddr < primAddr2) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+
+ bool hit;
+
+ /* todo: specialized intersect functions which don't fill in
+ * isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
+ * might give a few % performance improvement */
+
+ switch(p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr);
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, PATH_RAY_SHADOW, object, primAddr);
+ break;
+ }
+#endif
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ hit = bvh_cardinal_curve_intersect(kg, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr, ray->time, type, NULL, 0, 0);
+ else
+ hit = bvh_curve_intersect(kg, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr, ray->time, type, NULL, 0, 0);
+ break;
+ }
+#endif
+ default: {
+ hit = false;
+ break;
+ }
+ }
+
+ /* Shadow ray early termination. */
+ if(hit) {
+ /* detect if this surface has a shader with transparent shadows */
+
+ /* todo: optimize so primitive visibility flag indicates if
+ * the primitive has a transparent shadow shader? */
+ int prim = kernel_tex_fetch(__prim_index, isect_array->prim);
+ int shader = 0;
+
+#ifdef __HAIR__
+ if(kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
+#endif
+ {
+ shader = kernel_tex_fetch(__tri_shader, prim);
+ }
+#ifdef __HAIR__
+ else {
+ float4 str = kernel_tex_fetch(__curves, prim);
+ shader = __float_as_int(str.z);
+ }
+#endif
+ int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2);
+
+ /* if no transparent shadows, all light is blocked */
+ if(!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
+ return true;
+ }
+ /* if maximum number of hits reached, block all light */
+ else if(*num_hits == max_hits) {
+ return true;
+ }
+
+ /* move on to next entry in intersections array */
+ isect_array++;
+ (*num_hits)++;
+#if BVH_FEATURE(BVH_INSTANCING)
+ num_hits_in_instance++;
+#endif
+
+ isect_array->t = isect_t;
+ }
+
+ primAddr++;
+ }
+ }
+#if BVH_FEATURE(BVH_INSTANCING)
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -primAddr-1);
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
+#else
+ bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
+#endif
+
+ num_hits_in_instance = 0;
+ isect_array->t = isect_t;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect_t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(stackPtr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
+
+ if(num_hits_in_instance) {
+ float t_fac;
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_tfm);
+#else
+ bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
+#endif
+
+ /* scale isect->t to adjust for instancing */
+ for(int i = 0; i < num_hits_in_instance; i++)
+ (isect_array-i-1)->t *= t_fac;
+ }
+ else {
+ float ignore_t = FLT_MAX;
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_tfm);
+#else
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t);
+#endif
+ }
+
+ isect_t = tmax;
+ isect_array->t = isect_t;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(tmax);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return false;
+}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h
new file mode 100644
index 00000000000..ef1754e711c
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h
@@ -0,0 +1,320 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
+ * and code copyright 2009-2012 Intel Corporation
+ *
+ * Modifications 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.
+ */
+
+/* This is a template BVH traversal function for subsurface scattering, where
+ * various features can be enabled/disabled. This way we can compile optimized
+ * versions for each case without new features slowing things down.
+ *
+ * BVH_INSTANCING: object instancing
+ * BVH_MOTION: motion blur rendering
+ *
+ */
+
+ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ int subsurface_object,
+ uint *lcg_state,
+ int max_hits)
+{
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps (for non shadow rays).
+ * - Separate version for shadow rays.
+ * - Likely and unlikely for if() statements.
+ * - SSE for hair.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
+ traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+
+ /* Traversal variables in registers. */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+
+ /* Ray parameters in registers. */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = ray->t;
+ uint num_hits = 0;
+
+#if BVH_FEATURE(BVH_MOTION)
+ Transform ob_tfm;
+#endif
+
+ ssef tnear(0.0f), tfar(isect_t);
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+
+#ifdef __KERNEL_AVX2__
+ float3 P_idir = P*idir;
+ sse3f P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ ssef dist;
+ int traverseChild = qbvh_node_intersect(kg,
+ tnear,
+ tfar,
+#ifdef __KERNEL_AVX2__
+ P_idir4,
+#else
+ org,
+#endif
+ idir4,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ nodeAddr,
+ &dist);
+
+ if(traverseChild != 0) {
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(traverseChild);
+ if(traverseChild == 0) {
+ nodeAddr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float*)&dist)[r];
+ r = __bscf(traverseChild);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ if(d1 < d0) {
+ nodeAddr = c1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+ continue;
+ }
+ else {
+ nodeAddr = c0;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2]);
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float*)&dist)[r];
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c3;
+ traversalStack[stackPtr].dist = d3;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2],
+ &traversalStack[stackPtr - 3]);
+ }
+
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_QNODE_SIZE+6);
+ int primAddr = __float_as_int(leaf.x);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(primAddr >= 0) {
+#endif
+ int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+
+ /* Primitive intersection. */
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* Intersect ray against primitive, */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from the same object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object) {
+ continue;
+ }
+ triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
+ }
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* Intersect ray against primitive. */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from the same object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object) {
+ continue;
+ }
+ motion_triangle_intersect_subsurface(kg, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
+ }
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+ }
+#if BVH_FEATURE(BVH_INSTANCING)
+ else {
+ /* Instance push. */
+ if(subsurface_object == kernel_tex_fetch(__prim_object, -primAddr-1)) {
+ object = subsurface_object;
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
+#else
+ bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect_t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(stackPtr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
+
+ /* Instance pop. */
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm);
+#else
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect_t);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect_t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return num_hits;
+}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_traversal.h b/intern/cycles/kernel/geom/geom_qbvh_traversal.h
new file mode 100644
index 00000000000..64da51360de
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_qbvh_traversal.h
@@ -0,0 +1,412 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
+ * and code copyright 2009-2012 Intel Corporation
+ *
+ * Modifications 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.
+ */
+
+/* This is a template BVH traversal function, where various features can be
+ * enabled/disabled. This way we can compile optimized versions for each case
+ * without new features slowing things down.
+ *
+ * BVH_INSTANCING: object instancing
+ * BVH_HAIR: hair curve rendering
+ * BVH_HAIR_MINIMUM_WIDTH: hair curve rendering with minimum width
+ * BVH_MOTION: motion blur rendering
+ *
+ */
+
+ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ const uint visibility
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ ,uint *lcg_state,
+ float difl,
+ float extmax
+#endif
+ )
+{
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps (for non shadow rays).
+ * - Separate version for shadow rays.
+ * - Likely and unlikely for if() statements.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
+ traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+ traversalStack[0].dist = -FLT_MAX;
+
+ /* Traversal variables in registers. */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+ float nodeDist = -FLT_MAX;
+
+ /* Ray parameters in registers. */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+
+#if BVH_FEATURE(BVH_MOTION)
+ Transform ob_tfm;
+#endif
+
+ isect->t = ray->t;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
+
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps = 0;
+#endif
+
+ ssef tnear(0.0f), tfar(ray->t);
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+
+#ifdef __KERNEL_AVX2__
+ float3 P_idir = P*idir;
+ sse3f P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ if(UNLIKELY(nodeDist > isect->t)) {
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ nodeDist = traversalStack[stackPtr].dist;
+ --stackPtr;
+ continue;
+ }
+
+ int traverseChild;
+ ssef dist;
+
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ if(difl != 0.0f) {
+ /* NOTE: We extend all the child BB instead of fetching
+ * and checking visibility flags for each of the,
+ *
+ * Need to test if doing opposite would be any faster.
+ */
+ traverseChild = qbvh_node_intersect_robust(kg,
+ tnear,
+ tfar,
+#ifdef __KERNEL_AVX2__
+ P_idir4,
+#else
+ org,
+#endif
+ idir4,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ nodeAddr,
+ difl,
+ &dist);
+ }
+ else
+#endif
+ {
+ traverseChild = qbvh_node_intersect(kg,
+ tnear,
+ tfar,
+#ifdef __KERNEL_AVX2__
+ P_idir4,
+#else
+ org,
+#endif
+ idir4,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ nodeAddr,
+ &dist);
+ }
+
+ if(traverseChild != 0) {
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(traverseChild);
+ float d0 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ nodeAddr = __float_as_int(cnodes[r]);
+ nodeDist = d0;
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ r = __bscf(traverseChild);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ if(d1 < d0) {
+ nodeAddr = c1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+ continue;
+ }
+ else {
+ nodeAddr = c0;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2]);
+ nodeAddr = traversalStack[stackPtr].addr;
+ nodeDist = traversalStack[stackPtr].dist;
+ --stackPtr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float*)&dist)[r];
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c3;
+ traversalStack[stackPtr].dist = d3;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2],
+ &traversalStack[stackPtr - 3]);
+ }
+
+ nodeAddr = traversalStack[stackPtr].addr;
+ nodeDist = traversalStack[stackPtr].dist;
+ --stackPtr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_QNODE_SIZE+6);
+
+#ifdef __VISIBILITY_FLAG__
+ if(UNLIKELY((nodeDist > isect->t) || ((__float_as_uint(leaf.z) & visibility) == 0)))
+#else
+ if(UNLIKELY((nodeDist > isect->t)))
+#endif
+ {
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ nodeDist = traversalStack[stackPtr].dist;
+ --stackPtr;
+ continue;
+ }
+
+ int primAddr = __float_as_int(leaf.x);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(primAddr >= 0) {
+#endif
+ int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ nodeDist = traversalStack[stackPtr].dist;
+ --stackPtr;
+
+ /* Primitive intersection. */
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr)) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ }
+ }
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_MOTION) */
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ bool hit;
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
+ else
+ hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
+ if(hit) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_HAIR) */
+ }
+ }
+#if BVH_FEATURE(BVH_INSTANCING)
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -primAddr-1);
+
+#if BVH_FEATURE(BVH_MOTION)
+ qbvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &nodeDist, &ob_tfm);
+#else
+ qbvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t, &nodeDist);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect->t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
+ traversalStack[stackPtr].dist = -FLT_MAX;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(stackPtr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
+
+ /* Instance pop. */
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
+#else
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect->t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr].addr;
+ nodeDist = traversalStack[stackPtr].dist;
+ --stackPtr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return (isect->prim != PRIM_NONE);
+}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume.h b/intern/cycles/kernel/geom/geom_qbvh_volume.h
new file mode 100644
index 00000000000..a2a8d1a20ab
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_qbvh_volume.h
@@ -0,0 +1,349 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
+ * and code copyright 2009-2012 Intel Corporation
+ *
+ * Modifications 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.
+ */
+
+/* This is a template BVH traversal function for volumes, where
+ * various features can be enabled/disabled. This way we can compile optimized
+ * versions for each case without new features slowing things down.
+ *
+ * BVH_INSTANCING: object instancing
+ * BVH_HAIR: hair curve rendering
+ * BVH_MOTION: motion blur rendering
+ *
+ */
+
+ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect)
+{
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps.
+ * - Likely and unlikely for if() statements.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
+ traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+
+ /* Traversal variables in registers. */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+
+ /* Ray parameters in registers. */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+
+ const uint visibility = PATH_RAY_ALL_VISIBILITY;
+
+#if BVH_FEATURE(BVH_MOTION)
+ Transform ob_tfm;
+#endif
+
+ isect->t = ray->t;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
+
+ ssef tnear(0.0f), tfar(ray->t);
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+
+#ifdef __KERNEL_AVX2__
+ float3 P_idir = P*idir;
+ sse3f P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+
+ ssef dist;
+ int traverseChild = qbvh_node_intersect(kg,
+ tnear,
+ tfar,
+#ifdef __KERNEL_AVX2__
+ P_idir4,
+#else
+ org,
+#endif
+ idir4,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ nodeAddr,
+ &dist);
+
+ if(traverseChild != 0) {
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(traverseChild);
+ if(traverseChild == 0) {
+ nodeAddr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float*)&dist)[r];
+ r = __bscf(traverseChild);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ if(d1 < d0) {
+ nodeAddr = c1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+ continue;
+ }
+ else {
+ nodeAddr = c0;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c1;
+ traversalStack[stackPtr].dist = d1;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c0;
+ traversalStack[stackPtr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float*)&dist)[r];
+ if(traverseChild == 0) {
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2]);
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(traverseChild);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float*)&dist)[r];
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c3;
+ traversalStack[stackPtr].dist = d3;
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = c2;
+ traversalStack[stackPtr].dist = d2;
+ qbvh_stack_sort(&traversalStack[stackPtr],
+ &traversalStack[stackPtr - 1],
+ &traversalStack[stackPtr - 2],
+ &traversalStack[stackPtr - 3]);
+ }
+
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_QNODE_SIZE+6);
+ int primAddr = __float_as_int(leaf.x);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(primAddr >= 0) {
+#endif
+ int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
+
+ /* Pop. */
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+
+ /* Primitive intersection. */
+ switch(p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
+ }
+ break;
+ }
+#if BVH_FEATURE(BVH_MOTION)
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
+ }
+ break;
+ }
+#endif
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
+ else
+ bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
+ }
+ break;
+ }
+#endif
+ }
+ }
+#if BVH_FEATURE(BVH_INSTANCING)
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+
+ if(object_flag & SD_OBJECT_HAS_VOLUME) {
+
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
+#else
+ bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect->t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ ++stackPtr;
+ kernel_assert(stackPtr < BVH_QSTACK_SIZE);
+ traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* Pop. */
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ if(stackPtr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
+
+ /* Instance pop. */
+#if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm);
+#else
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
+#endif
+
+ if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
+ if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
+ if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
+ tfar = ssef(isect->t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+#ifdef __KERNEL_AVX2__
+ P_idir = P*idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+#else
+ org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+#endif
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ object = OBJECT_NONE;
+ nodeAddr = traversalStack[stackPtr].addr;
+ --stackPtr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return (isect->prim != PRIM_NONE);
+}
diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h
index c08a82ee038..dd3928682e3 100644
--- a/intern/cycles/kernel/geom/geom_triangle.h
+++ b/intern/cycles/kernel/geom/geom_triangle.h
@@ -23,99 +23,6 @@
CCL_NAMESPACE_BEGIN
-/* Refine triangle intersection to more precise hit point. For rays that travel
- * far the precision is often not so good, this reintersects the primitive from
- * a closer distance. */
-
-ccl_device_inline float3 triangle_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray)
-{
- float3 P = ray->P;
- float3 D = ray->D;
- float t = isect->t;
-
-#ifdef __INTERSECTION_REFINE__
- if(isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
-#else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
-#endif
-
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D*t);
- D = normalize_len(D, &t);
- }
-
- P = P + D*t;
-
- float4 v00 = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0);
- float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
- float invDz = 1.0f/(D.x*v00.x + D.y*v00.y + D.z*v00.z);
- float rt = Oz * invDz;
-
- P = P + D*rt;
-
- if(isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
-#else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
-#endif
-
- P = transform_point(&tfm, P);
- }
-
- return P;
-#else
- return P + D*t;
-#endif
-}
-
-/* same as above, except that isect->t is assumed to be in object space for instancing */
-ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray)
-{
- float3 P = ray->P;
- float3 D = ray->D;
- float t = isect->t;
-
-#ifdef __INTERSECTION_REFINE__
- if(isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
-#else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
-#endif
-
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D);
- D = normalize(D);
- }
-
- P = P + D*t;
-
- float4 v00 = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0);
- float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
- float invDz = 1.0f/(D.x*v00.x + D.y*v00.y + D.z*v00.z);
- float rt = Oz * invDz;
-
- P = P + D*rt;
-
- if(isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
-#else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
-#endif
-
- P = transform_point(&tfm, P);
- }
-
- return P;
-#else
- return P + D*t;
-#endif
-}
-
/* normal on triangle */
ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
{
@@ -298,116 +205,4 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData
}
}
-/* Ray-Triangle intersection for BVH traversal
- *
- * Based on Sven Woop's algorithm with precomputed triangle storage */
-
-ccl_device_inline bool triangle_intersect(KernelGlobals *kg, Intersection *isect,
- float3 P, float3 dir, uint visibility, int object, int triAddr)
-{
- /* compute and check intersection t-value */
- float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0);
- float4 v11 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1);
-
- float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
- float invDz = 1.0f/(dir.x*v00.x + dir.y*v00.y + dir.z*v00.z);
- float t = Oz * invDz;
-
- if(t > 0.0f && t < isect->t) {
- /* compute and check barycentric u */
- float Ox = v11.w + P.x*v11.x + P.y*v11.y + P.z*v11.z;
- float Dx = dir.x*v11.x + dir.y*v11.y + dir.z*v11.z;
- float u = Ox + t*Dx;
-
- if(u >= 0.0f) {
- /* compute and check barycentric v */
- float4 v22 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
- float Oy = v22.w + P.x*v22.x + P.y*v22.y + P.z*v22.z;
- float Dy = dir.x*v22.x + dir.y*v22.y + dir.z*v22.z;
- float v = Oy + t*Dy;
-
- if(v >= 0.0f && u + v <= 1.0f) {
-#ifdef __VISIBILITY_FLAG__
- /* visibility flag test. we do it here under the assumption
- * that most triangles are culled by node flags */
- if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility)
-#endif
- {
- /* record intersection */
- isect->t = t;
- isect->u = u;
- isect->v = v;
- isect->prim = triAddr;
- isect->object = object;
- isect->type = PRIMITIVE_TRIANGLE;
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
-/* Special ray intersection routines for subsurface scattering. In that case we
- * only want to intersect with primitives in the same object, and if case of
- * multiple hits we pick a single random primitive as the intersection point. */
-
-#ifdef __SUBSURFACE__
-ccl_device_inline void triangle_intersect_subsurface(KernelGlobals *kg, Intersection *isect_array,
- float3 P, float3 dir, int object, int triAddr, float tmax, uint *num_hits, uint *lcg_state, int max_hits)
-{
- /* compute and check intersection t-value */
- float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0);
- float4 v11 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1);
-
- float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
- float invDz = 1.0f/(dir.x*v00.x + dir.y*v00.y + dir.z*v00.z);
- float t = Oz * invDz;
-
- if(t > 0.0f && t < tmax) {
- /* compute and check barycentric u */
- float Ox = v11.w + P.x*v11.x + P.y*v11.y + P.z*v11.z;
- float Dx = dir.x*v11.x + dir.y*v11.y + dir.z*v11.z;
- float u = Ox + t*Dx;
-
- if(u >= 0.0f) {
- /* compute and check barycentric v */
- float4 v22 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
- float Oy = v22.w + P.x*v22.x + P.y*v22.y + P.z*v22.z;
- float Dy = dir.x*v22.x + dir.y*v22.y + dir.z*v22.z;
- float v = Oy + t*Dy;
-
- if(v >= 0.0f && u + v <= 1.0f) {
- (*num_hits)++;
-
- int hit;
-
- if(*num_hits <= max_hits) {
- hit = *num_hits - 1;
- }
- else {
- /* reservoir sampling: if we are at the maximum number of
- * hits, randomly replace element or skip it */
- hit = lcg_step_uint(lcg_state) % *num_hits;
-
- if(hit >= max_hits)
- return;
- }
-
- /* record intersection */
- Intersection *isect = &isect_array[hit];
- isect->t = t;
- isect->u = u;
- isect->v = v;
- isect->prim = triAddr;
- isect->object = object;
- isect->type = PRIMITIVE_TRIANGLE;
- }
- }
- }
-}
-#endif
-
CCL_NAMESPACE_END
-
diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h
new file mode 100644
index 00000000000..475ee50f876
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h
@@ -0,0 +1,417 @@
+/*
+ * 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.
+ */
+
+/* Triangle/Ray intersections .
+ *
+ * For BVH ray intersection we use a precomputed triangle storage to accelerate
+ * intersection at the cost of more memory usage.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+/* Workaround stupidness of CUDA/OpenCL which doesn't allow to access indexed
+ * component of float3 value.
+ */
+#ifndef __KERNEL_CPU__
+# define IDX(vec, idx) \
+ ((idx == 0) ? ((vec).x) : ( (idx == 1) ? ((vec).y) : ((vec).z) ))
+#else
+# define IDX(vec, idx) ((vec)[idx])
+#endif
+
+/* Ray-Triangle intersection for BVH traversal
+ *
+ * Sven Woop
+ * Watertight Ray/Triangle Intersection
+ *
+ * http://jcgt.org/published/0002/01/05/paper.pdf
+ */
+
+/* Precalculated data for the ray->tri intersection. */
+typedef struct IsectPrecalc {
+ /* Maximal dimension kz, and orthogonal dimensions. */
+ int kx, ky, kz;
+
+ /* Shear constants. */
+ float Sx, Sy, Sz;
+} IsectPrecalc;
+
+/* Workaround for CUDA toolkit 6.5.16. */
+#ifdef __KERNEL_CPU__
+ccl_device_inline
+#else
+ccl_device_noinline
+#endif
+void triangle_intersect_precalc(float3 dir,
+ IsectPrecalc *isect_precalc)
+{
+ /* Calculate dimension where the ray direction is maximal. */
+ int kz = util_max_axis(make_float3(fabsf(dir.x),
+ fabsf(dir.y),
+ fabsf(dir.z)));
+ int kx = kz + 1; if(kx == 3) kx = 0;
+ int ky = kx + 1; if(ky == 3) ky = 0;
+
+ /* Swap kx and ky dimensions to preserve winding direction of triangles. */
+ if(IDX(dir, kz) < 0.0f) {
+ int tmp = kx;
+ kx = ky;
+ kx = tmp;
+ }
+
+ /* Calculate the shear constants. */
+ float inf_dir_z = 1.0f / IDX(dir, kz);
+ isect_precalc->Sx = IDX(dir, kx) * inf_dir_z;
+ isect_precalc->Sy = IDX(dir, ky) * inf_dir_z;
+ isect_precalc->Sz = inf_dir_z;
+
+ /* Store the dimensions. */
+ isect_precalc->kx = kx;
+ isect_precalc->ky = ky;
+ isect_precalc->kz = kz;
+}
+
+/* TODO(sergey): Make it general utility function. */
+ccl_device_inline float xor_signmast(float x, int y)
+{
+ return __int_as_float(__float_as_int(x) ^ y);
+}
+
+ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
+ const IsectPrecalc *isect_precalc,
+ Intersection *isect,
+ float3 P,
+ float3 dir,
+ uint visibility,
+ int object,
+ int triAddr)
+{
+ const int kx = isect_precalc->kx;
+ const int ky = isect_precalc->ky;
+ const int kz = isect_precalc->kz;
+ const float Sx = isect_precalc->Sx;
+ const float Sy = isect_precalc->Sy;
+ const float Sz = isect_precalc->Sz;
+
+ /* Calculate vertices relative to ray origin. */
+ float3 tri[3];
+ tri[0] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0));
+ tri[1] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1));
+ tri[2] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2));
+
+ const float3 A = tri[0] - P;
+ const float3 B = tri[1] - P;
+ const float3 C = tri[2] - P;
+
+ const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz);
+ const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz);
+ const float C_kx = IDX(C, kx), C_ky = IDX(C, ky), C_kz = IDX(C, kz);
+
+ /* Perform shear and scale of vertices. */
+ const float Ax = A_kx - Sx * A_kz;
+ const float Ay = A_ky - Sy * A_kz;
+ const float Bx = B_kx - Sx * B_kz;
+ const float By = B_ky - Sy * B_kz;
+ const float Cx = C_kx - Sx * C_kz;
+ const float Cy = C_ky - Sy * C_kz;
+
+ /* Calculate scaled barycentric coordinates. */
+ float U = Cx * By - Cy * Bx;
+ int sign_mask = (__float_as_int(U) & 0x80000000);
+ float V = Ax * Cy - Ay * Cx;
+ if(sign_mask != (__float_as_int(V) & 0x80000000)) {
+ return false;
+ }
+ float W = Bx * Ay - By * Ax;
+ if(sign_mask != (__float_as_int(W) & 0x80000000)) {
+ return false;
+ }
+
+ /* Calculate determinant. */
+ float det = U + V + W;
+ if(UNLIKELY(det == 0.0f)) {
+ return false;
+ }
+
+ /* Calculate scaled z−coordinates of vertices and use them to calculate
+ * the hit distance.
+ */
+ const float Az = Sz * A_kz;
+ const float Bz = Sz * B_kz;
+ const float Cz = Sz * C_kz;
+ const float T = U * Az + V * Bz + W * Cz;
+
+ if ((xor_signmast(T, sign_mask) < 0.0f) ||
+ (xor_signmast(T, sign_mask) > isect->t * xor_signmast(det, sign_mask)))
+ {
+ return false;
+ }
+
+#ifdef __VISIBILITY_FLAG__
+ /* visibility flag test. we do it here under the assumption
+ * that most triangles are culled by node flags */
+ if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility)
+#endif
+ {
+ /* Normalize U, V, W, and T. */
+ const float inv_det = 1.0f / det;
+ isect->prim = triAddr;
+ isect->object = object;
+ isect->type = PRIMITIVE_TRIANGLE;
+ isect->u = U * inv_det;
+ isect->v = V * inv_det;
+ isect->t = T * inv_det;
+ return true;
+ }
+ return false;
+}
+
+/* Special ray intersection routines for subsurface scattering. In that case we
+ * only want to intersect with primitives in the same object, and if case of
+ * multiple hits we pick a single random primitive as the intersection point.
+ */
+
+#ifdef __SUBSURFACE__
+ccl_device_inline void triangle_intersect_subsurface(
+ KernelGlobals *kg,
+ const IsectPrecalc *isect_precalc,
+ Intersection *isect_array,
+ float3 P,
+ float3 dir,
+ int object,
+ int triAddr,
+ float tmax,
+ uint *num_hits,
+ uint *lcg_state,
+ int max_hits)
+{
+ const int kx = isect_precalc->kx;
+ const int ky = isect_precalc->ky;
+ const int kz = isect_precalc->kz;
+ const float Sx = isect_precalc->Sx;
+ const float Sy = isect_precalc->Sy;
+ const float Sz = isect_precalc->Sz;
+
+ /* Calculate vertices relative to ray origin. */
+ float3 tri[3];
+ int prim = kernel_tex_fetch(__prim_index, triAddr);
+ triangle_vertices(kg, prim, tri);
+
+ const float3 A = tri[0] - P;
+ const float3 B = tri[1] - P;
+ const float3 C = tri[2] - P;
+
+ const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz);
+ const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz);
+ const float C_kx = IDX(C, kx), C_ky = IDX(C, ky), C_kz = IDX(C, kz);
+
+ /* Perform shear and scale of vertices. */
+ const float Ax = A_kx - Sx * A_kz;
+ const float Ay = A_ky - Sy * A_kz;
+ const float Bx = B_kx - Sx * B_kz;
+ const float By = B_ky - Sy * B_kz;
+ const float Cx = C_kx - Sx * C_kz;
+ const float Cy = C_ky - Sy * C_kz;
+
+ /* Calculate scaled barycentric coordinates. */
+ float U = Cx * By - Cy * Bx;
+ int sign_mask = (__float_as_int(U) & 0x80000000);
+ float V = Ax * Cy - Ay * Cx;
+ if(sign_mask != (__float_as_int(V) & 0x80000000)) {
+ return;
+ }
+ float W = Bx * Ay - By * Ax;
+ if(sign_mask != (__float_as_int(W) & 0x80000000)) {
+ return;
+ }
+
+ /* Calculate determinant. */
+ float det = U + V + W;
+ if(UNLIKELY(det == 0.0f)) {
+ return;
+ }
+
+ /* Calculate scaled z−coordinates of vertices and use them to calculate
+ * the hit distance.
+ */
+ const float Az = Sz * A_kz;
+ const float Bz = Sz * B_kz;
+ const float Cz = Sz * C_kz;
+ const float T = U * Az + V * Bz + W * Cz;
+
+ if ((xor_signmast(T, sign_mask) < 0.0f) ||
+ (xor_signmast(T, sign_mask) > tmax * xor_signmast(det, sign_mask)))
+ {
+ return;
+ }
+
+ /* Normalize U, V, W, and T. */
+ const float inv_det = 1.0f / det;
+
+ (*num_hits)++;
+ int hit;
+
+ if(*num_hits <= max_hits) {
+ hit = *num_hits - 1;
+ }
+ else {
+ /* reservoir sampling: if we are at the maximum number of
+ * hits, randomly replace element or skip it */
+ hit = lcg_step_uint(lcg_state) % *num_hits;
+
+ if(hit >= max_hits)
+ return;
+ }
+
+ /* record intersection */
+ Intersection *isect = &isect_array[hit];
+ isect->prim = triAddr;
+ isect->object = object;
+ isect->type = PRIMITIVE_TRIANGLE;
+ isect->u = U * inv_det;
+ isect->v = V * inv_det;
+ isect->t = T * inv_det;
+}
+#endif
+
+/* Refine triangle intersection to more precise hit point. For rays that travel
+ * far the precision is often not so good, this reintersects the primitive from
+ * a closer distance. */
+
+/* Reintersections uses the paper:
+ *
+ * Tomas Moeller
+ * Fast, minimum storage ray/triangle intersection
+ * http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf
+ */
+
+ccl_device_inline float3 triangle_refine(KernelGlobals *kg,
+ ShaderData *sd,
+ const Intersection *isect,
+ const Ray *ray)
+{
+ float3 P = ray->P;
+ float3 D = ray->D;
+ float t = isect->t;
+
+#ifdef __INTERSECTION_REFINE__
+ if(isect->object != OBJECT_NONE) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_itfm;
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D*t);
+ D = normalize_len(D, &t);
+ }
+
+ P = P + D*t;
+
+ float3 tri[3];
+ tri[0] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0));
+ tri[1] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1));
+ tri[2] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2));
+
+ float3 edge1 = tri[0] - tri[2];
+ float3 edge2 = tri[1] - tri[2];
+ float3 tvec = P - tri[2];
+ float3 qvec = cross(tvec, edge1);
+ float3 pvec = cross(D, edge2);
+ float rt = dot(edge2, qvec) / dot(edge1, pvec);
+
+ P = P + D*rt;
+
+ if(isect->object != OBJECT_NONE) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_tfm;
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ }
+
+ return P;
+#else
+ return P + D*t;
+#endif
+}
+
+/* Same as above, except that isect->t is assumed to be in object space for
+ * instancing.
+ */
+ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
+ ShaderData *sd,
+ const Intersection *isect,
+ const Ray *ray)
+{
+ float3 P = ray->P;
+ float3 D = ray->D;
+ float t = isect->t;
+
+#ifdef __INTERSECTION_REFINE__
+ if(isect->object != OBJECT_NONE) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_itfm;
+#else
+ Transform tfm = object_fetch_transform(kg,
+ isect->object,
+ OBJECT_INVERSE_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D);
+ D = normalize(D);
+ }
+
+ P = P + D*t;
+
+ float3 tri[3];
+ int prim = kernel_tex_fetch(__prim_index, isect->prim);
+ triangle_vertices(kg, prim, tri);
+
+ float3 edge1 = tri[0] - tri[2];
+ float3 edge2 = tri[1] - tri[2];
+ float3 tvec = P - tri[2];
+ float3 qvec = cross(tvec, edge1);
+ float3 pvec = cross(D, edge2);
+ float rt = dot(edge2, qvec) / dot(edge1, pvec);
+
+ P = P + D*rt;
+
+ if(isect->object != OBJECT_NONE) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_tfm;
+#else
+ Transform tfm = object_fetch_transform(kg,
+ isect->object,
+ OBJECT_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ }
+
+ return P;
+#else
+ return P + D*t;
+#endif
+}
+
+#undef IDX
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h
index 3cb6d168f80..c33509fbf4f 100644
--- a/intern/cycles/kernel/geom/geom_volume.h
+++ b/intern/cycles/kernel/geom/geom_volume.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* Volume Primitive
diff --git a/intern/cycles/kernel/kernel.cl b/intern/cycles/kernel/kernel.cl
index 4f20ef9ca15..5a47260a4ee 100644
--- a/intern/cycles/kernel/kernel.cl
+++ b/intern/cycles/kernel/kernel.cl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* OpenCL kernel entry points - unfinished */
diff --git a/intern/cycles/kernel/kernel.cpp b/intern/cycles/kernel/kernel.cpp
index fa2113fbb46..133887ff655 100644
--- a/intern/cycles/kernel/kernel.cpp
+++ b/intern/cycles/kernel/kernel.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* CPU kernel entry points */
diff --git a/intern/cycles/kernel/kernel.cu b/intern/cycles/kernel/kernel.cu
index 489daacddde..64069fc049f 100644
--- a/intern/cycles/kernel/kernel.cu
+++ b/intern/cycles/kernel/kernel.cu
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* CUDA kernel entry points */
diff --git a/intern/cycles/kernel/kernel.h b/intern/cycles/kernel/kernel.h
index 19e06b88797..0996e51b7a0 100644
--- a/intern/cycles/kernel/kernel.h
+++ b/intern/cycles/kernel/kernel.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __KERNEL_H__
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index b0efcdc66a7..369c615eade 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_avx.cpp b/intern/cycles/kernel/kernel_avx.cpp
index e7ff21a6f09..13317881e7b 100644
--- a/intern/cycles/kernel/kernel_avx.cpp
+++ b/intern/cycles/kernel/kernel_avx.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* Optimized CPU kernel entry points. This file is compiled with AVX
diff --git a/intern/cycles/kernel/kernel_avx2.cpp b/intern/cycles/kernel/kernel_avx2.cpp
index cb1662bbfbe..3d4e21afbda 100644
--- a/intern/cycles/kernel/kernel_avx2.cpp
+++ b/intern/cycles/kernel/kernel_avx2.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* Optimized CPU kernel entry points. This file is compiled with AVX2
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index e80bfb32e89..c6cec48c1c0 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index 5c83358a56d..e6d5714914c 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -88,8 +88,10 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo
#ifdef __CAMERA_CLIPPING__
/* clipping */
- ray->P += kernel_data.cam.nearclip*ray->D;
- ray->t = kernel_data.cam.cliplength;
+ float3 Pclip = normalize(Pcamera);
+ float z_inv = 1.0f / Pclip.z;
+ ray->P += kernel_data.cam.nearclip*ray->D * z_inv;
+ ray->t = kernel_data.cam.cliplength * z_inv;
#else
ray->t = FLT_MAX;
#endif
diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h
index 08c8bdd369d..a7a2fb8f216 100644
--- a/intern/cycles/kernel/kernel_compat_cpu.h
+++ b/intern/cycles/kernel/kernel_compat_cpu.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __KERNEL_COMPAT_CPU_H__
@@ -52,7 +52,7 @@ template<typename T> struct texture {
return data[index];
}
-#if 0
+#ifdef __KERNEL_SSE2__
ccl_always_inline ssef fetch_ssef(int index)
{
kernel_assert(index >= 0 && index < width);
@@ -344,6 +344,12 @@ typedef texture_image<uchar4> texture_image_uchar4;
#define kernel_data (kg->__data)
+#ifdef __KERNEL_SSE2__
+typedef vector3<sseb> sse3b;
+typedef vector3<ssef> sse3f;
+typedef vector3<ssei> sse3i;
+#endif
+
CCL_NAMESPACE_END
#endif /* __KERNEL_COMPAT_CPU_H__ */
diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h
index f14f3262274..904736c190c 100644
--- a/intern/cycles/kernel/kernel_compat_cuda.h
+++ b/intern/cycles/kernel/kernel_compat_cuda.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __KERNEL_COMPAT_CUDA_H__
diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h
index 58031a41b78..d480ec0f270 100644
--- a/intern/cycles/kernel/kernel_compat_opencl.h
+++ b/intern/cycles/kernel/kernel_compat_opencl.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __KERNEL_COMPAT_OPENCL_H__
diff --git a/intern/cycles/kernel/kernel_debug.h b/intern/cycles/kernel/kernel_debug.h
index bf1bc0e9db8..f532442ba41 100644
--- a/intern/cycles/kernel/kernel_debug.h
+++ b/intern/cycles/kernel/kernel_debug.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_differential.h b/intern/cycles/kernel/kernel_differential.h
index daba2d927b7..e5fbd5b450e 100644
--- a/intern/cycles/kernel/kernel_differential.h
+++ b/intern/cycles/kernel/kernel_differential.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 4b2bb723ab6..7523105607f 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
@@ -188,7 +188,7 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, PathState *st
/* use visibility flag to skip lights */
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_GLOSSY) && (state->flag & PATH_RAY_REFLECT)) ||
((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)) ||
((ls.shader & SHADER_EXCLUDE_SCATTER) && (state->flag & PATH_RAY_VOLUME_SCATTER)))
continue;
@@ -232,7 +232,7 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg, PathState *sta
/* use visibility flag to skip lights */
if(shader & SHADER_EXCLUDE_ANY) {
if(((shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) ||
- ((shader & SHADER_EXCLUDE_GLOSSY) && (state->flag & PATH_RAY_GLOSSY)) ||
+ ((shader & SHADER_EXCLUDE_GLOSSY) && (state->flag & PATH_RAY_REFLECT)) ||
((shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)) ||
((shader & SHADER_EXCLUDE_CAMERA) && (state->flag & PATH_RAY_CAMERA)) ||
((shader & SHADER_EXCLUDE_SCATTER) && (state->flag & PATH_RAY_VOLUME_SCATTER)))
diff --git a/intern/cycles/kernel/kernel_film.h b/intern/cycles/kernel/kernel_film.h
index dc5f6e7ce38..4668b40b86d 100644
--- a/intern/cycles/kernel/kernel_film.h
+++ b/intern/cycles/kernel/kernel_film.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h
index 6bd2ec0662c..0a9753baca2 100644
--- a/intern/cycles/kernel/kernel_globals.h
+++ b/intern/cycles/kernel/kernel_globals.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* Constant Globals */
diff --git a/intern/cycles/kernel/kernel_jitter.h b/intern/cycles/kernel/kernel_jitter.h
index 2a5b7689e57..6aa29311ee6 100644
--- a/intern/cycles/kernel/kernel_jitter.h
+++ b/intern/cycles/kernel/kernel_jitter.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* TODO(sergey): Consider moving portable ctz/clz stuff to util. */
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 9dfbfd91881..41920e4a97f 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_math.h b/intern/cycles/kernel/kernel_math.h
index 97621db1cf3..132b042a12a 100644
--- a/intern/cycles/kernel/kernel_math.h
+++ b/intern/cycles/kernel/kernel_math.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __KERNEL_MATH_H__
diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h
index b3b6fc02894..6bb39ee485d 100644
--- a/intern/cycles/kernel/kernel_passes.h
+++ b/intern/cycles/kernel/kernel_passes.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index c03229f0a3a..8eb6866068e 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifdef __OSL__
diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h
index f29168642a4..ab146c72cd0 100644
--- a/intern/cycles/kernel/kernel_path_state.h
+++ b/intern/cycles/kernel/kernel_path_state.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h
index e5ba1f41c47..d2704c367e4 100644
--- a/intern/cycles/kernel/kernel_path_surface.h
+++ b/intern/cycles/kernel/kernel_path_surface.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h
index 11d3d94657b..10576ac90d1 100644
--- a/intern/cycles/kernel/kernel_path_volume.h
+++ b/intern/cycles/kernel/kernel_path_volume.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_projection.h b/intern/cycles/kernel/kernel_projection.h
index 6744471d659..bd18fd21354 100644
--- a/intern/cycles/kernel/kernel_projection.h
+++ b/intern/cycles/kernel/kernel_projection.h
@@ -55,18 +55,18 @@ ccl_device float3 spherical_to_direction(float theta, float phi)
/* Equirectangular coordinates <-> Cartesian direction */
-ccl_device float2 direction_to_equirectangular(float3 dir)
+ccl_device float2 direction_to_equirectangular_range(float3 dir, float4 range)
{
- float u = -atan2f(dir.y, dir.x)/(M_2PI_F) + 0.5f;
- float v = atan2f(dir.z, hypotf(dir.x, dir.y))/M_PI_F + 0.5f;
+ float u = (atan2f(dir.y, dir.x) - range.y) / range.x;
+ float v = (acosf(dir.z / len(dir)) - range.w) / range.z;
return make_float2(u, v);
}
-ccl_device float3 equirectangular_to_direction(float u, float v)
+ccl_device float3 equirectangular_range_to_direction(float u, float v, float4 range)
{
- float phi = M_PI_F*(1.0f - 2.0f*u);
- float theta = M_PI_F*(1.0f - v);
+ float phi = range.x*u + range.y;
+ float theta = range.z*v + range.w;
return make_float3(
sinf(theta)*cosf(phi),
@@ -74,6 +74,16 @@ ccl_device float3 equirectangular_to_direction(float u, float v)
cosf(theta));
}
+ccl_device float2 direction_to_equirectangular(float3 dir)
+{
+ return direction_to_equirectangular_range(dir, make_float4(-M_2PI_F, M_PI_F, -M_PI_F, M_PI_F));
+}
+
+ccl_device float3 equirectangular_to_direction(float u, float v)
+{
+ return equirectangular_range_to_direction(u, v, make_float4(-M_2PI_F, M_PI_F, -M_PI_F, M_PI_F));
+}
+
/* Fisheye <-> Cartesian direction */
ccl_device float2 direction_to_fisheye(float3 dir, float fov)
@@ -180,7 +190,7 @@ ccl_device float3 panorama_to_direction(KernelGlobals *kg, float u, float v)
{
switch(kernel_data.cam.panorama_type) {
case PANORAMA_EQUIRECTANGULAR:
- return equirectangular_to_direction(u, v);
+ return equirectangular_range_to_direction(u, v, kernel_data.cam.equirectangular_range);
case PANORAMA_FISHEYE_EQUIDISTANT:
return fisheye_to_direction(u, v, kernel_data.cam.fisheye_fov);
case PANORAMA_FISHEYE_EQUISOLID:
@@ -194,7 +204,7 @@ ccl_device float2 direction_to_panorama(KernelGlobals *kg, float3 dir)
{
switch(kernel_data.cam.panorama_type) {
case PANORAMA_EQUIRECTANGULAR:
- return direction_to_equirectangular(dir);
+ return direction_to_equirectangular_range(dir, kernel_data.cam.equirectangular_range);
case PANORAMA_FISHEYE_EQUIDISTANT:
return direction_to_fisheye(dir, kernel_data.cam.fisheye_fov);
case PANORAMA_FISHEYE_EQUISOLID:
diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h
index 236f74c0a82..40767bac013 100644
--- a/intern/cycles/kernel/kernel_random.h
+++ b/intern/cycles/kernel/kernel_random.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "kernel_jitter.h"
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index db08c328d7e..87b6208bcf4 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/*
@@ -681,7 +681,7 @@ ccl_device float3 shader_bsdf_subsurface(KernelGlobals *kg, ShaderData *sd)
for(int i = 0; i< sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSSRDF(sc->type))
+ if(CLOSURE_IS_BSSRDF(sc->type) || CLOSURE_IS_BSDF_BSSRDF(sc->type))
eval += sc->weight;
}
diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h
index 61954282c28..8923fcebee5 100644
--- a/intern/cycles/kernel/kernel_shadow.h
+++ b/intern/cycles/kernel/kernel_shadow.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_sse2.cpp b/intern/cycles/kernel/kernel_sse2.cpp
index 740998e8c92..1bcc5eaa74f 100644
--- a/intern/cycles/kernel/kernel_sse2.cpp
+++ b/intern/cycles/kernel/kernel_sse2.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* Optimized CPU kernel entry points. This file is compiled with SSE2
diff --git a/intern/cycles/kernel/kernel_sse3.cpp b/intern/cycles/kernel/kernel_sse3.cpp
index da73a3a1c97..311f9e8f6be 100644
--- a/intern/cycles/kernel/kernel_sse3.cpp
+++ b/intern/cycles/kernel/kernel_sse3.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* Optimized CPU kernel entry points. This file is compiled with SSE3/SSSE3
diff --git a/intern/cycles/kernel/kernel_sse41.cpp b/intern/cycles/kernel/kernel_sse41.cpp
index 5704f60e138..4a4137cae9f 100644
--- a/intern/cycles/kernel/kernel_sse41.cpp
+++ b/intern/cycles/kernel/kernel_sse41.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* Optimized CPU kernel entry points. This file is compiled with SSE3/SSSE3
diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h
index fb927e81f22..2da060c32a2 100644
--- a/intern/cycles/kernel/kernel_subsurface.h
+++ b/intern/cycles/kernel/kernel_subsurface.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index ef46b2f707f..374dc6d1dd9 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef KERNEL_TEX
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 25b13f74b30..77d3ea874d0 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __KERNEL_TYPES_H__
@@ -57,6 +57,9 @@ CCL_NAMESPACE_BEGIN
/* device capabilities */
#ifdef __KERNEL_CPU__
+#ifdef __KERNEL_SSE2__
+# define __QBVH__
+#endif
#define __KERNEL_SHADING__
#define __KERNEL_ADV_SHADING__
#define __BRANCHED_PATH__
@@ -478,7 +481,12 @@ typedef enum PrimitiveType {
PRIMITIVE_ALL_TRIANGLE = (PRIMITIVE_TRIANGLE|PRIMITIVE_MOTION_TRIANGLE),
PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE|PRIMITIVE_MOTION_CURVE),
PRIMITIVE_ALL_MOTION = (PRIMITIVE_MOTION_TRIANGLE|PRIMITIVE_MOTION_CURVE),
- PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE)
+ PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE),
+
+ /* Total number of different primitives.
+ * NOTE: This is an actual value, not a bitflag.
+ */
+ PRIMITIVE_NUM_TOTAL = 4,
} PrimitiveType;
#define PRIMITIVE_PACK_SEGMENT(type, segment) ((segment << 16) | type)
@@ -539,34 +547,25 @@ typedef enum AttributeStandard {
#define MAX_CLOSURE 1
#endif
-/* TODO(sergey): This is rather nasty bug happening in here, which
- * could be simply a compilers bug for which we can't find a generic
- * platform independent workaround. Also even if it's a compiler
- * issue, it's not so simple to upgrade the compiler in the release
- * environment for Linux and doing it so closer to the release is
- * rather a risky business.
- *
- * For this release it's probably safer to stick with such a rather
- * dirty solution, and look for a cleaner fix during the next release
- * cycle.
+/* This struct is to be 16 bytes aligned, we also keep some extra precautions:
+ * - All the float3 members are in the beginning of the struct, so compiler
+ * does not put own padding trying to align this members.
+ * - We make sure OSL pointer is also 16 bytes aligned.
*/
typedef struct ShaderClosure {
- ClosureType type;
float3 weight;
-#ifndef __APPLE__
+ float3 N;
+ float3 T;
+
+ ClosureType type;
float sample_weight;
-#endif
float data0;
float data1;
float data2;
+ int pad1, pad2, pad3;
- float3 N;
- float3 T;
-#ifdef __APPLE__
- float sample_weight;
-#endif
#ifdef __OSL__
- void *prim;
+ void *prim, *pad4;
#endif
} ShaderClosure;
@@ -596,28 +595,27 @@ enum ShaderDataFlag {
SD_BSDF = (1 << 2), /* have bsdf closure? */
SD_BSDF_HAS_EVAL = (1 << 3), /* have non-singular bsdf closure? */
SD_PHASE_HAS_EVAL = (1 << 3), /* have non-singular phase closure? */
- SD_BSDF_GLOSSY = (1 << 4), /* have glossy bsdf */
- SD_BSSRDF = (1 << 5), /* have bssrdf */
- SD_HOLDOUT = (1 << 6), /* have holdout closure? */
- SD_ABSORPTION = (1 << 7), /* have volume absorption closure? */
- SD_SCATTER = (1 << 8), /* have volume phase closure? */
- SD_AO = (1 << 9), /* have ao closure? */
- SD_TRANSPARENT = (1 << 10), /* have transparent closure? */
+ SD_BSSRDF = (1 << 4), /* have bssrdf */
+ SD_HOLDOUT = (1 << 5), /* have holdout closure? */
+ SD_ABSORPTION = (1 << 6), /* have volume absorption closure? */
+ SD_SCATTER = (1 << 7), /* have volume phase closure? */
+ SD_AO = (1 << 8), /* have ao closure? */
+ SD_TRANSPARENT = (1 << 9), /* have transparent closure? */
- SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY|
- SD_BSSRDF|SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO),
+ SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF|
+ SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO),
/* shader flags */
- SD_USE_MIS = (1 << 11), /* direct light sample */
- SD_HAS_TRANSPARENT_SHADOW = (1 << 12), /* has transparent shadow */
- SD_HAS_VOLUME = (1 << 13), /* has volume shader */
- SD_HAS_ONLY_VOLUME = (1 << 14), /* has only volume shader, no surface */
- SD_HETEROGENEOUS_VOLUME = (1 << 15), /* has heterogeneous volume */
- SD_HAS_BSSRDF_BUMP = (1 << 16), /* bssrdf normal uses bump */
- SD_VOLUME_EQUIANGULAR = (1 << 17), /* use equiangular sampling */
- SD_VOLUME_MIS = (1 << 18), /* use multiple importance sampling */
- SD_VOLUME_CUBIC = (1 << 19), /* use cubic interpolation for voxels */
- SD_HAS_BUMP = (1 << 20), /* has data connected to the displacement input */
+ SD_USE_MIS = (1 << 10), /* direct light sample */
+ SD_HAS_TRANSPARENT_SHADOW = (1 << 11), /* has transparent shadow */
+ SD_HAS_VOLUME = (1 << 12), /* has volume shader */
+ SD_HAS_ONLY_VOLUME = (1 << 13), /* has only volume shader, no surface */
+ SD_HETEROGENEOUS_VOLUME = (1 << 14), /* has heterogeneous volume */
+ SD_HAS_BSSRDF_BUMP = (1 << 15), /* bssrdf normal uses bump */
+ SD_VOLUME_EQUIANGULAR = (1 << 16), /* use equiangular sampling */
+ SD_VOLUME_MIS = (1 << 17), /* use multiple importance sampling */
+ SD_VOLUME_CUBIC = (1 << 18), /* use cubic interpolation for voxels */
+ SD_HAS_BUMP = (1 << 19), /* has data connected to the displacement input */
SD_SHADER_FLAGS = (SD_USE_MIS|SD_HAS_TRANSPARENT_SHADOW|SD_HAS_VOLUME|
SD_HAS_ONLY_VOLUME|SD_HETEROGENEOUS_VOLUME|
@@ -625,12 +623,13 @@ enum ShaderDataFlag {
SD_VOLUME_CUBIC|SD_HAS_BUMP),
/* object flags */
- SD_HOLDOUT_MASK = (1 << 21), /* holdout for camera rays */
- SD_OBJECT_MOTION = (1 << 22), /* has object motion blur */
- SD_TRANSFORM_APPLIED = (1 << 23), /* vertices have transform applied */
- SD_NEGATIVE_SCALE_APPLIED = (1 << 24), /* vertices have negative scale applied */
- SD_OBJECT_HAS_VOLUME = (1 << 25), /* object has a volume shader */
- SD_OBJECT_INTERSECTS_VOLUME = (1 << 26), /* object intersects AABB of an object with volume shader */
+ SD_HOLDOUT_MASK = (1 << 20), /* holdout for camera rays */
+ SD_OBJECT_MOTION = (1 << 21), /* has object motion blur */
+ SD_TRANSFORM_APPLIED = (1 << 22), /* vertices have transform applied */
+ SD_NEGATIVE_SCALE_APPLIED = (1 << 23), /* vertices have negative scale applied */
+ SD_OBJECT_HAS_VOLUME = (1 << 24), /* object has a volume shader */
+ SD_OBJECT_INTERSECTS_VOLUME = (1 << 25), /* object intersects AABB of an object with volume shader */
+ SD_OBJECT_HAS_VERTEX_MOTION = (1 << 26), /* has position for motion vertices */
SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED|
SD_NEGATIVE_SCALE_APPLIED|SD_OBJECT_HAS_VOLUME|
@@ -768,6 +767,7 @@ typedef struct KernelCamera {
int panorama_type;
float fisheye_fov;
float fisheye_lens;
+ float4 equirectangular_range;
/* matrices */
Transform cameratoworld;
@@ -956,8 +956,8 @@ typedef struct KernelBVH {
int have_motion;
int have_curves;
int have_instancing;
-
- int pad1, pad2, pad3;
+ int use_qbvh;
+ int pad1, pad2;
} KernelBVH;
typedef enum CurveFlag {
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 6a39ba928f0..b2181952aeb 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/osl/SConscript b/intern/cycles/kernel/osl/SConscript
index d721edbaf6e..58b0204a1b9 100644
--- a/intern/cycles/kernel/osl/SConscript
+++ b/intern/cycles/kernel/osl/SConscript
@@ -38,6 +38,7 @@ incs.append(env['BF_OIIO_INC'])
incs.append(env['BF_BOOST_INC'])
incs.append(env['BF_OSL_INC'])
incs.append(env['BF_OPENEXR_INC'].split())
+incs.append('#/intern/atomic')
defs.append('CCL_NAMESPACE_BEGIN=namespace ccl {')
defs.append('CCL_NAMESPACE_END=}')
@@ -46,6 +47,17 @@ defs.append('WITH_OSL')
if env['WITH_BF_CYCLES_DEBUG']:
defs.append('WITH_CYCLES_DEBUG')
+if env['WITH_BF_CYCLES_LOGGING']:
+ defs.append('WITH_CYCLES_LOGGING')
+ defs.append('GOOGLE_GLOG_DLL_DECL=')
+ defs.append('CYCLES_GFLAGS_NAMESPACE=gflags')
+ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ incs.append('#extern/libmv/third_party/glog/src/windows')
+ incs.append('#extern/libmv/third_party/gflags')
+ else:
+ incs.append('#extern/libmv/third_party/glog/src')
+ incs.append('#extern/libmv/third_party/gflags')
+
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
cxxflags.append('-DBOOST_NO_RTTI -DBOOST_NO_TYPEID /fp:fast'.split())
incs.append(env['BF_PTHREADS_INC'])
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index cc9942b024e..1d99f1d2682 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -189,11 +189,7 @@ static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, O
/* optimization: it's possible to not use a prepare function at all and
* only initialize the actual class when accessing the closure component
* data, but then we need to map the id to the class somehow */
-#ifdef CLOSURE_PREPARE
- ss->register_closure(name, id, params, prepare, NULL, NULL);
-#else
- ss->register_closure(name, id, params, prepare, NULL);
-#endif
+ ss->register_closure(name, id, params, prepare, NULL, 16);
}
void OSLShader::register_closures(OSLShadingSystem *ss_)
diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h
index 9c3134e41c9..e349ac676b0 100644
--- a/intern/cycles/kernel/osl/osl_globals.h
+++ b/intern/cycles/kernel/osl/osl_globals.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __OSL_GLOBALS_H__
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 7a93aa05222..73c21fb1214 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <string.h>
diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h
index e9026d95f34..190234a7706 100644
--- a/intern/cycles/kernel/osl/osl_services.h
+++ b/intern/cycles/kernel/osl/osl_services.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __OSL_SERVICES_H__
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index ca0c2cc4415..ebf72ae11f4 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <OSL/oslexec.h>
diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h
index 40f50d8b0e9..15dd74f9d38 100644
--- a/intern/cycles/kernel/osl/osl_shader.h
+++ b/intern/cycles/kernel/osl/osl_shader.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __OSL_SHADER_H__
diff --git a/intern/cycles/kernel/shaders/node_absorption_volume.osl b/intern/cycles/kernel/shaders/node_absorption_volume.osl
index 6bac83ba4f5..18f662ebbbd 100644
--- a/intern/cycles/kernel/shaders/node_absorption_volume.osl
+++ b/intern/cycles/kernel/shaders/node_absorption_volume.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_add_closure.osl b/intern/cycles/kernel/shaders/node_add_closure.osl
index b826fb22784..b6596e0b6bd 100644
--- a/intern/cycles/kernel/shaders/node_add_closure.osl
+++ b/intern/cycles/kernel/shaders/node_add_closure.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
index 961aed1016b..5f056122bbe 100644
--- a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
+++ b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
index da1e4f77107..281ed4e8726 100644
--- a/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_attribute.osl b/intern/cycles/kernel/shaders/node_attribute.osl
index 43f69fab053..67183e9ffe0 100644
--- a/intern/cycles/kernel/shaders/node_attribute.osl
+++ b/intern/cycles/kernel/shaders/node_attribute.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_background.osl b/intern/cycles/kernel/shaders/node_background.osl
index c4379a8f71b..613d4e360fa 100644
--- a/intern/cycles/kernel/shaders/node_background.osl
+++ b/intern/cycles/kernel/shaders/node_background.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_blackbody.osl b/intern/cycles/kernel/shaders/node_blackbody.osl
index d26e56ab06d..1da6894d0f0 100644
--- a/intern/cycles/kernel/shaders/node_blackbody.osl
+++ b/intern/cycles/kernel/shaders/node_blackbody.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_brick_texture.osl b/intern/cycles/kernel/shaders/node_brick_texture.osl
index c9fb3542aef..0b4993e9832 100644
--- a/intern/cycles/kernel/shaders/node_brick_texture.osl
+++ b/intern/cycles/kernel/shaders/node_brick_texture.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_brightness.osl b/intern/cycles/kernel/shaders/node_brightness.osl
index 468b0f052c3..00cfb167885 100644
--- a/intern/cycles/kernel/shaders/node_brightness.osl
+++ b/intern/cycles/kernel/shaders/node_brightness.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_bump.osl b/intern/cycles/kernel/shaders/node_bump.osl
index bbc08760cd5..9882857f2ec 100644
--- a/intern/cycles/kernel/shaders/node_bump.osl
+++ b/intern/cycles/kernel/shaders/node_bump.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_camera.osl b/intern/cycles/kernel/shaders/node_camera.osl
index 20ebb7dc095..5e90cb8b8ee 100644
--- a/intern/cycles/kernel/shaders/node_camera.osl
+++ b/intern/cycles/kernel/shaders/node_camera.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_checker_texture.osl b/intern/cycles/kernel/shaders/node_checker_texture.osl
index a6d21fd36f3..ae84c71dd42 100644
--- a/intern/cycles/kernel/shaders/node_checker_texture.osl
+++ b/intern/cycles/kernel/shaders/node_checker_texture.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_color.h b/intern/cycles/kernel/shaders/node_color.h
index 095e628f20c..4a17286a07f 100644
--- a/intern/cycles/kernel/shaders/node_color.h
+++ b/intern/cycles/kernel/shaders/node_color.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
float color_srgb_to_scene_linear(float c)
diff --git a/intern/cycles/kernel/shaders/node_combine_hsv.osl b/intern/cycles/kernel/shaders/node_combine_hsv.osl
index 010773acc5c..6b922bf4e6b 100644
--- a/intern/cycles/kernel/shaders/node_combine_hsv.osl
+++ b/intern/cycles/kernel/shaders/node_combine_hsv.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_combine_rgb.osl b/intern/cycles/kernel/shaders/node_combine_rgb.osl
index 8466a89b536..f343fdefd84 100644
--- a/intern/cycles/kernel/shaders/node_combine_rgb.osl
+++ b/intern/cycles/kernel/shaders/node_combine_rgb.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_combine_xyz.osl b/intern/cycles/kernel/shaders/node_combine_xyz.osl
index 933dee5bd78..86182056b09 100644
--- a/intern/cycles/kernel/shaders/node_combine_xyz.osl
+++ b/intern/cycles/kernel/shaders/node_combine_xyz.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_color.osl b/intern/cycles/kernel/shaders/node_convert_from_color.osl
index 2f4503e66e3..44074317f42 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_color.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_color.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_float.osl b/intern/cycles/kernel/shaders/node_convert_from_float.osl
index f5b91903078..fc5c79c4c64 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_float.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_float.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_int.osl b/intern/cycles/kernel/shaders/node_convert_from_int.osl
index 110922a5df1..3c3785ebc0d 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_int.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_int.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_normal.osl b/intern/cycles/kernel/shaders/node_convert_from_normal.osl
index 995c86d8828..8ecc56ac8ce 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_normal.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_normal.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_point.osl b/intern/cycles/kernel/shaders/node_convert_from_point.osl
index 2ed151273a8..e5913b7a1e4 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_point.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_point.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_string.osl b/intern/cycles/kernel/shaders/node_convert_from_string.osl
index 50cce252be4..0466734277b 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_string.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_string.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_convert_from_vector.osl b/intern/cycles/kernel/shaders/node_convert_from_vector.osl
index 035c46625a0..79c5cb04550 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_vector.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_vector.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl b/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl
index e8c94660e4f..2bef2d65baa 100644
--- a/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_emission.osl b/intern/cycles/kernel/shaders/node_emission.osl
index b28d731c19f..c36e2a4c0f3 100644
--- a/intern/cycles/kernel/shaders/node_emission.osl
+++ b/intern/cycles/kernel/shaders/node_emission.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_environment_texture.osl b/intern/cycles/kernel/shaders/node_environment_texture.osl
index 136ccdf8b18..14f0226a0e5 100644
--- a/intern/cycles/kernel/shaders/node_environment_texture.osl
+++ b/intern/cycles/kernel/shaders/node_environment_texture.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_fresnel.h b/intern/cycles/kernel/shaders/node_fresnel.h
index d192c5d02de..de2d40a849c 100644
--- a/intern/cycles/kernel/shaders/node_fresnel.h
+++ b/intern/cycles/kernel/shaders/node_fresnel.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
float fresnel_dielectric_cos(float cosi, float eta)
diff --git a/intern/cycles/kernel/shaders/node_fresnel.osl b/intern/cycles/kernel/shaders/node_fresnel.osl
index 7ef553c0f39..8bec7b432f5 100644
--- a/intern/cycles/kernel/shaders/node_fresnel.osl
+++ b/intern/cycles/kernel/shaders/node_fresnel.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_gamma.osl b/intern/cycles/kernel/shaders/node_gamma.osl
index a2ad3f766fe..bc4c1b34266 100644
--- a/intern/cycles/kernel/shaders/node_gamma.osl
+++ b/intern/cycles/kernel/shaders/node_gamma.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_geometry.osl b/intern/cycles/kernel/shaders/node_geometry.osl
index cd68f07b21e..580ccba8238 100644
--- a/intern/cycles/kernel/shaders/node_geometry.osl
+++ b/intern/cycles/kernel/shaders/node_geometry.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_glass_bsdf.osl b/intern/cycles/kernel/shaders/node_glass_bsdf.osl
index b3d6133553b..68bc107cc5e 100644
--- a/intern/cycles/kernel/shaders/node_glass_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_glass_bsdf.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_glossy_bsdf.osl b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl
index 5c727ca6917..d3250b32d0b 100644
--- a/intern/cycles/kernel/shaders/node_glossy_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_gradient_texture.osl b/intern/cycles/kernel/shaders/node_gradient_texture.osl
index 5aa05917dc2..52b49688ab3 100644
--- a/intern/cycles/kernel/shaders/node_gradient_texture.osl
+++ b/intern/cycles/kernel/shaders/node_gradient_texture.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_hair_info.osl b/intern/cycles/kernel/shaders/node_hair_info.osl
index 1d1ba1983e1..965d2a3c7f7 100644
--- a/intern/cycles/kernel/shaders/node_hair_info.osl
+++ b/intern/cycles/kernel/shaders/node_hair_info.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_holdout.osl b/intern/cycles/kernel/shaders/node_holdout.osl
index cafad1b5757..78a9f46fd15 100644
--- a/intern/cycles/kernel/shaders/node_holdout.osl
+++ b/intern/cycles/kernel/shaders/node_holdout.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_hsv.osl b/intern/cycles/kernel/shaders/node_hsv.osl
index 5f4300ee31d..8d9e50fed6b 100644
--- a/intern/cycles/kernel/shaders/node_hsv.osl
+++ b/intern/cycles/kernel/shaders/node_hsv.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl
index 18b5fb4b31f..a55640a9168 100644
--- a/intern/cycles/kernel/shaders/node_image_texture.osl
+++ b/intern/cycles/kernel/shaders/node_image_texture.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_invert.osl b/intern/cycles/kernel/shaders/node_invert.osl
index 81ef2d0dc3d..b33b0a43d63 100644
--- a/intern/cycles/kernel/shaders/node_invert.osl
+++ b/intern/cycles/kernel/shaders/node_invert.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_layer_weight.osl b/intern/cycles/kernel/shaders/node_layer_weight.osl
index d03ebe2239a..f583df25773 100644
--- a/intern/cycles/kernel/shaders/node_layer_weight.osl
+++ b/intern/cycles/kernel/shaders/node_layer_weight.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_light_falloff.osl b/intern/cycles/kernel/shaders/node_light_falloff.osl
index 311b87f3764..a594e33d643 100644
--- a/intern/cycles/kernel/shaders/node_light_falloff.osl
+++ b/intern/cycles/kernel/shaders/node_light_falloff.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_light_path.osl b/intern/cycles/kernel/shaders/node_light_path.osl
index 95fbcabf917..99a92c4f403 100644
--- a/intern/cycles/kernel/shaders/node_light_path.osl
+++ b/intern/cycles/kernel/shaders/node_light_path.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_magic_texture.osl b/intern/cycles/kernel/shaders/node_magic_texture.osl
index b8afc6e29ac..c09523f205b 100644
--- a/intern/cycles/kernel/shaders/node_magic_texture.osl
+++ b/intern/cycles/kernel/shaders/node_magic_texture.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_mapping.osl b/intern/cycles/kernel/shaders/node_mapping.osl
index 46ff9f05e07..69106957ee4 100644
--- a/intern/cycles/kernel/shaders/node_mapping.osl
+++ b/intern/cycles/kernel/shaders/node_mapping.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_math.osl b/intern/cycles/kernel/shaders/node_math.osl
index abb6a359e75..bbc008b4299 100644
--- a/intern/cycles/kernel/shaders/node_math.osl
+++ b/intern/cycles/kernel/shaders/node_math.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_mix.osl b/intern/cycles/kernel/shaders/node_mix.osl
index dd54fd814de..9ef58e4cbba 100644
--- a/intern/cycles/kernel/shaders/node_mix.osl
+++ b/intern/cycles/kernel/shaders/node_mix.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_mix_closure.osl b/intern/cycles/kernel/shaders/node_mix_closure.osl
index 79d71c97371..5946dfdaaba 100644
--- a/intern/cycles/kernel/shaders/node_mix_closure.osl
+++ b/intern/cycles/kernel/shaders/node_mix_closure.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
index a32c3d4b1b8..a349dc8cb9a 100644
--- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_noise_texture.osl b/intern/cycles/kernel/shaders/node_noise_texture.osl
index 912795966e0..dabc0b6843f 100644
--- a/intern/cycles/kernel/shaders/node_noise_texture.osl
+++ b/intern/cycles/kernel/shaders/node_noise_texture.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_normal.osl b/intern/cycles/kernel/shaders/node_normal.osl
index 14af044e0c0..2d04978fc72 100644
--- a/intern/cycles/kernel/shaders/node_normal.osl
+++ b/intern/cycles/kernel/shaders/node_normal.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
@@ -23,6 +23,6 @@ shader node_normal(
output float Dot = 1.0)
{
NormalOut = normalize(Direction);
- Dot = dot(NormalOut, NormalIn);
+ Dot = dot(NormalOut, normalize(NormalIn));
}
diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl
index c2080ecb194..01be566fb20 100644
--- a/intern/cycles/kernel/shaders/node_normal_map.osl
+++ b/intern/cycles/kernel/shaders/node_normal_map.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_object_info.osl b/intern/cycles/kernel/shaders/node_object_info.osl
index 1ebe767e82d..dd7c663b8d8 100644
--- a/intern/cycles/kernel/shaders/node_object_info.osl
+++ b/intern/cycles/kernel/shaders/node_object_info.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_output_displacement.osl b/intern/cycles/kernel/shaders/node_output_displacement.osl
index 613d6be5f3b..d0688cfda8d 100644
--- a/intern/cycles/kernel/shaders/node_output_displacement.osl
+++ b/intern/cycles/kernel/shaders/node_output_displacement.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_output_surface.osl b/intern/cycles/kernel/shaders/node_output_surface.osl
index fb16e85ce0d..2cc4575a8c8 100644
--- a/intern/cycles/kernel/shaders/node_output_surface.osl
+++ b/intern/cycles/kernel/shaders/node_output_surface.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_output_volume.osl b/intern/cycles/kernel/shaders/node_output_volume.osl
index 11a884b7d75..f220ba866e3 100644
--- a/intern/cycles/kernel/shaders/node_output_volume.osl
+++ b/intern/cycles/kernel/shaders/node_output_volume.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_particle_info.osl b/intern/cycles/kernel/shaders/node_particle_info.osl
index 077b0c114da..768b7753d02 100644
--- a/intern/cycles/kernel/shaders/node_particle_info.osl
+++ b/intern/cycles/kernel/shaders/node_particle_info.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
index 4a32415b482..d458ca730a4 100644
--- a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_rgb_curves.osl b/intern/cycles/kernel/shaders/node_rgb_curves.osl
index 4e0f8721144..60cb273ba98 100644
--- a/intern/cycles/kernel/shaders/node_rgb_curves.osl
+++ b/intern/cycles/kernel/shaders/node_rgb_curves.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_rgb_ramp.osl b/intern/cycles/kernel/shaders/node_rgb_ramp.osl
index d3c2e9573d2..0202ba0bf79 100644
--- a/intern/cycles/kernel/shaders/node_rgb_ramp.osl
+++ b/intern/cycles/kernel/shaders/node_rgb_ramp.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_scatter_volume.osl b/intern/cycles/kernel/shaders/node_scatter_volume.osl
index 77c157bd92b..002e2750fca 100644
--- a/intern/cycles/kernel/shaders/node_scatter_volume.osl
+++ b/intern/cycles/kernel/shaders/node_scatter_volume.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_separate_hsv.osl b/intern/cycles/kernel/shaders/node_separate_hsv.osl
index 94fc5de9122..2a804040294 100644
--- a/intern/cycles/kernel/shaders/node_separate_hsv.osl
+++ b/intern/cycles/kernel/shaders/node_separate_hsv.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_separate_rgb.osl b/intern/cycles/kernel/shaders/node_separate_rgb.osl
index aebb63a0ee4..43d9e3aa4b1 100644
--- a/intern/cycles/kernel/shaders/node_separate_rgb.osl
+++ b/intern/cycles/kernel/shaders/node_separate_rgb.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_separate_xyz.osl b/intern/cycles/kernel/shaders/node_separate_xyz.osl
index 63725cb9995..e1963a1902f 100644
--- a/intern/cycles/kernel/shaders/node_separate_xyz.osl
+++ b/intern/cycles/kernel/shaders/node_separate_xyz.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_set_normal.osl b/intern/cycles/kernel/shaders/node_set_normal.osl
index 8eef152308a..7ca7ac9350c 100644
--- a/intern/cycles/kernel/shaders/node_set_normal.osl
+++ b/intern/cycles/kernel/shaders/node_set_normal.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl
index 85c2dbdb2c2..05eed23bea8 100644
--- a/intern/cycles/kernel/shaders/node_sky_texture.osl
+++ b/intern/cycles/kernel/shaders/node_sky_texture.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
index 1c0cd74c0be..dbbf657776c 100644
--- a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
+++ b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_tangent.osl b/intern/cycles/kernel/shaders/node_tangent.osl
index 41a2b2b0216..53a47396f9f 100644
--- a/intern/cycles/kernel/shaders/node_tangent.osl
+++ b/intern/cycles/kernel/shaders/node_tangent.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_texture.h b/intern/cycles/kernel/shaders/node_texture.h
index 2710eed414a..5f9cd5afa47 100644
--- a/intern/cycles/kernel/shaders/node_texture.h
+++ b/intern/cycles/kernel/shaders/node_texture.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* Voronoi Distances */
diff --git a/intern/cycles/kernel/shaders/node_texture_coordinate.osl b/intern/cycles/kernel/shaders/node_texture_coordinate.osl
index 8fdf469df21..f8a6f787288 100644
--- a/intern/cycles/kernel/shaders/node_texture_coordinate.osl
+++ b/intern/cycles/kernel/shaders/node_texture_coordinate.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_toon_bsdf.osl b/intern/cycles/kernel/shaders/node_toon_bsdf.osl
index 1f7e1b8e6e1..75c5d06f847 100644
--- a/intern/cycles/kernel/shaders/node_toon_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_toon_bsdf.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_translucent_bsdf.osl b/intern/cycles/kernel/shaders/node_translucent_bsdf.osl
index 8059f5788ec..94d23d35326 100644
--- a/intern/cycles/kernel/shaders/node_translucent_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_translucent_bsdf.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_transparent_bsdf.osl b/intern/cycles/kernel/shaders/node_transparent_bsdf.osl
index 552e4106b0c..5d6798f19a6 100644
--- a/intern/cycles/kernel/shaders/node_transparent_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_transparent_bsdf.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_uv_map.osl b/intern/cycles/kernel/shaders/node_uv_map.osl
index 01c984aff4c..77e2e8d12d7 100644
--- a/intern/cycles/kernel/shaders/node_uv_map.osl
+++ b/intern/cycles/kernel/shaders/node_uv_map.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_value.osl b/intern/cycles/kernel/shaders/node_value.osl
index aebfab35d2a..f75388d1f76 100644
--- a/intern/cycles/kernel/shaders/node_value.osl
+++ b/intern/cycles/kernel/shaders/node_value.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_vector_curves.osl b/intern/cycles/kernel/shaders/node_vector_curves.osl
index 137ebe112eb..7bbf97d95ea 100644
--- a/intern/cycles/kernel/shaders/node_vector_curves.osl
+++ b/intern/cycles/kernel/shaders/node_vector_curves.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_vector_math.osl b/intern/cycles/kernel/shaders/node_vector_math.osl
index 0c8857deae2..f83412dc0f7 100644
--- a/intern/cycles/kernel/shaders/node_vector_math.osl
+++ b/intern/cycles/kernel/shaders/node_vector_math.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_vector_transform.osl b/intern/cycles/kernel/shaders/node_vector_transform.osl
index 6fb0ab1d8cc..8ebaa31ab25 100644
--- a/intern/cycles/kernel/shaders/node_vector_transform.osl
+++ b/intern/cycles/kernel/shaders/node_vector_transform.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_velvet_bsdf.osl b/intern/cycles/kernel/shaders/node_velvet_bsdf.osl
index 37b26babc64..456c26998c8 100644
--- a/intern/cycles/kernel/shaders/node_velvet_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_velvet_bsdf.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_voronoi_texture.osl b/intern/cycles/kernel/shaders/node_voronoi_texture.osl
index 7a1e0016690..df169599d08 100644
--- a/intern/cycles/kernel/shaders/node_voronoi_texture.osl
+++ b/intern/cycles/kernel/shaders/node_voronoi_texture.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl
index ba40207b446..a95752fc592 100644
--- a/intern/cycles/kernel/shaders/node_wave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_wave_texture.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_wavelength.osl b/intern/cycles/kernel/shaders/node_wavelength.osl
index 4333c1fd944..79e7043d4bf 100644
--- a/intern/cycles/kernel/shaders/node_wavelength.osl
+++ b/intern/cycles/kernel/shaders/node_wavelength.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/shaders/node_wireframe.osl b/intern/cycles/kernel/shaders/node_wireframe.osl
index db8925c9efc..936e9bb5754 100644
--- a/intern/cycles/kernel/shaders/node_wireframe.osl
+++ b/intern/cycles/kernel/shaders/node_wireframe.osl
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "stdosl.h"
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index 5acfbbf972b..3465a743c3f 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __SVM_H__
diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h
index fd0ea7fef31..b63978b6e1f 100644
--- a/intern/cycles/kernel/svm/svm_attribute.h
+++ b/intern/cycles/kernel/svm/svm_attribute.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_brick.h b/intern/cycles/kernel/svm/svm_brick.h
index 97c2b545c5f..a46392cd544 100644
--- a/intern/cycles/kernel/svm/svm_brick.h
+++ b/intern/cycles/kernel/svm/svm_brick.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_brightness.h b/intern/cycles/kernel/svm/svm_brightness.h
index 9b330b3213f..631bd1825ee 100644
--- a/intern/cycles/kernel/svm/svm_brightness.h
+++ b/intern/cycles/kernel/svm/svm_brightness.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_camera.h b/intern/cycles/kernel/svm/svm_camera.h
index bfe9289fa02..e03745cb331 100644
--- a/intern/cycles/kernel/svm/svm_camera.h
+++ b/intern/cycles/kernel/svm/svm_camera.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_checker.h b/intern/cycles/kernel/svm/svm_checker.h
index e0408ad334a..186bf7df55f 100644
--- a/intern/cycles/kernel/svm/svm_checker.h
+++ b/intern/cycles/kernel/svm/svm_checker.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 30110db3ef9..e4e3b683cd1 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_convert.h b/intern/cycles/kernel/svm/svm_convert.h
index b221e0728ec..34080377083 100644
--- a/intern/cycles/kernel/svm/svm_convert.h
+++ b/intern/cycles/kernel/svm/svm_convert.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_displace.h b/intern/cycles/kernel/svm/svm_displace.h
index 6cd5ee4b375..4a058905a93 100644
--- a/intern/cycles/kernel/svm/svm_displace.h
+++ b/intern/cycles/kernel/svm/svm_displace.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_fresnel.h b/intern/cycles/kernel/svm/svm_fresnel.h
index 5def52205eb..3703ec55015 100644
--- a/intern/cycles/kernel/svm/svm_fresnel.h
+++ b/intern/cycles/kernel/svm/svm_fresnel.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_gamma.h b/intern/cycles/kernel/svm/svm_gamma.h
index c4749e7b936..8bc59b9c673 100644
--- a/intern/cycles/kernel/svm/svm_gamma.h
+++ b/intern/cycles/kernel/svm/svm_gamma.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h
index fe681ec92af..efbefa77d28 100644
--- a/intern/cycles/kernel/svm/svm_geometry.h
+++ b/intern/cycles/kernel/svm/svm_geometry.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_gradient.h b/intern/cycles/kernel/svm/svm_gradient.h
index a4b3c0583f7..a5e385faddc 100644
--- a/intern/cycles/kernel/svm/svm_gradient.h
+++ b/intern/cycles/kernel/svm/svm_gradient.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_hsv.h b/intern/cycles/kernel/svm/svm_hsv.h
index a02d853be1a..eeb4ba25e91 100644
--- a/intern/cycles/kernel/svm/svm_hsv.h
+++ b/intern/cycles/kernel/svm/svm_hsv.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __SVM_HSV_H__
diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h
index 8a256c9bda5..9948a192117 100644
--- a/intern/cycles/kernel/svm/svm_image.h
+++ b/intern/cycles/kernel/svm/svm_image.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_invert.h b/intern/cycles/kernel/svm/svm_invert.h
index eb47e9ad4ab..152b49174e0 100644
--- a/intern/cycles/kernel/svm/svm_invert.h
+++ b/intern/cycles/kernel/svm/svm_invert.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_light_path.h b/intern/cycles/kernel/svm/svm_light_path.h
index da544c63ae0..677d139c5d4 100644
--- a/intern/cycles/kernel/svm/svm_light_path.h
+++ b/intern/cycles/kernel/svm/svm_light_path.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_magic.h b/intern/cycles/kernel/svm/svm_magic.h
index b661f5cacf8..ac87c77d719 100644
--- a/intern/cycles/kernel/svm/svm_magic.h
+++ b/intern/cycles/kernel/svm/svm_magic.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_mapping.h b/intern/cycles/kernel/svm/svm_mapping.h
index c9fa8502dd1..0a890545af4 100644
--- a/intern/cycles/kernel/svm/svm_mapping.h
+++ b/intern/cycles/kernel/svm/svm_mapping.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h
index e3d8c1f3242..d633e54ed8d 100644
--- a/intern/cycles/kernel/svm/svm_math.h
+++ b/intern/cycles/kernel/svm/svm_math.h
@@ -11,49 +11,11 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
-ccl_device float average_fac(float3 v)
-{
- return (fabsf(v.x) + fabsf(v.y) + fabsf(v.z))/3.0f;
-}
-
-ccl_device void svm_vector_math(float *Fac, float3 *Vector, NodeVectorMath type, float3 Vector1, float3 Vector2)
-{
- if(type == NODE_VECTOR_MATH_ADD) {
- *Vector = Vector1 + Vector2;
- *Fac = average_fac(*Vector);
- }
- else if(type == NODE_VECTOR_MATH_SUBTRACT) {
- *Vector = Vector1 - Vector2;
- *Fac = average_fac(*Vector);
- }
- else if(type == NODE_VECTOR_MATH_AVERAGE) {
- *Fac = len(Vector1 + Vector2);
- *Vector = normalize(Vector1 + Vector2);
- }
- else if(type == NODE_VECTOR_MATH_DOT_PRODUCT) {
- *Fac = dot(Vector1, Vector2);
- *Vector = make_float3(0.0f, 0.0f, 0.0f);
- }
- else if(type == NODE_VECTOR_MATH_CROSS_PRODUCT) {
- float3 c = cross(Vector1, Vector2);
- *Fac = len(c);
- *Vector = normalize(c);
- }
- else if(type == NODE_VECTOR_MATH_NORMALIZE) {
- *Fac = len(Vector1);
- *Vector = normalize(Vector1);
- }
- else {
- *Fac = 0.0f;
- *Vector = make_float3(0.0f, 0.0f, 0.0f);
- }
-}
-
/* Nodes */
ccl_device void svm_node_math(KernelGlobals *kg, ShaderData *sd, float *stack, uint itype, uint f1_offset, uint f2_offset, int *offset)
diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h
index b813bf531dc..39cc14d5e8e 100644
--- a/intern/cycles/kernel/svm/svm_math_util.h
+++ b/intern/cycles/kernel/svm/svm_math_util.h
@@ -11,11 +11,49 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
+ccl_device float average_fac(float3 v)
+{
+ return (fabsf(v.x) + fabsf(v.y) + fabsf(v.z))/3.0f;
+}
+
+ccl_device void svm_vector_math(float *Fac, float3 *Vector, NodeVectorMath type, float3 Vector1, float3 Vector2)
+{
+ if(type == NODE_VECTOR_MATH_ADD) {
+ *Vector = Vector1 + Vector2;
+ *Fac = average_fac(*Vector);
+ }
+ else if(type == NODE_VECTOR_MATH_SUBTRACT) {
+ *Vector = Vector1 - Vector2;
+ *Fac = average_fac(*Vector);
+ }
+ else if(type == NODE_VECTOR_MATH_AVERAGE) {
+ *Fac = len(Vector1 + Vector2);
+ *Vector = normalize(Vector1 + Vector2);
+ }
+ else if(type == NODE_VECTOR_MATH_DOT_PRODUCT) {
+ *Fac = dot(Vector1, Vector2);
+ *Vector = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ else if(type == NODE_VECTOR_MATH_CROSS_PRODUCT) {
+ float3 c = cross(Vector1, Vector2);
+ *Fac = len(c);
+ *Vector = normalize(c);
+ }
+ else if(type == NODE_VECTOR_MATH_NORMALIZE) {
+ *Fac = len(Vector1);
+ *Vector = normalize(Vector1);
+ }
+ else {
+ *Fac = 0.0f;
+ *Vector = make_float3(0.0f, 0.0f, 0.0f);
+ }
+}
+
ccl_device float svm_math(NodeMath type, float Fac1, float Fac2)
{
float Fac;
diff --git a/intern/cycles/kernel/svm/svm_mix.h b/intern/cycles/kernel/svm/svm_mix.h
index edc3903865e..b6b1966cb3b 100644
--- a/intern/cycles/kernel/svm/svm_mix.h
+++ b/intern/cycles/kernel/svm/svm_mix.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_musgrave.h b/intern/cycles/kernel/svm/svm_musgrave.h
index 61171d6849c..2f81ddaa74c 100644
--- a/intern/cycles/kernel/svm/svm_musgrave.h
+++ b/intern/cycles/kernel/svm/svm_musgrave.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_noisetex.h b/intern/cycles/kernel/svm/svm_noisetex.h
index 5d5cfe6ffcc..eccd119b74f 100644
--- a/intern/cycles/kernel/svm/svm_noisetex.h
+++ b/intern/cycles/kernel/svm/svm_noisetex.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_normal.h b/intern/cycles/kernel/svm/svm_normal.h
index 8695031b8b9..67b5321e0de 100644
--- a/intern/cycles/kernel/svm/svm_normal.h
+++ b/intern/cycles/kernel/svm/svm_normal.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_ramp.h b/intern/cycles/kernel/svm/svm_ramp.h
index 55eee3d24c3..998f649a571 100644
--- a/intern/cycles/kernel/svm/svm_ramp.h
+++ b/intern/cycles/kernel/svm/svm_ramp.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __SVM_RAMP_H__
diff --git a/intern/cycles/kernel/svm/svm_sepcomb_hsv.h b/intern/cycles/kernel/svm/svm_sepcomb_hsv.h
index 111d5d47988..68f9fea02f0 100644
--- a/intern/cycles/kernel/svm/svm_sepcomb_hsv.h
+++ b/intern/cycles/kernel/svm/svm_sepcomb_hsv.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_sepcomb_vector.h b/intern/cycles/kernel/svm/svm_sepcomb_vector.h
index c8e7e34f87d..7a5a69f6dff 100644
--- a/intern/cycles/kernel/svm/svm_sepcomb_vector.h
+++ b/intern/cycles/kernel/svm/svm_sepcomb_vector.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_sky.h b/intern/cycles/kernel/svm/svm_sky.h
index 500b5146931..4c8e3a32271 100644
--- a/intern/cycles/kernel/svm/svm_sky.h
+++ b/intern/cycles/kernel/svm/svm_sky.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index a17e4a25efe..b69f0d1c1c8 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_texture.h b/intern/cycles/kernel/svm/svm_texture.h
index d97c85db36a..c5dc213c82d 100644
--- a/intern/cycles/kernel/svm/svm_texture.h
+++ b/intern/cycles/kernel/svm/svm_texture.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index fbe669c1fab..b1439aa1616 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __SVM_TYPES_H__
diff --git a/intern/cycles/kernel/svm/svm_value.h b/intern/cycles/kernel/svm/svm_value.h
index 7beed065288..c1c2b539df3 100644
--- a/intern/cycles/kernel/svm/svm_value.h
+++ b/intern/cycles/kernel/svm/svm_value.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_vector_transform.h b/intern/cycles/kernel/svm/svm_vector_transform.h
index 61d33aeb8cf..a16786f3ed3 100644
--- a/intern/cycles/kernel/svm/svm_vector_transform.h
+++ b/intern/cycles/kernel/svm/svm_vector_transform.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_voronoi.h b/intern/cycles/kernel/svm/svm_voronoi.h
index 083a2f30e06..5a2e6e97dd3 100644
--- a/intern/cycles/kernel/svm/svm_voronoi.h
+++ b/intern/cycles/kernel/svm/svm_voronoi.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/svm/svm_wave.h b/intern/cycles/kernel/svm/svm_wave.h
index 7f9081539a4..36b59c3684c 100644
--- a/intern/cycles/kernel/svm/svm_wave.h
+++ b/intern/cycles/kernel/svm/svm_wave.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index c3907da39d0..2dc6962633d 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -11,7 +11,7 @@ set(INC
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_DIR}
)
set(SRC
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index 8abf869a775..bf83c970bf8 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "image.h"
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index f5227ebde52..bbc6cf7f65f 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __ATTRIBUTE_H__
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp
index 3926ecb99d6..d731b3346fe 100644
--- a/intern/cycles/render/background.cpp
+++ b/intern/cycles/render/background.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "background.h"
diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h
index cf627862513..26a727291ee 100644
--- a/intern/cycles/render/background.h
+++ b/intern/cycles/render/background.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __BACKGROUND_H__
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index 5723a22dd84..1e8c1ac8bc9 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "bake.h"
diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h
index 186fbbeea4d..9ff10dafa0e 100644
--- a/intern/cycles/render/bake.h
+++ b/intern/cycles/render/bake.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __BAKE_H__
diff --git a/intern/cycles/render/blackbody.h b/intern/cycles/render/blackbody.h
index c3be0ebdf30..5671cbaf9bd 100644
--- a/intern/cycles/render/blackbody.h
+++ b/intern/cycles/render/blackbody.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __BLACKBODY_H__
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index 756e16b38b5..5202bf5862c 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdlib.h>
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index 27ab20bbafd..4fa1c51d821 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __BUFFERS_H__
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 110adb4d036..5b0d51e60c2 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "camera.h"
@@ -47,6 +47,10 @@ Camera::Camera()
panorama_type = PANORAMA_EQUIRECTANGULAR;
fisheye_fov = M_PI_F;
fisheye_lens = 10.5f;
+ latitude_min = -M_PI_2_F;
+ latitude_max = M_PI_2_F;
+ longitude_min = -M_PI_F;
+ longitude_max = M_PI_F;
fov = M_PI_4_F;
sensorwidth = 0.036f;
@@ -253,6 +257,8 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kcam->panorama_type = panorama_type;
kcam->fisheye_fov = fisheye_fov;
kcam->fisheye_lens = fisheye_lens;
+ kcam->equirectangular_range = make_float4(longitude_min - longitude_max, -longitude_min,
+ latitude_min - latitude_max, -latitude_min + M_PI_2_F);
/* sensor size */
kcam->sensorwidth = sensorwidth;
@@ -316,7 +322,11 @@ bool Camera::modified(const Camera& cam)
(aperture_ratio == cam.aperture_ratio) &&
(panorama_type == cam.panorama_type) &&
(fisheye_fov == cam.fisheye_fov) &&
- (fisheye_lens == cam.fisheye_lens));
+ (fisheye_lens == cam.fisheye_lens) &&
+ (latitude_min == cam.latitude_min) &&
+ (latitude_max == cam.latitude_max) &&
+ (longitude_min == cam.longitude_min) &&
+ (longitude_max == cam.longitude_max));
}
bool Camera::motion_modified(const Camera& cam)
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 788ae7b9bb6..9525cce8109 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __CAMERA_H__
@@ -53,6 +53,10 @@ public:
PanoramaType panorama_type;
float fisheye_fov;
float fisheye_lens;
+ float latitude_min;
+ float latitude_max;
+ float longitude_min;
+ float longitude_max;
/* anamorphic lens bokeh */
float aperture_ratio;
diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp
index dc7665fe144..80dc6434cde 100644
--- a/intern/cycles/render/curves.cpp
+++ b/intern/cycles/render/curves.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "device.h"
diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h
index 6fd0fff57fb..22ab5d05f8a 100644
--- a/intern/cycles/render/curves.h
+++ b/intern/cycles/render/curves.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __CURVES_H__
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 19f959d4ea1..c6d12928dd4 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "camera.h"
diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h
index cc7183bfd95..e2cd63cc2ed 100644
--- a/intern/cycles/render/film.h
+++ b/intern/cycles/render/film.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __FILM_H__
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 8fd8663b5a4..8f8a69373da 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "attribute.h"
@@ -844,7 +844,7 @@ void ShaderGraph::dump_graph(const char *filename)
return;
}
- fprintf(fd, "digraph dependencygraph {\n");
+ fprintf(fd, "digraph shader_graph {\n");
fprintf(fd, "ranksep=1.5\n");
fprintf(fd, "splines=false\n");
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index 7b95703d3aa..9130f7f04a0 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __GRAPH_H__
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index eb2c3333c44..61a0a81d51d 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "device.h"
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 535f0ff156d..2f5dcb6efd5 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __IMAGE_H__
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index ae7cc30eb23..17c50ca826f 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "device.h"
@@ -59,6 +59,10 @@ Integrator::Integrator()
mesh_light_samples = 1;
subsurface_samples = 1;
volume_samples = 1;
+
+ sample_all_lights_direct = true;
+ sample_all_lights_indirect = true;
+
method = PATH;
sampling_pattern = SAMPLING_PATTERN_SOBOL;
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index 110c354823b..fd2ad14488d 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __INTEGRATOR_H__
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 8d1cec10187..ca6853ecb6e 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "background.h"
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index cf769ac5aed..1f8eac6a97f 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __LIGHT_H__
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 6137f7d4fdc..815ecb310f4 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "bvh.h"
@@ -30,6 +30,7 @@
#include "util_cache.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_progress.h"
#include "util_set.h"
@@ -980,6 +981,9 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
/* bvh build */
progress.set_status("Updating Scene BVH", "Building");
+ VLOG(1) << (scene->params.use_qbvh ? "Using QBVH optimization structure"
+ : "Using regular BVH optimization structure");
+
BVHParams bparams;
bparams.top_level = true;
bparams.use_qbvh = scene->params.use_qbvh;
@@ -1027,6 +1031,7 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
}
dscene->data.bvh.root = pack.root_index;
+ dscene->data.bvh.use_qbvh = scene->params.use_qbvh;
}
void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
@@ -1094,7 +1099,12 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
foreach(Mesh *mesh, scene->meshes) {
if(mesh->need_update) {
- pool.push(function_bind(&Mesh::compute_bvh, mesh, &scene->params, &progress, i, num_bvh));
+ pool.push(function_bind(&Mesh::compute_bvh,
+ mesh,
+ &scene->params,
+ &progress,
+ i,
+ num_bvh));
i++;
}
}
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 7e34b761faf..90894564591 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __MESH_H__
diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index 4c0ee76299c..1ba0c7f7291 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "device.h"
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 62bdf7cd162..625b829ba24 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "image.h"
@@ -3754,11 +3754,31 @@ void VectorMathNode::compile(SVMCompiler& compiler)
ShaderOutput *value_out = output("Value");
ShaderOutput *vector_out = output("Vector");
- compiler.stack_assign(vector1_in);
- compiler.stack_assign(vector2_in);
compiler.stack_assign(value_out);
compiler.stack_assign(vector_out);
+ /* Optimize vector math node without links to a single value node. */
+ if(vector1_in->link == NULL && vector2_in->link == NULL) {
+ float optimized_value;
+ float3 optimized_vector;
+ svm_vector_math(&optimized_value,
+ &optimized_vector,
+ (NodeVectorMath)type_enum[type],
+ vector1_in->value,
+ vector2_in->value);
+
+ compiler.add_node(NODE_VALUE_F,
+ __float_as_int(optimized_value),
+ value_out->stack_offset);
+
+ compiler.add_node(NODE_VALUE_V, vector_out->stack_offset);
+ compiler.add_node(NODE_VALUE_V, optimized_vector);
+ return;
+ }
+
+ compiler.stack_assign(vector1_in);
+ compiler.stack_assign(vector2_in);
+
compiler.add_node(NODE_VECTOR_MATH, type_enum[type], vector1_in->stack_offset, vector2_in->stack_offset);
compiler.add_node(NODE_VECTOR_MATH, value_out->stack_offset, vector_out->stack_offset);
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 31b6f4e50c4..3140ec939bb 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __NODES_H__
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 46ddab235d9..87c45ceb151 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "device.h"
@@ -318,6 +318,9 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
mtfm_pre = mtfm_pre * itfm;
mtfm_post = mtfm_post * itfm;
}
+ else {
+ flag |= SD_OBJECT_HAS_VERTEX_MOTION;
+ }
memcpy(&objects_vector[i*OBJECT_VECTOR_SIZE+0], &mtfm_pre, sizeof(float4)*3);
memcpy(&objects_vector[i*OBJECT_VECTOR_SIZE+3], &mtfm_post, sizeof(float4)*3);
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index 2c69b83a2e9..574d44b6599 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __OBJECT_H__
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index b9180552ac2..08d69386724 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "device.h"
@@ -30,6 +30,7 @@
#include "osl_shader.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_md5.h"
#include "util_path.h"
#include "util_progress.h"
@@ -194,6 +195,8 @@ void OSLShaderManager::shading_system_init()
ss_shared->attribute("searchpath:shader", path_get("shader"));
//ss_shared->attribute("greedyjit", 1);
+ VLOG(1) << "Using shader search path: " << path_get("shader");
+
/* our own ray types */
static const char *raytypes[] = {
"camera", /* PATH_RAY_CAMERA */
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index 5824e2ace64..bc6a9d8fbbd 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __OSL_H__
diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp
index 255effa86dd..f2f154cdab4 100644
--- a/intern/cycles/render/particles.cpp
+++ b/intern/cycles/render/particles.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "device.h"
diff --git a/intern/cycles/render/particles.h b/intern/cycles/render/particles.h
index a606722f9c3..bf2b6b77015 100644
--- a/intern/cycles/render/particles.h
+++ b/intern/cycles/render/particles.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __PARTICLES_H__
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 3662c29587e..ee7cef1950b 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdlib.h>
@@ -153,81 +153,83 @@ void Scene::device_update(Device *device_, Progress& progress)
progress.set_status("Updating Shaders");
shader_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Images");
image_manager->device_update(device, &dscene, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Background");
background->device_update(device, &dscene, this);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Objects");
object_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Meshes");
mesh_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Objects Flags");
object_manager->device_update_flags(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Hair Systems");
curve_system_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Lookup Tables");
lookup_tables->device_update(device, &dscene);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
/* TODO(sergey): Make sure camera is not needed above. */
progress.set_status("Updating Camera");
camera->device_update(device, &dscene, this);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Lights");
light_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Particle Systems");
particle_system_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Film");
film->device_update(device, &dscene, this);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Integrator");
integrator->device_update(device, &dscene, this);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Lookup Tables");
lookup_tables->device_update(device, &dscene);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Baking");
bake_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel()) return;
+ if(progress.get_cancel() || device->have_error()) return;
- progress.set_status("Updating Device", "Writing constant memory");
- device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
+ if(device->have_error() == false) {
+ progress.set_status("Updating Device", "Writing constant memory");
+ device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
+ }
}
Scene::MotionType Scene::need_motion(bool advanced_shading)
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 5d205225d97..53c3a95903c 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __SCENE_H__
@@ -26,6 +26,7 @@
#include "util_param.h"
#include "util_string.h"
+#include "util_system.h"
#include "util_thread.h"
#include "util_types.h"
#include "util_vector.h"
@@ -135,11 +136,7 @@ public:
bvh_type = BVH_DYNAMIC;
use_bvh_cache = false;
use_bvh_spatial_split = false;
-#ifdef __QBVH__
- use_qbvh = true;
-#else
use_qbvh = false;
-#endif
persistent_data = false;
}
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 9fcd9fa85f5..c633f4b8497 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <string.h>
@@ -199,8 +199,7 @@ void Session::run_gpu()
paused_time = 0.0;
last_update_time = time_dt();
- if(!params.background)
- progress.set_start_time(start_time + paused_time);
+ progress.set_render_start_time(start_time + paused_time);
while(!progress.get_cancel()) {
/* advance to next tile */
@@ -233,6 +232,7 @@ void Session::run_gpu()
if(!params.background)
progress.set_start_time(start_time + paused_time);
+ progress.set_render_start_time(start_time + paused_time);
update_status_time(pause, no_tiles);
progress.set_update();
@@ -251,7 +251,7 @@ void Session::run_gpu()
update_scene();
if(!device->error_message().empty())
- progress.set_cancel(device->error_message());
+ progress.set_error(device->error_message());
if(progress.get_cancel())
break;
@@ -292,7 +292,7 @@ void Session::run_gpu()
}
if(!device->error_message().empty())
- progress.set_cancel(device->error_message());
+ progress.set_error(device->error_message());
tiles_written = update_progressive_refine(progress.get_cancel());
@@ -517,6 +517,7 @@ void Session::run_cpu()
if(!params.background)
progress.set_start_time(start_time + paused_time);
+ progress.set_render_start_time(start_time + paused_time);
update_status_time(pause, no_tiles);
progress.set_update();
@@ -540,7 +541,7 @@ void Session::run_cpu()
update_scene();
if(!device->error_message().empty())
- progress.set_cancel(device->error_message());
+ progress.set_error(device->error_message());
if(progress.get_cancel())
break;
@@ -558,7 +559,7 @@ void Session::run_cpu()
need_tonemap = true;
if(!device->error_message().empty())
- progress.set_cancel(device->error_message());
+ progress.set_error(device->error_message());
}
device->task_wait();
@@ -580,7 +581,7 @@ void Session::run_cpu()
}
if(!device->error_message().empty())
- progress.set_cancel(device->error_message());
+ progress.set_error(device->error_message());
tiles_written = update_progressive_refine(progress.get_cancel());
}
@@ -604,7 +605,7 @@ void Session::load_kernels()
if(message.empty())
message = "Failed loading render kernel, see console for errors";
- progress.set_cancel(message);
+ progress.set_error(message);
progress.set_status("Error", message);
progress.set_update();
return;
@@ -665,7 +666,8 @@ void Session::reset_(BufferParams& buffer_params, int samples)
paused_time = 0.0;
if(!params.background)
- progress.set_start_time(start_time + paused_time);
+ progress.set_start_time(start_time);
+ progress.set_render_start_time(start_time);
}
void Session::reset(BufferParams& buffer_params, int samples)
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index 9da7a0aafa3..a39a2a081dd 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __SESSION_H__
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 5c30d191d34..db7c93e5e5d 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "background.h"
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index b267731abe5..58960e7fc89 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -11,13 +11,22 @@
* 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
+ * limitations under the License.
*/
#ifndef __SHADER_H__
#define __SHADER_H__
#ifdef WITH_OSL
+# if defined(_MSC_VER)
+/* Prevent OSL from polluting the context with weird macros from windows.h.
+ * TODO(sergey): Ideally it's only enough to have class/struct declarations in
+ * the header and skip header include here.
+ */
+# define NOGDI
+# define NOMINMAX
+# define WIN32_LEAN_AND_MEAN
+# endif
# include <OSL/oslexec.h>
#endif
diff --git a/intern/cycles/render/sobol.h b/intern/cycles/render/sobol.h
index b5eaa67db3e..574f148b9a2 100644
--- a/intern/cycles/render/sobol.h
+++ b/intern/cycles/render/sobol.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __SOBOL_H__
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 13c63d9420c..8216669a1ec 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "device.h"
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index c1dd96e4d80..4b390fb88f9 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __SVM_H__
diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp
index a8d502c432d..faf7ea3409b 100644
--- a/intern/cycles/render/tables.cpp
+++ b/intern/cycles/render/tables.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "device.h"
diff --git a/intern/cycles/render/tables.h b/intern/cycles/render/tables.h
index 059940cbeb6..4efa09fa3c1 100644
--- a/intern/cycles/render/tables.h
+++ b/intern/cycles/render/tables.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __TABLES_H__
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index e37d8e5f8a1..675f49ec300 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "tile.h"
diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h
index 7796518b6bc..c9bdc86f029 100644
--- a/intern/cycles/render/tile.h
+++ b/intern/cycles/render/tile.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __TILE_H__
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index 6bd18d08ba0..44bab066dde 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "camera.h"
diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h
index 9cf5b0d50b8..b7e61748779 100644
--- a/intern/cycles/subd/subd_dice.h
+++ b/intern/cycles/subd/subd_dice.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __SUBD_DICE_H__
diff --git a/intern/cycles/subd/subd_patch.cpp b/intern/cycles/subd/subd_patch.cpp
index fe9fa791813..0db46ec492d 100644
--- a/intern/cycles/subd/subd_patch.cpp
+++ b/intern/cycles/subd/subd_patch.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/* Parts adapted from code in the public domain in NVidia Mesh Tools. */
diff --git a/intern/cycles/subd/subd_patch.h b/intern/cycles/subd/subd_patch.h
index 48f35d78711..9be4606c248 100644
--- a/intern/cycles/subd/subd_patch.h
+++ b/intern/cycles/subd/subd_patch.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __SUBD_PATCH_H__
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index 6bbf4af3f85..df4d451e8eb 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "camera.h"
diff --git a/intern/cycles/subd/subd_split.h b/intern/cycles/subd/subd_split.h
index 3f9a2721977..df4935ee624 100644
--- a/intern/cycles/subd/subd_split.h
+++ b/intern/cycles/subd/subd_split.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __SUBD_SPLIT_H__
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index 842d5efac79..d52bcd6a7aa 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -5,12 +5,11 @@ set(INC
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_DIR}
)
set(SRC
util_cache.cpp
- util_dynlib.cpp
util_logging.cpp
util_md5.cpp
util_path.cpp
@@ -22,6 +21,10 @@ set(SRC
util_transform.cpp
)
+if(NOT CYCLES_STANDALONE_REPOSITORY)
+ add_definitions(-DWITH_GLEW_MX)
+endif()
+
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
list(APPEND SRC
util_view.cpp
@@ -31,10 +34,10 @@ endif()
set(SRC_HEADERS
util_algorithm.h
util_args.h
+ util_atomic.h
util_boundbox.h
util_cache.h
util_debug.h
- util_dynlib.h
util_foreach.h
util_function.h
util_half.h
diff --git a/intern/cycles/util/util_algorithm.h b/intern/cycles/util/util_algorithm.h
index 5865f3f04bb..5c79c00cc98 100644
--- a/intern/cycles/util/util_algorithm.h
+++ b/intern/cycles/util/util_algorithm.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_ALGORITHM_H__
diff --git a/intern/cycles/util/util_args.h b/intern/cycles/util/util_args.h
index 55933c895bf..a53fc061758 100644
--- a/intern/cycles/util/util_args.h
+++ b/intern/cycles/util/util_args.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_ARGS_H__
diff --git a/intern/cycles/util/util_dynlib.h b/intern/cycles/util/util_atomic.h
index b30cf98c1b9..7bbd97b8667 100644
--- a/intern/cycles/util/util_dynlib.h
+++ b/intern/cycles/util/util_atomic.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2013 Blender Foundation
+ * 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.
@@ -11,21 +11,23 @@
* 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
+ * limitations under the License.
*/
-#ifndef __UTIL_DYNLIB_H__
-#define __UTIL_DYNLIB_H__
+#ifndef __UTIL_ATOMIC_H__
+#define __UTIL_ATOMIC_H__
-CCL_NAMESPACE_BEGIN
+/* Using atomic ops header from Blender. */
+#include "atomic_ops.h"
-struct DynamicLibrary;
-
-DynamicLibrary *dynamic_library_open(const char *name);
-void *dynamic_library_find(DynamicLibrary *lib, const char *name);
-void dynamic_library_close(DynamicLibrary *lib);
-
-CCL_NAMESPACE_END
-
-#endif /* __UTIL_DYNLIB_H__ */
+ATOMIC_INLINE void atomic_update_max_z(size_t *maximum_value, size_t value)
+{
+ size_t prev_value = *maximum_value;
+ while (prev_value < value) {
+ if (atomic_cas_z(maximum_value, prev_value, value) != prev_value) {
+ break;
+ }
+ }
+}
+#endif /* __UTIL_ATOMIC_H__ */
diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h
index a71e0399619..cef5adc0a61 100644
--- a/intern/cycles/util/util_boundbox.h
+++ b/intern/cycles/util/util_boundbox.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_BOUNDBOX_H__
diff --git a/intern/cycles/util/util_cache.cpp b/intern/cycles/util/util_cache.cpp
index e20c3a67b75..fbc760fddad 100644
--- a/intern/cycles/util/util_cache.cpp
+++ b/intern/cycles/util/util_cache.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdio.h>
diff --git a/intern/cycles/util/util_cache.h b/intern/cycles/util/util_cache.h
index bfb2877a22b..9d001a6f1ff 100644
--- a/intern/cycles/util/util_cache.h
+++ b/intern/cycles/util/util_cache.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_CACHE_H__
diff --git a/intern/cycles/util/util_color.h b/intern/cycles/util/util_color.h
index 53b3d72de67..d3598f84b94 100644
--- a/intern/cycles/util/util_color.h
+++ b/intern/cycles/util/util_color.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_COLOR_H__
diff --git a/intern/cycles/util/util_debug.h b/intern/cycles/util/util_debug.h
index 79fac506b98..6b61a49fcc3 100644
--- a/intern/cycles/util/util_debug.h
+++ b/intern/cycles/util/util_debug.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_DEBUG_H__
diff --git a/intern/cycles/util/util_dynlib.cpp b/intern/cycles/util/util_dynlib.cpp
deleted file mode 100644
index 587cad607c8..00000000000
--- a/intern/cycles/util/util_dynlib.cpp
+++ /dev/null
@@ -1,94 +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 <stdlib.h>
-
-#include "util_dynlib.h"
-
-#ifdef _WIN32
-
-#include <windows.h>
-
-CCL_NAMESPACE_BEGIN
-
-struct DynamicLibrary {
- HMODULE module;
-};
-
-DynamicLibrary *dynamic_library_open(const char *name)
-{
- HMODULE module = LoadLibrary(name);
-
- if(!module)
- return NULL;
-
- DynamicLibrary *lib = new DynamicLibrary();
- lib->module = module;
-
- return lib;
-}
-
-void *dynamic_library_find(DynamicLibrary *lib, const char *name)
-{
- return (void*)GetProcAddress(lib->module, name);
-}
-
-void dynamic_library_close(DynamicLibrary *lib)
-{
- FreeLibrary(lib->module);
- delete lib;
-}
-
-CCL_NAMESPACE_END
-
-#else
-
-#include <dlfcn.h>
-
-CCL_NAMESPACE_BEGIN
-
-struct DynamicLibrary {
- void *module;
-};
-
-DynamicLibrary *dynamic_library_open(const char *name)
-{
- void *module = dlopen(name, RTLD_NOW);
-
- if(!module)
- return NULL;
-
- DynamicLibrary *lib = new DynamicLibrary();
- lib->module = module;
-
- return lib;
-}
-
-void *dynamic_library_find(DynamicLibrary *lib, const char *name)
-{
- return dlsym(lib->module, name);
-}
-
-void dynamic_library_close(DynamicLibrary *lib)
-{
- dlclose(lib->module);
- delete lib;
-}
-
-CCL_NAMESPACE_END
-
-#endif
-
diff --git a/intern/cycles/util/util_foreach.h b/intern/cycles/util/util_foreach.h
index df3277fbf37..065bd33ebd2 100644
--- a/intern/cycles/util/util_foreach.h
+++ b/intern/cycles/util/util_foreach.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_FOREACH_H__
diff --git a/intern/cycles/util/util_function.h b/intern/cycles/util/util_function.h
index 6aa014a08a6..7a312efaad7 100644
--- a/intern/cycles/util/util_function.h
+++ b/intern/cycles/util/util_function.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_FUNCTION_H__
diff --git a/intern/cycles/util/util_half.h b/intern/cycles/util/util_half.h
index 397133618be..76941569bd2 100644
--- a/intern/cycles/util/util_half.h
+++ b/intern/cycles/util/util_half.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_HALF_H__
diff --git a/intern/cycles/util/util_hash.h b/intern/cycles/util/util_hash.h
index edd2448efa4..bbbedc22a47 100644
--- a/intern/cycles/util/util_hash.h
+++ b/intern/cycles/util/util_hash.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_HASH_H__
diff --git a/intern/cycles/util/util_image.h b/intern/cycles/util/util_image.h
index 4b8140e7a7a..bb8a31c6fec 100644
--- a/intern/cycles/util/util_image.h
+++ b/intern/cycles/util/util_image.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_IMAGE_H__
diff --git a/intern/cycles/util/util_list.h b/intern/cycles/util/util_list.h
index 2aa0b7381e3..6cb27e6defe 100644
--- a/intern/cycles/util/util_list.h
+++ b/intern/cycles/util/util_list.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_LIST_H__
diff --git a/intern/cycles/util/util_logging.cpp b/intern/cycles/util/util_logging.cpp
index 0722f16cf45..03041723e15 100644
--- a/intern/cycles/util/util_logging.cpp
+++ b/intern/cycles/util/util_logging.cpp
@@ -11,15 +11,63 @@
* 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
+ * limitations under the License.
*/
#include <util_logging.h>
#include "util_math.h"
+#include <stdio.h>
+#ifdef _MSC_VER
+# define snprintf _snprintf
+#endif
+
CCL_NAMESPACE_BEGIN
+void util_logging_init(const char *argv0)
+{
+#ifdef WITH_CYCLES_LOGGING
+ using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
+
+ /* Make it so FATAL messages are always print into console. */
+ char severity_fatal[32];
+ snprintf(severity_fatal, sizeof(severity_fatal), "%d",
+ google::GLOG_FATAL);
+
+ google::InitGoogleLogging(argv0);
+ SetCommandLineOption("logtostderr", "1");
+ SetCommandLineOption("v", "0");
+ SetCommandLineOption("stderrthreshold", severity_fatal);
+ SetCommandLineOption("minloglevel", severity_fatal);
+#else
+ (void) argv0;
+#endif
+}
+
+void util_logging_start(void)
+{
+#ifdef WITH_CYCLES_LOGGING
+ using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
+ SetCommandLineOption("logtostderr", "1");
+ SetCommandLineOption("v", "2");
+ SetCommandLineOption("stderrthreshold", "1");
+ SetCommandLineOption("minloglevel", "0");
+#endif
+}
+
+void util_logging_verbosity_set(int verbosity)
+{
+#ifdef WITH_CYCLES_LOGGING
+ using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
+ char val[10];
+ snprintf(val, sizeof(val), "%d", verbosity);
+ SetCommandLineOption("v", val);
+#else
+ (void) verbosity;
+#endif
+}
+
std::ostream& operator <<(std::ostream &os,
const float3 &value)
{
diff --git a/intern/cycles/util/util_logging.h b/intern/cycles/util/util_logging.h
index 2c5455051a4..7fc42ac355a 100644
--- a/intern/cycles/util/util_logging.h
+++ b/intern/cycles/util/util_logging.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_LOGGING_H__
@@ -45,6 +45,10 @@ public:
struct float3;
+void util_logging_init(const char *argv0);
+void util_logging_start(void);
+void util_logging_verbosity_set(int verbosity);
+
std::ostream& operator <<(std::ostream &os,
const float3 &value);
diff --git a/intern/cycles/util/util_map.h b/intern/cycles/util/util_map.h
index 77500e4712d..54d6a8d6424 100644
--- a/intern/cycles/util/util_map.h
+++ b/intern/cycles/util/util_map.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_MAP_H__
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 78005546a01..177a72bc1c9 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_MATH_H__
@@ -124,6 +124,24 @@ ccl_device_inline double min(double a, double b)
return (a < b)? a: b;
}
+/* These 2 guys are templated for usage with registers data.
+ *
+ * NOTE: Since this is CPU-only functions it is ok to use references here.
+ * But for other devices we'll need to be careful about this.
+ */
+
+template<typename T>
+ccl_device_inline T min4(const T& a, const T& b, const T& c, const T& d)
+{
+ return min(min(a,b),min(c,d));
+}
+
+template<typename T>
+ccl_device_inline T max4(const T& a, const T& b, const T& c, const T& d)
+{
+ return max(max(a,b),max(c,d));
+}
+
#endif
ccl_device_inline float min4(float a, float b, float c, float d)
@@ -1452,6 +1470,22 @@ ccl_device bool map_to_sphere(float *r_u, float *r_v,
}
}
+ccl_device_inline int util_max_axis(float3 vec)
+{
+ if(vec.x > vec.y) {
+ if(vec.x > vec.z)
+ return 0;
+ else
+ return 2;
+ }
+ else {
+ if(vec.y > vec.z)
+ return 1;
+ else
+ return 2;
+ }
+}
+
CCL_NAMESPACE_END
#endif /* __UTIL_MATH_H__ */
diff --git a/intern/cycles/util/util_opengl.h b/intern/cycles/util/util_opengl.h
index 667a5db653d..0b5462e0a09 100644
--- a/intern/cycles/util/util_opengl.h
+++ b/intern/cycles/util/util_opengl.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_OPENGL_H__
@@ -20,6 +20,12 @@
/* OpenGL header includes, used everywhere we use OpenGL, to deal with
* platform differences in one central place. */
-#include "glew-mx.h"
+#ifdef WITH_GLEW_MX
+# include "glew-mx.h"
+#else
+# include <GL/glew.h>
+# define mxCreateContext() glewInit()
+# define mxMakeCurrentContext(x) (x)
+#endif
#endif /* __UTIL_OPENGL_H__ */
diff --git a/intern/cycles/util/util_optimization.h b/intern/cycles/util/util_optimization.h
index 2feb3d6ab7e..b230bb1a627 100644
--- a/intern/cycles/util/util_optimization.h
+++ b/intern/cycles/util/util_optimization.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_OPTIMIZATION_H__
@@ -130,6 +130,9 @@
/* MinGW64 has conflicting declarations for these SSE headers in <windows.h>.
* Since we can't avoid including <windows.h>, better only include that */
+#define NOGDI
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
diff --git a/intern/cycles/util/util_param.h b/intern/cycles/util/util_param.h
index ef20ff0fcd2..69bcbf80a78 100644
--- a/intern/cycles/util/util_param.h
+++ b/intern/cycles/util/util_param.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_PARAM_H__
diff --git a/intern/cycles/util/util_path.cpp b/intern/cycles/util/util_path.cpp
index aa424045ece..b688033fc9b 100644
--- a/intern/cycles/util/util_path.cpp
+++ b/intern/cycles/util/util_path.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "util_debug.h"
diff --git a/intern/cycles/util/util_path.h b/intern/cycles/util/util_path.h
index fd9ea11740d..b81d71d1c0f 100644
--- a/intern/cycles/util/util_path.h
+++ b/intern/cycles/util/util_path.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_PATH_H__
diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h
index e721a3f5047..315aa753bdd 100644
--- a/intern/cycles/util/util_progress.h
+++ b/intern/cycles/util/util_progress.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_PROGRESS_H__
@@ -46,6 +46,8 @@ public:
update_cb = NULL;
cancel = false;
cancel_message = "";
+ error = false;
+ error_message = "";
cancel_cb = NULL;
}
@@ -59,7 +61,7 @@ public:
thread_scoped_lock lock(progress.progress_mutex);
progress.get_status(status, substatus);
- progress.get_tile(tile, total_time, tile_time);
+ progress.get_tile(tile, total_time, render_time, tile_time);
sample = progress.get_sample();
@@ -71,7 +73,9 @@ public:
tile = 0;
sample = 0;
start_time = time_dt();
+ render_start_time = time_dt();
total_time = 0.0f;
+ render_time = 0.0f;
tile_time = 0.0f;
status = "Initializing";
substatus = "";
@@ -79,6 +83,8 @@ public:
sync_substatus = "";
cancel = false;
cancel_message = "";
+ error = false;
+ error_message = "";
}
/* cancel */
@@ -108,6 +114,28 @@ public:
cancel_cb = function;
}
+ /* error */
+ void set_error(const string& error_message_)
+ {
+ thread_scoped_lock lock(progress_mutex);
+ error_message = error_message_;
+ error = true;
+ /* If error happens we also stop rendering. */
+ cancel_message = error_message_;
+ cancel = true;
+ }
+
+ bool get_error()
+ {
+ return error;
+ }
+
+ string get_error_message()
+ {
+ thread_scoped_lock lock(progress_mutex);
+ return error_message;
+ }
+
/* tile and timing information */
void set_start_time(double start_time_)
@@ -117,21 +145,30 @@ public:
start_time = start_time_;
}
+ void set_render_start_time(double render_start_time_)
+ {
+ thread_scoped_lock lock(progress_mutex);
+
+ render_start_time = render_start_time_;
+ }
+
void set_tile(int tile_, double tile_time_)
{
thread_scoped_lock lock(progress_mutex);
tile = tile_;
total_time = time_dt() - start_time;
+ render_time = time_dt() - render_start_time;
tile_time = tile_time_;
}
- void get_tile(int& tile_, double& total_time_, double& tile_time_)
+ void get_tile(int& tile_, double& total_time_, double& render_time_, double& tile_time_)
{
thread_scoped_lock lock(progress_mutex);
tile_ = tile;
total_time_ = (total_time > 0.0)? total_time: 0.0;
+ render_time_ = (render_time > 0.0)? render_time: 0.0;
tile_time_ = tile_time;
}
@@ -169,6 +206,7 @@ public:
status = status_;
substatus = substatus_;
total_time = time_dt() - start_time;
+ render_time = time_dt() - render_start_time;
}
set_update();
@@ -180,6 +218,7 @@ public:
thread_scoped_lock lock(progress_mutex);
substatus = substatus_;
total_time = time_dt() - start_time;
+ render_time = time_dt() - render_start_time;
}
set_update();
@@ -192,6 +231,7 @@ public:
sync_status = status_;
sync_substatus = substatus_;
total_time = time_dt() - start_time;
+ render_time = time_dt() - render_start_time;
}
set_update();
@@ -204,6 +244,7 @@ public:
thread_scoped_lock lock(progress_mutex);
sync_substatus = substatus_;
total_time = time_dt() - start_time;
+ render_time = time_dt() - render_start_time;
}
set_update();
@@ -247,8 +288,8 @@ protected:
int tile; /* counter for rendered tiles */
int sample; /* counter of rendered samples, global for all tiles */
- double start_time;
- double total_time;
+ double start_time, render_start_time;
+ double total_time, render_time;
double tile_time;
string status;
@@ -259,6 +300,9 @@ protected:
volatile bool cancel;
string cancel_message;
+
+ volatile bool error;
+ string error_message;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_set.h b/intern/cycles/util/util_set.h
index 6078114e714..73a2bf19899 100644
--- a/intern/cycles/util/util_set.h
+++ b/intern/cycles/util/util_set.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_SET_H__
diff --git a/intern/cycles/util/util_simd.cpp b/intern/cycles/util/util_simd.cpp
index 0436823e62a..eb9e32800e1 100644
--- a/intern/cycles/util/util_simd.cpp
+++ b/intern/cycles/util/util_simd.cpp
@@ -12,7 +12,7 @@
* 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
+ * limitations under the License.
*/
#ifdef WITH_KERNEL_SSE2
diff --git a/intern/cycles/util/util_simd.h b/intern/cycles/util/util_simd.h
index 39506a6359b..625f26c1316 100644
--- a/intern/cycles/util/util_simd.h
+++ b/intern/cycles/util/util_simd.h
@@ -12,7 +12,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_SIMD_TYPES_H__
diff --git a/intern/cycles/util/util_sseb.h b/intern/cycles/util/util_sseb.h
index be510256dd3..4e1d1b39f3a 100644
--- a/intern/cycles/util/util_sseb.h
+++ b/intern/cycles/util/util_sseb.h
@@ -12,7 +12,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_SSEB_H__
diff --git a/intern/cycles/util/util_ssef.h b/intern/cycles/util/util_ssef.h
index 5e452ea03b4..073f2c69dbf 100644
--- a/intern/cycles/util/util_ssef.h
+++ b/intern/cycles/util/util_ssef.h
@@ -12,7 +12,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_SSEF_H__
diff --git a/intern/cycles/util/util_ssei.h b/intern/cycles/util/util_ssei.h
index 5f5a8686e35..0539425ac9e 100644
--- a/intern/cycles/util/util_ssei.h
+++ b/intern/cycles/util/util_ssei.h
@@ -12,7 +12,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_SSEI_H__
diff --git a/intern/cycles/util/util_stats.h b/intern/cycles/util/util_stats.h
index 8758b823084..ce27067dc5e 100644
--- a/intern/cycles/util/util_stats.h
+++ b/intern/cycles/util/util_stats.h
@@ -11,12 +11,14 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_STATS_H__
#define __UTIL_STATS_H__
+#include "util_atomic.h"
+
CCL_NAMESPACE_BEGIN
class Stats {
@@ -24,14 +26,13 @@ public:
Stats() : mem_used(0), mem_peak(0) {}
void mem_alloc(size_t size) {
- mem_used += size;
- if(mem_used > mem_peak)
- mem_peak = mem_used;
+ atomic_add_z(&mem_used, size);
+ atomic_update_max_z(&mem_peak, mem_used);
}
void mem_free(size_t size) {
assert(mem_used >= size);
- mem_used -= size;
+ atomic_sub_z(&mem_used, size);
}
size_t mem_used;
diff --git a/intern/cycles/util/util_string.cpp b/intern/cycles/util/util_string.cpp
index f38d8d3282f..8675ff3679d 100644
--- a/intern/cycles/util/util_string.cpp
+++ b/intern/cycles/util/util_string.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdarg.h>
diff --git a/intern/cycles/util/util_string.h b/intern/cycles/util/util_string.h
index 6808f085834..fa1671fd1ee 100644
--- a/intern/cycles/util/util_string.h
+++ b/intern/cycles/util/util_string.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_STRING_H__
diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp
index 7c0445577e2..998fad6b00d 100644
--- a/intern/cycles/util/util_system.cpp
+++ b/intern/cycles/util/util_system.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "util_system.h"
diff --git a/intern/cycles/util/util_system.h b/intern/cycles/util/util_system.h
index 0e8868c7dfc..4e7e00f85fd 100644
--- a/intern/cycles/util/util_system.h
+++ b/intern/cycles/util/util_system.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_SYSTEM_H__
diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp
index 14a81ecbb05..e43b26ddfe2 100644
--- a/intern/cycles/util/util_task.cpp
+++ b/intern/cycles/util/util_task.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include "util_debug.h"
diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h
index 42a1e2f5a58..8fac12e9987 100644
--- a/intern/cycles/util/util_task.h
+++ b/intern/cycles/util/util_task.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_TASK_H__
diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h
index f2698d043fb..fbbb9b42e31 100644
--- a/intern/cycles/util/util_thread.h
+++ b/intern/cycles/util/util_thread.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_THREAD_H__
diff --git a/intern/cycles/util/util_time.cpp b/intern/cycles/util/util_time.cpp
index dd91b024940..9668b0f9882 100644
--- a/intern/cycles/util/util_time.cpp
+++ b/intern/cycles/util/util_time.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdlib.h>
diff --git a/intern/cycles/util/util_time.h b/intern/cycles/util/util_time.h
index 3df17272e2f..14ffea7f3da 100644
--- a/intern/cycles/util/util_time.h
+++ b/intern/cycles/util/util_time.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_TIME_H__
diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp
index 14613558501..0a1c09ae3d5 100644
--- a/intern/cycles/util/util_transform.cpp
+++ b/intern/cycles/util/util_transform.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
/*
diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h
index 5b3dbe42f69..453d44bdcce 100644
--- a/intern/cycles/util/util_transform.h
+++ b/intern/cycles/util/util_transform.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_TRANSFORM_H__
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index ce84200d0b6..df61b6ead21 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_TYPES_H__
@@ -264,6 +264,19 @@ struct ccl_try_align(16) float4 {
__forceinline float& operator[](int i) { return *(&x + i); }
};
+template<typename T>
+class vector3
+{
+public:
+ T x, y, z;
+
+ ccl_always_inline vector3() {}
+ ccl_always_inline vector3(const T& a)
+ : x(a), y(a), z(a) {}
+ ccl_always_inline vector3(const T& x, const T& y, const T& z)
+ : x(x), y(y), z(z) {}
+};
+
#endif
#ifndef __KERNEL_GPU__
diff --git a/intern/cycles/util/util_vector.h b/intern/cycles/util/util_vector.h
index 3d885691c92..269fe04a4ae 100644
--- a/intern/cycles/util/util_vector.h
+++ b/intern/cycles/util/util_vector.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_VECTOR_H__
diff --git a/intern/cycles/util/util_view.cpp b/intern/cycles/util/util_view.cpp
index fe08389fe3f..e77ebb2fe3e 100644
--- a/intern/cycles/util/util_view.cpp
+++ b/intern/cycles/util/util_view.cpp
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#include <stdio.h>
diff --git a/intern/cycles/util/util_view.h b/intern/cycles/util/util_view.h
index 65d890eb6af..5def0564175 100644
--- a/intern/cycles/util/util_view.h
+++ b/intern/cycles/util/util_view.h
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_VIEW_H__
diff --git a/intern/cycles/util/util_xml.h b/intern/cycles/util/util_xml.h
index 9d1ebc2114a..cfd0afc95f7 100644
--- a/intern/cycles/util/util_xml.h
+++ b/intern/cycles/util/util_xml.h
@@ -11,15 +11,15 @@
* 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
+ * limitations under the License.
*/
#ifndef __UTIL_XML_H__
#define __UTIL_XML_H__
-/* PugiXML from OpenImageIO is used for XML parsing. */
+/* PugiXML is used for XML parsing. */
-#include <OpenImageIO/pugixml.hpp>
+#include <pugixml.hpp>
CCL_NAMESPACE_BEGIN
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 3ce269c2b4f..dc55a81b0d8 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -280,6 +280,16 @@ elseif(WIN32)
)
endif()
+ if(WITH_INPUT_IME)
+ add_definitions(-DWITH_INPUT_IME)
+
+ list(APPEND SRC
+ intern/GHOST_ImeWin32.cpp
+
+ intern/GHOST_ImeWin32.h
+ )
+ endif()
+
if(WITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManagerWin32.cpp
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 7b47f0526a2..c0f2651dd8b 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -897,6 +897,30 @@ extern int GHOST_UseNativePixels(void);
*/
extern float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle);
+/**
+ * Enable IME attached to the given window, i.e. allows user-input
+ * events to be dispatched to the IME.
+ * \param windowhandle Window handle of the caller
+ * \param x Requested x-coordinate of the rectangle
+ * \param y Requested y-coordinate of the rectangle
+ * \param w Requested width of the rectangle
+ * \param h Requested height of the rectangle
+ * \param complete Whether or not to complete the ongoing composition
+ * true: Start a new composition
+ * false: Move the IME windows to the given position without finishing it.
+ */
+extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
+ GHOST_TInt32 x,
+ GHOST_TInt32 y,
+ GHOST_TInt32 w,
+ GHOST_TInt32 h,
+ int complete);
+/**
+ * Disable the IME attached to the given window, i.e. prohibits any user-input
+ * events from being dispatched to the IME.
+ * \param windowhandle The window handle of the caller
+ */
+extern void GHOST_EndIME(GHOST_WindowHandle windowhandle);
#ifdef __cplusplus
}
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index 71dc193a81b..3f8215dc7c2 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -331,6 +331,29 @@ public:
virtual float getNativePixelSize(void) = 0;
+#ifdef WITH_INPUT_IME
+ /**
+ * Enable IME attached to the given window, i.e. allows user-input
+ * events to be dispatched to the IME.
+ * \param x Requested x-coordinate of the rectangle
+ * \param y Requested y-coordinate of the rectangle
+ * \param w Requested width of the rectangle
+ * \param h Requested height of the rectangle
+ * \param complete Whether or not to complete the ongoing composition
+ * true: Start a new composition
+ * false: Move the IME windows to the given position without finishing it.
+ */
+ virtual void beginIME(
+ GHOST_TInt32 x, GHOST_TInt32 y,
+ GHOST_TInt32 w, GHOST_TInt32 h,
+ int completed) = 0;
+
+ /**
+ * Disable the IME attached to the given window, i.e. prohibits any user-input
+ * events from being dispatched to the IME.
+ */
+ virtual void endIME() = 0;
+#endif /* WITH_INPUT_IME */
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IWindow")
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 7333ba025a5..c4a7490c71c 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -190,6 +190,10 @@ typedef enum {
GHOST_kEventTimer,
+ GHOST_kEventImeCompositionStart,
+ GHOST_kEventImeComposition,
+ GHOST_kEventImeCompositionEnd,
+
GHOST_kNumEventTypes
} GHOST_TEventType;
@@ -436,6 +440,22 @@ typedef struct {
GHOST_TEventDataPtr data;
} GHOST_TEventDragnDropData;
+/** similar to wmImeData */
+typedef struct {
+ /** size_t */
+ GHOST_TUserDataPtr result_len, composite_len;
+ /** char * utf8 encoding */
+ GHOST_TUserDataPtr result, composite;
+ /** Cursor position in the IME composition. */
+ int cursor_position;
+ /** Represents the position of the beginning of the selection */
+ int target_start;
+ /** Represents the position of the end of the selection */
+ int target_end;
+ /** custom temporal data */
+ GHOST_TUserDataPtr tmp;
+} GHOST_TEventImeData;
+
typedef struct {
int count;
GHOST_TUns8 **strings;
diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript
index 5a4572c164d..025559e11a4 100644
--- a/intern/ghost/SConscript
+++ b/intern/ghost/SConscript
@@ -154,6 +154,14 @@ if env['BF_GHOST_DEBUG']:
else:
sources.remove('intern' + os.sep + 'GHOST_EventPrinter.cpp')
+if env['WITH_BF_IME'] and window_system in ('win32-vc', 'win32-mingw', 'win64-vc', 'win64-mingw'):
+ defs.append('WITH_INPUT_IME')
+elif env['WITH_BF_IME']:
+ print "IME input is only supported on Windows! Please disable WITH_BF_IME!"
+ Exit()
+else:
+ sources.remove('intern' + os.sep + 'GHOST_ImeWin32.cpp')
+
if env['WITH_BF_3DMOUSE']:
defs.append('WITH_INPUT_NDOF')
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 5a2e638f01a..0da77ac5e20 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -915,3 +915,21 @@ float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle)
return 1.0f;
}
+#ifdef WITH_INPUT_IME
+
+void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
+ GHOST_TInt32 x, GHOST_TInt32 y,
+ GHOST_TInt32 w, GHOST_TInt32 h,
+ int complete)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
+ window->beginIME(x, y, w, h, complete);
+}
+
+void GHOST_EndIME(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
+ window->endIME();
+}
+
+#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
index b96a1dc93de..0b290c617a5 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.mm
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -75,9 +75,10 @@ GHOST_ContextCGL::GHOST_ContextCGL(
GHOST_ContextCGL::~GHOST_ContextCGL()
{
if (m_openGLContext != nil) {
- if (m_openGLContext == [NSOpenGLContext currentContext])
+ if (m_openGLContext == [NSOpenGLContext currentContext]) {
[NSOpenGLContext clearCurrentContext];
[m_openGLView clearGLContext];
+ }
if (m_openGLContext != s_sharedOpenGLContext || s_sharedCount == 1) {
assert(s_sharedCount > 0);
@@ -192,11 +193,7 @@ static void makeAttribList(
* Maybe a command line flag is better... */
if (getenv("BLENDER_SOFTWAREGL")) {
attribs.push_back(NSOpenGLPFARendererID);
-#if defined(__ppc__) || defined(__ppc64__)
- attribs.push_back(kCGLRendererAppleSWID);
-#else
attribs.push_back(kCGLRendererGenericFloatID);
-#endif
}
else {
attribs.push_back(NSOpenGLPFAAccelerated);
diff --git a/intern/ghost/intern/GHOST_ImeWin32.cpp b/intern/ghost/intern/GHOST_ImeWin32.cpp
new file mode 100644
index 00000000000..ef8eb9827ff
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ImeWin32.cpp
@@ -0,0 +1,517 @@
+/*
+ * ***** 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) 2010 The Chromium Authors. All rights reserved.
+ * All rights reserved.
+ *
+ * The Original Code is: some of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+/** \file ghost/intern/GHOST_ImeWin32.cpp
+ * \ingroup GHOST
+ */
+
+
+#include "GHOST_C-api.h"
+#include "GHOST_ImeWin32.h"
+#include "GHOST_WindowWin32.h"
+#include "utfconv.h"
+
+
+GHOST_ImeWin32::GHOST_ImeWin32()
+ : ime_status_(false),
+ input_language_id_(LANG_USER_DEFAULT),
+ is_composing_(false),
+ system_caret_(false),
+ caret_rect_(-1, -1, 0, 0),
+ is_first(true),
+ is_enable(true)
+{
+}
+
+
+GHOST_ImeWin32::~GHOST_ImeWin32()
+{
+}
+
+
+bool GHOST_ImeWin32::SetInputLanguage()
+{
+ /**
+ * Retrieve the current keyboard layout from Windows and determine whether
+ * or not the current input context has IMEs.
+ * Also save its input language for language-specific operations required
+ * while composing a text.
+ */
+ HKL keyboard_layout = ::GetKeyboardLayout(0);
+ input_language_id_ = reinterpret_cast<LANGID>(keyboard_layout);
+ ime_status_ = ::ImmIsIME(keyboard_layout);
+ return ime_status_;
+}
+
+
+void GHOST_ImeWin32::CreateImeWindow(HWND window_handle)
+{
+ /**
+ * When a user disables TSF (Text Service Framework) and CUAS (Cicero
+ * Unaware Application Support), Chinese IMEs somehow ignore function calls
+ * to ::ImmSetCandidateWindow(), i.e. they do not move their candidate
+ * window to the position given as its parameters, and use the position
+ * of the current system caret instead, i.e. it uses ::GetCaretPos() to
+ * retrieve the position of their IME candidate window.
+ * Therefore, we create a temporary system caret for Chinese IMEs and use
+ * it during this input context.
+ * Since some third-party Japanese IME also uses ::GetCaretPos() to determine
+ * their window position, we also create a caret for Japanese IMEs.
+ */
+ if (PRIMARYLANGID(input_language_id_) == LANG_CHINESE ||
+ PRIMARYLANGID(input_language_id_) == LANG_JAPANESE) {
+ if (!system_caret_) {
+ if (::CreateCaret(window_handle, NULL, 1, 1)) {
+ system_caret_ = true;
+ }
+ }
+ }
+ /* Restore the positions of the IME windows. */
+ UpdateImeWindow(window_handle);
+}
+
+
+void GHOST_ImeWin32::SetImeWindowStyle(HWND window_handle, UINT message, WPARAM wparam, LPARAM lparam, BOOL *handled)
+{
+ /**
+ * To prevent the IMM (Input Method Manager) from displaying the IME
+ * composition window, Update the styles of the IME windows and EXPLICITLY
+ * call ::DefWindowProc() here.
+ * NOTE(hbono): We can NEVER let WTL call ::DefWindowProc() when we update
+ * the styles of IME windows because the 'lparam' variable is a local one
+ * and all its updates disappear in returning from this function, i.e. WTL
+ * does not call ::DefWindowProc() with our updated 'lparam' value but call
+ * the function with its original value and over-writes our window styles.
+ */
+ *handled = TRUE;
+ lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
+ ::DefWindowProc(window_handle, message, wparam, lparam);
+}
+
+
+void GHOST_ImeWin32::DestroyImeWindow(HWND window_handle)
+{
+ /* Destroy the system caret if we have created for this IME input context. */
+ if (system_caret_) {
+ ::DestroyCaret();
+ system_caret_ = false;
+ }
+}
+
+
+void GHOST_ImeWin32::MoveImeWindow(HWND window_handle, HIMC imm_context)
+{
+ int x = caret_rect_.m_l;
+ int y = caret_rect_.m_t;
+ const int kCaretMargin = 1;
+ /**
+ * As written in a comment in GHOST_ImeWin32::CreateImeWindow(),
+ * Chinese IMEs ignore function calls to ::ImmSetCandidateWindow()
+ * when a user disables TSF (Text Service Framework) and CUAS (Cicero
+ * Unaware Application Support).
+ * On the other hand, when a user enables TSF and CUAS, Chinese IMEs
+ * ignore the position of the current system caret and uses the
+ * parameters given to ::ImmSetCandidateWindow() with its 'dwStyle'
+ * parameter CFS_CANDIDATEPOS.
+ * Therefore, we do not only call ::ImmSetCandidateWindow() but also
+ * set the positions of the temporary system caret if it exists.
+ */
+ CANDIDATEFORM candidate_position = { 0, CFS_CANDIDATEPOS, { x, y },
+ { 0, 0, 0, 0 } };
+ ::ImmSetCandidateWindow(imm_context, &candidate_position);
+ if (system_caret_) {
+ switch (PRIMARYLANGID(input_language_id_)) {
+ case LANG_JAPANESE:
+ ::SetCaretPos(x, y + caret_rect_.getHeight());
+ break;
+ default:
+ ::SetCaretPos(x, y);
+ break;
+ }
+ }
+ if (PRIMARYLANGID(input_language_id_) == LANG_KOREAN) {
+ /**
+ * Chinese IMEs and Japanese IMEs require the upper-left corner of
+ * the caret to move the position of their candidate windows.
+ * On the other hand, Korean IMEs require the lower-left corner of the
+ * caret to move their candidate windows.
+ */
+ y += kCaretMargin;
+ }
+ /**
+ * Japanese IMEs and Korean IMEs also use the rectangle given to
+ * ::ImmSetCandidateWindow() with its 'dwStyle' parameter CFS_EXCLUDE
+ * to move their candidate windows when a user disables TSF and CUAS.
+ * Therefore, we also set this parameter here.
+ */
+ CANDIDATEFORM exclude_rectangle = { 0, CFS_EXCLUDE, { x, y },
+ { x, y, x + caret_rect_.getWidth(), y + caret_rect_.getHeight() } };
+ ::ImmSetCandidateWindow(imm_context, &exclude_rectangle);
+}
+
+
+void GHOST_ImeWin32::UpdateImeWindow(HWND window_handle)
+{
+ /* Just move the IME window attached to the given window. */
+ if (caret_rect_.m_l >= 0 && caret_rect_.m_t >= 0) {
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ MoveImeWindow(window_handle, imm_context);
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+ }
+}
+
+
+void GHOST_ImeWin32::CleanupComposition(HWND window_handle)
+{
+ /**
+ * Notify the IMM attached to the given window to complete the ongoing
+ * composition, (this case happens when the given window is de-activated
+ * while composing a text and re-activated), and reset the omposition status.
+ */
+ if (is_composing_) {
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ ::ImmNotifyIME(imm_context, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+ ResetComposition(window_handle);
+ }
+}
+
+
+void GHOST_ImeWin32::CheckFirst(HWND window_handle)
+{
+ if (is_first) {
+ this->EndIME(window_handle);
+ is_first = false;
+ }
+}
+
+
+void GHOST_ImeWin32::ResetComposition(HWND window_handle)
+{
+ /* Currently, just reset the composition status. */
+ is_composing_ = false;
+}
+
+
+void GHOST_ImeWin32::CompleteComposition(HWND window_handle, HIMC imm_context)
+{
+ /**
+ * We have to confirm there is an ongoing composition before completing it.
+ * This is for preventing some IMEs from getting confused while completing an
+ * ongoing composition even if they do not have any ongoing compositions.)
+ */
+ if (is_composing_) {
+ ::ImmNotifyIME(imm_context, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
+ ResetComposition(window_handle);
+ }
+}
+
+
+void GHOST_ImeWin32::GetCaret(HIMC imm_context, LPARAM lparam, ImeComposition *composition)
+{
+ /**
+ * This operation is optional and language-dependent because the caret
+ * style is depended on the language, e.g.:
+ * * Korean IMEs: the caret is a blinking block,
+ * (It contains only one hangul character);
+ * * Chinese IMEs: the caret is a blinking line,
+ * (i.e. they do not need to retrieve the target selection);
+ * * Japanese IMEs: the caret is a selection (or underlined) block,
+ * (which can contain one or more Japanese characters).
+ */
+ int target_start = -1;
+ int target_end = -1;
+ switch (PRIMARYLANGID(input_language_id_)) {
+ case LANG_KOREAN:
+ if (lparam & CS_NOMOVECARET) {
+ target_start = 0;
+ target_end = 1;
+ }
+ break;
+ case LANG_CHINESE:
+ {
+ int clause_size = ImmGetCompositionStringW(imm_context, GCS_COMPCLAUSE, NULL, 0);
+ if (clause_size) {
+ static std::vector<unsigned long> clauses;
+ clause_size = clause_size / sizeof(clauses[0]);
+ clauses.resize(clause_size);
+ ImmGetCompositionStringW(imm_context, GCS_COMPCLAUSE, &clauses[0],
+ sizeof(clauses[0]) *clause_size);
+ if (composition->cursor_position == composition->ime_string.size()) {
+ target_start = clauses[clause_size - 2];
+ target_end = clauses[clause_size - 1];
+ }
+ else {
+ for (int i = 0; i < clause_size - 1; i++) {
+ if (clauses[i] == composition->cursor_position) {
+ target_start = clauses[i];
+ target_end = clauses[i + 1];
+ break;
+ }
+ }
+ }
+ }
+ else {
+ if (composition->cursor_position != -1) {
+ target_start = composition->cursor_position;
+ target_end = composition->ime_string.size();
+ }
+ }
+ break;
+ }
+ case LANG_JAPANESE:
+
+ /**
+ * For Japanese IMEs, the robustest way to retrieve the caret
+ * is scanning the attribute of the latest composition string and
+ * retrieving the begining and the end of the target clause, i.e.
+ * a clause being converted.
+ */
+ if (lparam & GCS_COMPATTR) {
+ int attribute_size = ::ImmGetCompositionStringW(imm_context,
+ GCS_COMPATTR,
+ NULL, 0);
+ if (attribute_size > 0) {
+ char *attribute_data = new char[attribute_size];
+ if (attribute_data) {
+ ::ImmGetCompositionStringW(imm_context, GCS_COMPATTR,
+ attribute_data, attribute_size);
+ for (target_start = 0; target_start < attribute_size;
+ ++target_start) {
+ if (IsTargetAttribute(attribute_data[target_start]))
+ break;
+ }
+ for (target_end = target_start; target_end < attribute_size;
+ ++target_end) {
+ if (!IsTargetAttribute(attribute_data[target_end]))
+ break;
+ }
+ if (target_start == attribute_size) {
+ /**
+ * This composition clause does not contain any target clauses,
+ * i.e. this clauses is an input clause.
+ * We treat whole this clause as a target clause.
+ */
+ target_end = target_start;
+ target_start = 0;
+ }
+ if (target_start != -1 && target_start < attribute_size &&
+ attribute_data[target_start] == ATTR_TARGET_NOTCONVERTED)
+ {
+ composition->cursor_position = target_start;
+ }
+ }
+ delete[] attribute_data;
+ }
+ }
+ break;
+ }
+ composition->target_start = target_start;
+ composition->target_end = target_end;
+}
+
+
+bool GHOST_ImeWin32::GetString(HIMC imm_context, WPARAM lparam, int type, ImeComposition *composition)
+{
+ bool result = false;
+ if (lparam & type) {
+ int string_size = ::ImmGetCompositionStringW(imm_context, type, NULL, 0);
+ if (string_size > 0) {
+ int string_length = string_size / sizeof(wchar_t);
+ wchar_t *string_data = new wchar_t[string_length + 1];
+ string_data[string_length] = '\0';
+ if (string_data) {
+ /* Fill the given ImeComposition object. */
+ ::ImmGetCompositionStringW(imm_context, type,
+ string_data, string_size);
+ composition->string_type = type;
+ composition->ime_string = string_data;
+ result = true;
+ }
+ delete[] string_data;
+ }
+ }
+ return result;
+}
+
+
+bool GHOST_ImeWin32::GetResult(HWND window_handle, LPARAM lparam, ImeComposition *composition)
+{
+ bool result = false;
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ /* Copy the result string to the ImeComposition object. */
+ result = GetString(imm_context, lparam, GCS_RESULTSTR, composition);
+ /**
+ * Reset all the other parameters because a result string does not
+ * have composition attributes.
+ */
+ composition->cursor_position = -1;
+ composition->target_start = -1;
+ composition->target_end = -1;
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+ return result;
+}
+
+
+bool GHOST_ImeWin32::GetComposition(HWND window_handle, LPARAM lparam, ImeComposition *composition)
+{
+ bool result = false;
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ /* Copy the composition string to the ImeComposition object. */
+ result = GetString(imm_context, lparam, GCS_COMPSTR, composition);
+
+ /* Retrieve the cursor position in the IME composition. */
+ int cursor_position = ::ImmGetCompositionStringW(imm_context, GCS_CURSORPOS, NULL, 0);
+ composition->cursor_position = cursor_position;
+ composition->target_start = -1;
+ composition->target_end = -1;
+
+ /* Retrieve the target selection and Update the ImeComposition object. */
+ GetCaret(imm_context, lparam, composition);
+
+ /* Mark that there is an ongoing composition. */
+ is_composing_ = true;
+
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+ return result;
+}
+
+
+void GHOST_ImeWin32::EndIME(HWND window_handle)
+{
+ /**
+ * A renderer process have moved its input focus to a password input
+ * when there is an ongoing composition, e.g. a user has clicked a
+ * mouse button and selected a password input while composing a text.
+ * For this case, we have to complete the ongoing composition and
+ * clean up the resources attached to this object BEFORE DISABLING THE IME.
+ */
+ if (!is_enable) return;
+ is_enable = false;
+ CleanupComposition(window_handle);
+ ::ImmAssociateContextEx(window_handle, NULL, 0);
+ eventImeData.composite_len = 0;
+}
+
+
+void GHOST_ImeWin32::BeginIME(HWND window_handle, const GHOST_Rect &caret_rect, bool complete)
+{
+ if (is_enable && complete) return;
+ is_enable = true;
+ /**
+ * Load the default IME context.
+ * NOTE(hbono)
+ * IMM ignores this call if the IME context is loaded. Therefore, we do
+ * not have to check whether or not the IME context is loaded.
+ */
+ ::ImmAssociateContextEx(window_handle, NULL, IACE_DEFAULT);
+ /* Complete the ongoing composition and move the IME windows. */
+ HIMC imm_context = ::ImmGetContext(window_handle);
+ if (imm_context) {
+ if (complete) {
+ /**
+ * A renderer process have moved its input focus to another edit
+ * control when there is an ongoing composition, e.g. a user has
+ * clicked a mouse button and selected another edit control while
+ * composing a text.
+ * For this case, we have to complete the ongoing composition and
+ * hide the IME windows BEFORE MOVING THEM.
+ */
+ CompleteComposition(window_handle, imm_context);
+ }
+ /**
+ * Save the caret position, and Update the position of the IME window.
+ * This update is used for moving an IME window when a renderer process
+ * resize/moves the input caret.
+ */
+ if (caret_rect.m_l >= 0 && caret_rect.m_t >= 0) {
+ caret_rect_ = caret_rect;
+ MoveImeWindow(window_handle, imm_context);
+ }
+ ::ImmReleaseContext(window_handle, imm_context);
+ }
+}
+
+
+static void convert_utf16_to_utf8_len(std::wstring s, int &len)
+{
+ if (len >= 0 && len <= s.size())
+ len = count_utf_8_from_16(s.substr(0, len).c_str()) - 1;
+ else
+ len = -1;
+}
+
+
+static size_t updateUtf8Buf(ImeComposition &info)
+{
+ size_t len = count_utf_8_from_16(info.ime_string.c_str());
+ info.utf8_buf.resize(len);
+ conv_utf_16_to_8(info.ime_string.c_str(), &info.utf8_buf[0], len);
+ convert_utf16_to_utf8_len(info.ime_string, info.cursor_position);
+ convert_utf16_to_utf8_len(info.ime_string, info.target_start);
+ convert_utf16_to_utf8_len(info.ime_string, info.target_end);
+ return len - 1;
+}
+
+
+void GHOST_ImeWin32::UpdateInfo(HWND window_handle)
+{
+ int res = this->GetResult(window_handle, GCS_RESULTSTR, &resultInfo);
+ int comp = this->GetComposition(window_handle, GCS_COMPSTR | GCS_COMPATTR, &compInfo);
+ /* convert wchar to utf8 */
+ if (res) {
+ eventImeData.result_len = (GHOST_TUserDataPtr)updateUtf8Buf(resultInfo);
+ eventImeData.result = &resultInfo.utf8_buf[0];
+ }
+ else {
+ eventImeData.result = 0;
+ eventImeData.result_len = 0;
+ }
+ if (comp) {
+ eventImeData.composite_len = (GHOST_TUserDataPtr)updateUtf8Buf(compInfo);
+ eventImeData.composite = &compInfo.utf8_buf[0];
+ eventImeData.cursor_position = compInfo.cursor_position;
+ eventImeData.target_start = compInfo.target_start;
+ eventImeData.target_end = compInfo.target_end;
+ }
+ else {
+ eventImeData.composite = 0;
+ eventImeData.composite_len = 0;
+ eventImeData.cursor_position = -1;
+ eventImeData.target_start = -1;
+ eventImeData.target_end = -1;
+ }
+}
diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h
new file mode 100644
index 00000000000..5b2d71875e8
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ImeWin32.h
@@ -0,0 +1,401 @@
+/*
+ * ***** 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) 2010 The Chromium Authors. All rights reserved.
+ * All rights reserved.
+ *
+ * The Original Code is: some of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+
+/** \file ghost/intern/GHOST_ImeWin32.h
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_IME_H__
+#define __GHOST_IME_H__
+
+#include <windows.h>
+
+#include <string>
+
+#include "GHOST_Event.h"
+#include "GHOST_Rect.h"
+#include <vector>
+
+class GHOST_EventIME : public GHOST_Event
+{
+public:
+ /**
+ * Constructor.
+ * \param msec The time this event was generated.
+ * \param type The type of key event.
+ * \param key The key code of the key.
+ */
+ GHOST_EventIME(GHOST_TUns64 msec,
+ GHOST_TEventType type,
+ GHOST_IWindow *window, void *customdata)
+ : GHOST_Event(msec, type, window)
+ {
+ this->m_data = customdata;
+ }
+
+};
+
+
+/**
+ * This header file defines a struct and a class used for encapsulating IMM32
+ * APIs, controls IMEs attached to a window, and enables the 'on-the-spot'
+ * input without deep knowledge about the APIs, i.e. knowledge about the
+ * language-specific and IME-specific behaviors.
+ * The following items enumerates the simplest steps for an (window)
+ * application to control its IMEs with the struct and the class defined
+ * this file.
+ * 1. Add an instance of the GHOST_ImeWin32 class to its window class.
+ * (The GHOST_ImeWin32 class needs a window handle.)
+ * 2. Add messages handlers listed in the following subsections, follow the
+ * instructions written in each subsection, and use the GHOST_ImeWin32 class.
+ * 2.1. WM_IME_SETCONTEXT (0x0281)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::CreateImeWindow();
+ * - GHOST_ImeWin32::CleanupComposition(), and;
+ * - GHOST_ImeWin32::SetImeWindowStyle().
+ * An application MUST prevent from calling ::DefWindowProc().
+ * 2.2. WM_IME_STARTCOMPOSITION (0x010D)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::CreateImeWindow(), and;
+ * - GHOST_ImeWin32::ResetComposition().
+ * An application MUST prevent from calling ::DefWindowProc().
+ * 2.3. WM_IME_COMPOSITION (0x010F)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::UpdateImeWindow();
+ * - GHOST_ImeWin32::GetResult();
+ * - GHOST_ImeWin32::GetComposition(), and;
+ * - GHOST_ImeWin32::ResetComposition() (optional).
+ * An application MUST prevent from calling ::DefWindowProc().
+ * 2.4. WM_IME_ENDCOMPOSITION (0x010E)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::ResetComposition(), and;
+ * - GHOST_ImeWin32::DestroyImeWindow().
+ * An application CAN call ::DefWindowProc().
+ * 2.5. WM_INPUTLANGCHANGE (0x0051)
+ * Call the functions listed below:
+ * - GHOST_ImeWin32::SetInputLanguage().
+ * An application CAN call ::DefWindowProc().
+ */
+
+/* This struct represents the status of an ongoing composition. */
+struct ImeComposition {
+ /* Represents the cursor position in the IME composition. */
+ int cursor_position;
+
+ /* Represents the position of the beginning of the selection */
+ int target_start;
+
+ /* Represents the position of the end of the selection */
+ int target_end;
+
+ /**
+ * Represents the type of the string in the 'ime_string' parameter.
+ * Its possible values and description are listed below:
+ * Value Description
+ * 0 The parameter is not used.
+ * GCS_RESULTSTR The parameter represents a result string.
+ * GCS_COMPSTR The parameter represents a composition string.
+ */
+ int string_type;
+
+ /* Represents the string retrieved from IME (Input Method Editor) */
+ std::wstring ime_string;
+ std::vector<char> utf8_buf;
+ std::vector<unsigned char> format;
+};
+
+/**
+ * This class controls the IMM (Input Method Manager) through IMM32 APIs and
+ * enables it to retrieve the string being controled by the IMM. (I wrote
+ * a note to describe the reason why I do not use 'IME' but 'IMM' below.)
+ * NOTE(hbono):
+ * Fortunately or unfortunately, TSF (Text Service Framework) and
+ * CUAS (Cicero Unaware Application Support) allows IMM32 APIs for
+ * retrieving not only the inputs from IMEs (Input Method Editors), used
+ * only for inputting East-Asian language texts, but also the ones from
+ * tablets (on Windows XP Tablet PC Edition and Windows Vista), voice
+ * recognizers (e.g. ViaVoice and Microsoft Office), etc.
+ * We can disable TSF and CUAS in Windows XP Tablet PC Edition. On the other
+ * hand, we can NEVER disable either TSF or CUAS in Windows Vista, i.e.
+ * THIS CLASS IS NOT ONLY USED ON THE INPUT CONTEXTS OF EAST-ASIAN
+ * LANGUAGES BUT ALSO USED ON THE INPUT CONTEXTS OF ALL LANGUAGES.
+ */
+class GHOST_ImeWin32 {
+public:
+ GHOST_ImeWin32();
+ ~GHOST_ImeWin32();
+
+ /* Retrieves whether or not there is an ongoing composition. */
+ bool is_composing() const {return is_composing_;}
+
+ /**
+ * Retrieves the input language from Windows and update it.
+ * Return values
+ * * true
+ * The given input language has IMEs.
+ * * false
+ * The given input language does not have IMEs.
+ */
+ bool SetInputLanguage();
+
+ /**
+ * Create the IME windows, and allocate required resources for them.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void CreateImeWindow(HWND window_handle);
+
+ /**
+ * Update the style of the IME windows.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ * * message [in] (UINT)
+ * * wparam [in] (WPARAM)
+ * * lparam [in] (LPARAM)
+ * Represent the windows message of the caller.
+ * These parameters are used for verifying if this function is called
+ * in a handler function for WM_IME_SETCONTEXT messages because this
+ * function uses ::DefWindowProc() to update the style.
+ * A caller just has to pass the input parameters for the handler
+ * function without modifications.
+ * * handled [out] (BOOL*)
+ * Returns ::DefWindowProc() is really called in this function.
+ * PLEASE DO NOT CALL ::DefWindowProc() IF THIS VALUE IS TRUE!
+ * All the window styles set in this function are over-written when
+ * calling ::DefWindowProc() after returning this function.
+ */
+ void SetImeWindowStyle(HWND window_handle, UINT message,
+ WPARAM wparam, LPARAM lparam, BOOL* handled);
+
+ /**
+ * Destroy the IME windows and all the resources attached to them.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void DestroyImeWindow(HWND window_handle);
+
+ /**
+ * Update the position of the IME windows.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void UpdateImeWindow(HWND window_handle);
+
+ /**
+ * Clean up the all resources attached to the given GHOST_ImeWin32 object, and
+ * reset its composition status.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void CleanupComposition(HWND window_handle);
+
+ /**
+ * Reset the composition status.
+ * Cancel the ongoing composition if it exists.
+ * NOTE(hbono): This method does not release the allocated resources.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void ResetComposition(HWND window_handle);
+
+ /**
+ * Retrieve a composition result of the ongoing composition if it exists.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ * * lparam [in] (LPARAM)
+ * Specifies the updated members of the ongoing composition, and must be
+ * the same parameter of a WM_IME_COMPOSITION message handler.
+ * This parameter is used for checking if the ongoing composition has
+ * its result string,
+ * * composition [out] (ImeComposition)
+ * Represents the struct contains the composition result.
+ * Return values
+ * * true
+ * The ongoing composition has a composition result.
+ * * false
+ * The ongoing composition does not have composition results.
+ * Remarks
+ * This function is designed for being called from WM_IME_COMPOSITION
+ * message handlers.
+ */
+ bool GetResult(HWND window_handle, LPARAM lparam,
+ ImeComposition* composition);
+
+ /**
+ * Retrieve the current composition status of the ongoing composition.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ * * lparam [in] (LPARAM)
+ * Specifies the updated members of the ongoing composition, and must be
+ * the same parameter of a WM_IME_COMPOSITION message handler.
+ * This parameter is used for checking if the ongoing composition has
+ * its result string,
+ * * composition [out] (ImeComposition)
+ * Represents the struct contains the composition status.
+ * Return values
+ * * true
+ * The status of the ongoing composition is updated.
+ * * false
+ * The status of the ongoing composition is not updated.
+ * Remarks
+ * This function is designed for being called from WM_IME_COMPOSITION
+ * message handlers.
+ */
+ bool GetComposition(HWND window_handle, LPARAM lparam,
+ ImeComposition* composition);
+
+ /**
+ * Enable the IME attached to the given window, i.e. allows user-input
+ * events to be dispatched to the IME.
+ * In Chrome, this function is used when:
+ * * a renderer process moves its input focus to another edit control, or;
+ * * a renrerer process moves the position of the focused edit control.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ * * caret_rect [in] (const gfx::Rect&)
+ * Represent the rectangle of the input caret.
+ * This rectangle is used for controlling the positions of IME windows.
+ * * complete [in] (bool)
+ * Represents whether or not to complete the ongoing composition.
+ * + true
+ * After finishing the ongoing composition and close its IME windows,
+ * start another composition and display its IME windows to the given
+ * position.
+ * + false
+ * Just move the IME windows of the ongoing composition to the given
+ * position without finishing it.
+ */
+ void BeginIME(HWND window_handle,
+ const GHOST_Rect& caret_rect,
+ bool complete);
+
+ /**
+ * Disable the IME attached to the given window, i.e. prohibits any user-input
+ * events from being dispatched to the IME.
+ * In Chrome, this function is used when:
+ * * a renreder process sets its input focus to a password input.
+ * Parameters
+ * * window_handle [in] (HWND)
+ * Represents the window handle of the caller.
+ */
+ void EndIME(HWND window_handle);
+
+ /* Updatg resultInfo and compInfo */
+ void UpdateInfo(HWND window_handle);
+
+ /* disable ime when start up */
+ void CheckFirst(HWND window_handle);
+
+ ImeComposition resultInfo, compInfo;
+ GHOST_TEventImeData eventImeData;
+
+protected:
+ /* Determines whether or not the given attribute represents a target (a.k.a. a selection). */
+ bool IsTargetAttribute(char attribute) const {
+ return (attribute == ATTR_TARGET_CONVERTED ||
+ attribute == ATTR_TARGET_NOTCONVERTED);
+ }
+
+ /* Retrieve the target area. */
+ void GetCaret(HIMC imm_context, LPARAM lparam,
+ ImeComposition* composition);
+
+ /* Update the position of the IME windows. */
+ void MoveImeWindow(HWND window_handle, HIMC imm_context);
+
+ /* Complete the ongoing composition if it exists. */
+ void CompleteComposition(HWND window_handle, HIMC imm_context);
+
+ /* Retrieve a string from the IMM. */
+ bool GetString(HIMC imm_context, WPARAM lparam, int type,
+ ImeComposition* composition);
+
+private:
+ /**
+ * Represents whether or not there is an ongoing composition in a browser
+ * process, i.e. whether or not a browser process is composing a text.
+ */
+ bool is_composing_;
+
+ /**
+ * This value represents whether or not the current input context has IMEs.
+ * The following table shows the list of IME status:
+ * Value Description
+ * false The current input language does not have IMEs.
+ * true The current input language has IMEs.
+ */
+ bool ime_status_;
+
+ /**
+ * The current input Language ID retrieved from Windows, which consists of:
+ * * Primary Language ID (bit 0 to bit 9), which shows a natunal language
+ * (English, Korean, Chinese, Japanese, etc.) and;
+ * * Sub-Language ID (bit 10 to bit 15), which shows a geometrical region
+ * the language is spoken (For English, United States, United Kingdom,
+ * Australia, Canada, etc.)
+ * The following list enumerates some examples for the Language ID:
+ * * "en-US" (0x0409)
+ * MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
+ * * "ko-KR" (0x0412)
+ * MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN);
+ * * "zh-TW" (0x0404)
+ * MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL);
+ * * "zh-CN" (0x0804)
+ * MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);
+ * * "ja-JP" (0x0411)
+ * MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), etc.
+ * (See <winnt.h> for other available values.)
+ * This Language ID is used for processing language-specific operations in
+ * IME functions.
+ */
+ LANGID input_language_id_;
+
+ /**
+ * Represents whether or not the current input context has created a system
+ * caret to set the position of its IME candidate window.
+ * * true: it creates a system caret.
+ * * false: it does not create a system caret.
+ */
+ bool system_caret_;
+
+ /* The rectangle of the input caret retrieved from a renderer process. */
+ GHOST_Rect caret_rect_;
+
+ /* used for disable ime when start up */
+ bool is_first, is_enable;
+};
+
+#endif * __GHOST_IME_H__
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index 9bd6226d5c2..27285e49e9e 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -146,8 +146,8 @@ static const NDOF_ButtonT SpaceExplorer_HID_map[] = {
NDOF_BUTTON_ROTATE
};
-/* this is the older SpacePilot (sans Pro)
- * thanks to polosson for info about this device */
+// this is the older SpacePilot (sans Pro)
+// thanks to polosson for info about this device
static const NDOF_ButtonT SpacePilot_HID_map[] = {
NDOF_BUTTON_1,
NDOF_BUTTON_2,
@@ -190,17 +190,17 @@ 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.0f)
+ : 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:
@@ -228,7 +228,7 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
// that I don't have access to. Thanks!
switch (vendor_id) {
- case 0x046D: // Logitech (3Dconnexion)
+ case 0x046D: // Logitech (3Dconnexion was a subsidiary)
switch (product_id) {
// -- current devices --
case 0xC626: // full-size SpaceNavigator
@@ -281,6 +281,29 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
printf("ndof: unknown Logitech product %04hx\n", product_id);
}
break;
+ case 0x256F: // 3Dconnexion
+ switch (product_id) {
+ case 0xC62E: // plugged in
+ case 0xC62F: // wireless
+ puts("ndof: using SpaceMouse Wireless");
+ m_deviceType = NDOF_SpaceMouseWireless;
+ m_buttonCount = 2;
+ m_hidMap = Modern3Dx_HID_map;
+ break;
+ case 0xC631: // plugged in
+ case 0xC632: // wireless
+ puts("ndof: using SpaceMouse Pro Wireless");
+ m_deviceType = NDOF_SpaceMouseProWireless;
+ m_buttonCount = 27;
+ // ^^ actually has 15 buttons, but their HID codes range from 0 to 26
+ m_buttonMask = 0x07C0F137;
+ m_hidMap = Modern3Dx_HID_map;
+ break;
+
+ default:
+ printf("ndof: unknown 3Dconnexion product %04hx\n", product_id);
+ }
+ break;
default:
printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id);
}
@@ -390,9 +413,9 @@ void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time)
void GHOST_NDOFManager::setDeadZone(float dz)
{
- if (dz < 0.f) {
+ if (dz < 0.0f) {
// negative values don't make sense, so clamp at zero
- dz = 0.f;
+ dz = 0.0f;
}
else if (dz > 0.5f) {
// warn the rogue user/developer, but allow it
@@ -405,14 +428,14 @@ void GHOST_NDOFManager::setDeadZone(float dz)
static bool atHomePosition(GHOST_TEventNDOFMotionData *ndof)
{
-#define HOME(foo) (ndof->foo == 0.f)
+#define HOME(foo) (ndof->foo == 0.0f)
return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz);
#undef HOME
}
static bool nearHomePosition(GHOST_TEventNDOFMotionData *ndof, float threshold)
{
- if (threshold == 0.f) {
+ if (threshold == 0.0f) {
return atHomePosition(ndof);
}
else {
@@ -442,7 +465,7 @@ bool GHOST_NDOFManager::sendMotionEvent()
// scale axis values here to normalize them to around +/- 1
// they are scaled again for overall sensitivity in the WM based on user prefs
- const float scale = 1.f / 350.f; // 3Dconnexion devices send +/- 350 usually
+ const float scale = 1.0f / 350.0f; // 3Dconnexion devices send +/- 350 usually
data->tx = scale * m_translation[0];
data->ty = scale * m_translation[1];
diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h
index 0b2080e36a9..48a4881afb1 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.h
+++ b/intern/ghost/intern/GHOST_NDOFManager.h
@@ -20,7 +20,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-
+
#ifndef __GHOST_NDOFMANAGER_H__
#define __GHOST_NDOFMANAGER_H__
@@ -38,6 +38,8 @@ typedef enum {
NDOF_SpaceExplorer,
NDOF_SpacePilotPro,
NDOF_SpaceMousePro,
+ NDOF_SpaceMouseWireless,
+ NDOF_SpaceMouseProWireless,
// older devices
NDOF_SpacePilot,
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index cfa1e8bf566..3ce9a4b9576 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -205,6 +205,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
return GHOST_kKeyUnknown;
default:
+ {
/* alphanumerical or punctuation key that is remappable in int'l keyboards */
if ((recvChar >= 'A') && (recvChar <= 'Z')) {
return (GHOST_TKey) (recvChar - 'A' + GHOST_kKeyA);
@@ -213,27 +214,25 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
return (GHOST_TKey) (recvChar - 'a' + GHOST_kKeyA);
}
else {
-
- /* Leopard and Snow Leopard 64bit compatible API*/
- CFDataRef uchrHandle; /*the keyboard layout*/
- TISInputSourceRef kbdTISHandle;
-
- kbdTISHandle = TISCopyCurrentKeyboardLayoutInputSource();
- uchrHandle = (CFDataRef)TISGetInputSourceProperty(kbdTISHandle,kTISPropertyUnicodeKeyLayoutData);
- CFRelease(kbdTISHandle);
-
- /*get actual character value of the "remappable" keys in int'l keyboards,
- if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
- then fallback on using the received charactersIgnoringModifiers */
- if (uchrHandle)
- {
- UInt32 deadKeyState=0;
- UniCharCount actualStrLength=0;
+ /* Leopard and Snow Leopard 64bit compatible API*/
+ CFDataRef uchrHandle; /*the keyboard layout*/
+ TISInputSourceRef kbdTISHandle;
- UCKeyTranslate((UCKeyboardLayout*)CFDataGetBytePtr(uchrHandle), rawCode, keyAction, 0,
- LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
+ kbdTISHandle = TISCopyCurrentKeyboardLayoutInputSource();
+ uchrHandle = (CFDataRef)TISGetInputSourceProperty(kbdTISHandle,kTISPropertyUnicodeKeyLayoutData);
+ CFRelease(kbdTISHandle);
- }
+ /*get actual character value of the "remappable" keys in int'l keyboards,
+ if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
+ then fallback on using the received charactersIgnoringModifiers */
+ if (uchrHandle) {
+ UInt32 deadKeyState=0;
+ UniCharCount actualStrLength=0;
+
+ UCKeyTranslate((UCKeyboardLayout*)CFDataGetBytePtr(uchrHandle), rawCode, keyAction, 0,
+ LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
+
+ }
switch (recvChar) {
case '-': return GHOST_kKeyMinus;
@@ -251,10 +250,29 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
return GHOST_kKeyUnknown;
}
}
+ }
}
return GHOST_kKeyUnknown;
}
+#pragma mark Utility functions
+
+#define FIRSTFILEBUFLG 512
+static bool g_hasFirstFile = false;
+static char g_firstFileBuf[512];
+
+//TODO:Need to investigate this. Function called too early in creator.c to have g_hasFirstFile == true
+extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG])
+{
+ if (g_hasFirstFile) {
+ strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1);
+ buf[FIRSTFILEBUFLG - 1] = '\0';
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
#pragma mark Cocoa objects
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 0767ad5a8f9..4247c4f31ce 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -508,6 +508,7 @@ GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const &raw
//! note: this function can be extended to include other exotic cases as they arise.
// This function was added in response to bug [#25715]
+// This is going to be a long list [T42426]
GHOST_TKey GHOST_SystemWin32::processSpecialKey(GHOST_IWindow *window, short vKey, short scanCode) const
{
GHOST_TKey key = GHOST_kKeyUnknown;
@@ -515,6 +516,10 @@ GHOST_TKey GHOST_SystemWin32::processSpecialKey(GHOST_IWindow *window, short vKe
case LANG_FRENCH:
if (vKey == VK_OEM_8) key = GHOST_kKeyF13; // oem key; used purely for shortcuts .
break;
+ case LANG_ENGLISH:
+ if (SUBLANGID(m_langId) == SUBLANG_ENGLISH_UK && vKey == VK_OEM_8) // "`¬"
+ key = GHOST_kKeyAccentGrave;
+ break;
}
return key;
@@ -787,6 +792,15 @@ GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_
return new GHOST_Event(system->getMilliSeconds(), type, window);
}
+#ifdef WITH_INPUT_IME
+GHOST_Event *GHOST_SystemWin32::processImeEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TEventImeData *data)
+{
+ GHOST_System *system = (GHOST_System *)getSystem();
+ return new GHOST_EventIME(system->getMilliSeconds(), type, window, data);
+}
+#endif
+
+
GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(
GHOST_TEventType eventType,
GHOST_TDragnDropTypes draggedObjectType,
@@ -899,6 +913,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
LRESULT lResult = 0;
GHOST_SystemWin32 *system = ((GHOST_SystemWin32 *)getSystem());
+ GHOST_EventManager *eventManager = system->getEventManager();
GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized");
if (hwnd) {
@@ -907,8 +922,13 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
switch (msg) {
// we need to check if new key layout has AltGr
case WM_INPUTLANGCHANGE:
+ {
system->handleKeyboardChange();
+#ifdef WITH_INPUT_IME
+ window->getImeInput()->SetInputLanguage();
+#endif
break;
+ }
////////////////////////////////////////////////////////////////////////
// Keyboard events, processed
////////////////////////////////////////////////////////////////////////
@@ -944,6 +964,56 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
}
+#ifdef WITH_INPUT_IME
+ ////////////////////////////////////////////////////////////////////////
+ // IME events, processed, read more in GHOST_IME.h
+ ////////////////////////////////////////////////////////////////////////
+ case WM_IME_SETCONTEXT:
+ {
+ window->getImeInput()->SetInputLanguage();
+ window->getImeInput()->CreateImeWindow(window->getHWND());
+ window->getImeInput()->CleanupComposition(window->getHWND());
+ window->getImeInput()->CheckFirst(window->getHWND());
+ break;
+ }
+ case WM_IME_STARTCOMPOSITION:
+ {
+ eventHandled = true;
+ /* remove input event before start comp event, avoid redundant input */
+ eventManager->removeTypeEvents(GHOST_kEventKeyDown, window);
+ window->getImeInput()->CreateImeWindow(window->getHWND());
+ window->getImeInput()->ResetComposition(window->getHWND());
+ event = processImeEvent(
+ GHOST_kEventImeCompositionStart,
+ window,
+ &window->getImeInput()->eventImeData);
+ break;
+ }
+ case WM_IME_COMPOSITION:
+ {
+ eventHandled = true;
+ window->getImeInput()->UpdateImeWindow(window->getHWND());
+ window->getImeInput()->UpdateInfo(window->getHWND());
+ event = processImeEvent(
+ GHOST_kEventImeComposition,
+ window,
+ &window->getImeInput()->eventImeData);
+ break;
+ }
+ case WM_IME_ENDCOMPOSITION:
+ {
+ eventHandled = true;
+ /* remove input event after end comp event, avoid redundant input */
+ eventManager->removeTypeEvents(GHOST_kEventKeyDown, window);
+ window->getImeInput()->ResetComposition(window->getHWND());
+ window->getImeInput()->DestroyImeWindow(window->getHWND());
+ event = processImeEvent(
+ GHOST_kEventImeCompositionEnd,
+ window,
+ &window->getImeInput()->eventImeData);
+ break;
+ }
+#endif /* WITH_INPUT_IME */
////////////////////////////////////////////////////////////////////////
// Keyboard events, ignored
////////////////////////////////////////////////////////////////////////
@@ -1060,17 +1130,13 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
/* 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);
+ HWND mouse_hwnd = ChildWindowFromPoint(HWND_DESKTOP, 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 -
- */
+ /* Happens when wmouse is not over of any of blender windows. */
event = processWheelEvent(window, wParam, lParam);
}
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 79fed06c6a5..cb3b8ee3cfc 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -307,6 +307,15 @@ protected:
static GHOST_Event *processWindowEvent(GHOST_TEventType type, GHOST_IWindow *window);
/**
+ * Creates a IME event.
+ * \param type The type of event to create.
+ * \param window The window receiving the event (the active window).
+ * \param data IME data.
+ * \return The event created.
+ */
+ static GHOST_Event *processImeEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TEventImeData *data);
+
+ /**
* Handles minimum window size.
* \param minmax The MINMAXINFO structure.
*/
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 15b81998aab..ac31c54666b 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -295,6 +295,22 @@ public:
return 1.0f;
}
+#ifdef WITH_INPUT_IME
+ virtual void beginIME(GHOST_TInt32 x,
+ GHOST_TInt32 y,
+ GHOST_TInt32 w,
+ GHOST_TInt32 h,
+ int completed)
+ {
+ /* do nothing temporarily if not in windows */
+ }
+
+ virtual void endIME()
+ {
+ /* do nothing temporarily if not in windows */
+ }
+#endif /* WITH_INPUT_IME */
+
protected:
/**
* Tries to install a rendering context in this window.
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index ab313b06f66..65d371c8ca8 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -645,6 +645,8 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
m_lionStyleFullScreen = true;
}
+ [NSApp activateIgnoringOtherApps:YES]; // raise application to front, important for new blender instance animation play case
+
[pool drain];
}
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 64ea7192616..4e384881f2c 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -1050,3 +1050,16 @@ GHOST_TSuccess GHOST_WindowWin32::endProgressBar()
return GHOST_kFailure;
}
+
+#ifdef WITH_INPUT_IME
+void GHOST_WindowWin32::beginIME(GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed)
+{
+ this->getImeInput()->BeginIME(this->getHWND(), GHOST_Rect(x, y - h , x, y), (bool)completed);
+}
+
+
+void GHOST_WindowWin32::endIME()
+{
+ this->getImeInput()->EndIME(this->getHWND());
+}
+#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index 7b12d8c583e..c4575d0f9b0 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -39,6 +39,9 @@
#include "GHOST_Window.h"
#include "GHOST_TaskbarWin32.h"
+#ifdef WITH_INPUT_IME
+# include "GHOST_ImeWin32.h"
+#endif
#include <wintab.h>
#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)
@@ -253,6 +256,17 @@ public:
/** if the window currently resizing */
bool m_inLiveResize;
+#ifdef WITH_INPUT_IME
+ GHOST_ImeWin32 *getImeInput() {return &m_imeImput;}
+
+ virtual void beginIME(
+ GHOST_TInt32 x, GHOST_TInt32 y,
+ GHOST_TInt32 w, GHOST_TInt32 h,
+ int completed);
+
+ virtual void endIME();
+#endif /* WITH_INPUT_IME */
+
private:
/**
@@ -339,6 +353,11 @@ private:
/** Hwnd to parent window */
GHOST_TEmbedderWindowID m_parentWindowHwnd;
+
+#ifdef WITH_INPUT_IME
+ /** Handle input method editors event */
+ GHOST_ImeWin32 m_imeImput;
+#endif
};
#endif // __GHOST_WINDOWWIN32_H__
diff --git a/intern/opennl/superlu/smemory.c b/intern/opennl/superlu/smemory.c
index a76f60a1758..c3b28a90e62 100644
--- a/intern/opennl/superlu/smemory.c
+++ b/intern/opennl/superlu/smemory.c
@@ -483,7 +483,7 @@ void
else lword = sizeof(double);
if ( Glu->MemModel == SYSTEM ) {
- new_mem = (void *) SUPERLU_MALLOC(new_len * lword);
+ new_mem = (void *) SUPERLU_MALLOC((size_t)new_len * (size_t)lword);
/* new_mem = (void *) calloc(new_len, lword); */
if ( no_expand != 0 ) {
tries = 0;
@@ -494,7 +494,7 @@ void
if ( ++tries > 10 ) return (NULL);
alpha = Reduce(alpha);
new_len = alpha * *prev_len;
- new_mem = (void *) SUPERLU_MALLOC(new_len * lword);
+ new_mem = (void *) SUPERLU_MALLOC((size_t)new_len * (size_t)lword);
/* new_mem = (void *) calloc(new_len, lword); */
}
}
@@ -509,7 +509,7 @@ void
} else { /* MemModel == USER */
if ( no_expand == 0 ) {
- new_mem = suser_malloc(new_len * lword, HEAD);
+ new_mem = suser_malloc((size_t)new_len * (size_t)lword, HEAD);
if ( NotDoubleAlign(new_mem) &&
(type == LUSUP || type == UCOL) ) {
old_mem = new_mem;
diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg
index ed5e84778f9..3408d729698 100644
--- a/release/datafiles/blender_icons.svg
+++ b/release/datafiles/blender_icons.svg
@@ -27,6 +27,137 @@
<defs
id="defs4">
<linearGradient
+ inkscape:collect="always"
+ id="linearGradient20043">
+ <stop
+ style="stop-color:#f6e18c;stop-opacity:1;"
+ offset="0"
+ id="stop20045" />
+ <stop
+ style="stop-color:#f6e18c;stop-opacity:0;"
+ offset="1"
+ id="stop20047" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient20020">
+ <stop
+ style="stop-color:#f6e18c;stop-opacity:1;"
+ offset="0"
+ id="stop20022" />
+ <stop
+ style="stop-color:#f6e18c;stop-opacity:0;"
+ offset="1"
+ id="stop20024" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18512">
+ <stop
+ id="stop18514"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop18516"
+ offset="1"
+ style="stop-color:#f20000;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18495"
+ inkscape:collect="always">
+ <stop
+ id="stop18497"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop18499"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18479"
+ inkscape:collect="always">
+ <stop
+ id="stop18481"
+ offset="0"
+ style="stop-color:#8d8d8d;stop-opacity:1;" />
+ <stop
+ id="stop18483"
+ offset="1"
+ style="stop-color:#8d8d8d;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient18414">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop18416" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop18418" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18370"
+ inkscape:collect="always">
+ <stop
+ id="stop18372"
+ offset="0"
+ style="stop-color:#afafaf;stop-opacity:1;" />
+ <stop
+ id="stop18374"
+ offset="1"
+ style="stop-color:#afafaf;stop-opacity:0;" />
+ </linearGradient>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path17576"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ <linearGradient
+ id="linearGradient17566"
+ inkscape:collect="always">
+ <stop
+ id="stop17568"
+ offset="0"
+ style="stop-color:#cad8ee;stop-opacity:1;" />
+ <stop
+ id="stop17570"
+ offset="1"
+ style="stop-color:#cad8ee;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient17560">
+ <stop
+ id="stop17562"
+ offset="0"
+ style="stop-color:#ffe991;stop-opacity:1;" />
+ <stop
+ id="stop17564"
+ offset="1"
+ style="stop-color:#ffe991;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient17542"
+ inkscape:collect="always">
+ <stop
+ id="stop17544"
+ offset="0"
+ style="stop-color:#799ed3;stop-opacity:1;" />
+ <stop
+ id="stop17546"
+ offset="1"
+ style="stop-color:#799ed3;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
id="linearGradient17265">
<stop
style="stop-color:#ffb769;stop-opacity:1;"
@@ -29053,6 +29184,392 @@
id="linearGradient17872"
xlink:href="#linearGradient319-36-40-2-4"
inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient23974-41">
+ <stop
+ id="stop23976-66"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-15"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-68">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-221" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-90" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-84">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-86" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-6" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9030-4">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-3" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-8">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-0" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-648" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16605">
+ <stop
+ id="stop16607"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop16609"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18105-1">
+ <stop
+ id="stop18107-7"
+ offset="0"
+ style="stop-color:#162d50;stop-opacity:1" />
+ <stop
+ id="stop18109-8"
+ offset="1"
+ style="stop-color:#1e3e70;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17542"
+ id="linearGradient18237"
+ gradientUnits="userSpaceOnUse"
+ x1="231.35262"
+ y1="465.73871"
+ x2="246.08743"
+ y2="465.14655"
+ gradientTransform="matrix(0.86988738,-0.49325039,0.49325039,0.86988738,0,0.02266763)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17566"
+ id="linearGradient18239"
+ gradientUnits="userSpaceOnUse"
+ x1="430.78629"
+ y1="290.24094"
+ x2="440.83713"
+ y2="286.97058" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-41"
+ id="linearGradient18243"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-142.53857,-4.802156)"
+ x1="107.39532"
+ y1="58.065113"
+ x2="127.70434"
+ y2="58.065113" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-68"
+ id="linearGradient18245"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.1000194,0,0,1.0998287,110.29549,-8.6726854)"
+ x1="30.389694"
+ y1="95.008034"
+ x2="65.52562"
+ y2="93.69249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-84"
+ id="linearGradient18247"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6,0)"
+ x1="483.00034"
+ y1="163"
+ x2="476.68781"
+ y2="162.85956" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-4"
+ id="linearGradient18249"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(342.00029,383.00889)"
+ x1="123.36729"
+ y1="-219.24783"
+ x2="134.30893"
+ y2="-218.00888" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-8"
+ id="linearGradient18251"
+ gradientUnits="userSpaceOnUse"
+ x1="475.00034"
+ y1="155"
+ x2="469.75034"
+ y2="155" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-41"
+ id="linearGradient18253"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(14.285126,-0.22103087)"
+ x1="442.81525"
+ y1="290.49384"
+ x2="436.5"
+ y2="290.5249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18105-1"
+ id="linearGradient18255"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.285126,-0.22097087)"
+ x1="445.99902"
+ y1="288.5"
+ x2="407.3793"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17560-4"
+ id="linearGradient18241-0"
+ gradientUnits="userSpaceOnUse"
+ x1="327.77432"
+ y1="251.04707"
+ x2="335.80118"
+ y2="247.0696" />
+ <linearGradient
+ id="linearGradient17560-4">
+ <stop
+ id="stop17562-3"
+ offset="0"
+ style="stop-color:#ffe991;stop-opacity:1;" />
+ <stop
+ id="stop17564-1"
+ offset="1"
+ style="stop-color:#ffe991;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18370"
+ id="linearGradient18368"
+ x1="432.83759"
+ y1="289.15814"
+ x2="441.44028"
+ y2="283.54819"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ y2="245.78732"
+ x2="335.8941"
+ y1="251.04707"
+ x1="327.77432"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient18313-9"
+ xlink:href="#linearGradient17560-4-9"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient17560-4-9">
+ <stop
+ id="stop17562-3-7"
+ offset="0"
+ style="stop-color:#ffe991;stop-opacity:1;" />
+ <stop
+ id="stop17564-1-4"
+ offset="1"
+ style="stop-color:#ffe991;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18414"
+ id="linearGradient18420"
+ x1="333.8428"
+ y1="253.4225"
+ x2="327.0369"
+ y2="243.12526"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18414-5"
+ id="linearGradient18420-1"
+ x1="333.8428"
+ y1="253.4225"
+ x2="327.0369"
+ y2="243.12526"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient18414-5">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop18416-8" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop18418-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18479"
+ id="linearGradient18476"
+ x1="427.86765"
+ y1="284.7648"
+ x2="431.31277"
+ y2="278.92789"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.46468729,2.0195829)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18495"
+ id="linearGradient18493"
+ x1="323.68958"
+ y1="248.71513"
+ x2="335.125"
+ y2="245.5"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20020"
+ id="linearGradient20026"
+ x1="331.22147"
+ y1="249.03816"
+ x2="336.11465"
+ y2="244.64084"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20043"
+ id="linearGradient20049"
+ x1="148.21956"
+ y1="506.48343"
+ x2="155.67555"
+ y2="506.45177"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ y2="30.023426"
+ x2="278.25537"
+ y1="3.6831069"
+ x1="253.78497"
+ gradientTransform="matrix(0.888889,0,0,1,513.5,184.50451)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient39254-5"
+ xlink:href="#linearGradient17555"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient17555">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.49803922;"
+ offset="0"
+ id="stop17557" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.49803922;"
+ offset="1"
+ id="stop17559" />
+ </linearGradient>
+ <radialGradient
+ r="6.9000001"
+ fy="206.40076"
+ fx="756.83508"
+ cy="206.40076"
+ cx="756.83508"
+ gradientTransform="matrix(0.3817213,-0.4377393,0.4780868,0.4169055,368.09749,451.76937)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient39256-9"
+ xlink:href="#linearGradient17549"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient17549">
+ <stop
+ id="stop17551"
+ offset="0"
+ style="stop-color:#7f7f7f;stop-opacity:1;" />
+ <stop
+ id="stop17553"
+ offset="1"
+ style="stop-color:#7f7f7f;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ y2="249"
+ x2="93.0625"
+ y1="241.125"
+ x1="87"
+ gradientTransform="translate(670,-33)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient39258-0"
+ xlink:href="#linearGradient17543"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient17543">
+ <stop
+ id="stop17545"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop17547"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ y2="305"
+ x2="758"
+ y1="300.83292"
+ x1="754.28558"
+ gradientTransform="translate(0,-95.999998)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient16784"
+ xlink:href="#linearGradient17530"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient17530">
+ <stop
+ style="stop-color:#7f7f7f;stop-opacity:1;"
+ offset="0"
+ id="stop17532" />
+ <stop
+ style="stop-color:#7f7f7f;stop-opacity:0;"
+ offset="1"
+ id="stop17534" />
+ </linearGradient>
+ <linearGradient
+ y2="305"
+ x2="758"
+ y1="300.83292"
+ x1="754.28558"
+ gradientTransform="translate(0,-95.999998)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient16880"
+ xlink:href="#linearGradient17530"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18370"
+ id="linearGradient16720"
+ gradientUnits="userSpaceOnUse"
+ x1="432.83759"
+ y1="289.15814"
+ x2="441.44028"
+ y2="283.54819" />
</defs>
<sodipodi:namedview
id="base"
@@ -29064,14 +29581,14 @@
objecttolerance="10000"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="8"
- inkscape:cx="475.21328"
- inkscape:cy="281.82297"
+ inkscape:zoom="16"
+ inkscape:cx="495.37384"
+ inkscape:cy="572.11918"
inkscape:document-units="px"
- inkscape:current-layer="layer1"
+ inkscape:current-layer="g18198-9"
showgrid="true"
inkscape:window-width="1920"
- inkscape:window-height="980"
+ inkscape:window-height="995"
inkscape:window-x="0"
inkscape:window-y="28"
inkscape:snap-nodes="false"
@@ -89624,6 +90141,136 @@
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
inkscape:connector-curvature="0" />
+ <g
+ id="g18205"
+ transform="matrix(1.0087429,0,0,0.97482999,-2.7977369,3.5855352)">
+ <rect
+ ry="1.5303751"
+ rx="1.479782"
+ y="243.54448"
+ x="320"
+ height="16.413118"
+ width="15.861326"
+ id="rect18203"
+ style="fill:none;stroke:none" />
+ <g
+ id="g18198"
+ transform="translate(-105.12972,-37.013919)">
+ <path
+ style="fill:url(#linearGradient18237);fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 425.50477,292.38372 15.04989,-10.90405 -0.0101,6.77582 -9.51239,8.38266 z"
+ id="rect16727"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;stroke:url(#linearGradient18239);stroke-width:0.94270116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 439.79125,287.61126 -8.80214,7.81233 -3.87477,-2.96997 12.64026,-9.16307"
+ id="rect16727-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ transform="matrix(0.74622014,-0.66569926,0.64008794,0.76830165,0,0)"
+ style="fill:url(#linearGradient20049);fill-opacity:1;stroke:none"
+ d="m 155.67553,506.23194 -0.63498,0.7272 c 0,0 -7.96167,0.0866 -11.40538,0.0765 -1.63408,-0.005 -1.64706,-1.90745 -0.31608,-1.84971 3.85215,0.16711 12.35647,1.04592 12.35647,1.04592 z"
+ id="rect20031"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsscc" />
+ </g>
+ <g
+ style="display:inline;enable-background:new;fill-opacity:1;fill:url(#linearGradient18368)"
+ id="g18198-9"
+ transform="translate(-105.1466,-36.99669)">
+ <path
+ style="fill:url(#linearGradient18420);fill-opacity:1;stroke:none"
+ d="m 321.20705,242.0789 c 2.69584,0.64081 4.09152,0.77931 6.28874,0.55186 0.26517,2.2318 0.84364,4.80456 2.06664,6.25861 -2.05408,-0.68406 -3.57488,-1.60349 -4.80908,-2.47909 -1.36678,-1.11314 -2.52984,-2.47523 -3.5463,-4.33138 z"
+ id="path18412"
+ inkscape:connector-curvature="0"
+ transform="matrix(0.99133288,0,0,1.0258199,107.92009,33.318577)"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;stroke:#1a1a1a;stroke-width:0.70590025;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.49803922;stroke-dasharray:none"
+ d="m 433.63404,285.72236 c 0.73437,0.0551 1.7644,-0.46216 6.92062,-4.29741 0,3.16617 -0.0101,4.19989 -0.0101,6.77582 -0.44137,0.51649 -6.49867,5.40547 -7.65364,-6.3635 -3.13764,0.28442 -4.5477,0.084 -7.20028,-0.77628 1.34066,3.00122 2.84213,4.52716 4.53015,5.73115 2.02689,1.39249 4.23484,2.31245 6.40718,2.76405"
+ id="rect16727-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;stroke:url(#linearGradient18476);stroke-width:0.70590028;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.49803922000000000;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 429.7959,286.22706 c -0.643,-0.69986 -1.96564,-2.36658 -2.68852,-3.95331 2.06071,0.57118 3.81157,0.50289 5.11146,0.38221 0.26288,2.28943 0.88014,4.42993 1.66538,5.3435"
+ id="path18412-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:url(#linearGradient18493);fill-opacity:1;stroke:none"
+ d="m 335.20234,242.58443 c 0,0.84375 -0.005,3.9971 -0.005,5.75999 -2.37119,1.76035 -4.7166,1.79719 -6.03803,-1.54307 1.55369,-1.16687 6.02002,-4.2052 6.02002,-4.2052 z"
+ id="path18485"
+ inkscape:connector-curvature="0"
+ transform="matrix(0.99133288,0,0,1.0258199,107.92009,33.318577)"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:url(#linearGradient20026);fill-opacity:1;stroke:none"
+ d="m 335.23044,245.54814 c 0,0 0.0166,0.39923 0.0166,1.01647 -0.82312,0.76235 -3.0673,2.74764 -4.18325,2.66033 -0.29848,-0.14345 -0.39809,-0.20898 -0.62335,-0.46278 1.10175,-0.45288 2.17708,-1.29548 4.79,-3.21402 z"
+ id="path20010"
+ inkscape:connector-curvature="0"
+ transform="matrix(0.99133288,0,0,1.0258199,107.90321,33.335806)"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#ffe991;fill-opacity:1;stroke:none"
+ d="m 329.55657,248.86283 c -1.41211,-0.48222 -3.92872,-1.40598 -4.73299,-4.22946 -0.39317,-1.38024 1.7085,-1.41702 1.92756,-0.24049 0.45159,2.42548 1.89945,3.56397 2.80543,4.46995 z"
+ id="path18570"
+ inkscape:connector-curvature="0"
+ transform="matrix(0.99133288,0,0,1.0258199,107.90321,33.335806)"
+ sodipodi:nodetypes="cssc" />
+ <g
+ transform="matrix(0.99133288,0,0,1.0258199,-153.79179,-122.50347)"
+ id="g39239-8"
+ style="fill:url(#linearGradient16720);display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient39254-5);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 756.16666,204.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
+ id="path39241-60"
+ sodipodi:nodetypes="cccccc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cccccc"
+ id="path39243-9"
+ d="m 756.16666,204.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
+ style="opacity:0.3;fill:url(#radialGradient39256-9);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path39245-1"
+ style="fill:none;stroke:url(#linearGradient39258-0);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 754.5,209 0,9.5 m 3.5,-13 7.5,0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path39247-8"
+ d="m 753,208 4,0 0,-4 -4,4 z"
+ style="fill:#ffffff;fill-opacity:0.49803922;fill-rule:evenodd;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path39249-0"
+ style="fill:none;stroke:#7f7f7f;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 753.5,207.00001 0,12.49999 13,0 0,-14.99999 -10.5,0 -2.5,2.5 z"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient16880);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 757.5,206.5 0,2 -2,0"
+ id="path39251-2" />
+ </g>
+ </g>
+ </g>
</g>
<g
inkscape:groupmode="layer"
diff --git a/release/datafiles/blender_icons16/icon16_file_hidden.dat b/release/datafiles/blender_icons16/icon16_file_hidden.dat
new file mode 100644
index 00000000000..19b5eda9d6b
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_file_hidden.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_mod_data_transfer.dat b/release/datafiles/blender_icons16/icon16_mod_data_transfer.dat
new file mode 100644
index 00000000000..53b5d3eae1a
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_mod_data_transfer.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_file_hidden.dat b/release/datafiles/blender_icons32/icon32_file_hidden.dat
new file mode 100644
index 00000000000..373fa44f192
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_file_hidden.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_mod_data_transfer.dat b/release/datafiles/blender_icons32/icon32_mod_data_transfer.dat
new file mode 100644
index 00000000000..a405606a0e5
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_mod_data_transfer.dat
Binary files differ
diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio
index 1d2c730ecab..1cf9a3bb36e 100644
--- a/release/datafiles/colormanagement/config.ocio
+++ b/release/datafiles/colormanagement/config.ocio
@@ -25,7 +25,7 @@ roles:
# Default color space sequencer is working in
default_sequencer: sRGB
- # Color spaces for color picking and exture painting (not internally supported yet)
+ # Color spaces for color picking and texture painting (not internally supported yet)
color_picking: Raw
texture_paint: Raw
diff --git a/release/datafiles/locale b/release/datafiles/locale
-Subproject c980697651ad7f21a7cd8ad23dc26e482b5fa75
+Subproject ca3f663ff4ac139f36f43647dc5cf481132fbed
diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png
index 76bb67b7263..e8d09694a64 100644
--- a/release/datafiles/splash.png
+++ b/release/datafiles/splash.png
Binary files differ
diff --git a/release/datafiles/splash_2x.png b/release/datafiles/splash_2x.png
index c0eaba50460..d20fb682970 100644
--- a/release/datafiles/splash_2x.png
+++ b/release/datafiles/splash_2x.png
Binary files differ
diff --git a/release/datafiles/startup.blend b/release/datafiles/startup.blend
index 8b58493fe3a..23bb2646a54 100644
--- a/release/datafiles/startup.blend
+++ b/release/datafiles/startup.blend
Binary files differ
diff --git a/release/scripts/addons b/release/scripts/addons
+Subproject 1068cf3057c0a1cd3a60d53722f6d20856eace8
diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib
-Subproject 8f33ffcebed445755d3453b8f486306bcf2b142
+Subproject 24d59d37f7b0210cdb7154bc7fc1b6da1584eab
diff --git a/release/scripts/freestyle/modules/parameter_editor.py b/release/scripts/freestyle/modules/parameter_editor.py
index 9ac5c665f1e..ba79c5514e2 100644
--- a/release/scripts/freestyle/modules/parameter_editor.py
+++ b/release/scripts/freestyle/modules/parameter_editor.py
@@ -97,7 +97,7 @@ from freestyle.utils import (
stroke_normal,
bound,
pairwise,
- BoundedProperty
+ BoundedProperty,
)
from _freestyle import (
blendRamp,
@@ -110,6 +110,12 @@ from mathutils import Vector
from math import pi, sin, cos, acos, radians
from itertools import cycle, tee
+# lists of callback functions
+# WARNING: highly experimental, not a stable API
+callbacks_lineset_pre = []
+callbacks_modifiers_post = []
+callbacks_lineset_post = []
+
class ColorRampModifier(StrokeShader):
"""Primitive for the color modifiers."""
@@ -878,6 +884,21 @@ class Seed:
_seed = Seed()
+def get_dashed_pattern(linestyle):
+ """Extracts the dashed pattern from the various UI options """
+ pattern = []
+ if linestyle.dash1 > 0 and linestyle.gap1 > 0:
+ pattern.append(linestyle.dash1)
+ pattern.append(linestyle.gap1)
+ if linestyle.dash2 > 0 and linestyle.gap2 > 0:
+ pattern.append(linestyle.dash2)
+ pattern.append(linestyle.gap2)
+ if linestyle.dash3 > 0 and linestyle.gap3 > 0:
+ pattern.append(linestyle.dash3)
+ pattern.append(linestyle.gap3)
+ return pattern
+
+
integration_types = {
'MEAN': IntegrationType.MEAN,
'MIN': IntegrationType.MIN,
@@ -887,13 +908,16 @@ integration_types = {
# main function for parameter processing
-
def process(layer_name, lineset_name):
scene = getCurrentScene()
layer = scene.render.layers[layer_name]
lineset = layer.freestyle_settings.linesets[lineset_name]
linestyle = lineset.linestyle
+ # execute line set pre-processing callback functions
+ for fn in callbacks_lineset_pre:
+ fn(scene, layer, lineset)
+
selection_criteria = []
# prepare selection criteria by visibility
if lineset.select_by_visibility:
@@ -1172,24 +1196,26 @@ def process(layer_name, lineset_name):
has_tex = True
if has_tex:
shaders_list.append(StrokeTextureStepShader(linestyle.texture_spacing))
+
+ # execute post-base stylization callbacks
+ for fn in callbacks_modifiers_post:
+ shaders_list.extend(fn(scene, layer, lineset))
+
# -- 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:
- pattern.append(linestyle.dash1)
- pattern.append(linestyle.gap1)
- if linestyle.dash2 > 0 and linestyle.gap2 > 0:
- pattern.append(linestyle.dash2)
- pattern.append(linestyle.gap2)
- if linestyle.dash3 > 0 and linestyle.gap3 > 0:
- pattern.append(linestyle.dash3)
- pattern.append(linestyle.gap3)
+ pattern = get_dashed_pattern(linestyle)
if len(pattern) > 0:
shaders_list.append(DashedLineShader(pattern))
+
# create strokes using the shaders list
Operators.create(TrueUP1D(), shaders_list)
+
+ # execute line set post-processing callback functions
+ for fn in callbacks_lineset_post:
+ fn(scene, layer, lineset)
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 a887ebde449..587aaed1bf8 100644
--- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
@@ -220,7 +220,6 @@ class SpellChecker():
"polycount",
"polygonization", "polygonalization", # yuck!
"selectability",
- "slurph",
"stitchable",
"symmetrize",
"trackability",
@@ -266,6 +265,7 @@ class SpellChecker():
"ok",
"orco",
"ortho",
+ "pano",
"persp",
"pref", "prefs",
"prev",
diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py
index 3a2f9bde2c7..b0d2233b380 100644
--- a/release/scripts/modules/bpy/__init__.py
+++ b/release/scripts/modules/bpy/__init__.py
@@ -38,10 +38,10 @@ __all__ = (
from _bpy import types, props, app, data, context
# python modules
-from . import utils, path, ops
+from . import utils, path
# fake operator module
-ops = ops.ops_fake_module
+from .ops import ops_fake_module as ops
def main():
diff --git a/release/scripts/modules/bpy/ops.py b/release/scripts/modules/bpy/ops.py
index 1bdb9eba48c..d3d9255123b 100644
--- a/release/scripts/modules/bpy/ops.py
+++ b/release/scripts/modules/bpy/ops.py
@@ -36,6 +36,7 @@ class BPyOps:
bpy.ops
"""
+ __slots__ = ()
def __getattr__(self, module):
"""
diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py
index b1877a9d439..81de0d7c6f0 100644
--- a/release/scripts/modules/bpy_extras/io_utils.py
+++ b/release/scripts/modules/bpy_extras/io_utils.py
@@ -21,6 +21,7 @@
__all__ = (
"ExportHelper",
"ImportHelper",
+ "OrientationHelper",
"axis_conversion",
"axis_conversion_ensure",
"create_derived_objects",
@@ -116,6 +117,43 @@ class ImportHelper:
return _check_axis_conversion(self)
+class OrientationHelper:
+
+ def _update_axis_forward(self, context):
+ if self.axis_forward[-1] == self.axis_up[-1]:
+ self.axis_up = self.axis_up[0:-1] + 'XYZ'[('XYZ'.index(self.axis_up[-1]) + 1) % 3]
+
+ axis_forward = EnumProperty(
+ name="Forward",
+ items=(('X', "X Forward", ""),
+ ('Y', "Y Forward", ""),
+ ('Z', "Z Forward", ""),
+ ('-X', "-X Forward", ""),
+ ('-Y', "-Y Forward", ""),
+ ('-Z', "-Z Forward", ""),
+ ),
+ default='-Z',
+ update=_update_axis_forward,
+ )
+
+ def _update_axis_up(self, context):
+ if self.axis_up[-1] == self.axis_forward[-1]:
+ self.axis_forward = self.axis_forward[0:-1] + 'XYZ'[('XYZ'.index(self.axis_forward[-1]) + 1) % 3]
+
+ axis_up = EnumProperty(
+ name="Up",
+ items=(('X', "X Up", ""),
+ ('Y', "Y Up", ""),
+ ('Z', "Z Up", ""),
+ ('-X', "-X Up", ""),
+ ('-Y', "-Y Up", ""),
+ ('-Z', "-Z Up", ""),
+ ),
+ default='Y',
+ update=_update_axis_up,
+ )
+
+
# Axis conversion function, not pretty LUT
# use lookup table to convert between any axis
_axis_convert_matrix = (
diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py
index c50b320dceb..3f5a23683ee 100644
--- a/release/scripts/modules/bpy_extras/keyconfig_utils.py
+++ b/release/scripts/modules/bpy_extras/keyconfig_utils.py
@@ -32,7 +32,10 @@ KM_HIERARCHY = [
('View2D', 'EMPTY', 'WINDOW', []), # view 2d navigation (per region)
('View2D Buttons List', 'EMPTY', 'WINDOW', []), # view 2d with buttons navigation
('Header', 'EMPTY', 'WINDOW', []), # header stuff (per region)
- ('Grease Pencil', 'EMPTY', 'WINDOW', []), # grease pencil stuff (per region)
+
+ ('Grease Pencil', 'EMPTY', 'WINDOW', [ # grease pencil stuff (per region)
+ ('Grease Pencil Stroke Edit Mode', 'EMPTY', 'WINDOW', []),
+ ]),
('3D View', 'VIEW_3D', 'WINDOW', [ # view 3d navigation and generic stuff (select, transform)
('Object Mode', 'EMPTY', 'WINDOW', []),
@@ -56,6 +59,7 @@ KM_HIERARCHY = [
('Knife Tool Modal Map', 'EMPTY', 'WINDOW', []),
('Paint Stroke Modal', 'EMPTY', 'WINDOW', []),
+ ('Paint Curve', 'EMPTY', 'WINDOW', []),
('Object Non-modal', 'EMPTY', 'WINDOW', []), # mode change
diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index 01390760c76..13ef86b23c0 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -99,7 +99,7 @@ def add_object_align_init(context, operator):
return location * rotation
-def object_data_add(context, obdata, operator=None, use_active_layer=True):
+def object_data_add(context, obdata, operator=None, use_active_layer=True, name=None):
"""
Add an object using the view context and preference to to initialize the
location, rotation and layer.
@@ -110,6 +110,8 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
:type obdata: valid object data type or None.
:arg operator: The operator, checked for location and rotation properties.
:type operator: :class:`bpy.types.Operator`
+ :arg name: Optional name
+ :type name: string
:return: the newly created object in the scene.
:rtype: :class:`bpy.types.ObjectBase`
"""
@@ -119,7 +121,10 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
for ob in scene.objects:
ob.select = False
- obj_new = bpy.data.objects.new(obdata.name, obdata)
+ if name is None:
+ name = "Object" if obdata is None else obdata.name
+
+ obj_new = bpy.data.objects.new(name, obdata)
base = scene.objects.link(obj_new)
base.select = True
@@ -150,7 +155,7 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
obj_act.mode == 'EDIT' and
obj_act.type == obj_new.type):
- _obdata = bpy.data.meshes.new(obdata.name)
+ _obdata = bpy.data.meshes.new(name)
obj_act = bpy.data.objects.new(_obdata.name, _obdata)
obj_act.matrix_world = obj_new.matrix_world
scene.objects.link(obj_act)
@@ -169,7 +174,8 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
#scene.objects.active = obj_new
bpy.ops.object.join() # join into the active.
- bpy.data.meshes.remove(obdata)
+ if obdata:
+ bpy.data.meshes.remove(obdata)
# base is freed, set to active object
base = scene.object_bases.active
diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py
index b25024fca9b..ec4a395f1e1 100644
--- a/release/scripts/modules/bpy_extras/view3d_utils.py
+++ b/release/scripts/modules/bpy_extras/view3d_utils.py
@@ -63,10 +63,18 @@ def region_2d_to_vector_3d(region, rv3d, coord):
return view_vector
-def region_2d_to_origin_3d(region, rv3d, coord):
+def region_2d_to_origin_3d(region, rv3d, coord, clamp=None):
"""
Return the 3d view origin from the region relative 2d coords.
+ .. note::
+
+ Orthographic views have a less obvious origin, the far clip is used to define the viewport near/far extents.
+ Since far clip can be a very large value, the result may give with numeric precision issues.
+
+ To avoid this problem, you can optionally clamp the far clip to a smaller value
+ based on the data you're operating on.
+
:arg region: region of the 3D viewport, typically bpy.context.region.
:type region: :class:`bpy.types.Region`
:arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
@@ -74,6 +82,9 @@ def region_2d_to_origin_3d(region, rv3d, coord):
:arg coord: 2d coordinates relative to the region;
(event.mouse_region_x, event.mouse_region_y) for example.
:type coord: 2d vector
+ :arg clamp: Clamp the maximum far-clip value used.
+ (negative value will move the offset away from the view_location)
+ :type clamp: float or None
:return: The origin of the viewpoint in 3d space.
:rtype: :class:`mathutils.Vector`
"""
@@ -89,6 +100,20 @@ def region_2d_to_origin_3d(region, rv3d, coord):
origin_start = ((persinv.col[0].xyz * dx) +
(persinv.col[1].xyz * dy) +
viewinv.translation)
+
+ if clamp != 0.0:
+ if rv3d.view_perspective != 'CAMERA':
+ # this value is scaled to the far clip already
+ origin_offset = persinv.col[2].xyz
+ if clamp is not None:
+ if clamp < 0.0:
+ origin_offset.negate()
+ clamp = -clamp
+ if origin_offset.length > clamp:
+ origin_offset.length = clamp
+
+ origin_start -= origin_offset
+
return origin_start
diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py
index 3643ad89ea6..353362ed168 100644
--- a/release/scripts/modules/rna_info.py
+++ b/release/scripts/modules/rna_info.py
@@ -487,6 +487,12 @@ def GetInfoOperatorRNA(bl_rna):
def BuildRNAInfo():
+
+ # needed on successive calls to prevent stale data access
+ for cls in (InfoStructRNA, InfoFunctionRNA, InfoOperatorRNA, InfoPropertyRNA):
+ cls.global_lookup.clear()
+ del cls
+
# Use for faster lookups
# use rna_struct.identifier as the key for each dict
rna_struct_dict = {} # store identifier:rna lookups
diff --git a/release/scripts/modules/rna_keymap_ui.py b/release/scripts/modules/rna_keymap_ui.py
index 12d99a00d44..21d1959a037 100644
--- a/release/scripts/modules/rna_keymap_ui.py
+++ b/release/scripts/modules/rna_keymap_ui.py
@@ -236,7 +236,7 @@ def draw_filtered(display_keymaps, filter_type, filter_text, layout):
"MMB": 'MIDDLEMOUSE',
})
_EVENT_TYPE_MAP_EXTRA.update({
- "%d" % i: "NUMPAD_%d" % i for i in range(9)
+ "%d" % i: "NUMPAD_%d" % i for i in range(10)
})
# done with once off init
diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py
index 7fd97c4d347..cecb2a767ef 100644
--- a/release/scripts/modules/sys_info.py
+++ b/release/scripts/modules/sys_info.py
@@ -187,6 +187,12 @@ def write_sysinfo(op):
bgl.glGetIntegerv(bgl.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, limit)
output.write("Maximum Pipeline Image Units:\t%d\n" % limit[0])
+ if bpy.app.build_options.cycles:
+ import cycles
+ output.write("\nCycles\n")
+ output.write(lilies)
+ output.write(cycles.engine.system_info())
+
output.current_line_index = 0
op.report({'INFO'}, "System information generated in 'system-info.txt'")
diff --git a/release/scripts/presets/interface_theme/back_to_black.xml b/release/scripts/presets/interface_theme/back_to_black.xml
index 6fa423f9594..6520d81b900 100644
--- a/release/scripts/presets/interface_theme/back_to_black.xml
+++ b/release/scripts/presets/interface_theme/back_to_black.xml
@@ -5,7 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
- emboss="#ffffff05"
+ widget_emboss="#ffffff05"
axis_x="#dc0000"
axis_y="#00dc00"
axis_z="#0000dc">
diff --git a/release/scripts/presets/interface_theme/blender_24x.xml b/release/scripts/presets/interface_theme/blender_24x.xml
index e7f6eff6070..bb9b03d56ea 100644
--- a/release/scripts/presets/interface_theme/blender_24x.xml
+++ b/release/scripts/presets/interface_theme/blender_24x.xml
@@ -5,7 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
- emboss="#ffffff05"
+ widget_emboss="#ffffff05"
axis_x="#dc0000"
axis_y="#00dc00"
axis_z="#0000dc">
diff --git a/release/scripts/presets/interface_theme/elsyiun.xml b/release/scripts/presets/interface_theme/elsyiun.xml
index 03f72a2ee75..6734850f876 100644
--- a/release/scripts/presets/interface_theme/elsyiun.xml
+++ b/release/scripts/presets/interface_theme/elsyiun.xml
@@ -5,7 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
- emboss="#ffffff05"
+ widget_emboss="#ffffff05"
axis_x="#dc0000"
axis_y="#00dc00"
axis_z="#0000dc">
diff --git a/release/scripts/presets/interface_theme/graph.xml b/release/scripts/presets/interface_theme/graph.xml
index 5319d229786..1cb9a8985e4 100644
--- a/release/scripts/presets/interface_theme/graph.xml
+++ b/release/scripts/presets/interface_theme/graph.xml
@@ -5,7 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
- emboss="#ffffff05"
+ widget_emboss="#ffffff05"
axis_x="#dc0000"
axis_y="#00dc00"
axis_z="#0000dc">
diff --git a/release/scripts/presets/interface_theme/hexagon.xml b/release/scripts/presets/interface_theme/hexagon.xml
index e2d1b6bba6a..40228e832a7 100644
--- a/release/scripts/presets/interface_theme/hexagon.xml
+++ b/release/scripts/presets/interface_theme/hexagon.xml
@@ -5,7 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
- emboss="#ffffff05"
+ widget_emboss="#ffffff05"
axis_x="#dc0000"
axis_y="#00dc00"
axis_z="#0000dc">
diff --git a/release/scripts/presets/interface_theme/science_lab.xml b/release/scripts/presets/interface_theme/science_lab.xml
index 8c96c506348..98dddfb0014 100644
--- a/release/scripts/presets/interface_theme/science_lab.xml
+++ b/release/scripts/presets/interface_theme/science_lab.xml
@@ -5,7 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
- emboss="#ffffff05"
+ widget_emboss="#ffffff05"
axis_x="#dc4800"
axis_y="#73dc00"
axis_z="#00c2ff">
diff --git a/release/scripts/presets/interface_theme/softimage.xml b/release/scripts/presets/interface_theme/softimage.xml
index 5c99032ad33..d58e04619ed 100644
--- a/release/scripts/presets/interface_theme/softimage.xml
+++ b/release/scripts/presets/interface_theme/softimage.xml
@@ -5,7 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
- emboss="#ffffff05"
+ widget_emboss="#ffffff05"
axis_x="#ff5a5a"
axis_y="#58ff58"
axis_z="#6262ff">
diff --git a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
index b27aa181f6d..b2743f36c02 100644
--- a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
+++ b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
@@ -5,7 +5,7 @@
menu_shadow_width="12"
icon_file=""
icon_alpha="1"
- emboss="#ffffff05"
+ widget_emboss="#ffffff05"
axis_x="#dc0000"
axis_y="#00dc00"
axis_z="#0000dc">
diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
index f29bf07ab3a..73e6bcd9b0c 100644
--- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py
+++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
@@ -708,6 +708,7 @@ def main(context,
island_margin,
projection_limit,
user_area_weight,
+ use_aspect
):
global USER_FILL_HOLES
global USER_FILL_HOLES_QUALITY
@@ -720,7 +721,6 @@ def main(context,
global dict_matrix
dict_matrix = {}
-
# Constants:
# Takes a list of faces that make up a UV island and rotate
# until they optimally fit inside a square.
@@ -992,9 +992,31 @@ def main(context,
print("Smart Projection time: %.2f" % (time.time() - time1))
# Window.DrawProgressBar(0.9, "Smart Projections done, time: %.2f sec" % (time.time() - time1))
+ # aspect correction is only done in edit mode - and only smart unwrap supports currently
if is_editmode:
bpy.ops.object.mode_set(mode='EDIT')
+ if use_aspect:
+ import bmesh
+ aspect = context.scene.uvedit_aspect(context.active_object)
+ if aspect[0] > aspect[1]:
+ aspect[0] = aspect[1]/aspect[0];
+ aspect[1] = 1.0
+ else:
+ aspect[1] = aspect[0]/aspect[1];
+ aspect[0] = 1.0
+
+ bm = bmesh.from_edit_mesh(me)
+
+ uv_act = bm.loops.layers.uv.active
+
+ faces = [f for f in bm.faces if f.select]
+
+ for f in faces:
+ for l in f.loops:
+ l[uv_act].uv[0] *= aspect[0]
+ l[uv_act].uv[1] *= aspect[1]
+
dict_matrix.clear()
#XXX Window.DrawProgressBar(1.0, "")
@@ -1017,7 +1039,7 @@ def main(context,
]
"""
-from bpy.props import FloatProperty
+from bpy.props import FloatProperty, BoolProperty
class SmartProject(Operator):
@@ -1046,6 +1068,11 @@ class SmartProject(Operator):
min=0.0, max=1.0,
default=0.0,
)
+ use_aspect = BoolProperty(
+ name="Correct Aspect",
+ description="Map UVs taking image aspect ratio into account",
+ default=True
+ )
@classmethod
def poll(cls, context):
@@ -1056,6 +1083,7 @@ class SmartProject(Operator):
self.island_margin,
self.angle_limit,
self.user_area_weight,
+ self.use_aspect
)
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index 6174dd95f2a..99b1a7a090a 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -117,6 +117,7 @@ def register():
WindowManager.addon_search = StringProperty(
name="Search",
description="Search within the selected filter",
+ options={'TEXTEDIT_UPDATE'},
)
WindowManager.addon_filter = EnumProperty(
items=addon_filter_items,
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index e6b62cae6ef..0c5aae1de2f 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -768,9 +768,27 @@ class ConstraintButtonsPanel():
col = layout.column()
col.label(text="Chain Scaling:")
col.prop(con, "use_y_stretch")
- col.prop(con, "xz_scale_mode")
col.prop(con, "use_curve_radius")
+ layout.prop(con, "xz_scale_mode")
+
+ if con.xz_scale_mode == 'VOLUME_PRESERVE':
+ layout.prop(con, "bulge", text="Volume Variation")
+ split = layout.split()
+ col = split.column(align=True)
+ col.prop(con, "use_bulge_min", text="Volume Min")
+ sub = col.column()
+ sub.active = con.use_bulge_min
+ sub.prop(con, "bulge_min", text="")
+ col = split.column(align=True)
+ col.prop(con, "use_bulge_max", text="Volume Max")
+ sub = col.column()
+ sub.active = con.use_bulge_max
+ sub.prop(con, "bulge_max", text="")
+ col = layout.column()
+ col.active = con.use_bulge_min or con.use_bulge_max
+ col.prop(con, "bulge_smooth", text="Smooth")
+
def PIVOT(self, context, layout, con):
self.target_template(layout, con)
diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index 0600c87244b..fee3e589074 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -98,6 +98,14 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
row = layout.row()
row.prop(ccam, "fisheye_lens", text="Lens")
row.prop(ccam, "fisheye_fov")
+ elif ccam.panorama_type == 'EQUIRECTANGULAR':
+ row = layout.row()
+ sub = row.column(align=True)
+ sub.prop(ccam, "latitude_min");
+ sub.prop(ccam, "latitude_max");
+ sub = row.column(align=True)
+ sub.prop(ccam, "longitude_min");
+ sub.prop(ccam, "longitude_max");
elif engine == 'BLENDER_RENDER':
row = col.row()
if cam.lens_unit == 'MILLIMETERS':
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 5a59a238d19..670ecf495be 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -29,7 +29,7 @@ class MESH_MT_vertex_group_specials(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("object.vertex_group_sort", icon='SORTALPHA').sort_type = "NAME"
+ layout.operator("object.vertex_group_sort", icon='SORTALPHA', text="Sort by Name").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')
@@ -317,7 +317,6 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
row = layout.column()
row.active = enable_edit_value
row.prop(key, "eval_time")
- row.prop(key, "slurph")
class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 8da7573fabc..309a332a867 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -1231,6 +1231,121 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "material_offset", text="Material Offset")
+ def DATA_TRANSFER(self, layout, ob, md):
+ row = layout.row(align=True)
+ row.prop(md, "object")
+ sub = row.row(align=True)
+ sub.active = bool(md.object)
+ sub.prop(md, "use_object_transform", text="", icon='GROUP')
+
+ layout.separator()
+
+ split = layout.split(0.333)
+ split.prop(md, "use_vert_data")
+ use_vert = md.use_vert_data
+ row = split.row()
+ row.active = use_vert
+ row.prop(md, "vert_mapping", text="")
+ if use_vert:
+ col = layout.column(align=True)
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_verts_vgroup")
+ row = split.row(align=True)
+ row.prop(md, "layers_vgroup_select_src", text="")
+ row.label(icon='RIGHTARROW_THIN')
+ row.prop(md, "layers_vgroup_select_dst", text="")
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_verts")
+
+ layout.separator()
+
+ split = layout.split(0.333)
+ split.prop(md, "use_edge_data")
+ use_edge = md.use_edge_data
+ row = split.row()
+ row.active = use_edge
+ row.prop(md, "edge_mapping", text="")
+ if use_edge:
+ col = layout.column(align=True)
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_edges")
+
+ layout.separator()
+
+ split = layout.split(0.333)
+ split.prop(md, "use_loop_data")
+ use_loop = md.use_loop_data
+ row = split.row()
+ row.active = use_loop
+ row.prop(md, "loop_mapping", text="")
+ if use_loop:
+ col = layout.column(align=True)
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_loops")
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_loops_vcol")
+ row = split.row(align=True)
+ row.prop(md, "layers_vcol_select_src", text="")
+ row.label(icon='RIGHTARROW')
+ row.prop(md, "layers_vcol_select_dst", text="")
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_loops_uv")
+ row = split.row(align=True)
+ row.prop(md, "layers_uv_select_src", text="")
+ row.label(icon='RIGHTARROW')
+ row.prop(md, "layers_uv_select_dst", text="")
+ col.prop(md, "islands_precision")
+
+ layout.separator()
+
+ split = layout.split(0.333)
+ split.prop(md, "use_poly_data")
+ use_poly = md.use_poly_data
+ row = split.row()
+ row.active = use_poly
+ row.prop(md, "poly_mapping", text="")
+ if use_poly:
+ col = layout.column(align=True)
+ split = col.split(0.333, align=True)
+ sub = split.column(align=True)
+ sub.prop(md, "data_types_polys")
+
+ layout.separator()
+
+ split = layout.split()
+ col = split.column()
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.active = md.use_max_distance
+ sub.prop(md, "max_distance")
+ row.prop(md, "use_max_distance", text="", icon='STYLUS_PRESSURE')
+
+ col = split.column()
+ col.prop(md, "ray_radius")
+
+ layout.separator()
+
+ split = layout.split()
+ col = split.column()
+ col.prop(md, "mix_mode")
+ col.prop(md, "mix_factor")
+
+ col = split.column()
+ row = col.row()
+ row.active = bool(md.object)
+ row.operator("object.datalayout_transfer", text="Generate Data Layers")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ sub = row.row(align=True)
+ sub.active = bool(md.vertex_group)
+ sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index 4789d119192..81079edd938 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -19,11 +19,34 @@
# <pep8 compliant>
-class GreasePencilPanel():
+from bpy.types import Menu, UIList
+
+
+def gpencil_stroke_placement_settings(context, layout, gpd):
+ col = layout.column(align=True)
+
+ col.label(text="Stroke Placement:")
+
+ row = col.row(align=True)
+ row.prop_enum(gpd, "draw_mode", 'VIEW')
+ row.prop_enum(gpd, "draw_mode", 'CURSOR')
+
+ if context.space_data.type == 'VIEW_3D':
+ row = col.row(align=True)
+ row.prop_enum(gpd, "draw_mode", 'SURFACE')
+ row.prop_enum(gpd, "draw_mode", 'STROKE')
+
+ row = col.row(align=False)
+ row.active = gpd.draw_mode in {'SURFACE', 'STROKE'}
+ row.prop(gpd, "use_stroke_endpoints")
+
+
+class GreasePencilDrawingToolsPanel():
# subclass must set
# bl_space_type = 'IMAGE_EDITOR'
- # bl_region_type = 'TOOLS'
bl_label = "Grease Pencil"
+ bl_category = "Grease Pencil"
+ bl_region_type = 'TOOLS'
@staticmethod
def draw(self, context):
@@ -31,19 +54,435 @@ class GreasePencilPanel():
col = layout.column(align=True)
+ col.label(text="Draw:")
row = col.row(align=True)
row.operator("gpencil.draw", text="Draw").mode = 'DRAW'
- row.operator("gpencil.draw", text="Line").mode = 'DRAW_STRAIGHT'
+ row.operator("gpencil.draw", text="Erase").mode = 'ERASER'
row = col.row(align=True)
+ row.operator("gpencil.draw", text="Line").mode = 'DRAW_STRAIGHT'
row.operator("gpencil.draw", text="Poly").mode = 'DRAW_POLY'
- row.operator("gpencil.draw", text="Erase").mode = 'ERASER'
row = col.row(align=True)
- row.prop(context.tool_settings, "use_grease_pencil_sessions")
+ row.prop(context.tool_settings, "use_grease_pencil_sessions", text="Continuous Drawing")
+
+ if context.space_data.type in {'VIEW_3D', 'CLIP_EDITOR'}:
+ col.separator()
+ col.label("Data Source:")
+ row = col.row(align=True)
+ if context.space_data.type == 'VIEW_3D':
+ row.prop(context.tool_settings, "grease_pencil_source", expand=True)
+ elif context.space_data.type == 'CLIP_EDITOR':
+ row.prop(context.space_data, "grease_pencil_source", expand=True)
+
+ gpd = context.gpencil_data
+ if gpd:
+ col.separator()
+ gpencil_stroke_placement_settings(context, col, gpd)
if context.space_data.type == 'VIEW_3D':
col.separator()
+ col.separator()
- col.label(text="Measure:")
+ col.label(text="Tools:")
+ col.operator("gpencil.convert", text="Convert...")
col.operator("view3d.ruler")
+
+
+class GreasePencilStrokeEditPanel():
+ # subclass must set
+ # bl_space_type = 'IMAGE_EDITOR'
+ bl_label = "Edit Strokes"
+ bl_category = "Grease Pencil"
+ bl_region_type = 'TOOLS'
+
+ @classmethod
+ def poll(cls, context):
+ return (context.gpencil_data is not None)
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+
+ gpd = context.gpencil_data
+ edit_ok = bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
+
+ col = layout.column(align=True)
+ col.prop(gpd, "use_stroke_edit_mode", text="Enable Editing", icon='EDIT', toggle=True)
+
+ col.separator()
+
+ col.label(text="Select:")
+ subcol = col.column(align=True)
+ subcol.active = edit_ok
+ subcol.operator("gpencil.select_all", text="Select All")
+ subcol.operator("gpencil.select_border")
+ subcol.operator("gpencil.select_circle")
+
+ col.separator()
+
+ subcol = col.column(align=True)
+ subcol.active = edit_ok
+ subcol.operator("gpencil.select_linked")
+ subcol.operator("gpencil.select_more")
+ subcol.operator("gpencil.select_less")
+
+ col.separator()
+
+ col.label(text="Edit:")
+ row = col.row(align=True)
+ row.active = edit_ok
+ row.operator("gpencil.copy", text="Copy")
+ row.operator("gpencil.paste", text="Paste")
+
+ subcol = col.column(align=True)
+ subcol.active = edit_ok
+ subcol.operator("gpencil.delete", text="Delete")
+ subcol.operator("gpencil.duplicate_move", text="Duplicate")
+ subcol.operator("transform.mirror", text="Mirror").gpencil_strokes = True
+
+ col.separator()
+
+ subcol = col.column(align=True)
+ subcol.active = edit_ok
+ subcol.operator("transform.translate").gpencil_strokes = True # icon='MAN_TRANS'
+ subcol.operator("transform.rotate").gpencil_strokes = True # icon='MAN_ROT'
+ subcol.operator("transform.resize", text="Scale").gpencil_strokes = True # icon='MAN_SCALE'
+
+ col.separator()
+
+ subcol = col.column(align=True)
+ subcol.active = edit_ok
+ subcol.operator("transform.bend", text="Bend").gpencil_strokes = True
+ subcol.operator("transform.shear", text="Shear").gpencil_strokes = True
+ subcol.operator("transform.tosphere", text="To Sphere").gpencil_strokes = True
+
+
+###############################
+
+class GPENCIL_PIE_tool_palette(Menu):
+ """A pie menu for quick access to Grease Pencil tools"""
+ bl_label = "Grease Pencil Tools"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ gpd = context.gpencil_data
+
+ # W - Drawing Types
+ col = pie.column()
+ col.operator("gpencil.draw", text="Draw", icon='GREASEPENCIL').mode = 'DRAW'
+ col.operator("gpencil.draw", text="Straight Lines", icon='LINE_DATA').mode = 'DRAW_STRAIGHT'
+ col.operator("gpencil.draw", text="Poly", icon='MESH_DATA').mode = 'DRAW_POLY'
+
+ # E - Eraser
+ # XXX: needs a dedicated icon...
+ col = pie.column()
+ col.operator("gpencil.draw", text="Eraser", icon='FORCE_CURVE').mode = 'ERASER'
+
+ # E - "Settings" Palette is included here too, since it needs to be in a stable position...
+ if gpd and gpd.layers.active:
+ col.separator()
+ col.operator("wm.call_menu_pie", text="Settings...", icon='SCRIPTWIN').name = "GPENCIL_PIE_settings_palette"
+
+ # Editing tools
+ if gpd:
+ if gpd.use_stroke_edit_mode and context.editable_gpencil_strokes:
+ # S - Exit Edit Mode
+ pie.prop(gpd, "use_stroke_edit_mode", text="Exit Edit Mode", icon='EDIT')
+
+ # N - Transforms
+ col = pie.column()
+ row = col.row(align=True)
+ row.operator("transform.translate", icon='MAN_TRANS').gpencil_strokes = True
+ row.operator("transform.rotate", icon='MAN_ROT').gpencil_strokes = True
+ row.operator("transform.resize", text="Scale", icon='MAN_SCALE').gpencil_strokes = True
+ row = col.row(align=True)
+ row.label("Proportional Edit:")
+ row.prop(context.tool_settings, "proportional_edit", text="", icon_only=True)
+ row.prop(context.tool_settings, "proportional_edit_falloff", text="", icon_only=True)
+
+ # NW - Select (Non-Modal)
+ col = pie.column()
+ col.operator("gpencil.select_all", text="Select All", icon='PARTICLE_POINT')
+ col.operator("gpencil.select_all", text="Select Inverse", icon='BLANK1')
+ col.operator("gpencil.select_linked", text="Select Linked", icon='LINKED')
+
+ # NE - Select (Modal)
+ col = pie.column()
+ col.operator("gpencil.select_border", text="Border Select", icon='BORDER_RECT')
+ col.operator("gpencil.select_circle", text="Circle Select", icon='META_EMPTY')
+ col.operator("gpencil.select_lasso", text="Lasso Select", icon='BORDER_LASSO')
+
+ # SW - Edit Tools
+ col = pie.column()
+ col.operator("gpencil.duplicate_move", icon='PARTICLE_PATH', text="Duplicate")
+ col.operator("gpencil.delete", icon='X', text="Delete...")
+
+ # SE - More Tools
+ pie.operator("wm.call_menu_pie", text="More...").name = "GPENCIL_PIE_tools_more"
+ else:
+ # Toggle Edit Mode
+ pie.prop(gpd, "use_stroke_edit_mode", text="Enable Stroke Editing", icon='EDIT')
+
+
+class GPENCIL_PIE_settings_palette(Menu):
+ """A pie menu for quick access to Grease Pencil settings"""
+ bl_label = "Grease Pencil Settings"
+
+ @classmethod
+ def poll(cls, context):
+ return bool(context.gpencil_data and context.active_gpencil_layer)
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ # gpd = context.gpencil_data
+ gpl = context.active_gpencil_layer
+
+ # W - Stroke draw settings
+ col = pie.column(align=True)
+ col.label(text="Stroke")
+ col.prop(gpl, "color", text="")
+ col.prop(gpl, "alpha", text="", slider=True)
+
+ # E - Fill draw settings
+ col = pie.column(align=True)
+ col.label(text="Fill")
+ col.prop(gpl, "fill_color", text="")
+ col.prop(gpl, "fill_alpha", text="", slider=True)
+
+ # S - Layer settings
+ col = pie.column()
+ col.prop(gpl, "line_width", slider=True)
+ # col.prop(gpl, "use_volumetric_strokes")
+ col.prop(gpl, "use_onion_skinning")
+
+ # N - Active Layer
+ # XXX: this should show an operator to change the active layer instead
+ col = pie.column()
+ col.label("Active Layer: ")
+ col.prop(gpl, "info", text="")
+ # col.prop(gpd, "layers")
+ row = col.row()
+ row.prop(gpl, "lock")
+ row.prop(gpl, "hide")
+
+
+class GPENCIL_PIE_tools_more(Menu):
+ """A pie menu for accessing more Grease Pencil tools"""
+ bl_label = "More Grease Pencil Tools"
+
+ @classmethod
+ def poll(cls, context):
+ gpd = context.gpencil_data
+ return bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes)
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ # gpd = context.gpencil_data
+
+ col = pie.column(align=True)
+ col.operator("gpencil.copy", icon='COPYDOWN', text="Copy")
+ col.operator("gpencil.paste", icon='PASTEDOWN', text="Paste")
+
+ col = pie.column(align=True)
+ col.operator("gpencil.select_more", icon='ZOOMIN')
+ col.operator("gpencil.select_less", icon='ZOOMOUT')
+
+ pie.operator("transform.mirror", icon='MOD_MIRROR').gpencil_strokes = True
+ pie.operator("transform.bend", icon='MOD_SIMPLEDEFORM').gpencil_strokes = True
+ pie.operator("transform.shear", icon='MOD_TRIANGULATE').gpencil_strokes = True
+ pie.operator("transform.tosphere", icon='MOD_MULTIRES').gpencil_strokes = True
+
+ pie.operator("gpencil.convert", icon='OUTLINER_OB_CURVE', text="Convert...")
+ pie.operator("wm.call_menu_pie", text="Back to Main Palette...").name = "GPENCIL_PIE_tool_palette"
+
+
+class GPENCIL_UL_layer(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.GPencilLayer)
+ gpl = item
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ if gpl.lock:
+ layout.active = False
+
+ split = layout.split(percentage=0.25)
+ row = split.row(align=True)
+ row.prop(gpl, "color", text="", emboss = gpl.is_stroke_visible)
+ row.prop(gpl, "fill_color", text="", emboss = gpl.is_fill_visible)
+ split.prop(gpl, "info", text="", emboss=False)
+
+ row = layout.row(align=True)
+ row.prop(gpl, "lock", text="", emboss=False)
+ row.prop(gpl, "hide", text="", emboss=False)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+class GreasePencilDataPanel():
+ # subclass must set
+ # bl_space_type = 'IMAGE_EDITOR'
+ bl_label = "Grease Pencil"
+ bl_region_type = 'UI'
+
+ @staticmethod
+ def draw_header(self, context):
+ self.layout.prop(context.space_data, "show_grease_pencil", text="")
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+
+ # owner of Grease Pencil data
+ gpd_owner = context.gpencil_data_owner
+ gpd = context.gpencil_data
+
+ # Owner Selector
+ if context.space_data.type == 'VIEW_3D':
+ layout.prop(context.tool_settings, "grease_pencil_source", expand=True)
+ elif context.space_data.type == 'CLIP_EDITOR':
+ layout.prop(context.space_data, "grease_pencil_source", expand=True)
+
+ # Grease Pencil data selector
+ layout.template_ID(gpd_owner, "grease_pencil", new="gpencil.data_add", unlink="gpencil.data_unlink")
+
+ # Grease Pencil data...
+ if gpd:
+ self.draw_layers(context, layout, gpd)
+
+ def draw_layers(self, context, layout, gpd):
+ row = layout.row()
+
+ col = row.column()
+ col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index", rows=5)
+
+ col = row.column()
+
+ sub = col.column(align=True)
+ sub.operator("gpencil.layer_add", icon='ZOOMIN', text="")
+ sub.operator("gpencil.layer_remove", icon='ZOOMOUT', text="")
+
+ gpl = context.active_gpencil_layer
+ if gpl:
+ sub.operator("gpencil.layer_duplicate", icon='COPY_ID', text="") # XXX: needs a dedicated icon
+
+ col.separator()
+
+ sub = col.column(align=True)
+ sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
+ sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
+
+ if gpl:
+ self.draw_layer(layout, gpl)
+
+ def draw_layer(self, layout, gpl):
+ # layer settings
+ split = layout.split(percentage=0.5)
+ split.active = not gpl.lock
+
+ # Column 1 - Stroke
+ col = split.column(align=True)
+ col.label(text="Stroke:")
+ col.prop(gpl, "color", text="")
+ col.prop(gpl, "alpha", slider=True)
+
+ # Column 2 - Fill
+ col = split.column(align=True)
+ col.label(text="Fill:")
+ col.prop(gpl, "fill_color", text="")
+ col.prop(gpl, "fill_alpha", text="Opacity", slider=True)
+
+ # Options
+ split = layout.split(percentage=0.5)
+ split.active = not gpl.lock
+
+ col = split.column(align=True)
+ col.prop(gpl, "line_width", slider=True)
+ col.prop(gpl, "use_volumetric_strokes")
+
+ col = split.column(align=True)
+ col.prop(gpl, "show_x_ray")
+
+ # if debug:
+ # layout.prop(gpl, "show_points")
+
+ layout.separator()
+
+ # Full-Row - Frame Locking (and Delete Frame)
+ row = layout.row(align=True)
+ row.active = not gpl.lock
+
+ if gpl.active_frame:
+ lock_status = "Locked" if gpl.lock_frame else "Unlocked"
+ lock_label = "Frame: %d (%s)" % (gpl.active_frame.frame_number, lock_status)
+ else:
+ lock_label = "Lock Frame"
+ row.prop(gpl, "lock_frame", text=lock_label, icon='UNLOCKED')
+ row.operator("gpencil.active_frame_delete", text="", icon='X')
+
+ layout.separator()
+
+ # Onion skinning
+ col = layout.column(align=True)
+ col.active = not gpl.lock
+
+ row = col.row()
+ row.prop(gpl, "use_onion_skinning")
+ row.prop(gpl, "use_ghost_custom_colors", text="", icon='COLOR')
+
+ split = col.split(percentage=0.5)
+ split.active = gpl.use_onion_skinning
+
+ # - Before Frames
+ sub = split.column(align=True)
+ row = sub.row(align=True)
+ row.active = gpl.use_ghost_custom_colors
+ row.prop(gpl, "before_color", text="")
+ sub.prop(gpl, "ghost_before_range", text="Before")
+
+ # - After Frames
+ sub = split.column(align=True)
+ row = sub.row(align=True)
+ row.active = gpl.use_ghost_custom_colors
+ row.prop(gpl, "after_color", text="")
+ sub.prop(gpl, "ghost_after_range", text="After")
+
+
+class GreasePencilToolsPanel():
+ # subclass must set
+ # bl_space_type = 'IMAGE_EDITOR'
+ # bl_options = {'DEFAULT_CLOSED'}
+ bl_label = "Grease Pencil Settings"
+ bl_region_type = 'UI'
+
+ @classmethod
+ def poll(cls, context):
+ return (context.gpencil_data is not None)
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+
+ # gpd_owner = context.gpencil_data_owner
+ gpd = context.gpencil_data
+
+ layout.prop(gpd, "use_stroke_edit_mode", text="Enable Editing", icon='EDIT', toggle=True)
+
+ layout.separator()
+
+ layout.label("Proportional Edit:")
+ row = layout.row()
+ row.prop(context.tool_settings, "proportional_edit", text="")
+ row.prop(context.tool_settings, "proportional_edit_falloff", text="")
+
+ layout.separator()
+ layout.separator()
+
+ gpencil_stroke_placement_settings(context, layout, gpd)
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index f1042856e4c..ba1947b0c66 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -243,24 +243,23 @@ def brush_texture_settings(layout, brush, sculpt):
layout.operator("brush.stencil_reset_transform")
# angle and texture_angle_source
- if brush.brush_capabilities.has_texture_angle:
+ if tex_slot.has_texture_angle:
col = layout.column()
col.label(text="Angle:")
- row = col.row(align=True)
- if brush.brush_capabilities.has_texture_angle_source:
- if brush.brush_capabilities.has_random_texture_angle:
+ col.prop(tex_slot, "angle", text="")
+ if tex_slot.has_texture_angle_source:
+ col.prop(tex_slot, "use_rake", text="Rake")
+
+ if brush.brush_capabilities.has_random_texture_angle and tex_slot.has_random_texture_angle:
if sculpt:
if brush.sculpt_capabilities.has_random_texture_angle:
- row.prop(brush, "texture_angle_source_random", text="")
- else:
- row.prop(brush, "texture_angle_source_no_random", text="")
-
+ col.prop(tex_slot, "use_random", text="Random")
+ if tex_slot.use_random:
+ col.prop(tex_slot, "random_angle", text="")
else:
- row.prop(brush, "texture_angle_source_random", text="")
- else:
- row.prop(brush, "texture_angle_source_no_random", text="")
-
- row.prop(tex_slot, "angle", text="")
+ col.prop(tex_slot, "use_random", text="Random")
+ if tex_slot.use_random:
+ col.prop(tex_slot, "random_angle", text="")
# scale and offset
split = layout.split()
@@ -290,9 +289,18 @@ def brush_mask_texture_settings(layout, brush):
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="")
+ # angle and texture_angle_source
+ if mask_tex_slot.has_texture_angle:
+ col = layout.column()
+ col.label(text="Angle:")
+ col.prop(mask_tex_slot, "angle", text="")
+ if mask_tex_slot.has_texture_angle_source:
+ col.prop(mask_tex_slot, "use_rake", text="Rake")
+
+ if brush.brush_capabilities.has_random_texture_angle and mask_tex_slot.has_random_texture_angle:
+ col.prop(mask_tex_slot, "use_random", text="Random")
+ if mask_tex_slot.use_random:
+ col.prop(mask_tex_slot, "random_angle", text="")
# scale and offset
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py
index 2494e49d812..554eef8f0f1 100644
--- a/release/scripts/startup/bl_ui/properties_render_layer.py
+++ b/release/scripts/startup/bl_ui/properties_render_layer.py
@@ -48,7 +48,7 @@ class RENDERLAYER_UL_renderlayers(UIList):
class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
bl_label = "Layer List"
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
def draw(self, context):
layout = self.layout
@@ -56,6 +56,10 @@ class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
scene = context.scene
rd = scene.render
+ if rd.engine == 'BLENDER_GAME':
+ layout.label("Not available in the Game Engine")
+ return
+
row = layout.row()
col = row.column()
col.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index 6532ea1d911..260e804ac88 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -62,7 +62,8 @@ class SCENE_PT_scene(SceneButtonsPanel, Panel):
layout.prop(scene, "camera")
layout.prop(scene, "background_set", text="Background")
- layout.prop(scene, "active_clip", text="Active Clip")
+ if context.scene.render.engine != 'BLENDER_GAME':
+ layout.prop(scene, "active_clip", text="Active Clip")
class SCENE_PT_unit(SceneButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index d43792bc61d..d2f2612c84e 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -21,7 +21,11 @@
import bpy
from bpy.types import Panel, Header, Menu, UIList
from bpy.app.translations import pgettext_iface as iface_
-from bl_ui.properties_grease_pencil_common import GreasePencilPanel
+from bl_ui.properties_grease_pencil_common import (
+ GreasePencilDrawingToolsPanel,
+ GreasePencilStrokeEditPanel,
+ GreasePencilDataPanel
+ )
class CLIP_UL_tracking_objects(UIList):
@@ -422,7 +426,9 @@ class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel):
col = layout.column()
row = col.row()
row.prop(settings, "use_tripod_solver", text="Tripod")
- row.prop(settings, "use_keyframe_selection", text="Keyframe")
+ sub = row.row()
+ sub.active = not settings.use_tripod_solver
+ sub.prop(settings, "use_keyframe_selection", text="Keyframe")
col = layout.column(align=True)
col.active = (not settings.use_tripod_solver and
@@ -1050,12 +1056,6 @@ class CLIP_PT_tools_mask(MASK_PT_tools, Panel):
# --- end mask ---
-class CLIP_PT_tools_grease_pencil(GreasePencilPanel, Panel):
- bl_space_type = 'CLIP_EDITOR'
- bl_region_type = 'TOOLS'
- bl_category = "Grease Pencil"
-
-
class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'UI'
@@ -1110,6 +1110,26 @@ class CLIP_PT_tools_scenesetup(Panel):
layout.operator("clip.setup_tracking_scene")
+# Grease Pencil properties
+class CLIP_PT_grease_pencil(GreasePencilDataPanel, CLIP_PT_clip_view_panel, Panel):
+ bl_space_type = 'CLIP_EDITOR'
+ bl_region_type = 'UI'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+ # But, this should only be visible in "clip" view
+
+
+# Grease Pencil drawing tools
+class CLIP_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
+ bl_space_type = 'CLIP_EDITOR'
+
+
+# Grease Pencil stroke editing tools
+class CLIP_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
+ bl_space_type = 'CLIP_EDITOR'
+
+
class CLIP_MT_view(Menu):
bl_label = "View"
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index 79240bbf72a..f901d9d9262 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -91,6 +91,8 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False):
row.prop(dopesheet, "show_speakers", text="")
if bpy.data.linestyles:
row.prop(dopesheet, "show_linestyles", text="")
+ if bpy.data.grease_pencil:
+ row.prop(dopesheet, "show_gpencil", text="")
#######################################
@@ -129,6 +131,8 @@ class DOPESHEET_HT_header(Header):
row = layout.row(align=True)
row.operator("action.copy", text="", icon='COPYDOWN')
row.operator("action.paste", text="", icon='PASTEDOWN')
+ row.operator("action.paste", text="", icon='PASTEFLIPDOWN').flipped = True
+
class DOPESHEET_MT_editor_menus(Menu):
@@ -365,14 +369,16 @@ class DOPESHEET_MT_gpencil_frame(Menu):
layout = self.layout
layout.menu("DOPESHEET_MT_key_transform", text="Transform")
-
- #layout.operator_menu_enum("action.snap", "type", text="Snap")
- #layout.operator_menu_enum("action.mirror", "type", text="Mirror")
+ layout.operator_menu_enum("action.snap", "type", text="Snap")
+ layout.operator_menu_enum("action.mirror", "type", text="Mirror")
layout.separator()
layout.operator("action.duplicate")
layout.operator("action.delete")
+ layout.separator()
+ layout.operator("action.keyframe_type")
+
#layout.separator()
#layout.operator("action.copy")
#layout.operator("action.paste")
diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index b90eb7a89c3..6fe50c7eeb5 100644
--- a/release/scripts/startup/bl_ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -55,7 +55,7 @@ class FILEBROWSER_HT_header(Header):
layout.prop(params, "display_type", expand=True, text="")
layout.prop(params, "sort_method", expand=True, text="")
- layout.prop(params, "show_hidden")
+ layout.prop(params, "show_hidden", text="", icon='FILE_HIDDEN')
layout.prop(params, "use_filter", text="", icon='FILTER')
row = layout.row(align=True)
@@ -77,5 +77,9 @@ class FILEBROWSER_HT_header(Header):
row.prop(params, "use_filter_sound", text="")
row.prop(params, "use_filter_text", text="")
+ row.separator()
+ row.prop(params, "filter_search", text="", icon='VIEWZOOM')
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 6fc3d9e4f2b..6b784033bfb 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -52,6 +52,7 @@ class GRAPH_HT_header(Header):
row = layout.row(align=True)
row.operator("graph.copy", text="", icon='COPYDOWN')
row.operator("graph.paste", text="", icon='PASTEDOWN')
+ row.operator("graph.paste", text="", icon='PASTEFLIPDOWN').flipped = True
row = layout.row(align=True)
if st.has_ghost_curves:
@@ -189,10 +190,14 @@ class GRAPH_MT_channel(Menu):
layout.separator()
layout.operator("anim.channels_editable_toggle")
- layout.operator("anim.channels_visibility_set")
layout.operator_menu_enum("graph.extrapolation_type", "type", text="Extrapolation Mode")
layout.separator()
+ layout.operator("graph.hide", text="Hide Selected Curves").unselected = False
+ layout.operator("graph.hide", text="Hide Unselected Curves").unselected = True
+ layout.operator("graph.reveal")
+
+ layout.separator()
layout.operator("anim.channels_expand")
layout.operator("anim.channels_collapse")
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 56c0bda5608..a1da262d9f2 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -25,7 +25,11 @@ from bl_ui.properties_paint_common import (
brush_texpaint_common,
brush_mask_texture_settings,
)
-from bl_ui.properties_grease_pencil_common import GreasePencilPanel
+from bl_ui.properties_grease_pencil_common import (
+ GreasePencilDrawingToolsPanel,
+ GreasePencilStrokeEditPanel,
+ GreasePencilDataPanel
+ )
from bpy.app.translations import pgettext_iface as iface_
@@ -1149,10 +1153,21 @@ class IMAGE_PT_scope_sample(Panel):
sub.prop(sima.scopes, "accuracy")
-class IMAGE_PT_tools_grease_pencil(GreasePencilPanel, Panel):
+# Grease Pencil properties
+class IMAGE_PT_grease_pencil(GreasePencilDataPanel, Panel):
+ bl_space_type = 'IMAGE_EDITOR'
+ bl_region_type = 'UI'
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+
+# Grease Pencil drawing tools
+class IMAGE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
+ bl_space_type = 'IMAGE_EDITOR'
+
+
+# Grease Pencil stroke editing tools
+class IMAGE_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
bl_space_type = 'IMAGE_EDITOR'
- bl_region_type = 'TOOLS'
- bl_category = "Grease Pencil"
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index 67b2bbe1905..b642b61fcdc 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -57,12 +57,15 @@ 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:
- row.label("Auto-run disabled: %s" % bpy.app.autoexec_fail_message, icon='ERROR')
+ row.label("Auto-run disabled", icon='ERROR')
if bpy.data.is_saved:
props = row.operator("wm.revert_mainfile", icon='SCREEN_BACK', text="Reload Trusted")
props.use_scripts = True
row.operator("script.autoexec_warn_clear", text="Ignore")
+
+ # include last so text doesn't push buttons out of the header
+ row.label(bpy.app.autoexec_fail_message)
return
row.operator("wm.splash", text="", icon='BLENDER', emboss=False)
@@ -129,6 +132,7 @@ class INFO_MT_file(Menu):
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.link", text="Link", icon='LINK_BLEND')
layout.operator("wm.append", text="Append", icon='APPEND_BLEND')
+ layout.menu("INFO_MT_file_previews")
layout.separator()
@@ -192,6 +196,15 @@ class INFO_MT_file_external_data(Menu):
layout.operator("file.find_missing_files")
+class INFO_MT_file_previews(Menu):
+ bl_label = "Data Previews"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("wm.previews_ensure")
+
+
class INFO_MT_game(Menu):
bl_label = "Game"
@@ -276,7 +289,7 @@ class INFO_MT_help(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("wm.url_open", text="Manual", icon='HELP').url = "http://wiki.blender.org/index.php/Doc:2.6/Manual"
+ layout.operator("wm.url_open", text="Manual", icon='HELP').url = "http://www.blender.org/manual"
layout.operator("wm.url_open", text="Release Log", icon='URL').url = "http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/%d.%d" % bpy.app.version[:2]
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 17eeeec2480..4cc72f1dc4b 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -19,6 +19,12 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
+from bl_ui.properties_grease_pencil_common import (
+ GreasePencilDrawingToolsPanel,
+ GreasePencilStrokeEditPanel,
+ GreasePencilDataPanel,
+ GreasePencilToolsPanel,
+ )
class NODE_HT_header(Header):
@@ -439,6 +445,45 @@ class NODE_UL_interface_sockets(bpy.types.UIList):
layout.template_node_socket(color)
+# Grease Pencil properties
+class NODE_PT_grease_pencil(GreasePencilDataPanel, Panel):
+ bl_space_type = 'NODE_EDITOR'
+ bl_region_type = 'UI'
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+
+ @classmethod
+ def poll(cls, context):
+ snode = context.space_data
+ return snode is not None and snode.node_tree is not None
+
+
+class NODE_PT_grease_pencil_tools(GreasePencilToolsPanel, Panel):
+ bl_space_type = 'NODE_EDITOR'
+ bl_region_type = 'UI'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ # NOTE: this is just a wrapper around the generic GP tools panel
+ # It contains access to some essential tools usually found only in
+ # toolbar, but which may not necessarily be open
+
+
+# Tool Shelf ------------------
+
+
+# Grease Pencil drawing tools
+class NODE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
+ bl_space_type = 'NODE_EDITOR'
+ bl_region_type = 'TOOLS'
+
+
+# Grease Pencil stroke editing tools
+class NODE_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
+ bl_space_type = 'NODE_EDITOR'
+ bl_region_type = 'TOOLS'
+
+# -----------------------------
+
def node_draw_tree_view(layout, context):
pass
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index feb90da3d63..66b3cbe73d9 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
+from bl_ui.properties_grease_pencil_common import GreasePencilDataPanel, GreasePencilToolsPanel
from bpy.app.translations import pgettext_iface as iface_
@@ -82,6 +83,7 @@ class SEQUENCER_HT_header(Header):
layout.separator()
layout.operator("sequencer.refresh_all")
+ layout.prop(st, "show_backdrop")
else:
if st.view_type == 'SEQUENCER_PREVIEW':
layout.separator()
@@ -101,6 +103,17 @@ class SEQUENCER_HT_header(Header):
row = layout.row()
row.prop(st, "overlay_type", text="")
+ if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
+ gpd = context.gpencil_data
+ toolsettings = context.tool_settings
+
+ # Proportional editing
+ if gpd and gpd.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.prop(toolsettings, "proportional_edit", icon_only=True)
+ if toolsettings.proportional_edit != 'DISABLED':
+ row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
+
row = layout.row(align=True)
row.operator("render.opengl", text="", icon='RENDER_STILL').sequencer = True
props = row.operator("render.opengl", text="", icon='RENDER_ANIMATION')
@@ -149,8 +162,10 @@ class SEQUENCER_MT_view(Menu):
layout = self.layout
st = context.space_data
+ is_preview = st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}
+ is_sequencer_view = st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}
- if st.view_type in {'PREVIEW'}:
+ if st.view_type == 'PREVIEW':
# Specifying the REGION_PREVIEW context is needed in preview-only
# mode, else the lookup for the shortcut will fail in
# wm_keymap_item_find_props() (see #32595).
@@ -160,10 +175,10 @@ class SEQUENCER_MT_view(Menu):
layout.separator()
- if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
+ if is_sequencer_view:
layout.operator("sequencer.view_all", text="View all Sequences")
layout.operator("sequencer.view_selected")
- if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
+ if is_preview:
layout.operator_context = 'INVOKE_REGION_PREVIEW'
layout.operator("sequencer.view_all_preview", text="Fit preview in window")
@@ -181,11 +196,14 @@ class SEQUENCER_MT_view(Menu):
# # XXX, invokes in the header view
# layout.operator("sequencer.view_ghost_border", text="Overlay Border")
- if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
+ if is_sequencer_view:
layout.prop(st, "show_seconds")
layout.prop(st, "show_frame_indicator")
+ layout.prop(st, "show_strip_offset")
- if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
+ layout.prop_menu_enum(st, "waveform_draw_type")
+
+ if is_preview:
if st.display_mode == 'IMAGE':
layout.prop(st, "show_safe_margin")
elif st.display_mode == 'WAVEFORM':
@@ -193,7 +211,7 @@ class SEQUENCER_MT_view(Menu):
layout.separator()
- if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
+ if is_sequencer_view:
layout.prop(st, "use_marker_sync")
layout.separator()
@@ -428,7 +446,8 @@ class SequencerButtonsPanel_Output():
@staticmethod
def has_preview(context):
- return (context.space_data.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'})
+ st = context.space_data
+ return (st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}) or st.show_backdrop
@classmethod
def poll(cls, context):
@@ -716,6 +735,7 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ st = context.space_data
strip = act_strip(context)
sound = strip.sound
@@ -734,7 +754,9 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
row.prop(sound, "use_memory_cache")
- layout.prop(strip, "show_waveform")
+ if st.waveform_draw_type == 'DEFAULT_WAVEFORMS':
+ layout.prop(strip, "show_waveform")
+
layout.prop(strip, "volume")
layout.prop(strip, "pitch")
layout.prop(strip, "pan")
@@ -776,6 +798,8 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
layout.label(text="Camera Override")
layout.template_ID(strip, "scene_camera")
+ layout.prop(strip, "use_grease_pencil", text="Show Grease Pencil")
+
if scene:
layout.prop(scene, "audio_volume", text="Audio Volume")
@@ -1012,5 +1036,22 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
col.prop(mod, "contrast")
+class SEQUENCER_PT_grease_pencil(GreasePencilDataPanel, SequencerButtonsPanel_Output, Panel):
+ bl_space_type = 'SEQUENCE_EDITOR'
+ bl_region_type = 'UI'
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+ # But, it should only show up when there are images in the preview region
+
+
+class SEQUENCER_PT_grease_pencil_tools(GreasePencilToolsPanel, SequencerButtonsPanel_Output, Panel):
+ bl_space_type = 'SEQUENCE_EDITOR'
+ bl_region_type = 'UI'
+
+ # NOTE: this is just a wrapper around the generic GP tools panel
+ # It contains access to some essential tools usually found only in
+ # toolbar, which doesn't exist here...
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 82621154450..10394e50581 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -776,7 +776,7 @@ class USERPREF_PT_theme(Panel):
padding = subsplit.split(percentage=0.15)
colsub = padding.column()
colsub = padding.column()
- colsub.row().prop(ui, "emboss")
+ colsub.row().prop(ui, "widget_emboss")
col.separator()
col.separator()
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 0ea552e51e7..1db3aa0d144 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
+from bl_ui.properties_grease_pencil_common import GreasePencilDataPanel
from bl_ui.properties_paint_common import UnifiedPaintPanel
from bpy.app.translations import contexts as i18n_contexts
@@ -56,7 +57,12 @@ class VIEW3D_HT_header(Header):
row.prop(view, "use_occlude_geometry", text="")
# Proportional editing
- if mode in {'EDIT', 'PARTICLE_EDIT'}:
+ if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.prop(toolsettings, "proportional_edit", icon_only=True)
+ if toolsettings.proportional_edit != 'DISABLED':
+ row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
+ elif mode in {'EDIT', 'PARTICLE_EDIT'}:
row = layout.row(align=True)
row.prop(toolsettings, "proportional_edit", icon_only=True)
if toolsettings.proportional_edit != 'DISABLED':
@@ -66,6 +72,13 @@ class VIEW3D_HT_header(Header):
row.prop(toolsettings, "use_proportional_edit_objects", icon_only=True)
if toolsettings.use_proportional_edit_objects:
row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
+ else:
+ # Proportional editing
+ if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.prop(toolsettings, "proportional_edit", icon_only=True)
+ if toolsettings.proportional_edit != 'DISABLED':
+ row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
# Snap
if not obj or mode not in {'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT'}:
@@ -1082,6 +1095,8 @@ class VIEW3D_MT_object(Menu):
layout.separator()
layout.operator("object.join")
+ layout.operator("object.data_transfer")
+ layout.operator("object.datalayout_transfer")
layout.separator()
@@ -1154,12 +1169,16 @@ class VIEW3D_MT_object_specials(Menu):
props.header_text = "Camera Lens Scale: %.3f"
if not obj.data.dof_object:
- #layout.label(text="Test Has DOF obj");
- props = layout.operator("wm.context_modal_mouse", text="DOF Distance")
- props.data_path_iter = "selected_editable_objects"
- props.data_path_item = "data.dof_distance"
- props.input_scale = 0.02
- props.header_text = "DOF Distance: %.3f"
+ view = context.space_data
+ if view and view.camera == obj and view.region_3d.view_perspective == 'CAMERA':
+ props = layout.operator("ui.eyedropper_depth", text="DOF Distance (Pick)")
+ else:
+ props = layout.operator("wm.context_modal_mouse", text="DOF Distance")
+ props.data_path_iter = "selected_editable_objects"
+ props.data_path_item = "data.dof_distance"
+ props.input_scale = 0.02
+ props.header_text = "DOF Distance: %.3f"
+ del view
if obj.type in {'CURVE', 'FONT'}:
layout.operator_context = 'INVOKE_REGION_WIN'
@@ -1588,7 +1607,9 @@ class VIEW3D_MT_paint_weight(Menu):
layout.operator("object.vertex_group_quantize", text="Quantize")
layout.operator("object.vertex_group_levels", text="Levels")
layout.operator("object.vertex_group_blend", text="Blend")
- layout.operator("object.vertex_group_transfer_weight", text="Transfer Weights")
+ prop = layout.operator("object.data_transfer", text="Transfer Weights")
+ prop.use_reverse_transfer = True
+ prop.data_type = 'VGROUP_WEIGHTS'
layout.operator("object.vertex_group_limit_total", text="Limit Total")
layout.operator("object.vertex_group_fix", text="Fix Deforms")
@@ -2434,7 +2455,6 @@ class VIEW3D_MT_edit_curve_ctrlpoints(Menu):
if edit_object.type == 'CURVE':
layout.operator("transform.tilt")
layout.operator("curve.tilt_clear")
- layout.operator("curve.separate")
layout.separator()
@@ -2703,6 +2723,12 @@ class VIEW3D_MT_edit_armature_roll(Menu):
# ********** Panel **********
+class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'UI'
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+
class VIEW3D_PT_view3d_properties(Panel):
bl_space_type = 'VIEW_3D'
@@ -2813,6 +2839,7 @@ class VIEW3D_PT_view3d_display(Panel):
col = layout.column()
col.prop(view, "show_only_render")
+ col.prop(view, "show_world")
col = layout.column()
display_all = not view.show_only_render
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 95e2f440170..884de8356e2 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -19,7 +19,10 @@
# <pep8 compliant>
import bpy
from bpy.types import Menu, Panel, UIList
-from bl_ui.properties_grease_pencil_common import GreasePencilPanel
+from bl_ui.properties_grease_pencil_common import (
+ GreasePencilDrawingToolsPanel,
+ GreasePencilStrokeEditPanel
+ )
from bl_ui.properties_paint_common import (
UnifiedPaintPanel,
brush_texture_settings,
@@ -97,6 +100,13 @@ class VIEW3D_PT_tools_object(View3DPanel, Panel):
row.operator("object.shade_smooth", text="Smooth")
row.operator("object.shade_flat", text="Flat")
+ if obj_type in {'MESH'}:
+ col = layout.column(align=True)
+ col.label(text="Data Transfer:")
+ row = col.row(align=True)
+ row.operator("object.data_transfer", text="Data")
+ row.operator("object.datalayout_transfer", text="Data Layout")
+
class VIEW3D_PT_tools_add_object(View3DPanel, Panel):
bl_category = "Create"
@@ -794,7 +804,7 @@ class VIEW3D_PT_imapaint_tools_missing(Panel, View3DPaintPanel):
if toolsettings.missing_uvs:
col.separator()
col.label("Missing UVs", icon='INFO')
- col.label("Unwrap the mesh in edit mode or generate a simple UVs")
+ col.label("Unwrap the mesh in edit mode or generate a simple UV layer")
col.operator("paint.add_simple_uvs")
if toolsettings.mode == 'MATERIAL':
@@ -1587,7 +1597,9 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
col = layout.column()
col.operator("paint.weight_gradient")
- col.operator("object.vertex_group_transfer_weight", text="Transfer Weights")
+ prop = col.operator("object.data_transfer", text="Transfer Weights")
+ prop.use_reverse_transfer = True
+ prop.data_type = 'VGROUP_WEIGHTS'
class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
@@ -1801,11 +1813,14 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
sub.prop(pe, "fade_frames", slider=True)
-# Grease Pencil tools
-class VIEW3D_PT_tools_grease_pencil(GreasePencilPanel, Panel):
+# Grease Pencil drawing tools
+class VIEW3D_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
+ bl_space_type = 'VIEW_3D'
+
+
+# Grease Pencil stroke editing tools
+class VIEW3D_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
bl_space_type = 'VIEW_3D'
- bl_region_type = 'TOOLS'
- bl_category = "Grease Pencil"
# Note: moved here so that it's always in last position in 'Tools' panels!
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 8c2476bd430..1590bd49763 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -150,6 +150,7 @@ shader_node_categories = [
NodeItem("ShaderNodeRGBCurve"),
NodeItem("ShaderNodeInvert"),
NodeItem("ShaderNodeHueSaturation"),
+ NodeItem("ShaderNodeGamma"),
]),
ShaderOldNodeCategory("SH_OP_VECTOR", "Vector", items=[
NodeItem("ShaderNodeNormal"),
diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py
index 1aa13c90ca3..b72b2f76750 100644
--- a/release/scripts/templates_py/operator_modal_view3d_raycast.py
+++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py
@@ -14,10 +14,6 @@ def main(context, event, ray_max=1000.0):
view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
- if rv3d.view_perspective == 'ORTHO':
- # move ortho origin back
- ray_origin = ray_origin - (view_vector * (ray_max / 2.0))
-
ray_target = ray_origin + (view_vector * ray_max)
def visible_objects_and_duplis():
diff --git a/release/text/readme.html b/release/text/readme.html
index 0a0d16f0a54..6dbd3544a56 100644
--- a/release/text/readme.html
+++ b/release/text/readme.html
@@ -57,7 +57,7 @@
<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.73"><span class="s4">wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.73</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>
+Manual <a href="http://www.blender.org/manual"><span class="s4">www.blender.org/manual</span></a><br>
User Forum <a href="http://www.blenderartists.org/"><span class="s4">www.blenderartists.org</span></a><br>
IRC <a href="irc://irc.freenode.net/#blenderchat"><span class="s4">#blenderchat</span></a> or <a href="irc://irc.freenode.net/#blender"><span class="s4">#blender</span></a> on irc.freenode.net</span></p>
<p class="p4">Developers:</p>
diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h
index c11996799ff..b42e6f80022 100644
--- a/source/blender/blenfont/BLF_translation.h
+++ b/source/blender/blenfont/BLF_translation.h
@@ -163,6 +163,8 @@ const char *BLF_translate_do_new_dataname(const char *msgctxt, const char *msgid
#define BLF_I18NCONTEXT_ID_MESH "Mesh"
#define BLF_I18NCONTEXT_ID_NODETREE "NodeTree"
#define BLF_I18NCONTEXT_ID_OBJECT "Object"
+#define BLF_I18NCONTEXT_ID_PAINTCURVE "PaintCurve"
+#define BLF_I18NCONTEXT_ID_PALETTE "Palette"
#define BLF_I18NCONTEXT_ID_PARTICLESETTINGS "ParticleSettings"
#define BLF_I18NCONTEXT_ID_SCENE "Scene"
#define BLF_I18NCONTEXT_ID_SCREEN "Screen"
@@ -207,11 +209,15 @@ typedef struct
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_LAMP, "id_lamp"), \
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_LIBRARY, "id_library"), \
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_LATTICE, "id_lattice"), \
+ BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MASK, "id_mask"), \
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MATERIAL, "id_material"), \
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_METABALL, "id_metaball"), \
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MESH, "id_mesh"), \
+ BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MOVIECLIP, "id_movieclip"), \
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_NODETREE, "id_nodetree"), \
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_OBJECT, "id_object"), \
+ BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_PAINTCURVE, "id_paintcurve"), \
+ BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_PALETTE, "id_palette"), \
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_PARTICLESETTINGS, "id_particlesettings"), \
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SCENE, "id_scene"), \
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SCREEN, "id_screen"), \
@@ -223,8 +229,6 @@ typedef struct
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_VFONT, "id_vfont"), \
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_WORLD, "id_world"), \
BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_WINDOWMANAGER, "id_windowmanager"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MOVIECLIP, "id_movieclip"), \
- BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MASK, "id_mask"), \
{NULL, NULL, NULL} \
}
diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt
index 346d5bc64b8..392a9ede100 100644
--- a/source/blender/blenfont/CMakeLists.txt
+++ b/source/blender/blenfont/CMakeLists.txt
@@ -56,6 +56,12 @@ set(SRC
intern/blf_internal_types.h
)
+if(WIN32)
+ list(APPEND SRC
+ intern/blf_font_win32_compat.c
+ )
+endif()
+
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 4891c332c87..087c7c7345e 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -65,6 +65,10 @@
#include "BLI_strict_flags.h"
+#ifdef WIN32
+# define FT_New_Face FT_New_Face__win32_compat
+#endif
+
/* freetype2 handle ONLY for this file!. */
static FT_Library ft_lib;
static SpinLock ft_lib_mutex;
diff --git a/source/blender/blenfont/intern/blf_font_win32_compat.c b/source/blender/blenfont/intern/blf_font_win32_compat.c
new file mode 100644
index 00000000000..dd4a443e69f
--- /dev/null
+++ b/source/blender/blenfont/intern/blf_font_win32_compat.c
@@ -0,0 +1,145 @@
+/*
+ * ***** 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/blenfont/intern/blf_font_win32_compat.c
+ * \ingroup blf
+ *
+ * Workaround for win32 which needs to use BLI_fopen to access files.
+ *
+ * defines #FT_New_Face__win32_compat, a drop-in replacement for \a #FT_New_Face.
+ */
+
+#ifdef WIN32
+
+#include <stdio.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_fileops.h"
+
+#include "blf_internal.h"
+
+/* internal freetype defines */
+#define STREAM_FILE(stream) ((FILE *)stream->descriptor.pointer)
+#define FT_THROW(e) -1
+
+static void ft_ansi_stream_close(
+ FT_Stream stream)
+{
+ fclose(STREAM_FILE(stream));
+
+ stream->descriptor.pointer = NULL;
+ stream->size = 0;
+ stream->base = 0;
+
+ /* WARNING: this works but be careful!
+ * Checked freetype sources, there isn't any access after closing. */
+ MEM_freeN(stream);
+}
+
+static unsigned long ft_ansi_stream_io(
+ FT_Stream stream,
+ unsigned long offset,
+ unsigned char *buffer,
+ unsigned long count)
+{
+ FILE *file;
+ if (!count && offset > stream->size)
+ return 1;
+
+ file = STREAM_FILE(stream);
+
+ if (stream->pos != offset)
+ fseek(file, offset, SEEK_SET);
+
+ return fread(buffer, 1, count, file);
+}
+
+static FT_Error FT_Stream_Open__win32_compat(FT_Stream stream, const char *filepathname)
+{
+ FILE *file;
+ BLI_assert(stream);
+
+ stream->descriptor.pointer = NULL;
+ stream->pathname.pointer = (char *)filepathname;
+ stream->base = 0;
+ stream->pos = 0;
+ stream->read = NULL;
+ stream->close = NULL;
+
+ file = BLI_fopen(filepathname, "rb");
+ if (!file) {
+ fprintf(stderr,
+ "FT_Stream_Open: "
+ "could not open `%s'\n", filepathname);
+ return FT_THROW(Cannot_Open_Resource);
+ }
+
+ fseek(file, 0, SEEK_END);
+ stream->size = ftell(file);
+ if (!stream->size) {
+ fprintf(stderr,
+ "FT_Stream_Open: "
+ "opened `%s' but zero-sized\n", filepathname);
+ fclose(file);
+ return FT_THROW(Cannot_Open_Stream);
+ }
+
+ fseek(file, 0, SEEK_SET);
+
+ stream->descriptor.pointer = file;
+ stream->read = ft_ansi_stream_io;
+ stream->close = ft_ansi_stream_close;
+
+ return FT_Err_Ok;
+}
+
+FT_Error FT_New_Face__win32_compat(
+ FT_Library library,
+ const char *pathname,
+ FT_Long face_index,
+ FT_Face *aface)
+{
+ FT_Error err;
+ FT_Open_Args open;
+ FT_Stream stream = NULL;
+ stream = MEM_callocN(sizeof(*stream), __func__);
+
+ open.flags = FT_OPEN_STREAM;
+ open.stream = stream;
+ stream->pathname.pointer = (char *)pathname;
+
+ err = FT_Stream_Open__win32_compat(stream, pathname);
+ if (err) {
+ MEM_freeN(stream);
+ return err;
+ }
+
+ err = FT_Open_Face(library, &open, face_index, aface);
+ /* no need to free 'stream', its handled by FT_Open_Face if an error occurs */
+
+ return err;
+}
+
+#endif /* WIN32 */
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 7978d28a4ef..c65a0825a49 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -262,8 +262,8 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
g->xoff = -1;
g->yoff = -1;
bitmap = slot->bitmap;
- g->width = bitmap.width;
- g->height = bitmap.rows;
+ g->width = (int)bitmap.width;
+ g->height = (int)bitmap.rows;
if (g->width && g->height) {
if (sharp) {
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index 8cb2d377449..39b3e3397be 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -75,4 +75,11 @@ struct GlyphBLF *blf_glyph_add(struct FontBLF *font, unsigned int index, unsigne
void blf_glyph_free(struct GlyphBLF *g);
void blf_glyph_render(struct FontBLF *font, struct GlyphBLF *g, float x, float y);
+#ifdef WIN32
+/* blf_font_win32_compat.c */
+# ifdef FT_FREETYPE_H
+extern FT_Error FT_New_Face__win32_compat(FT_Library library, const char *pathname, FT_Long face_index, FT_Face *aface);
+# endif
+#endif
+
#endif /* __BLF_INTERNAL_H__ */
diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c
index 12d71827136..10614e8ca59 100644
--- a/source/blender/blenfont/intern/blf_lang.c
+++ b/source/blender/blenfont/intern/blf_lang.c
@@ -42,6 +42,7 @@
#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BKE_appdir.h"
#include "DNA_userdef_types.h"
@@ -79,7 +80,7 @@ static void free_locales(void)
static void fill_locales(void)
{
- const char * const languages_path = BLI_get_folder(BLENDER_DATAFILES, "locale");
+ const char * const languages_path = BKE_appdir_folder_id(BLENDER_DATAFILES, "locale");
char languages[FILE_MAX];
LinkNode *lines = NULL, *line;
char *str;
@@ -187,7 +188,7 @@ EnumPropertyItem *BLF_RNA_lang_enum_properties(void)
void BLF_lang_init(void)
{
#ifdef WITH_INTERNATIONAL
- const char * const messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale");
+ const char * const messagepath = BKE_appdir_folder_id(BLENDER_DATAFILES, "locale");
if (messagepath) {
bl_locale_init(messagepath, TEXT_DOMAIN_NAME);
diff --git a/source/blender/blenfont/intern/blf_translation.c b/source/blender/blenfont/intern/blf_translation.c
index 150ff1b2107..e7d2c14b16f 100644
--- a/source/blender/blenfont/intern/blf_translation.c
+++ b/source/blender/blenfont/intern/blf_translation.c
@@ -42,6 +42,8 @@
#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BKE_appdir.h"
+
#include "DNA_userdef_types.h" /* For user settings. */
#include "BPY_extern.h"
@@ -62,7 +64,7 @@ unsigned char *BLF_get_unifont(int *r_unifont_size)
{
#ifdef WITH_INTERNATIONAL
if (unifont_ttf == NULL) {
- const char * const fontpath = BLI_get_folder(BLENDER_DATAFILES, "fonts");
+ const char * const fontpath = BKE_appdir_folder_id(BLENDER_DATAFILES, "fonts");
if (fontpath) {
char unifont_path[1024];
@@ -97,7 +99,7 @@ unsigned char *BLF_get_unifont_mono(int *r_unifont_size)
{
#ifdef WITH_INTERNATIONAL
if (unifont_mono_ttf == NULL) {
- const char *fontpath = BLI_get_folder(BLENDER_DATAFILES, "fonts");
+ const char *fontpath = BKE_appdir_folder_id(BLENDER_DATAFILES, "fonts");
if (fontpath) {
char unifont_path[1024];
diff --git a/source/blender/blenfont/intern/blf_util.c b/source/blender/blenfont/intern/blf_util.c
index 06309a944e9..cdd81e33b0a 100644
--- a/source/blender/blenfont/intern/blf_util.c
+++ b/source/blender/blenfont/intern/blf_util.c
@@ -38,7 +38,6 @@
#include "blf_internal.h"
#include "BLI_utildefines.h"
-#include "BLI_string_utf8.h"
unsigned int blf_next_p2(unsigned int x)
{
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 229d2fc17cd..da4fcb4eca4 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -147,6 +147,7 @@ typedef int (*DMSetMaterial)(int mat_nr, void *attribs);
typedef int (*DMCompareDrawOptions)(void *userData, int cur_index, int next_index);
typedef void (*DMSetDrawInterpOptions)(void *userData, int index, float t);
typedef DMDrawOption (*DMSetDrawOptions)(void *userData, int index);
+typedef DMDrawOption (*DMSetDrawOptionsMappedTex)(void *userData, int origindex, int mat_nr);
typedef DMDrawOption (*DMSetDrawOptionsTex)(struct MTFace *tface, const bool has_vcol, int matnr);
typedef enum DMDrawFlag {
@@ -423,7 +424,7 @@ struct DerivedMesh {
* - Drawing options too complicated to enumerate, look at code.
*/
void (*drawMappedFacesTex)(DerivedMesh *dm,
- DMSetDrawOptions setDrawOptions,
+ DMSetDrawOptionsMappedTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData, DMDrawFlag uvflag);
diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h
new file mode 100644
index 00000000000..5e42f17be03
--- /dev/null
+++ b/source/blender/blenkernel/BKE_appdir.h
@@ -0,0 +1,80 @@
+/*
+ * ***** 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 __BKE_APPDIR_H__
+#define __BKE_APPDIR_H__
+
+/** \file BKE_appdir.h
+ * \ingroup bli
+ */
+
+/* note on naming: typical _get() suffix is omitted here,
+ * since its the main purpose of the API. */
+const char *BKE_appdir_folder_default(void);
+const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder);
+const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfolder);
+const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder);
+const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, const bool do_check);
+
+/* Initialize path to program executable */
+void BKE_appdir_program_path_init(const char *argv0);
+
+const char *BKE_appdir_program_path(void);
+const char *BKE_appdir_program_dir(void);
+
+/* Initialize path to temporary directory. */
+void BKE_tempdir_init(char *userdir);
+void BKE_tempdir_system_init(char *dir);
+
+const char *BKE_tempdir_base(void);
+const char *BKE_tempdir_session(void);
+void BKE_tempdir_session_purge(void);
+
+
+/* folder_id */
+enum {
+ /* general, will find based on user/local/system priority */
+ BLENDER_DATAFILES = 2,
+
+ /* user-specific */
+ BLENDER_USER_CONFIG = 31,
+ BLENDER_USER_DATAFILES = 32,
+ BLENDER_USER_SCRIPTS = 33,
+ BLENDER_USER_AUTOSAVE = 34,
+
+ /* system */
+ BLENDER_SYSTEM_DATAFILES = 52,
+ BLENDER_SYSTEM_SCRIPTS = 53,
+ BLENDER_SYSTEM_PYTHON = 54,
+};
+
+/* for BKE_appdir_folder_id_version only */
+enum {
+ BLENDER_RESOURCE_PATH_USER = 0,
+ BLENDER_RESOURCE_PATH_LOCAL = 1,
+ BLENDER_RESOURCE_PATH_SYSTEM = 2,
+};
+
+#define BLENDER_STARTUP_FILE "startup.blend"
+#define BLENDER_USERPREF_FILE "userpref.blend"
+#define BLENDER_QUIT_FILE "quit.blend"
+#define BLENDER_BOOKMARK_FILE "bookmarks.txt"
+#define BLENDER_HISTORY_FILE "recent-files.txt"
+
+#endif /* __BKE_APPDIR_H__ */
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 4c333c8332b..0215becd2a0 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -41,7 +41,7 @@ extern "C" {
/* these lines are grep'd, watch out for our not-so-awesome regex
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
-#define BLENDER_VERSION 272
+#define BLENDER_VERSION 273
#define BLENDER_SUBVERSION 2
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 270
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index d48753590bb..49975fa0276 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -62,12 +62,11 @@ int BKE_brush_clone_image_delete(struct Brush *brush);
/* jitter */
void BKE_brush_jitter_pos(const struct Scene *scene, struct Brush *brush,
const float pos[2], float jitterpos[2]);
-void BKE_brush_randomize_texture_coordinates(struct UnifiedPaintSettings *ups, bool mask);
+void BKE_brush_randomize_texture_coords(struct UnifiedPaintSettings *ups, bool mask);
/* brush curve */
void BKE_brush_curve_preset(struct Brush *b, int preset);
-float BKE_brush_curve_strength_clamp(struct Brush *br, float p, const float len);
-float BKE_brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */
+float BKE_brush_curve_strength(struct Brush *br, float p, const float len);
/* sampling */
float BKE_brush_sample_tex_3D(const Scene *scene, struct Brush *br, const float point[3],
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 4bc8fc44bb4..a360511dcd3 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -31,6 +31,7 @@
* \ingroup bke
*/
+#include "BLI_bitmap.h"
#include "BLI_kdopbvh.h"
/*
@@ -56,8 +57,8 @@ typedef struct BVHTreeFromMesh {
struct MEdge *edge; /* only used for BVHTreeFromMeshEdges */
struct MFace *face;
bool vert_allocated;
- bool face_allocated;
bool edge_allocated;
+ bool face_allocated;
/* radius for raycast */
float sphere_radius;
@@ -69,36 +70,28 @@ typedef struct BVHTreeFromMesh {
} BVHTreeFromMesh;
/*
- * Builds a bvh tree where nodes are the vertexs of the given mesh.
+ * Builds a bvh tree where nodes are the relevant elements of the given mesh.
* Configures BVHTreeFromMesh.
*
* The tree is build in mesh space coordinates, this means special care must be made on queries
* so that the coordinates and rays are first translated on the mesh local coordinates.
- * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becomes possible to reuse
- * a BVHTree.
+ * Reason for this is that bvh_from_mesh_* can use a cache in some cases and so it becomes possible to reuse a BVHTree.
*
* free_bvhtree_from_mesh should be called when the tree is no longer needed.
*/
BVHTree *bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
-
-/*
- * Builds a bvh tree where nodes are the faces of the given mesh.
- * Configures BVHTreeFromMesh.
- *
- * The tree is build in mesh space coordinates, this means special care must be made on queries
- * so that the coordinates and rays are first translated on the mesh local coordinates.
- * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becomes possible to reuse
- * a BVHTree.
- *
- * The returned value is the same as in data->tree, its only returned to make it easier to test
- * the success
- *
- * free_bvhtree_from_mesh should be called when the tree is no longer needed.
- */
-BVHTree *bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data, struct MVert *vert, const int numVerts,
+ const bool vert_allocated, BLI_bitmap *mask, int numVerts_active,
+ float epsilon, int tree_type, int axis);
BVHTree *bvhtree_from_mesh_edges(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+BVHTree *bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data, struct MVert *vert, const bool vert_allocated,
+ struct MFace *face, const int numFaces, const bool face_allocated,
+ BLI_bitmap *mask, int numFaces_active,
+ float epsilon, int tree_type, int axis);
+
/*
* Frees data allocated by a call to bvhtree_from_mesh_*.
*/
@@ -114,12 +107,13 @@ float nearest_point_in_tri_surface_squared(const float v0[3], const float v1[3],
* BVHCache
*/
-//Using local coordinates
-#define BVHTREE_FROM_FACES 0
-#define BVHTREE_FROM_VERTICES 1
-#define BVHTREE_FROM_EDGES 2
-
-#define BVHTREE_FROM_FACES_EDITMESH 3
+/* Using local coordinates */
+enum {
+ BVHTREE_FROM_VERTS = 0,
+ BVHTREE_FROM_EDGES = 1,
+ BVHTREE_FROM_FACES = 2,
+ BVHTREE_FROM_FACES_EDITMESH = 3,
+};
typedef struct LinkNode *BVHCache;
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index 01b401c6bcc..26d4986d93e 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -118,7 +118,9 @@ void BKE_camera_view_frame_ex(struct Scene *scene, struct Camera *camera, float
void BKE_camera_view_frame(struct Scene *scene, struct Camera *camera, float r_vec[4][3]);
bool BKE_camera_view_frame_fit_to_scene(struct Scene *scene, struct View3D *v3d, struct Object *camera_ob,
- float r_co[3]);
+ float r_co[3], float *r_scale);
+bool BKE_camera_view_frame_fit_to_coords(struct Scene *scene, float (*cos)[3], int num_cos,
+ struct Object *camera_ob, float r_co[3], float *r_scale);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 87da74dc119..82ae4930526 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -141,7 +141,8 @@ bool BKE_constraints_proxylocked_owner(struct Object *ob, struct bPoseChannel *p
struct bConstraintOb *BKE_constraints_make_evalob(struct Scene *scene, struct Object *ob, void *subdata, short datatype);
void BKE_constraints_clear_evalob(struct bConstraintOb *cob);
-void BKE_constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[4][4], short from, short to);
+void BKE_constraint_mat_convertspace(
+ struct Object *ob, struct bPoseChannel *pchan, float mat[4][4], short from, short to, const bool keep_scale);
void BKE_constraint_target_matrix_get(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime);
void BKE_constraint_targets_for_solving_get(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime);
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 877e376b343..ae0ef9ce314 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -56,6 +56,9 @@ struct Text;
struct ImBuf;
struct EditBone;
struct bPoseChannel;
+struct bGPdata;
+struct bGPDlayer;
+struct bGPDframe;
struct wmWindow;
struct wmWindowManager;
struct SpaceText;
@@ -275,6 +278,14 @@ struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C);
int CTX_data_selected_pose_bones(const bContext *C, ListBase *list);
int CTX_data_visible_pose_bones(const bContext *C, ListBase *list);
+struct bGPdata *CTX_data_gpencil_data(const bContext *C);
+struct bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C);
+struct bGPDframe *CTX_data_active_gpencil_frame(const bContext *C);
+int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list);
+int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
+int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 30a58891bda..f11aad27e4b 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -41,6 +41,8 @@ extern "C" {
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
+#include "DNA_customdata_types.h"
+
struct BMesh;
struct ID;
struct CustomData;
@@ -77,6 +79,9 @@ extern const CustomDataMask CD_MASK_EVERYTHING;
void customData_mask_layers__print(CustomDataMask mask);
+typedef void (*cd_interp)(void **sources, const float *weights, const float *sub_weights, int count, void *dest);
+typedef void (*cd_copy)(const void *source, void *dest, int count);
+
/**
* Checks if the layer at physical offset \a layer_n (in data->layers) support math
* the below operations.
@@ -96,6 +101,9 @@ bool CustomData_bmesh_has_free(const struct CustomData *data);
* implemented for mloopuv/mloopcol, for now.*/
void CustomData_data_copy_value(int type, const void *source, void *dest);
+/* Same as above, but doing advanced mixing. Only available for a few types of data (like colors...). */
+void CustomData_data_mix_value(int type, const void *source, void *dest, const int mixmode, const float mixfactor);
+
/* compares if data1 is equal to data2. type is a valid CustomData type
* enum (e.g. CD_MLOOPUV). the layer type's equal function is used to compare
* the data, if it exists, otherwise memcmp is used.*/
@@ -246,14 +254,14 @@ void *CustomData_bmesh_get_n(const struct CustomData *data, void *block, int typ
void *CustomData_bmesh_get_layer_n(const struct CustomData *data, void *block, int n);
bool CustomData_set_layer_name(const struct CustomData *data, int type, int n, const char *name);
+const char *CustomData_get_layer_name(const struct CustomData *data, int type, int n);
/* gets a pointer to the active or first layer of type
* returns NULL if there is no layer of type
*/
void *CustomData_get_layer(const struct CustomData *data, int type);
void *CustomData_get_layer_n(const struct CustomData *data, int type, int n);
-void *CustomData_get_layer_named(const struct CustomData *data, int type,
- const char *name);
+void *CustomData_get_layer_named(const struct CustomData *data, int type, const char *name);
int CustomData_get_offset(const struct CustomData *data, int type);
int CustomData_get_n_offset(const struct CustomData *data, int type, int n);
@@ -362,6 +370,82 @@ void CustomData_external_read(struct CustomData *data,
void CustomData_external_reload(struct CustomData *data,
struct ID *id, CustomDataMask mask, int totelem);
+/* Mesh-to-mesh transfer data. */
+
+struct MeshPairRemap;
+struct CustomDataTransferLayerMap;
+
+typedef void (*cd_datatransfer_interp)(
+ const struct CustomDataTransferLayerMap *laymap, void *dest,
+ void **sources, const float *weights, const int count, const float mix_factor);
+
+/**
+ * Fake CD_LAYERS (those are actually 'real' data stored directly into elements' structs, or otherwise not (directly)
+ * accessible to usual CDLayer system). */
+enum {
+ CD_FAKE = 1 << 8,
+
+ /* Vertices. */
+ CD_FAKE_MDEFORMVERT = CD_FAKE | CD_MDEFORMVERT, /* *sigh* due to how vgroups are stored :( . */
+ CD_FAKE_SHAPEKEY = CD_FAKE | CD_SHAPEKEY, /* Not available as real CD layer in non-bmesh context. */
+
+ /* Edges. */
+ CD_FAKE_SEAM = CD_FAKE | 100, /* UV seam flag for edges. */
+ CD_FAKE_CREASE = CD_FAKE | CD_CREASE, /* *sigh*. */
+
+ /* Multiple types of mesh elements... */
+ CD_FAKE_BWEIGHT = CD_FAKE | CD_BWEIGHT, /* *sigh*. */
+ CD_FAKE_UV = CD_FAKE | CD_MLOOPUV, /* UV flag, because we handle both loop's UVs and poly's textures. */
+
+ CD_FAKE_SHARP = CD_FAKE | 200, /* Sharp flag for edges, smooth flag for faces. */
+};
+
+enum {
+ ME_VERT = 1 << 0,
+ ME_EDGE = 1 << 1,
+ ME_POLY = 1 << 2,
+ ME_LOOP = 1 << 3,
+};
+
+/**
+ * How to filter out some elements (to leave untouched).
+ * Note those options are highly dependent on type of transferred data! */
+enum {
+ CDT_MIX_NOMIX = -1, /* Special case, only used because we abuse 'copy' CD callback. */
+ CDT_MIX_TRANSFER = 0,
+ CDT_MIX_REPLACE_ABOVE_THRESHOLD = 1,
+ CDT_MIX_REPLACE_BELOW_THRESHOLD = 2,
+ CDT_MIX_MIX = 16,
+ CDT_MIX_ADD = 17,
+ CDT_MIX_SUB = 18,
+ CDT_MIX_MUL = 19,
+ /* etc. etc. */
+};
+
+typedef struct CustomDataTransferLayerMap {
+ struct CustomDataTransferLayerMap *next, *prev;
+
+ int data_type;
+ int mix_mode;
+ float mix_factor;
+ const float *mix_weights; /* If non-NULL, array of weights, one for each dest item, replaces mix_factor. */
+
+ void *data_src; /* Data source array (can be regular CD data, vertices/edges/etc., keyblocks...). */
+ void *data_dst; /* Data dest array (same type as dat_src). */
+ int data_src_n; /* Index to affect in data_src (used e.g. for vgroups). */
+ int data_dst_n; /* Index to affect in data_dst (used e.g. for vgroups). */
+ size_t elem_size; /* Size of one element of data_src/data_dst. */
+
+ size_t data_size; /* Size of actual data we transfer. */
+ size_t data_offset; /* Offset of actual data we transfer (in element contained in data_src/dst). */
+ uint64_t data_flag; /* For bitflag transfer, flag(s) to affect in transfered data. */
+
+ cd_datatransfer_interp interp;
+} CustomDataTransferLayerMap;
+
+/* Those functions assume src_n and dst_n layers of given type exist in resp. src and dst. */
+void CustomData_data_transfer(const struct MeshPairRemap *me_remap, const CustomDataTransferLayerMap *laymap);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h
new file mode 100644
index 00000000000..d31804b3cae
--- /dev/null
+++ b/source/blender/blenkernel/BKE_data_transfer.h
@@ -0,0 +1,158 @@
+/*
+ * ***** 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): Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/BKE_data_transfer.h
+ * \ingroup bke
+ */
+
+#ifndef __BKE_DATA_TRANSFER_H__
+#define __BKE_DATA_TRANSFER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BKE_customdata.h"
+
+struct Object;
+struct Scene;
+struct SpaceTransform;
+struct ReportList;
+
+/* Warning, those def are stored in files (TransferData modifier), *DO NOT* modify those values. */
+enum {
+ DT_TYPE_MDEFORMVERT = 1 << 0,
+ DT_TYPE_SHAPEKEY = 1 << 1,
+ DT_TYPE_SKIN = 1 << 2,
+ DT_TYPE_BWEIGHT_VERT = 1 << 3,
+
+ DT_TYPE_SHARP_EDGE = 1 << 8,
+ DT_TYPE_SEAM = 1 << 9,
+ DT_TYPE_CREASE = 1 << 10,
+ DT_TYPE_BWEIGHT_EDGE = 1 << 11,
+ DT_TYPE_FREESTYLE_EDGE = 1 << 12,
+
+ DT_TYPE_VCOL = 1 << 16,
+
+ DT_TYPE_UV = 1 << 24,
+ DT_TYPE_SHARP_FACE = 1 << 25,
+ DT_TYPE_FREESTYLE_FACE = 1 << 26,
+#define \
+ DT_TYPE_MAX 27
+
+ DT_TYPE_VERT_ALL = DT_TYPE_MDEFORMVERT | DT_TYPE_SHAPEKEY | DT_TYPE_SKIN | DT_TYPE_BWEIGHT_VERT,
+ DT_TYPE_EDGE_ALL = DT_TYPE_SHARP_EDGE | DT_TYPE_SEAM | DT_TYPE_CREASE | DT_TYPE_BWEIGHT_EDGE |
+ DT_TYPE_FREESTYLE_EDGE,
+ DT_TYPE_LOOP_ALL = DT_TYPE_VCOL | DT_TYPE_UV,
+ DT_TYPE_POLY_ALL = DT_TYPE_UV | DT_TYPE_SHARP_FACE | DT_TYPE_FREESTYLE_FACE,
+};
+
+
+CustomDataMask BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types);
+bool BKE_object_data_transfer_get_dttypes_capacity(
+ const int dtdata_types, bool *r_advanced_mixing, bool *r_threshold);
+int BKE_object_data_transfer_get_dttypes_item_types(const int dtdata_types);
+
+int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type);
+int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type);
+
+#define DT_DATATYPE_IS_VERT(_dt) \
+ ELEM(_dt, DT_TYPE_MDEFORMVERT, DT_TYPE_SHAPEKEY, DT_TYPE_SKIN, DT_TYPE_BWEIGHT_VERT)
+#define DT_DATATYPE_IS_EDGE(_dt) \
+ ELEM(_dt, DT_TYPE_CREASE, DT_TYPE_SHARP_EDGE, DT_TYPE_SEAM, DT_TYPE_BWEIGHT_EDGE, DT_TYPE_FREESTYLE_EDGE)
+#define DT_DATATYPE_IS_LOOP(_dt) \
+ ELEM(_dt, DT_TYPE_UV, DT_TYPE_VCOL)
+#define DT_DATATYPE_IS_POLY(_dt) \
+ ELEM(_dt, DT_TYPE_UV, DT_TYPE_SHARP_FACE, DT_TYPE_FREESTYLE_FACE)
+
+#define DT_DATATYPE_IS_MULTILAYERS(_dt) \
+ ELEM(_dt, DT_TYPE_MDEFORMVERT, DT_TYPE_SHAPEKEY, DT_TYPE_VCOL, DT_TYPE_UV)
+
+
+enum {
+ DT_MULTILAYER_INDEX_INVALID = -1,
+ DT_MULTILAYER_INDEX_MDEFORMVERT = 0,
+ DT_MULTILAYER_INDEX_SHAPEKEY = 1,
+ DT_MULTILAYER_INDEX_VCOL = 2,
+ DT_MULTILAYER_INDEX_UV = 3,
+ DT_MULTILAYER_INDEX_MAX = 4,
+};
+
+/* Below we keep positive values for real layers idx (generated dynamically). */
+
+/* How to select data layers, for types supporting multi-layers.
+ * Here too, some options are highly dependent on type of transferred data! */
+enum {
+ DT_LAYERS_ACTIVE_SRC = -1,
+ DT_LAYERS_ALL_SRC = -2,
+ /* Datatype-specific. */
+ DT_LAYERS_VGROUP_SRC = 1 << 8,
+ DT_LAYERS_VGROUP_SRC_BONE_SELECT = -(DT_LAYERS_VGROUP_SRC | 1),
+ DT_LAYERS_VGROUP_SRC_BONE_DEFORM = -(DT_LAYERS_VGROUP_SRC | 2),
+ /* Other types-related modes... */
+};
+
+/* How to map a source layer to a destination layer, for types supporting multi-layers.
+ * Note: if no matching layer can be found, it will be created. */
+enum {
+ DT_LAYERS_ACTIVE_DST = -1, /* Only for DT_LAYERS_FROMSEL_ACTIVE. */
+ DT_LAYERS_NAME_DST = -2,
+ DT_LAYERS_INDEX_DST = -3,
+#if 0 /* TODO */
+ DT_LAYERS_CREATE_DST = -4, /* Never replace existing data in dst, always create new layers. */
+#endif
+};
+
+void BKE_object_data_transfer_layout(
+ struct Scene *scene, struct Object *ob_src, struct Object *ob_dst, const int data_types, const bool use_delete,
+ const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX]);
+
+bool BKE_object_data_transfer_mesh(
+ struct Scene *scene,
+ struct Object *ob_src, struct Object *ob_dst, const int data_types, bool use_create,
+ const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
+ struct SpaceTransform *space_transform, const float max_distance, const float ray_radius,
+ const float islands_handling_precision,
+ const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
+ const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
+ struct ReportList *reports);
+bool BKE_object_data_transfer_dm(
+ struct Scene *scene,
+ struct Object *ob_src, struct Object *ob_dst, struct DerivedMesh *dm_dst,
+ const int data_types, bool use_create,
+ const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
+ struct SpaceTransform *space_transform, const float max_distance, const float ray_radius,
+ const float islands_handling_precision,
+ const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
+ const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
+ struct ReportList *reports);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_DATA_TRANSFER_H__ */
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index e203549fef5..08312035e40 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -39,6 +39,10 @@ struct Object;
struct ListBase;
struct bDeformGroup;
struct MDeformVert;
+struct MVert;
+struct MEdge;
+struct MLoop;
+struct MPoly;
struct bDeformGroup *BKE_defgroup_new(struct Object *ob, const char *name);
void defgroup_copy_list(struct ListBase *lb1, struct ListBase *lb2);
@@ -85,6 +89,19 @@ void defvert_normalize_lock_map(struct MDeformVert *dvert,
const bool *vgroup_subset, const int vgroup_tot,
const bool *lock_flags, const int defbase_tot);
+/* Utilities to 'extract' a given vgroup into a simple float array, for verts, but also edges/polys/loops. */
+void BKE_defvert_extract_vgroup_to_vertweights(
+ struct MDeformVert *dvert, const int defgroup, const int num_verts, float *r_weights, const bool invert_vgroup);
+void BKE_defvert_extract_vgroup_to_edgeweights(
+ struct MDeformVert *dvert, const int defgroup, const int num_verts, struct MEdge *edges, const int num_edges,
+ float *r_weights, const bool invert_vgroup);
+void BKE_defvert_extract_vgroup_to_loopweights(
+ struct MDeformVert *dvert, const int defgroup, const int num_verts, struct MLoop *loops, const int num_loops,
+ float *r_weights, const bool invert_vgroup);
+void BKE_defvert_extract_vgroup_to_polyweights(
+ struct MDeformVert *dvert, const int defgroup, const int num_verts, struct MLoop *loops, const int num_loops,
+ struct MPoly *polys, const int num_polys, float *r_weights, const bool invert_vgroup);
+
/* utility function, note that MAX_VGROUP_NAME chars is the maximum string length since its only
* used with defgroups currently */
diff --git a/source/blender/blenkernel/BKE_editmesh_bvh.h b/source/blender/blenkernel/BKE_editmesh_bvh.h
index 168f700d132..3ee7dcd94b8 100644
--- a/source/blender/blenkernel/BKE_editmesh_bvh.h
+++ b/source/blender/blenkernel/BKE_editmesh_bvh.h
@@ -43,6 +43,8 @@ struct Scene;
typedef struct BMBVHTree BMBVHTree;
+typedef bool (*BMBVHTree_FaceFilter)(struct BMFace *f, void *userdata);
+
BMBVHTree *BKE_bmbvh_new_from_editmesh(
struct BMEditMesh *em, int flag,
const float (*cos_cage)[3], const bool cos_cage_free);
@@ -55,8 +57,16 @@ BMBVHTree *BKE_bmbvh_new(
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,
- float *r_dist, float r_hitout[3], float r_cagehit[3]);
+
+struct BMFace *BKE_bmbvh_ray_cast(
+ BMBVHTree *tree, const float co[3], const float dir[3], const float radius,
+ float *r_dist, float r_hitout[3], float r_cagehit[3]);
+
+struct BMFace *BKE_bmbvh_ray_cast_filter(
+ BMBVHTree *tree, const float co[3], const float dir[3], const float radius,
+ float *r_dist, float r_hitout[3], float r_cagehit[3],
+ BMBVHTree_FaceFilter filter, void *filter_cb);
+
/* find a face intersecting a segment (but not apart of the segment) */
struct BMFace *BKE_bmbvh_find_face_segment(BMBVHTree *tree, const float co_a[3], const float co_b[3],
float *r_fac, float r_hitout[3], float r_cagehit[3]);
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 86c111653d1..084c5527f21 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -35,6 +35,7 @@ struct ListBase;
struct bGPdata;
struct bGPDlayer;
struct bGPDframe;
+struct bGPDstroke;
/* ------------ Grease-Pencil API ------------------ */
@@ -43,17 +44,15 @@ void free_gpencil_frames(struct bGPDlayer *gpl);
void free_gpencil_layers(struct ListBase *list);
void BKE_gpencil_free(struct bGPdata *gpd);
+void gpencil_stroke_sync_selection(struct bGPDstroke *gps);
+
struct bGPDframe *gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe);
struct bGPDlayer *gpencil_layer_addnew(struct bGPdata *gpd, const char *name, int setactive);
struct bGPdata *gpencil_data_addnew(const char name[]);
struct bGPDframe *gpencil_frame_duplicate(struct bGPDframe *src);
struct bGPDlayer *gpencil_layer_duplicate(struct bGPDlayer *src);
-struct bGPdata *gpencil_data_duplicate(struct bGPdata *gpd);
-
-//struct bGPdata *gpencil_data_getactive(struct ScrArea *sa);
-//short gpencil_data_setactive(struct ScrArea *sa, struct bGPdata *gpd);
-//struct ScrArea *gpencil_data_findowner(struct bGPdata *gpd);
+struct bGPdata *gpencil_data_duplicate(struct bGPdata *gpd, bool internal_copy);
void gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf);
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 6d3d15e3565..5b10d7ebc06 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -40,18 +40,18 @@ typedef union IDPropertyTemplate {
float f;
double d;
struct {
- char *str;
- short len;
+ const char *str;
+ int len;
char subtype;
} string;
struct ID *id;
struct {
- short type;
- short len;
+ int len;
+ char type;
} array;
struct {
int matvec_size;
- float *example;
+ const float *example;
} matrix_or_vector;
} IDPropertyTemplate;
@@ -110,7 +110,7 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
bool IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2) ATTR_WARN_UNUSED_RESULT;
-struct IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+struct IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void IDP_FreeProperty(struct IDProperty *prop);
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index dc3d9f38b21..a225a27a00b 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -162,6 +162,7 @@ void BKE_image_alpha_mode_from_extension(struct Image *image);
/* returns a new image or NULL if it can't load */
struct Image *BKE_image_load(struct Main *bmain, const char *filepath);
/* returns existing Image when filename/type is same (frame optional) */
+struct Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists);
struct Image *BKE_image_load_exists(const char *filepath);
/* adds image, adds ibuf, generates color or pattern */
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index 31b2c7dc2b9..9535b921736 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -60,9 +60,11 @@ void key_curve_position_weights(float t, float data[4], int type);
void key_curve_tangent_weights(float t, float data[4], int type);
void key_curve_normal_weights(float t, float data[4], int type);
-float *BKE_key_evaluate_object_ex(struct Scene *scene, struct Object *ob, int *r_totelem,
- float *arr, size_t arr_size);
-float *BKE_key_evaluate_object(struct Scene *scene, struct Object *ob, int *r_totelem);
+float *BKE_key_evaluate_object_ex(
+ struct Object *ob, int *r_totelem,
+ float *arr, size_t arr_size);
+float *BKE_key_evaluate_object(
+ struct Object *ob, int *r_totelem);
struct Key *BKE_key_from_object(struct Object *ob);
struct KeyBlock *BKE_keyblock_from_object(struct Object *ob);
@@ -111,9 +113,6 @@ bool BKE_keyblock_move(struct Object *ob, int org_index, int new_index);
bool BKE_keyblock_is_basis(struct Key *key, const int index);
-/* key.c */
-extern int slurph_opt;
-
#ifdef __cplusplus
};
#endif
diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h
index ed7e506941c..da44c989146 100644
--- a/source/blender/blenkernel/BKE_mesh_mapping.h
+++ b/source/blender/blenkernel/BKE_mesh_mapping.h
@@ -31,8 +31,9 @@
* \ingroup bke
*/
-struct MPoly;
+struct MVert;
struct MEdge;
+struct MPoly;
struct MLoop;
struct MLoopUV;
@@ -109,6 +110,10 @@ void BKE_mesh_vert_poly_map_create(
MeshElemMap **r_map, int **r_mem,
const struct MPoly *mface, const struct MLoop *mloop,
int totvert, int totface, int totloop);
+void BKE_mesh_vert_loop_map_create(
+ MeshElemMap **r_map, int **r_mem,
+ const struct MPoly *mface, const struct MLoop *mloop,
+ int totvert, int totface, int totloop);
void BKE_mesh_vert_edge_map_create(
MeshElemMap **r_map, int **r_mem,
const struct MEdge *medge, int totvert, int totedge);
@@ -122,7 +127,61 @@ void BKE_mesh_origindex_map_create(
const int totorig,
const int *final_origindex, const int totfinal);
-/* smoothgroups */
+
+/* islands */
+
+/* Loop islands data helpers. */
+enum {
+ MISLAND_TYPE_NONE = 0,
+ MISLAND_TYPE_VERT = 1,
+ MISLAND_TYPE_EDGE = 2,
+ MISLAND_TYPE_POLY = 3,
+ MISLAND_TYPE_LOOP = 4,
+};
+
+typedef struct MeshIslandStore {
+ short item_type; /* MISLAND_TYPE_... */
+ short island_type; /* MISLAND_TYPE_... */
+ short innercut_type; /* MISLAND_TYPE_... */
+
+ int items_to_islands_num;
+ int *items_to_islands; /* map the item to the island index */
+
+ int islands_num;
+ size_t islands_num_alloc;
+ struct MeshElemMap **islands; /* Array of pointers, one item per island. */
+ struct MeshElemMap **innercuts; /* Array of pointers, one item per island. */
+
+ struct MemArena *mem; /* Memory arena, internal use only. */
+} MeshIslandStore;
+
+void BKE_mesh_loop_islands_init(
+ MeshIslandStore *island_store,
+ const short item_type, const int item_num, const short island_type, const short innercut_type);
+void BKE_mesh_loop_islands_clear(MeshIslandStore *island_store);
+void BKE_mesh_loop_islands_free(MeshIslandStore *island_store);
+void BKE_mesh_loop_islands_add(
+ MeshIslandStore *islands, const int item_num, int *item_indices,
+ const int num_island_items, int *island_item_indices,
+ const int num_innercut_items, int *innercut_item_indices);
+
+typedef bool (*MeshRemapIslandsCalc)(
+ struct MVert *verts, const int totvert,
+ struct MEdge *edges, const int totedge,
+ struct MPoly *polys, const int totpoly,
+ struct MLoop *loops, const int totloop,
+ struct MeshIslandStore *r_island_store);
+
+/* Above vert/UV mapping stuff does not do what we need here, but does things we do not need here.
+ * So better keep them separated for now, I think.
+ */
+bool BKE_mesh_calc_islands_loop_poly_uv(
+ struct MVert *verts, const int totvert,
+ struct MEdge *edges, const int totedge,
+ struct MPoly *polys, const int totpoly,
+ struct MLoop *loops, const int totloop,
+ MeshIslandStore *r_island_store);
+
int *BKE_mesh_calc_smoothgroups(
const struct MEdge *medge, const int totedge,
const struct MPoly *mpoly, const int totpoly,
diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h
new file mode 100644
index 00000000000..e1f37a63ff0
--- /dev/null
+++ b/source/blender/blenkernel/BKE_mesh_remap.h
@@ -0,0 +1,171 @@
+/*
+ * ***** 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 __BKE_MESH_REMAP_H__
+#define __BKE_MESH_REMAP_H__
+
+/** \file BKE_mesh_remap.h
+ * \ingroup bke
+ */
+
+struct CustomData;
+struct DerivedMesh;
+struct MVert;
+struct MeshElemMap;
+struct MemArena;
+
+/* Generic ways to map some geometry elements from a source mesh to a dest one. */
+
+typedef struct MeshPairRemapItem {
+ int sources_num;
+ int *indices_src; /* NULL if no source found. */
+ float *weights_src; /* NULL if no source found, else, always normalized! */
+ /* UNUSED (at the moment)*/
+ // float hit_dist; /* FLT_MAX if irrelevant or no source found. */
+ int island; /* For loops only. */
+} MeshPairRemapItem;
+
+/* All mapping computing func return this. */
+typedef struct MeshPairRemap {
+ int items_num;
+ MeshPairRemapItem *items; /* array, one item per dest element. */
+
+ struct MemArena *mem; /* memory arena, internal use only. */
+} MeshPairRemap;
+
+/* Helpers! */
+void BKE_mesh_remap_init(MeshPairRemap *map, const int items_num);
+void BKE_mesh_remap_free(MeshPairRemap *map);
+
+void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, const int index);
+
+/* TODO:
+ * Add other 'from/to' mapping sources, like e.g. using an UVMap, etc.
+ * http://blenderartists.org/forum/showthread.php?346458-Move-Vertices-to-the-location-of-the-Reference-Mesh-based-on-the-UV-Position
+ * We could also use similar topology mappings inside a same mesh
+ * (cf. Campbell's 'select face islands from similar topology' wip work).
+ * Also, users will have to check, whether we can get rid of some modes here, not sure all will be useful!
+ */
+enum {
+ MREMAP_USE_VERT = 1 << 4,
+ MREMAP_USE_EDGE = 1 << 5,
+ MREMAP_USE_LOOP = 1 << 6,
+ MREMAP_USE_POLY = 1 << 7,
+
+ MREMAP_USE_NEAREST = 1 << 8,
+ MREMAP_USE_NORPROJ = 1 << 9,
+ MREMAP_USE_INTERP = 1 << 10,
+ MREMAP_USE_NORMAL = 1 << 11,
+
+ /* ***** Target's vertices ***** */
+ MREMAP_MODE_VERT = 1 << 24,
+ /* Nearest source vert. */
+ MREMAP_MODE_VERT_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_VERT | MREMAP_USE_NEAREST,
+
+ /* Nearest vertex of nearest edge. */
+ MREMAP_MODE_VERT_EDGE_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_EDGE | MREMAP_USE_NEAREST,
+ /* This one uses two verts of selected edge (weighted interpolation). */
+ /* Nearest point on nearest edge. */
+ MREMAP_MODE_VERT_EDGEINTERP_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_EDGE | MREMAP_USE_NEAREST | MREMAP_USE_INTERP,
+
+ /* Nearest vertex of nearest poly. */
+ MREMAP_MODE_VERT_POLY_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
+ /* Those two use all verts of selected poly (weighted interpolation). */
+ /* Nearest point on nearest poly. */
+ MREMAP_MODE_VERT_POLYINTERP_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_POLY | MREMAP_USE_NEAREST | MREMAP_USE_INTERP,
+ /* Point on nearest face hit by ray from target vertex's normal. */
+ MREMAP_MODE_VERT_POLYINTERP_VNORPROJ = MREMAP_MODE_VERT | MREMAP_USE_POLY | MREMAP_USE_NORPROJ | MREMAP_USE_INTERP,
+
+ /* ***** Target's edges ***** */
+ MREMAP_MODE_EDGE = 1 << 25,
+
+ /* Source edge which both vertices are nearest of dest ones. */
+ MREMAP_MODE_EDGE_VERT_NEAREST = MREMAP_MODE_EDGE | MREMAP_USE_VERT | MREMAP_USE_NEAREST,
+
+ /* Nearest source edge (using mid-point). */
+ MREMAP_MODE_EDGE_NEAREST = MREMAP_MODE_EDGE | MREMAP_USE_EDGE | MREMAP_USE_NEAREST,
+
+ /* Nearest edge of nearest poly (using mid-point). */
+ MREMAP_MODE_EDGE_POLY_NEAREST = MREMAP_MODE_EDGE | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
+
+ /* Cast a set of rays from along dest edge, interpolating its vertices' normals, and use hit source edges. */
+ MREMAP_MODE_EDGE_EDGEINTERP_VNORPROJ = MREMAP_MODE_EDGE | MREMAP_USE_VERT | MREMAP_USE_NORPROJ | MREMAP_USE_INTERP,
+
+ /* ***** Target's loops ***** */
+ /* Note: when islands are given to loop mapping func, all loops from the same destination face will always be mapped
+ * to loops of source faces within a same island, regardless of mapping mode. */
+ MREMAP_MODE_LOOP = 1 << 26,
+
+ /* Best normal-matching loop from nearest vert. */
+ MREMAP_MODE_LOOP_NEAREST_LOOPNOR = MREMAP_MODE_LOOP | MREMAP_USE_LOOP | MREMAP_USE_VERT | MREMAP_USE_NEAREST | MREMAP_USE_NORMAL,
+ /* Loop from best normal-matching poly from nearest vert. */
+ MREMAP_MODE_LOOP_NEAREST_POLYNOR = MREMAP_MODE_LOOP | MREMAP_USE_POLY | MREMAP_USE_VERT | MREMAP_USE_NEAREST | MREMAP_USE_NORMAL,
+
+ /* Loop from nearest vertex of nearest poly. */
+ MREMAP_MODE_LOOP_POLY_NEAREST = MREMAP_MODE_LOOP | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
+ /* Those two use all verts of selected poly (weighted interpolation). */
+ /* Nearest point on nearest poly. */
+ MREMAP_MODE_LOOP_POLYINTERP_NEAREST = MREMAP_MODE_LOOP | MREMAP_USE_POLY | MREMAP_USE_NEAREST | MREMAP_USE_INTERP,
+ /* Point on nearest face hit by ray from target loop's normal. */
+ MREMAP_MODE_LOOP_POLYINTERP_LNORPROJ = MREMAP_MODE_LOOP | MREMAP_USE_POLY | MREMAP_USE_NORPROJ | MREMAP_USE_INTERP,
+
+ /* ***** Target's polygons ***** */
+ MREMAP_MODE_POLY = 1 << 27,
+
+ /* Nearest source poly. */
+ MREMAP_MODE_POLY_NEAREST = MREMAP_MODE_POLY | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
+ /* Source poly from best normal-matching dest poly. */
+ MREMAP_MODE_POLY_NOR = MREMAP_MODE_POLY | MREMAP_USE_POLY | MREMAP_USE_NORMAL,
+
+ /* Project dest poly onto source mesh using its normal, and use interpolation of all intersecting source polys. */
+ MREMAP_MODE_POLY_POLYINTERP_PNORPROJ = MREMAP_MODE_POLY | MREMAP_USE_POLY | MREMAP_USE_NORPROJ | MREMAP_USE_INTERP,
+
+ /* ***** Same topology, applies to all four elements types. ***** */
+ MREMAP_MODE_TOPOLOGY = MREMAP_MODE_VERT | MREMAP_MODE_EDGE | MREMAP_MODE_LOOP | MREMAP_MODE_POLY,
+};
+
+/* TODO add mesh2mesh versions (we'll need mesh versions of bvhtree funcs too, though!). */
+
+void BKE_mesh_remap_calc_verts_from_dm(
+ const int mode, const struct SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ const struct MVert *verts_dst, const int numverts_dst, const bool dirty_nors_dst,
+ struct DerivedMesh *dm_src, MeshPairRemap *r_map);
+
+void BKE_mesh_remap_calc_edges_from_dm(
+ const int mode, const struct SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ const struct MVert *verts_dst, const int numverts_dst, const struct MEdge *edges_dst, const int numedges_dst,
+ const bool dirty_nors_dst, struct DerivedMesh *dm_src, MeshPairRemap *r_map);
+
+void BKE_mesh_remap_calc_loops_from_dm(
+ const int mode, const struct SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ struct MVert *verts_dst, const int numverts_dst, struct MEdge *edges_dst, const int numedges_dst,
+ struct MLoop *loops_dst, const int numloops_dst, struct MPoly *polys_dst, const int numpolys_dst,
+ struct CustomData *ldata_dst, struct CustomData *pdata_dst,
+ const float split_angle_dst, const bool dirty_nors_dst,
+ struct DerivedMesh *dm_src,
+ MeshRemapIslandsCalc gen_islands_src, const float islands_precision_src, struct MeshPairRemap *r_map);
+
+void BKE_mesh_remap_calc_polys_from_dm(
+ const int mode, const struct SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ struct MVert *verts_dst, const int numverts_dst, struct MLoop *loops_dst, const int numloops_dst,
+ struct MPoly *polys_dst, const int numpolys_dst, struct CustomData *pdata_dst, const bool dirty_nors_dst,
+ struct DerivedMesh *dm_src, struct MeshPairRemap *r_map);
+
+#endif /* __BKE_MESH_REMAP_H__ */
diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h
index 341105cfdf7..a4aa58e22f1 100644
--- a/source/blender/blenkernel/BKE_movieclip.h
+++ b/source/blender/blenkernel/BKE_movieclip.h
@@ -46,6 +46,7 @@ void BKE_movieclip_unlink(struct Main *bmain, struct MovieClip *clip);
struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name);
void BKE_movieclip_reload(struct MovieClip *clip);
void BKE_movieclip_clear_cache(struct MovieClip *clip);
+void BKE_movieclip_clear_proxy_cache(struct MovieClip *clip);
struct ImBuf *BKE_movieclip_get_ibuf(struct MovieClip *clip, struct MovieClipUser *user);
struct ImBuf *BKE_movieclip_get_postprocessed_ibuf(struct MovieClip *clip, struct MovieClipUser *user, int postprocess_flag);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index cb96538ad81..573fa60f703 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -485,6 +485,7 @@ void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *n
void nodeSynchronizeID(struct bNode *node, bool copy_to_id);
int nodeSocketIsHidden(struct bNodeSocket *sock);
+void ntreeTagUsedSockets(struct bNodeTree *ntree);
/* Node Clipboard */
void BKE_node_clipboard_init(struct bNodeTree *ntree);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 1bfd26d4f8c..1bdbc339f21 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -181,7 +181,7 @@ int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float *
int BKE_object_insert_ptcache(struct Object *ob);
void BKE_object_delete_ptcache(struct Object *ob, int index);
-struct KeyBlock *BKE_object_insert_shape_key(struct Scene *scene, struct Object *ob, const char *name, const bool from_mix);
+struct KeyBlock *BKE_object_insert_shape_key(struct Object *ob, const char *name, const bool from_mix);
bool BKE_object_is_child_recursive(struct Object *ob_parent, struct Object *ob_child);
bool BKE_object_is_animated(struct Scene *scene, struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_object_deform.h b/source/blender/blenkernel/BKE_object_deform.h
index 6de7ff9bc1c..e956815d6f7 100644
--- a/source/blender/blenkernel/BKE_object_deform.h
+++ b/source/blender/blenkernel/BKE_object_deform.h
@@ -29,10 +29,54 @@
* used by painting and tools.
*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Object;
+struct ID;
+struct MDeformVert;
+struct bDeformGroup;
+
+/* General vgroup operations */
+void BKE_object_defgroup_remap_update_users(struct Object *ob, int *map);
+
+bool BKE_object_defgroup_array_get(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot);
+
+struct bDeformGroup *BKE_object_defgroup_add(struct Object *ob);
+struct bDeformGroup *BKE_object_defgroup_add_name(struct Object *ob, const char *name);
+struct MDeformVert *BKE_object_defgroup_data_create(struct ID *id);
+
+bool BKE_object_defgroup_clear(struct Object *ob, struct bDeformGroup *dg, const bool use_selection);
+bool BKE_object_defgroup_clear_all(struct Object *ob, const bool use_selection);
+
+void BKE_object_defgroup_remove(struct Object *ob, struct bDeformGroup *defgroup);
+void BKE_object_defgroup_remove_all(struct Object *ob);
+
+
+/* Select helpers */
+enum eVGroupSelect;
+bool *BKE_object_defgroup_subset_from_select_type(
+ struct Object *ob, enum eVGroupSelect subset_type, int *r_defgroup_tot, int *r_subset_count);
+void BKE_object_defgroup_subset_to_index_array(
+ const bool *defgroup_validmap, const int defgroup_tot, int *r_defgroup_subset_map);
+
+
+/* ********** */
+
+bool *BKE_object_defgroup_lock_flags_get(struct Object *ob, const int defbase_tot);
+bool *BKE_object_defgroup_validmap_get(struct Object *ob, const int defbase_tot);
+bool *BKE_object_defgroup_selected_get(struct Object *ob, int defbase_tot, int *r_dg_flags_sel_tot);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Select helpers */
+bool *BKE_objdef_vgroup_subset_from_select_type(
+ struct Object *ob, enum eVGroupSelect subset_type, int *r_vgroup_tot, int *r_subset_count);
+void BKE_objdef_vgroup_subset_to_index_array(
+ const bool *vgroup_validmap, const int vgroup_tot, int *r_vgroup_subset_map);
-bool *BKE_objdef_lock_flags_get(struct Object *ob, const int defbase_tot);
-bool *BKE_objdef_validmap_get(struct Object *ob, const int defbase_tot);
-bool *BKE_objdef_selected_get(struct Object *ob, int defbase_tot, int *r_dg_flags_sel_tot);
#endif /* __BKE_OBJECT_DEFORM_H__ */
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index b080ca37e67..9ad99f726ff 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -109,7 +109,7 @@ void BKE_palette_cleanup(struct Palette *palette);
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_init(struct UnifiedPaintSettings *ups, struct Paint *p, const char col[3]);
void BKE_paint_free(struct Paint *p);
void BKE_paint_copy(struct Paint *src, struct Paint *tar);
@@ -143,7 +143,9 @@ 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]);
+void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, struct Brush *brush, const float mouse_pos[2]);
+
+void BKE_paint_stroke_get_average(struct Scene *scene, struct Object *ob, float stroke[3]);
/* Session data (mode-specific) */
@@ -191,13 +193,6 @@ typedef struct SculptSession {
struct SculptStroke *stroke;
struct StrokeCache *cache;
-
- /* last paint/sculpt stroke location */
- bool last_stroke_valid;
- float last_stroke[3];
-
- float average_stroke_accum[3];
- int average_stroke_counter;
} SculptSession;
void BKE_free_sculptsession(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 49bc4e5f634..e56add721eb 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -364,7 +364,7 @@ void psys_get_pointcache_start_end(struct Scene *scene, ParticleSystem *psys, in
void psys_check_boid_data(struct ParticleSystem *psys);
-void psys_get_birth_coordinates(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, float dtime, float cfra);
+void psys_get_birth_coords(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, float dtime, float cfra);
void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 188b8e22815..4c11ec9923d 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -280,6 +280,7 @@ void BKE_screen_area_free(struct ScrArea *sa);
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_area_from_space(struct bScreen *sc, struct SpaceLink *sl) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype, const short min);
unsigned int BKE_screen_view3d_layer_active_ex(
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index e460d0d8917..24e8d6362c1 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -102,8 +102,10 @@ typedef struct SeqRenderData {
bool is_proxy_render;
} SeqRenderData;
-SeqRenderData BKE_sequencer_new_render_data(struct EvaluationContext *eval_ctx, struct Main *bmain,
- struct Scene *scene, int rectx, int recty, int preview_render_size);
+void BKE_sequencer_new_render_data(
+ struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *scene,
+ int rectx, int recty, int preview_render_size,
+ SeqRenderData *r_context);
/* Wipe effect */
enum {
@@ -377,12 +379,23 @@ struct Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine);
void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq);
void BKE_sequence_init_colorspace(struct Sequence *seq);
+/* RNA enums, just to be more readable */
+enum {
+ SEQ_SIDE_NONE = 0,
+ SEQ_SIDE_LEFT,
+ SEQ_SIDE_RIGHT,
+ SEQ_SIDE_BOTH
+};
+int BKE_sequencer_find_next_prev_edit(
+ struct Scene *scene, int cfra, const short side,
+ const bool do_skip_mute, const bool do_center, const bool do_unselected);
+
struct Sequence *BKE_sequencer_add_image_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
/* view3d draw callback, run when not in background view */
-typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, bool, bool, int, char[256]);
+typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, bool, bool, bool, int, char[256]);
extern SequencerDrawView sequencer_view3d_cb;
/* copy/paste */
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
index 50ca5fcdf7b..a4182b8405f 100644
--- a/source/blender/blenkernel/BKE_sound.h
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -71,8 +71,6 @@ void sound_delete(struct Main *bmain, struct bSound *sound);
void sound_cache(struct bSound *sound);
-void sound_cache_notifying(struct Main *main, struct bSound *sound);
-
void sound_delete_cache(struct bSound *sound);
void sound_load(struct Main *main, struct bSound *sound);
@@ -132,7 +130,7 @@ int sound_scene_playing(struct Scene *scene);
void sound_free_waveform(struct bSound *sound);
-void sound_read_waveform(struct bSound *sound);
+void sound_read_waveform(struct bSound *sound, short *stop);
void sound_update_scene(struct Main *bmain, struct Scene *scene);
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index 1e79eaa8431..96e88f80464 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -51,7 +51,7 @@ int BKE_text_reload (struct Text *text);
struct Text *BKE_text_load_ex(struct Main *bmain, const char *file, const char *relpath,
const bool is_internal);
struct Text *BKE_text_load (struct Main *bmain, const char *file, const char *relpath);
-struct Text *BKE_text_copy (struct Text *ta);
+struct Text *BKE_text_copy (struct Main *bmain, struct Text *ta);
void BKE_text_unlink (struct Main *bmain, struct Text *text);
void BKE_text_clear (struct Text *text);
void BKE_text_write (struct Text *text, const char *str);
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index 5f5cb4c17cb..e5fb60cf1b5 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -145,6 +145,9 @@ void BKE_tracking_plane_marker_delete(struct MovieTrackingPlaneTrack *plane_trac
struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(struct MovieTrackingPlaneTrack *plane_track, int framenr);
struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(struct MovieTrackingPlaneTrack *plane_track, int framenr);
struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+void BKE_tracking_plane_marker_get_subframe_corners(struct MovieTrackingPlaneTrack *plane_track,
+ float framenr,
+ float corners[4][2]);
/* **** Object **** */
struct MovieTrackingObject *BKE_tracking_object_add(struct MovieTracking *tracking, const char *name);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 353a3892f7d..328c465f07b 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -38,6 +38,7 @@ set(INC
../nodes
../pointcache
../render/extern/include
+ ../../../intern/ghost
../../../intern/guardedalloc
../../../intern/glew-mx
../../../intern/iksolver/extern
@@ -64,6 +65,7 @@ set(SRC
intern/addon.c
intern/anim.c
intern/anim_sys.c
+ intern/appdir.c
intern/armature.c
intern/autoexec.c
intern/blender.c
@@ -84,6 +86,7 @@ set(SRC
intern/curve.c
intern/customdata.c
intern/customdata_file.c
+ intern/data_transfer.c
intern/deform.c
intern/depsgraph.c
intern/displist.c
@@ -120,6 +123,7 @@ set(SRC
intern/mesh.c
intern/mesh_evaluate.c
intern/mesh_mapping.c
+ intern/mesh_remap.c
intern/mesh_validate.c
intern/modifier.c
intern/modifiers_bmesh.c
@@ -177,6 +181,7 @@ set(SRC
BKE_addon.h
BKE_anim.h
BKE_animsys.h
+ BKE_appdir.h
BKE_armature.h
BKE_autoexec.h
BKE_blender.h
@@ -199,6 +204,7 @@ set(SRC
BKE_curve.h
BKE_customdata.h
BKE_customdata_file.h
+ BKE_data_transfer.h
BKE_deform.h
BKE_depsgraph.h
BKE_displist.h
@@ -228,6 +234,7 @@ set(SRC
BKE_mball.h
BKE_mesh.h
BKE_mesh_mapping.h
+ BKE_mesh_remap.h
BKE_modifier.h
BKE_movieclip.h
BKE_multires.h
@@ -273,10 +280,24 @@ set(SRC
tracking_private.h
intern/CCGSubSurf.h
intern/pbvh_intern.h
+ intern/data_transfer_intern.h
)
+if(WITH_BINRELOC)
+ list(APPEND INC_SYS
+ ${BINRELOC_INCLUDE_DIRS}
+ )
+ add_definitions(-DWITH_BINRELOC)
+endif()
+
add_definitions(${GL_DEFINITIONS})
+if(WIN32)
+ list(APPEND INC
+ ../../../intern/utfconv
+ )
+endif()
+
if(WITH_AUDASPACE)
list(APPEND INC
../../../intern/audaspace/intern
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index e01d73c2718..6de55e276a1 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -46,6 +46,7 @@ incs = [
'#/intern/rigidbody',
'#/extern/bullet2/src',
env['BF_GLEW_INC'],
+ '#/intern/ghost',
'#/intern/glew-mx',
'#/intern/audaspace/intern',
'#/intern/elbeem/extern',
@@ -168,7 +169,11 @@ if env['WITH_BF_FREESTYLE']:
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
+ incs += ' ../../../intern/utfconv'
+if env['WITH_BF_BINRELOC']:
+ incs += ' #extern/binreloc/include'
+ defs.append('WITH_BINRELOC')
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [166,25]) #, cc_compileflags = env['CCFLAGS'].append('/WX') )
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index 623fb50b62c..9e5d4afffe2 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -172,29 +172,19 @@ static void *_ehash_lookup(EHash *eh, void *key)
/**/
-typedef struct _EHashIterator {
- EHash *eh;
- int curBucket;
- EHEntry *curEntry;
-} EHashIterator;
-
-static EHashIterator *_ehashIterator_new(EHash *eh)
+static void _ehashIterator_init(EHash *eh, EHashIterator *ehi)
{
- EHashIterator *ehi = EHASH_alloc(eh, sizeof(*ehi));
+ /* fill all members */
ehi->eh = eh;
- ehi->curEntry = NULL;
ehi->curBucket = -1;
+ ehi->curEntry = NULL;
+
while (!ehi->curEntry) {
ehi->curBucket++;
if (ehi->curBucket == ehi->eh->curSize)
break;
ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
}
- return ehi;
-}
-static void _ehashIterator_free(EHashIterator *ehi)
-{
- EHASH_free(ehi->eh, ehi);
}
static void *_ehashIterator_getCurrent(EHashIterator *ehi)
@@ -3051,17 +3041,17 @@ void *ccgSubSurf_getFaceGridData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int
/*** External API iterator functions ***/
-CCGVertIterator *ccgSubSurf_getVertIterator(CCGSubSurf *ss)
+void ccgSubSurf_initVertIterator(CCGSubSurf *ss, CCGVertIterator *viter)
{
- return (CCGVertIterator *) _ehashIterator_new(ss->vMap);
+ _ehashIterator_init(ss->vMap, viter);
}
-CCGEdgeIterator *ccgSubSurf_getEdgeIterator(CCGSubSurf *ss)
+void ccgSubSurf_initEdgeIterator(CCGSubSurf *ss, CCGEdgeIterator *eiter)
{
- return (CCGEdgeIterator *) _ehashIterator_new(ss->eMap);
+ _ehashIterator_init(ss->eMap, eiter);
}
-CCGFaceIterator *ccgSubSurf_getFaceIterator(CCGSubSurf *ss)
+void ccgSubSurf_initFaceIterator(CCGSubSurf *ss, CCGFaceIterator *fiter)
{
- return (CCGFaceIterator *) _ehashIterator_new(ss->fMap);
+ _ehashIterator_init(ss->fMap, fiter);
}
CCGVert *ccgVertIterator_getCurrent(CCGVertIterator *vi)
@@ -3076,10 +3066,6 @@ void ccgVertIterator_next(CCGVertIterator *vi)
{
_ehashIterator_next((EHashIterator *) vi);
}
-void ccgVertIterator_free(CCGVertIterator *vi)
-{
- _ehashIterator_free((EHashIterator *) vi);
-}
CCGEdge *ccgEdgeIterator_getCurrent(CCGEdgeIterator *vi)
{
@@ -3093,10 +3079,6 @@ void ccgEdgeIterator_next(CCGEdgeIterator *vi)
{
_ehashIterator_next((EHashIterator *) vi);
}
-void ccgEdgeIterator_free(CCGEdgeIterator *vi)
-{
- _ehashIterator_free((EHashIterator *) vi);
-}
CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *vi)
{
@@ -3110,10 +3092,6 @@ void ccgFaceIterator_next(CCGFaceIterator *vi)
{
_ehashIterator_next((EHashIterator *) vi);
}
-void ccgFaceIterator_free(CCGFaceIterator *vi)
-{
- _ehashIterator_free((EHashIterator *) vi);
-}
/*** Extern API final vert/edge/face interface ***/
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h
index fdf6d2df99f..2b86a2a66b2 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.h
+++ b/source/blender/blenkernel/intern/CCGSubSurf.h
@@ -53,6 +53,13 @@ typedef struct CCGAllocatorIFC {
void (*release) (CCGAllocatorHDL a);
} CCGAllocatorIFC;
+/* private, so we can allocate on the stack */
+typedef struct _EHashIterator {
+ struct _EHash *eh;
+ int curBucket;
+ struct _EHEntry *curEntry;
+} EHashIterator;
+
/***/
typedef enum {
@@ -163,27 +170,24 @@ int ccgSubSurf_getNumFinalFaces (const CCGSubSurf *ss);
/***/
-typedef struct CCGVertIterator CCGVertIterator;
-typedef struct CCGEdgeIterator CCGEdgeIterator;
-typedef struct CCGFaceIterator CCGFaceIterator;
+typedef struct _EHashIterator CCGVertIterator;
+typedef struct _EHashIterator CCGEdgeIterator;
+typedef struct _EHashIterator CCGFaceIterator;
-CCGVertIterator* ccgSubSurf_getVertIterator (CCGSubSurf *ss);
-CCGEdgeIterator* ccgSubSurf_getEdgeIterator (CCGSubSurf *ss);
-CCGFaceIterator* ccgSubSurf_getFaceIterator (CCGSubSurf *ss);
+void ccgSubSurf_initVertIterator(CCGSubSurf *ss, CCGVertIterator *viter);
+void ccgSubSurf_initEdgeIterator(CCGSubSurf *ss, CCGEdgeIterator *eiter);
+void ccgSubSurf_initFaceIterator(CCGSubSurf *ss, CCGFaceIterator *fiter);
CCGVert* ccgVertIterator_getCurrent (CCGVertIterator *vi);
int ccgVertIterator_isStopped (CCGVertIterator *vi);
void ccgVertIterator_next (CCGVertIterator *vi);
-void ccgVertIterator_free (CCGVertIterator *vi);
CCGEdge* ccgEdgeIterator_getCurrent (CCGEdgeIterator *ei);
int ccgEdgeIterator_isStopped (CCGEdgeIterator *ei);
void ccgEdgeIterator_next (CCGEdgeIterator *ei);
-void ccgEdgeIterator_free (CCGEdgeIterator *ei);
CCGFace* ccgFaceIterator_getCurrent (CCGFaceIterator *fi);
int ccgFaceIterator_isStopped (CCGFaceIterator *fi);
void ccgFaceIterator_next (CCGFaceIterator *fi);
-void ccgFaceIterator_free (CCGFaceIterator *fi);
#endif /* __CCGSUBSURF_H__ */
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 2a52376aa2d..9cc99a07353 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -75,13 +75,11 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
#include "BLI_sys_types.h" /* for intptr_t support */
#include "GPU_buffers.h"
-#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
-#include "GPU_material.h"
/* very slow! enable for testing only! */
-// #define USE_MODIFIER_VALIDATE
+//#define USE_MODIFIER_VALIDATE
#ifdef USE_MODIFIER_VALIDATE
# define ASSERT_IS_VALID_DM(dm) (BLI_assert((dm == NULL) || (DM_is_valid(dm) == true)))
@@ -1230,7 +1228,7 @@ static void calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const d
bool *defbase_sel = NULL;
if (draw_flag & CALC_WP_MULTIPAINT) {
- defbase_sel = BKE_objdef_selected_get(ob, defbase_tot, &defbase_sel_tot);
+ defbase_sel = BKE_object_defgroup_selected_get(ob, defbase_tot, &defbase_sel_tot);
}
for (i = numVerts; i != 0; i--, wc++, dv++) {
@@ -1453,8 +1451,10 @@ static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *UNUSED(ob))
*/
static void dm_ensure_display_normals(DerivedMesh *dm)
{
- /* this is for final output only, up until now this layer should be missing */
- BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
+ /* Note: dm *may* have a poly CD_NORMAL layer (generated by a modifier needing poly normals e.g.).
+ * We do not use it here, though. And it should be tagged as temp!
+ */
+ /* BLI_assert((CustomData_has_layer(&dm->polyData, CD_NORMAL) == false)); */
if ((dm->type == DM_TYPE_CDDM) &&
((dm->dirty & DM_DIRTY_NORMALS) || CustomData_has_layer(&dm->faceData, CD_NORMAL) == false))
@@ -1539,8 +1539,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
const bool has_multires = (mmd && mmd->sculptlvl != 0);
bool multires_applied = false;
- const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt;
- const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm);
+ const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt && !useRenderParams;
+ const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm) && !useRenderParams;
const int draw_flag = dm_drawflag_calc(scene->toolsettings);
/* Generic preview only in object mode! */
@@ -2021,10 +2021,10 @@ bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *
if (!modifier_isEnabled(scene, md, required_mode)) return 0;
if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
modifier_setError(md, "Modifier requires original data, bad stack position");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, DerivedMesh **cage_r,
@@ -2555,7 +2555,9 @@ DerivedMesh *object_get_derived_final(Object *ob, const bool for_render)
return ob->derivedFinal;
}
- if (em) {
+ /* only return the editmesh if its from this object because
+ * we don't a mesh from another object's modifier stack: T43122 */
+ if (em && (em->ob == ob)) {
DerivedMesh *dm = em->derivedFinal;
return dm;
}
@@ -3369,7 +3371,7 @@ static void dm_debug_info_layers(DynStr *dynstr, DerivedMesh *dm, CustomData *cd
CustomData_file_write_info(type, &structname, &structnum);
BLI_dynstr_appendf(dynstr,
" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
- name, structname, type, (void *)pt, size, pt_size);
+ name, structname, type, (const void *)pt, size, pt_size);
}
}
}
@@ -3433,7 +3435,7 @@ void DM_debug_print(DerivedMesh *dm)
void DM_debug_print_cdlayers(CustomData *data)
{
int i;
- CustomDataLayer *layer;
+ const CustomDataLayer *layer;
printf("{\n");
@@ -3445,7 +3447,7 @@ void DM_debug_print_cdlayers(CustomData *data)
int structnum;
CustomData_file_write_info(layer->type, &structname, &structnum);
printf(" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
- name, structname, layer->type, (void *)layer->data, size, (int)(MEM_allocN_len(layer->data) / size));
+ name, structname, layer->type, (const void *)layer->data, size, (int)(MEM_allocN_len(layer->data) / size));
}
printf("}\n");
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index e753a7f7948..f94f1e72638 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -215,6 +215,10 @@ bAction *BKE_action_copy(bAction *src)
}
}
+ if (src->id.lib) {
+ BKE_id_lib_local_paths(G.main, src->id.lib, &dst->id);
+ }
+
return dst;
}
@@ -450,9 +454,9 @@ bPoseChannel *BKE_pose_channel_find_name(const bPose *pose, const char *name)
return NULL;
if (pose->chanhash)
- return BLI_ghash_lookup(pose->chanhash, (void *)name);
+ return BLI_ghash_lookup(pose->chanhash, (const void *)name);
- return BLI_findstring(&((bPose *)pose)->chanbase, name, offsetof(bPoseChannel, name));
+ return BLI_findstring(&((const bPose *)pose)->chanbase, name, offsetof(bPoseChannel, name));
}
/**
@@ -1028,12 +1032,12 @@ bool action_has_motion(const bAction *act)
if (act) {
for (fcu = act->curves.first; fcu; fcu = fcu->next) {
if (fcu->totvert)
- return 1;
+ return true;
}
}
/* nothing found */
- return 0;
+ return false;
}
/* Calculate the extents of given action */
diff --git a/source/blender/blenkernel/intern/addon.c b/source/blender/blenkernel/intern/addon.c
index 119fa266908..28667d458b8 100644
--- a/source/blender/blenkernel/intern/addon.c
+++ b/source/blender/blenkernel/intern/addon.c
@@ -29,15 +29,9 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
-#include "BLI_string.h"
#include "BKE_addon.h" /* own include */
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "BLF_translation.h"
-
#include "MEM_guardedalloc.h"
static GHash *global_addonpreftype_hash = NULL;
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 2fb832dc72d..8e36449f214 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -83,7 +83,7 @@ bool id_type_can_have_animdata(ID *id)
{
/* sanity check */
if (id == NULL)
- return 0;
+ return false;
/* Only some ID-blocks have this info for now */
/* TODO: finish adding this for the other blocktypes */
@@ -100,13 +100,14 @@ bool id_type_can_have_animdata(ID *id)
case ID_SCE:
case ID_MC:
case ID_MSK:
+ case ID_GD:
{
- return 1;
+ return true;
}
/* no AnimData */
default:
- return 0;
+ return false;
}
}
@@ -193,20 +194,20 @@ bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act)
/* can set */
adt->action = act;
id_us_plus((ID *)adt->action);
- ok = 1;
+ ok = true;
}
else {
/* cannot set */
BKE_reportf(reports, RPT_ERROR,
"Could not set action '%s' onto ID '%s', as it does not have suitably rooted paths "
"for this purpose", act->id.name + 2, id->name);
- /* ok = 0; */
+ /* ok = false; */
}
}
else {
/* just clearing the action... */
adt->action = NULL;
- ok = 1;
+ ok = true;
}
return ok;
@@ -289,7 +290,7 @@ bool BKE_copy_animdata_id(ID *id_to, ID *id_from, const bool do_action)
AnimData *adt;
if ((id_to && id_from) && (GS(id_to->name) != GS(id_from->name)))
- return 0;
+ return false;
BKE_free_animdata(id_to);
@@ -299,7 +300,7 @@ bool BKE_copy_animdata_id(ID *id_to, ID *id_from, const bool do_action)
iat->adt = BKE_copy_animdata(adt, do_action);
}
- return 1;
+ return true;
}
void BKE_copy_animdata_id_action(ID *id)
@@ -1031,6 +1032,9 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u
/* line styles */
ANIMDATA_IDS_CB(mainptr->linestyle.first);
+
+ /* grease pencil */
+ ANIMDATA_IDS_CB(mainptr->gpencil.first);
}
/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
@@ -1119,6 +1123,9 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha
/* linestyles */
RENAMEFIX_ANIM_IDS(mainptr->linestyle.first);
+ /* grease pencil */
+ RENAMEFIX_ANIM_IDS(mainptr->gpencil.first);
+
/* scenes */
RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene);
}
@@ -1346,11 +1353,11 @@ static bool animsys_remap_path(AnimMapper *UNUSED(remap), char *path, char **dst
/* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */
*dst = path;
- return 0;
+ return false;
}
-/* less then 1.0 evaluates to false, use epsilon to avoid float error */
+/* less than 1.0 evaluates to false, use epsilon to avoid float error */
#define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON)))
/* Write the given value to a setting using RNA, and return success */
@@ -1375,7 +1382,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
path, array_index, array_len - 1);
}
- return 0;
+ return false;
}
switch (RNA_property_type(prop)) {
@@ -1429,7 +1436,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
break;
default:
/* nothing can be done here... so it is unsuccessful? */
- return 0;
+ return false;
}
/* RNA property update disabled for now - [#28525] [#28690] [#28774] [#28777] */
@@ -1468,7 +1475,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
}
/* successful */
- return 1;
+ return true;
}
else {
/* failed to get path */
@@ -1479,7 +1486,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
(ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>",
path, array_index);
}
- return 0;
+ return false;
}
}
@@ -2680,6 +2687,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime)
/* linestyles */
EVAL_ANIM_IDS(main->linestyle.first, ADT_RECALC_ANIM);
+ /* grease pencil */
+ EVAL_ANIM_IDS(main->gpencil.first, ADT_RECALC_ANIM);
+
/* objects */
/* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets
* this tagged by Depsgraph on framechange. This optimization means that objects
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
new file mode 100644
index 00000000000..50f9a9be05d
--- /dev/null
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -0,0 +1,808 @@
+/*
+ * ***** 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.
+ *
+ */
+
+/** \file blender/blenlib/intern/appdir.c
+ * \ingroup bke
+ *
+ * Access to application level directories.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
+
+#include "BKE_appdir.h" /* own include */
+
+#include "GHOST_Path-api.h"
+
+#include "../blenkernel/BKE_blender.h" /* BLENDER_VERSION, bad level include (no function call) */
+
+#include "MEM_guardedalloc.h"
+
+#ifdef WIN32
+# include "utf_winfunc.h"
+# include "utfconv.h"
+# include <io.h>
+# ifdef _WIN32_IE
+# undef _WIN32_IE
+# endif
+# define _WIN32_IE 0x0501
+# include <windows.h>
+# include <shlobj.h>
+# include "BLI_winstuff.h"
+#else /* non windows */
+# ifdef WITH_BINRELOC
+# include "binreloc.h"
+# endif
+# include <unistd.h> /* mkdtemp on OSX (and probably all *BSD?), not worth making specific check for this OS. */
+#endif /* WIN32 */
+
+/* local */
+static char bprogname[FILE_MAX]; /* full path to program executable */
+static char bprogdir[FILE_MAX]; /* full path to directory in which executable is located */
+static char btempdir_base[FILE_MAX]; /* persistent temporary directory */
+static char btempdir_session[FILE_MAX] = ""; /* volatile temporary directory */
+
+/* This is now only used to really get the user's default document folder */
+/* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
+ * as default location to save documents */
+const char *BKE_appdir_folder_default(void)
+{
+#ifndef WIN32
+ const char * const xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR");
+
+ if (xdg_documents_dir)
+ return xdg_documents_dir;
+
+ return getenv("HOME");
+#else /* Windows */
+ static char documentfolder[MAXPATHLEN];
+ HRESULT hResult;
+
+ /* Check for %HOME% env var */
+ if (uput_getenv("HOME", documentfolder, MAXPATHLEN)) {
+ if (BLI_is_dir(documentfolder)) return documentfolder;
+ }
+
+ /* add user profile support for WIN 2K / NT.
+ * This is %APPDATA%, which translates to either
+ * %USERPROFILE%\Application Data or since Vista
+ * to %USERPROFILE%\AppData\Roaming
+ */
+ hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
+
+ if (hResult == S_OK) {
+ if (BLI_is_dir(documentfolder)) return documentfolder;
+ }
+
+ return NULL;
+#endif /* WIN32 */
+}
+
+
+// #define PATH_DEBUG
+
+/* returns a formatted representation of the specified version number. Non-reentrant! */
+static char *blender_version_decimal(const int ver)
+{
+ static char version_str[5];
+ sprintf(version_str, "%d.%02d", ver / 100, ver % 100);
+ return version_str;
+}
+
+/**
+ * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath,
+ * returning true if result points to a directory.
+ */
+static bool test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
+{
+ char tmppath[FILE_MAX];
+
+ if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
+ else BLI_strncpy(tmppath, path_base, sizeof(tmppath));
+
+ /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
+ if (folder_name)
+ BLI_make_file_string("/", targetpath, tmppath, folder_name);
+ else
+ BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
+ /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile)
+ * if folder_name is specified but not otherwise? */
+
+ if (BLI_is_dir(targetpath)) {
+#ifdef PATH_DEBUG
+ printf("\t%s found: %s\n", __func__, targetpath);
+#endif
+ return true;
+ }
+ else {
+#ifdef PATH_DEBUG
+ printf("\t%s missing: %s\n", __func__, targetpath);
+#endif
+ //targetpath[0] = '\0';
+ return false;
+ }
+}
+
+/**
+ * Puts the value of the specified environment variable into *path if it exists
+ * and points at a directory. Returns true if this was done.
+ */
+static bool test_env_path(char *path, const char *envvar)
+{
+ const char *env = envvar ? getenv(envvar) : NULL;
+ if (!env) return false;
+
+ if (BLI_is_dir(env)) {
+ BLI_strncpy(path, env, FILE_MAX);
+#ifdef PATH_DEBUG
+ printf("\t%s env %s found: %s\n", __func__, envvar, env);
+#endif
+ return true;
+ }
+ else {
+ path[0] = '\0';
+#ifdef PATH_DEBUG
+ printf("\t%s env %s missing: %s\n", __func__, envvar, env);
+#endif
+ return false;
+ }
+}
+
+/**
+ * Constructs in \a targetpath the name of a directory relative to a version-specific
+ * subdirectory in the parent directory of the Blender executable.
+ *
+ * \param targetpath String to return path
+ * \param folder_name Optional folder name within version-specific directory
+ * \param subfolder_name Optional subfolder name within folder_name
+ * \param ver To construct name of version-specific directory within bprogdir
+ * \return true if such a directory exists.
+ */
+static bool get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
+{
+ char relfolder[FILE_MAX];
+
+#ifdef PATH_DEBUG
+ printf("%s...\n", __func__);
+#endif
+
+ if (folder_name) {
+ if (subfolder_name) {
+ BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
+ }
+ else {
+ BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
+ }
+ }
+ else {
+ relfolder[0] = '\0';
+ }
+
+ /* 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
+}
+
+/**
+ * Is this an install with user files kept together with the Blender executable and its
+ * installation files.
+ */
+static bool is_portable_install(void)
+{
+ /* detect portable install by the existence of config folder */
+ const int ver = BLENDER_VERSION;
+ char path[FILE_MAX];
+
+ return get_path_local(path, "config", NULL, ver);
+}
+
+/**
+ * Returns the path of a folder within the user-files area.
+ *
+ *
+ * \param targetpath String to return path
+ * \param folder_name default name of folder within user area
+ * \param subfolder_name optional name of subfolder within folder
+ * \param envvar name of environment variable which, if defined, overrides folder_name
+ * \param ver Blender version, used to construct a subdirectory name
+ * \return true if it was able to construct such a path.
+ */
+static bool get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
+{
+ char user_path[FILE_MAX];
+ const char *user_base_path;
+
+ /* for portable install, user path is always local */
+ if (is_portable_install())
+ return get_path_local(targetpath, folder_name, subfolder_name, ver);
+
+ user_path[0] = '\0';
+
+ if (test_env_path(user_path, envvar)) {
+ if (subfolder_name) {
+ return test_path(targetpath, user_path, NULL, subfolder_name);
+ }
+ else {
+ BLI_strncpy(targetpath, user_path, FILE_MAX);
+ return true;
+ }
+ }
+
+ user_base_path = (const char *)GHOST_getUserDir(ver, blender_version_decimal(ver));
+ if (user_base_path)
+ BLI_strncpy(user_path, user_base_path, FILE_MAX);
+
+ if (!user_path[0])
+ return false;
+
+#ifdef PATH_DEBUG
+ printf("%s: %s\n", __func__, user_path);
+#endif
+
+ if (subfolder_name) {
+ return test_path(targetpath, user_path, folder_name, subfolder_name);
+ }
+ else {
+ return test_path(targetpath, user_path, NULL, folder_name);
+ }
+}
+
+/**
+ * Returns the path of a folder within the Blender installation directory.
+ *
+ * \param targetpath String to return path
+ * \param folder_name default name of folder within installation area
+ * \param subfolder_name optional name of subfolder within folder
+ * \param envvar name of environment variable which, if defined, overrides folder_name
+ * \param ver Blender version, used to construct a subdirectory name
+ * \return true if it was able to construct such a path.
+ */
+static bool get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
+{
+ char system_path[FILE_MAX];
+ const char *system_base_path;
+ char cwd[FILE_MAX];
+ char relfolder[FILE_MAX];
+
+ if (folder_name) {
+ if (subfolder_name) {
+ BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
+ }
+ else {
+ BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
+ }
+ }
+ else {
+ relfolder[0] = '\0';
+ }
+
+ /* first allow developer only overrides to the system path
+ * these are only used when running blender from source */
+
+ /* try CWD/release/folder_name */
+ if (BLI_current_working_dir(cwd, sizeof(cwd))) {
+ if (test_path(targetpath, cwd, "release", relfolder)) {
+ return true;
+ }
+ }
+
+ /* try EXECUTABLE_DIR/release/folder_name */
+ if (test_path(targetpath, bprogdir, "release", relfolder))
+ return true;
+
+ /* end developer overrides */
+
+
+
+ system_path[0] = '\0';
+
+ if (test_env_path(system_path, envvar)) {
+ if (subfolder_name) {
+ return test_path(targetpath, system_path, NULL, subfolder_name);
+ }
+ else {
+ BLI_strncpy(targetpath, system_path, FILE_MAX);
+ return true;
+ }
+ }
+
+ system_base_path = (const char *)GHOST_getSystemDir(ver, blender_version_decimal(ver));
+ if (system_base_path)
+ BLI_strncpy(system_path, system_base_path, FILE_MAX);
+
+ if (!system_path[0])
+ return false;
+
+#ifdef PATH_DEBUG
+ printf("%s: %s\n", __func__, system_path);
+#endif
+
+ if (subfolder_name) {
+ /* try $BLENDERPATH/folder_name/subfolder_name */
+ return test_path(targetpath, system_path, folder_name, subfolder_name);
+ }
+ else {
+ /* try $BLENDERPATH/folder_name */
+ return test_path(targetpath, system_path, NULL, folder_name);
+ }
+}
+
+/* get a folder out of the 'folder_id' presets for paths */
+/* returns the path if found, NULL string if not */
+const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder)
+{
+ const int ver = BLENDER_VERSION;
+ static char path[FILE_MAX] = "";
+
+ switch (folder_id) {
+ case BLENDER_DATAFILES: /* general case */
+ if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
+ if (get_path_local(path, "datafiles", subfolder, ver)) break;
+ if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
+ return NULL;
+
+ case BLENDER_USER_DATAFILES:
+ if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
+ return NULL;
+
+ case BLENDER_SYSTEM_DATAFILES:
+ if (get_path_local(path, "datafiles", subfolder, ver)) break;
+ if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
+ return NULL;
+
+ case BLENDER_USER_AUTOSAVE:
+ if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
+ return NULL;
+
+ case BLENDER_USER_CONFIG:
+ if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
+ return NULL;
+
+ case BLENDER_USER_SCRIPTS:
+ if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
+ return NULL;
+
+ case BLENDER_SYSTEM_SCRIPTS:
+ if (get_path_local(path, "scripts", subfolder, ver)) break;
+ if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
+ return NULL;
+
+ case BLENDER_SYSTEM_PYTHON:
+ if (get_path_local(path, "python", subfolder, ver)) break;
+ if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
+ return NULL;
+
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ return path;
+}
+
+/**
+ * Returns the path to a folder in the user area without checking that it actually exists first.
+ */
+const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder)
+{
+ const int ver = BLENDER_VERSION;
+ static char path[FILE_MAX] = "";
+
+ switch (folder_id) {
+ case BLENDER_USER_DATAFILES:
+ get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
+ break;
+ case BLENDER_USER_CONFIG:
+ get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
+ break;
+ case BLENDER_USER_AUTOSAVE:
+ get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
+ break;
+ case BLENDER_USER_SCRIPTS:
+ get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ if ('\0' == path[0]) {
+ return NULL;
+ }
+ return path;
+}
+
+/**
+ * Returns the path to a folder in the user area, creating it if it doesn't exist.
+ */
+const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfolder)
+{
+ const char *path;
+
+ /* only for user folders */
+ if (!ELEM(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
+ return NULL;
+
+ path = BKE_appdir_folder_id(folder_id, subfolder);
+
+ if (!path) {
+ path = BKE_appdir_folder_id_user_notest(folder_id, subfolder);
+ if (path) BLI_dir_create_recursive(path);
+ }
+
+ return path;
+}
+
+/**
+ * Returns the path of the top-level version-specific local, user or system directory.
+ * If do_check, then the result will be NULL if the directory doesn't exist.
+ */
+const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, const bool do_check)
+{
+ static char path[FILE_MAX] = "";
+ bool ok;
+ switch (folder_id) {
+ case BLENDER_RESOURCE_PATH_USER:
+ ok = get_path_user(path, NULL, NULL, NULL, ver);
+ break;
+ case BLENDER_RESOURCE_PATH_LOCAL:
+ ok = get_path_local(path, NULL, NULL, ver);
+ break;
+ case BLENDER_RESOURCE_PATH_SYSTEM:
+ ok = get_path_system(path, NULL, NULL, NULL, ver);
+ break;
+ default:
+ path[0] = '\0'; /* in case do_check is false */
+ ok = false;
+ BLI_assert(!"incorrect ID");
+ break;
+ }
+
+ if (!ok && do_check) {
+ return NULL;
+ }
+
+ return path;
+}
+
+#ifdef PATH_DEBUG
+# undef PATH_DEBUG
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/* Preset paths */
+
+/**
+ * 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.
+ */
+static int add_win32_extension(char *name)
+{
+ int retval = 0;
+ int type;
+
+ type = BLI_exists(name);
+ if ((type == 0) || S_ISDIR(type)) {
+#ifdef _WIN32
+ char filename[FILE_MAX];
+ char ext[FILE_MAX];
+ const char *extensions = getenv("PATHEXT");
+ if (extensions) {
+ char *temp;
+ do {
+ strcpy(filename, name);
+ temp = strstr(extensions, ";");
+ if (temp) {
+ strncpy(ext, extensions, temp - extensions);
+ ext[temp - extensions] = 0;
+ extensions = temp + 1;
+ strcat(filename, ext);
+ }
+ else {
+ strcat(filename, extensions);
+ }
+
+ type = BLI_exists(filename);
+ if (type && (!S_ISDIR(type))) {
+ retval = 1;
+ strcpy(name, filename);
+ break;
+ }
+ } while (temp);
+ }
+#endif
+ }
+ else {
+ retval = 1;
+ }
+
+ return (retval);
+}
+
+/**
+ * Checks if name is a fully qualified filename to an executable.
+ * If not it searches $PATH for the file. On Windows it also
+ * adds the correct extension (.com .exe etc) from
+ * $PATHEXT if necessary. Also on Windows it translates
+ * the name to its 8.3 version to prevent problems with
+ * spaces and stuff. Final result is returned in fullname.
+ *
+ * \param fullname The full path and full name of the executable
+ * (must be FILE_MAX minimum)
+ * \param name The name of the executable (usually argv[0]) to be checked
+ */
+static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name)
+{
+ char filename[FILE_MAX];
+ const char *path = NULL, *temp;
+
+#ifdef _WIN32
+ const char *separator = ";";
+#else
+ const char *separator = ":";
+#endif
+
+
+#ifdef WITH_BINRELOC
+ /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */
+ path = br_find_exe(NULL);
+ if (path) {
+ BLI_strncpy(fullname, path, maxlen);
+ free((void *)path);
+ return;
+ }
+#endif
+
+#ifdef _WIN32
+ wchar_t *fullname_16 = MEM_mallocN(maxlen * sizeof(wchar_t), "ProgramPath");
+ if (GetModuleFileNameW(0, fullname_16, maxlen)) {
+ conv_utf_16_to_8(fullname_16, fullname, maxlen);
+ if (!BLI_exists(fullname)) {
+ printf("path can't be found: \"%.*s\"\n", (int)maxlen, fullname);
+ MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
+ }
+ MEM_freeN(fullname_16);
+ return;
+ }
+
+ MEM_freeN(fullname_16);
+#endif
+
+ /* unix and non linux */
+ if (name && name[0]) {
+
+ BLI_strncpy(fullname, name, maxlen);
+ if (name[0] == '.') {
+ char wdir[FILE_MAX] = "";
+ BLI_current_working_dir(wdir, sizeof(wdir)); /* backup cwd to restore after */
+
+ // not needed but avoids annoying /./ in name
+ if (name[1] == SEP)
+ BLI_join_dirfile(fullname, maxlen, wdir, name + 2);
+ else
+ BLI_join_dirfile(fullname, maxlen, wdir, name);
+
+ add_win32_extension(fullname); /* XXX, doesnt respect length */
+ }
+ else if (BLI_last_slash(name)) {
+ // full path
+ BLI_strncpy(fullname, name, maxlen);
+ add_win32_extension(fullname);
+ }
+ else {
+ // search for binary in $PATH
+ path = getenv("PATH");
+ if (path) {
+ do {
+ temp = strstr(path, separator);
+ if (temp) {
+ strncpy(filename, path, temp - path);
+ filename[temp - path] = 0;
+ path = temp + 1;
+ }
+ else {
+ strncpy(filename, path, sizeof(filename));
+ }
+ BLI_path_append(fullname, maxlen, name);
+ if (add_win32_extension(filename)) {
+ BLI_strncpy(fullname, filename, maxlen);
+ break;
+ }
+ } while (temp);
+ }
+ }
+#if defined(DEBUG)
+ if (strcmp(name, fullname)) {
+ printf("guessing '%s' == '%s'\n", name, fullname);
+ }
+#endif
+ }
+}
+
+void BKE_appdir_program_path_init(const char *argv0)
+{
+ bli_where_am_i(bprogname, sizeof(bprogname), argv0);
+ BLI_split_dir_part(bprogname, bprogdir, sizeof(bprogdir));
+}
+
+/**
+ * Path to executable
+ */
+const char *BKE_appdir_program_path(void)
+{
+ return bprogname;
+}
+
+/**
+ * Path to directory of executable
+ */
+const char *BKE_appdir_program_dir(void)
+{
+ return bprogdir;
+}
+
+/**
+ * Gets the temp directory when blender first runs.
+ * If the default path is not found, use try $TEMP
+ *
+ * Also make sure the temp dir has a trailing slash
+ *
+ * \param fullname The full path to the temporary temp directory
+ * \param basename The full path to the persistent temp directory (may be NULL)
+ * \param maxlen The size of the fullname buffer
+ * \param userdir Directory specified in user preferences
+ */
+static void BLI_where_is_temp(char *fullname, char *basename, const size_t maxlen, char *userdir)
+{
+ /* Clear existing temp dir, if needed. */
+ BKE_tempdir_session_purge();
+
+ fullname[0] = '\0';
+ if (basename) {
+ basename[0] = '\0';
+ }
+
+ if (userdir && BLI_is_dir(userdir)) {
+ BLI_strncpy(fullname, userdir, maxlen);
+ }
+
+
+#ifdef WIN32
+ if (fullname[0] == '\0') {
+ const char *tmp = getenv("TEMP"); /* Windows */
+ if (tmp && BLI_is_dir(tmp)) {
+ BLI_strncpy(fullname, tmp, maxlen);
+ }
+ }
+#else
+ /* Other OS's - Try TMP and TMPDIR */
+ if (fullname[0] == '\0') {
+ const char *tmp = getenv("TMP");
+ if (tmp && BLI_is_dir(tmp)) {
+ BLI_strncpy(fullname, tmp, maxlen);
+ }
+ }
+
+ if (fullname[0] == '\0') {
+ const char *tmp = getenv("TMPDIR");
+ if (tmp && BLI_is_dir(tmp)) {
+ BLI_strncpy(fullname, tmp, maxlen);
+ }
+ }
+#endif
+
+ if (fullname[0] == '\0') {
+ BLI_strncpy(fullname, "/tmp/", maxlen);
+ }
+ else {
+ /* add a trailing slash if needed */
+ BLI_add_slash(fullname);
+#ifdef WIN32
+ if (userdir && userdir != fullname) {
+ BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
+ }
+#endif
+ }
+
+ /* Now that we have a valid temp dir, add system-generated unique sub-dir. */
+ if (basename) {
+ /* 'XXXXXX' is kind of tag to be replaced by mktemp-familly by an uuid. */
+ char *tmp_name = BLI_strdupcat(fullname, "blender_XXXXXX");
+ const size_t ln = strlen(tmp_name) + 1;
+ if (ln <= maxlen) {
+#ifdef WIN32
+ if (_mktemp_s(tmp_name, ln) == 0) {
+ BLI_dir_create_recursive(tmp_name);
+ }
+#else
+ mkdtemp(tmp_name);
+#endif
+ }
+ if (BLI_is_dir(tmp_name)) {
+ BLI_strncpy(basename, fullname, maxlen);
+ BLI_strncpy(fullname, tmp_name, maxlen);
+ BLI_add_slash(fullname);
+ }
+ else {
+ printf("Warning! Could not generate a temp file name for '%s', falling back to '%s'\n", tmp_name, fullname);
+ }
+
+ MEM_freeN(tmp_name);
+ }
+}
+
+/**
+ * Sets btempdir_base to userdir if specified and is a valid directory, otherwise
+ * chooses a suitable OS-specific temporary directory.
+ * Sets btempdir_session to a mkdtemp-generated sub-dir of btempdir_base.
+ *
+ * \note On Window userdir will be set to the temporary directory!
+ */
+void BKE_tempdir_init(char *userdir)
+{
+ BLI_where_is_temp(btempdir_session, btempdir_base, FILE_MAX, userdir);
+;
+}
+
+/**
+ * Path to temporary directory (with trailing slash)
+ */
+const char *BKE_tempdir_session(void)
+{
+ return btempdir_session[0] ? btempdir_session : BKE_tempdir_base();
+}
+
+/**
+ * Path to persistent temporary directory (with trailing slash)
+ */
+const char *BKE_tempdir_base(void)
+{
+ return btempdir_base;
+}
+
+/**
+ * Path to the system temporary directory (with trailing slash)
+ */
+void BKE_tempdir_system_init(char *dir)
+{
+ BLI_where_is_temp(dir, NULL, FILE_MAX, NULL);
+}
+
+/**
+ * Delete content of this instance's temp dir.
+ */
+void BKE_tempdir_session_purge(void)
+{
+ if (btempdir_session[0] && BLI_is_dir(btempdir_session)) {
+ BLI_delete(btempdir_session, true, true);
+ }
+}
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index d3dcb2b72a0..431c24d3ed0 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -222,6 +222,10 @@ bArmature *BKE_armature_copy(bArmature *arm)
newArm->act_edbone = NULL;
newArm->sketch = NULL;
+ if (arm->id.lib) {
+ BKE_id_lib_local_paths(G.main, arm->id.lib, &newArm->id);
+ }
+
return newArm;
}
@@ -1654,6 +1658,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
pchanw.next = pchan->next;
pchanw.parent = pchan->parent;
pchanw.child = pchan->child;
+ pchanw.custom_tx = pchan->custom_tx;
pchanw.mpath = pchan->mpath;
pchan->mpath = NULL;
@@ -2161,9 +2166,9 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
mul_v3_fl(poseMat[2], scale);
break;
}
- case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC:
+ case CONSTRAINT_SPLINEIK_XZS_INVERSE:
{
- /* 'volume preservation' */
+ /* old 'volume preservation' method using the inverse scale */
float scale;
/* calculate volume preservation factor which is
@@ -2184,6 +2189,54 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
mul_v3_fl(poseMat[2], scale);
break;
}
+ case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC:
+ {
+ /* improved volume preservation based on the Stretch To constraint */
+ float final_scale;
+
+ /* as the basis for volume preservation, we use the inverse scale factor... */
+ if (fabsf(scaleFac) != 0.0f) {
+ /* NOTE: The method here is taken wholesale from the Stretch To constraint */
+ float bulge = powf(1.0f / fabsf(scaleFac), ikData->bulge);
+
+ if (bulge > 1.0f) {
+ if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MAX) {
+ float bulge_max = max_ff(ikData->bulge_max, 1.0f);
+ float hard = min_ff(bulge, bulge_max);
+
+ float range = bulge_max - 1.0f;
+ float scale = (range > 0.0f) ? 1.0f / range : 0.0f;
+ float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (0.5f * M_PI);
+
+ bulge = interpf(soft, hard, ikData->bulge_smooth);
+ }
+ }
+ if (bulge < 1.0f) {
+ if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MIN) {
+ float bulge_min = CLAMPIS(ikData->bulge_min, 0.0f, 1.0f);
+ float hard = max_ff(bulge, bulge_min);
+
+ float range = 1.0f - bulge_min;
+ float scale = (range > 0.0f) ? 1.0f / range : 0.0f;
+ float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (0.5f * M_PI);
+
+ bulge = interpf(soft, hard, ikData->bulge_smooth);
+ }
+ }
+
+ /* compute scale factor for xz axes from this value */
+ final_scale = sqrt(bulge);
+ }
+ else {
+ /* no scaling, so scale factor is simple */
+ final_scale = 1.0f;
+ }
+
+ /* apply the scaling (assuming normalised scale) */
+ mul_v3_fl(poseMat[0], final_scale);
+ mul_v3_fl(poseMat[2], final_scale);
+ break;
+ }
}
/* finally, multiply the x and z scaling by the radius of the curve too,
diff --git a/source/blender/blenkernel/intern/autoexec.c b/source/blender/blenkernel/intern/autoexec.c
index 872780bd50a..d9462cd0262 100644
--- a/source/blender/blenkernel/intern/autoexec.c
+++ b/source/blender/blenkernel/intern/autoexec.c
@@ -34,9 +34,12 @@
#include "BLI_utildefines.h"
#include "BLI_fnmatch.h"
-#include "BLI_string.h"
#include "BLI_path_util.h"
+#ifdef WIN32
+# include "BLI_string.h"
+#endif
+
#include "BKE_autoexec.h" /* own include */
/**
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index adfe43cb2a3..96f769587d9 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -61,6 +61,7 @@
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
+#include "BKE_appdir.h"
#include "BKE_blender.h"
#include "BKE_bpath.h"
#include "BKE_brush.h"
@@ -493,10 +494,11 @@ bool BKE_read_file_from_memory(
BLO_update_defaults_startup_blend(bfd->main);
setup_app_data(C, bfd, "<memory2>");
}
- else
+ else {
BKE_reports_prepend(reports, "Loading failed: ");
+ }
- return (bfd ? 1 : 0);
+ return (bfd != NULL);
}
/* memfile is the undo buffer */
@@ -516,10 +518,11 @@ bool BKE_read_file_from_memfile(
setup_app_data(C, bfd, "<memory1>");
}
- else
+ else {
BKE_reports_prepend(reports, "Loading failed: ");
+ }
- return (bfd ? 1 : 0);
+ return (bfd != NULL);
}
/* only read the userdef from a .blend */
@@ -687,7 +690,7 @@ void BKE_write_undo(bContext *C, const char *name)
counter = counter % U.undosteps;
BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter);
- BLI_make_file_string("/", filepath, BLI_temp_dir_session(), numstr);
+ BLI_make_file_string("/", filepath, BKE_tempdir_session(), numstr);
/* success = */ /* UNUSED */ BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);
@@ -834,13 +837,13 @@ bool BKE_undo_save_file(const char *filename)
int file, oflags;
if ((U.uiflag & USER_GLOBALUNDO) == 0) {
- return 0;
+ return false;
}
uel = curundo;
if (uel == NULL) {
fprintf(stderr, "No undo buffer to save recovery file\n");
- return 0;
+ return false;
}
/* note: This is currently used for autosave and 'quit.blend', where _not_ following symlinks is OK,
@@ -862,7 +865,7 @@ bool BKE_undo_save_file(const char *filename)
if (file == -1) {
fprintf(stderr, "Unable to save '%s': %s\n",
filename, errno ? strerror(errno) : "Unknown error opening file");
- return 0;
+ return false;
}
for (chunk = uel->memfile.chunks.first; chunk; chunk = chunk->next) {
@@ -876,9 +879,9 @@ bool BKE_undo_save_file(const char *filename)
if (chunk) {
fprintf(stderr, "Unable to save '%s': %s\n",
filename, errno ? strerror(errno) : "Unknown error writing file");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/* sets curscene */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 0fdd838f5fc..55d347a4fb2 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -33,7 +33,6 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_rand.h"
-#include "BLI_rect.h"
#include "BKE_brush.h"
#include "BKE_colortools.h"
@@ -49,7 +48,6 @@
#include "IMB_imbuf_types.h"
#include "RE_render_ext.h" /* externtex */
-#include "RE_shader_ext.h"
static RNG *brush_rng;
@@ -180,6 +178,10 @@ Brush *BKE_brush_copy(Brush *brush)
brushn->id.us++;
}
+ if (brush->id.lib) {
+ BKE_id_lib_local_paths(G.main, brush->id.lib, &brushn->id);
+ }
+
return brushn;
}
@@ -300,7 +302,6 @@ void BKE_brush_debug_print_state(Brush *br)
BR_TEST_FLAG(BRUSH_SIZE_PRESSURE);
BR_TEST_FLAG(BRUSH_JITTER_PRESSURE);
BR_TEST_FLAG(BRUSH_SPACING_PRESSURE);
- BR_TEST_FLAG(BRUSH_RAKE);
BR_TEST_FLAG(BRUSH_ANCHORED);
BR_TEST_FLAG(BRUSH_DIR_IN);
BR_TEST_FLAG(BRUSH_SPACE);
@@ -316,7 +317,6 @@ void BKE_brush_debug_print_state(Brush *br)
BR_TEST_FLAG(BRUSH_EDGE_TO_EDGE);
BR_TEST_FLAG(BRUSH_DRAG_DOT);
BR_TEST_FLAG(BRUSH_INVERSE_SMOOTH_PRESSURE);
- BR_TEST_FLAG(BRUSH_RANDOM_ROTATION);
BR_TEST_FLAG(BRUSH_PLANE_TRIM);
BR_TEST_FLAG(BRUSH_FRONTFACE);
BR_TEST_FLAG(BRUSH_CUSTOM_ICON);
@@ -702,7 +702,7 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
/* keep coordinates relative to mouse */
- rotation += ups->brush_rotation;
+ rotation += ups->brush_rotation_sec;
x = point_2d[0] - ups->mask_tex_mouse[0];
y = point_2d[1] - ups->mask_tex_mouse[1];
@@ -720,7 +720,7 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
y = point_2d[1];
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) {
- rotation += ups->brush_rotation;
+ rotation += ups->brush_rotation_sec;
/* these contain a random coordinate */
x = point_2d[0] - ups->mask_tex_mouse[0];
y = point_2d[1] - ups->mask_tex_mouse[1];
@@ -953,7 +953,7 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2],
jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread;
}
-void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups, bool mask)
+void BKE_brush_randomize_texture_coords(UnifiedPaintSettings *ups, bool mask)
{
/* we multiply with brush radius as an optimization for the brush
* texture sampling functions */
@@ -968,7 +968,7 @@ void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups, bool mas
}
/* Uses the brush curve control to find a strength value between 0 and 1 */
-float BKE_brush_curve_strength_clamp(Brush *br, float p, const float len)
+float BKE_brush_curve_strength(Brush *br, float p, const float len)
{
float strength;
@@ -981,17 +981,6 @@ float BKE_brush_curve_strength_clamp(Brush *br, float p, const float len)
return strength;
}
-/* same as above but can return negative values if the curve enables
- * used for sculpt only */
-float BKE_brush_curve_strength(Brush *br, float p, const float len)
-{
- if (p >= len)
- p = 1.0f;
- else
- p = p / len;
-
- return curvemapping_evaluateF(br->curve, 0, p);
-}
/* TODO: should probably be unified with BrushPainter stuff? */
unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side, bool use_secondary)
@@ -1049,7 +1038,7 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary)
for (i = 0; i < side; ++i) {
for (j = 0; j < side; ++j) {
float magn = sqrtf(pow2f(i - half) + pow2f(j - half));
- im->rect_float[i * side + j] = BKE_brush_curve_strength_clamp(br, magn, half);
+ im->rect_float[i * side + j] = BKE_brush_curve_strength(br, magn, half);
}
}
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index 4ad577a7bda..1a4a4bd6bce 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -65,9 +65,7 @@ static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, con
float idist;
float p1[3];
- float plane_normal[3], hit_point[3];
-
- normal_tri_v3(plane_normal, v0, v1, v2);
+ float hit_point[3];
madd_v3_v3v3fl(p1, ray->origin, ray->direction, m_dist);
if (isect_sweeping_sphere_tri_v3(ray->origin, p1, radius, v0, v1, v2, &idist, hit_point)) {
@@ -81,7 +79,7 @@ static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, con
* BVH from meshes callbacks
*/
-/* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces.
+/* Callback to bvh tree nearest point. The tree must have been built using bvhtree_from_mesh_faces.
* userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
static void mesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
{
@@ -145,7 +143,7 @@ static void editmesh_faces_nearest_point(void *userdata, int index, const float
}
}
-/* Callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces.
+/* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_faces.
* userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
@@ -214,7 +212,7 @@ static void editmesh_faces_spherecast(void *userdata, int index, const BVHTreeRa
}
}
-/* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_edges.
+/* Callback to bvh tree nearest point. The tree must have been built using bvhtree_from_mesh_edges.
* userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
static void mesh_edges_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
{
@@ -239,68 +237,140 @@ static void mesh_edges_nearest_point(void *userdata, int index, const float co[3
}
}
-/*
- * BVH builders
- */
-/* Builds a bvh tree.. where nodes are the vertexs of the given mesh */
-BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
+/* Helper, does all the point-spherecast work actually. */
+static void mesh_verts_spherecast_do(
+ const BVHTreeFromMesh *UNUSED(data), int index, const float v[3], const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
- BVHTree *tree;
- MVert *vert;
- bool vert_allocated;
+ float dist;
+ const float *r1;
+ float r2[3], i1[3];
+ r1 = ray->origin;
+ add_v3_v3v3(r2, r1, ray->direction);
+
+ closest_to_line_segment_v3(i1, v, r1, r2);
+
+ /* No hit if closest point is 'behind' the origin of the ray, or too far away from it. */
+ if ((dot_v3v3v3(r1, i1, r2) >= 0.0f) && ((dist = len_v3v3(r1, i1)) < hit->dist)) {
+ hit->index = index;
+ hit->dist = dist;
+ copy_v3_v3(hit->co, i1);
+ }
+}
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTICES);
- BLI_rw_mutex_unlock(&cache_rwlock);
+/* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_verts.
+ * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
+static void mesh_verts_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
+ float *v = data->vert[index].co;
- vert = DM_get_vert_array(dm, &vert_allocated);
+ mesh_verts_spherecast_do(data, index, v, ray, hit);
+}
- /* Not in cache */
- if (tree == NULL) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTICES);
- if (tree == NULL) {
- int i;
- int numVerts = dm->getNumVerts(dm);
+/* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_edges.
+ * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
+static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
+ MVert *vert = data->vert;
+ MEdge *edge = &data->edge[index];
- if (vert != NULL) {
- tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis);
+ const float radius_sq = SQUARE(data->sphere_radius);
+ float dist;
+ const float *v1, *v2, *r1;
+ float r2[3], i1[3], i2[3];
+ v1 = vert[edge->v1].co;
+ v2 = vert[edge->v2].co;
+
+ /* In case we get a zero-length edge, handle it as a point! */
+ if (equals_v3v3(v1, v2)) {
+ mesh_verts_spherecast_do(data, index, v1, ray, hit);
+ return;
+ }
- if (tree != NULL) {
- for (i = 0; i < numVerts; i++) {
- BLI_bvhtree_insert(tree, i, vert[i].co, 1);
- }
+ r1 = ray->origin;
+ add_v3_v3v3(r2, r1, ray->direction);
- BLI_bvhtree_balance(tree);
+ if (isect_line_line_v3(v1, v2, r1, r2, i1, i2)) {
+ /* No hit if intersection point is 'behind' the origin of the ray, or too far away from it. */
+ if ((dot_v3v3v3(r1, i2, r2) >= 0.0f) && ((dist = len_v3v3(r1, i2)) < hit->dist)) {
+ const float e_fac = line_point_factor_v3(i1, v1, v2);
+ if (e_fac < 0.0f) {
+ copy_v3_v3(i1, v1);
+ }
+ else if (e_fac > 1.0f) {
+ copy_v3_v3(i1, v2);
+ }
+ /* Ensure ray is really close enough from edge! */
+ if (len_squared_v3v3(i1, i2) <= radius_sq) {
+ hit->index = index;
+ hit->dist = dist;
+ copy_v3_v3(hit->co, i2);
+ }
+ }
+ }
+}
- /* Save on cache for later use */
-// printf("BVHTree built and saved on cache\n");
- bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_VERTICES);
+/*
+ * BVH builders
+ */
+
+/* ***** Vertex ***** */
+
+static BVHTree *bvhtree_from_mesh_verts_create_tree(float epsilon, int tree_type, int axis,
+ MVert *vert, const int numVerts,
+ BLI_bitmap *mask, int numVerts_active)
+{
+ BVHTree *tree = NULL;
+ int i;
+
+ if (vert) {
+ if (mask && numVerts_active < 0) {
+ numVerts_active = 0;
+ for (i = 0; i < numVerts; i++) {
+ if (BLI_BITMAP_TEST_BOOL(mask, i)) {
+ numVerts_active++;
}
}
}
- BLI_rw_mutex_unlock(&cache_rwlock);
- }
- else {
-// printf("BVHTree is already build, using cached tree\n");
+ else if (!mask) {
+ numVerts_active = numVerts;
+ }
+
+ tree = BLI_bvhtree_new(numVerts_active, epsilon, tree_type, axis);
+
+ if (tree) {
+ for (i = 0; i < numVerts; i++) {
+ if (mask && !BLI_BITMAP_TEST_BOOL(mask, i)) {
+ continue;
+ }
+ BLI_bvhtree_insert(tree, i, vert[i].co, 1);
+ }
+
+ BLI_bvhtree_balance(tree);
+ }
}
+ return tree;
+}
- /* Setup BVHTreeFromMesh */
+static void bvhtree_from_mesh_verts_setup_data(BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon,
+ MVert *vert, const bool vert_allocated)
+{
memset(data, 0, sizeof(*data));
- data->tree = tree;
- if (data->tree) {
- data->cached = true;
+ if (tree) {
+ data->tree = tree;
+ data->cached = is_cached;
/* a NULL nearest callback works fine
* remember the min distance to point is the same as the min distance to BV of point */
data->nearest_callback = NULL;
- data->raycast_callback = NULL;
+ data->raycast_callback = mesh_verts_spherecast;
data->vert = vert;
data->vert_allocated = vert_allocated;
- data->face = DM_get_tessface_array(dm, &data->face_allocated);
+ //data->face = DM_get_tessface_array(dm, &data->face_allocated); /* XXX WHY???? */
data->sphere_radius = epsilon;
}
@@ -309,184 +379,66 @@ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float e
MEM_freeN(vert);
}
}
-
- return data->tree;
}
-/* Builds a bvh tree.. where nodes are the faces of the given dm. */
-BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
+/* Builds a bvh tree where nodes are the vertices of the given dm */
+BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
- BMEditMesh *em = data->em_evil;
- const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_FACES;
BVHTree *tree;
MVert *vert;
- MFace *face;
- bool vert_allocated = false, face_allocated = false;
+ bool vert_allocated;
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
+ tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTS);
BLI_rw_mutex_unlock(&cache_rwlock);
- if (em == NULL) {
- vert = DM_get_vert_array(dm, &vert_allocated);
- face = DM_get_tessface_array(dm, &face_allocated);
- }
+ vert = DM_get_vert_array(dm, &vert_allocated);
/* Not in cache */
if (tree == NULL) {
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
+ tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTS);
if (tree == NULL) {
- int i;
- int numFaces;
-
- /* BMESH specific check that we have tessfaces,
- * we _could_ tessellate here but rather not - campbell
- *
- * this assert checks we have tessfaces,
- * if not caller should use DM_ensure_tessface() */
- if (em) {
- numFaces = em->tottri;
- }
- else {
- numFaces = dm->getNumTessFaces(dm);
- BLI_assert(!(numFaces == 0 && dm->getNumPolys(dm) != 0));
- }
-
- if (numFaces != 0) {
- /* Create a bvh-tree of the given target */
- // printf("%s: building BVH, total=%d\n", __func__, numFaces);
- tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
- if (tree != NULL) {
- if (em) {
- const struct BMLoop *(*looptris)[3] = (void *)em->looptris;
-
- /* avoid double-up on face searches for quads-ngons */
- bool insert_prev = false;
- BMFace *f_prev = NULL;
-
- /* data->em_evil is only set for snapping, and only for the mesh of the object
- * which is currently open in edit mode. When set, the bvhtree should not contain
- * faces that will interfere with snapping (e.g. faces that are hidden/selected
- * or faces that have selected verts).*/
-
- /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden
- * and/or selected. Even if the faces themselves are not selected for the snapped
- * transform, having a vertex selected means the face (and thus it's tessellated
- * triangles) will be moving and will not be a good snap targets.*/
- for (i = 0; i < em->tottri; i++) {
- const BMLoop **ltri = looptris[i];
- BMFace *f = ltri[0]->f;
- bool insert;
-
- /* Start with the assumption the triangle should be included for snapping. */
- if (f == f_prev) {
- insert = insert_prev;
- }
- else {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- /* Don't insert triangles tessellated from faces that are hidden
- * or selected*/
- insert = false;
- }
- else {
- BMLoop *l_iter, *l_first;
- insert = true;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- /* Don't insert triangles tessellated from faces that have
- * any selected verts.*/
- insert = false;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- /* skip if face doesn't change */
- f_prev = f;
- insert_prev = insert;
- }
-
- if (insert) {
- /* No reason found to block hit-testing the triangle for snap,
- * so insert it now.*/
- float co[3][3];
- copy_v3_v3(co[0], ltri[0]->v->co);
- copy_v3_v3(co[1], ltri[1]->v->co);
- copy_v3_v3(co[2], ltri[2]->v->co);
-
- BLI_bvhtree_insert(tree, i, co[0], 3);
- }
- }
- }
- else {
- if (vert != NULL && face != NULL) {
- for (i = 0; i < numFaces; i++) {
- float co[4][3];
- copy_v3_v3(co[0], vert[face[i].v1].co);
- copy_v3_v3(co[1], vert[face[i].v2].co);
- copy_v3_v3(co[2], vert[face[i].v3].co);
- if (face[i].v4)
- copy_v3_v3(co[3], vert[face[i].v4].co);
-
- BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
- }
- }
- }
- BLI_bvhtree_balance(tree);
-
- /* Save on cache for later use */
-// printf("BVHTree built and saved on cache\n");
- bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
- }
+ tree = bvhtree_from_mesh_verts_create_tree(epsilon, tree_type, axis, vert, dm->getNumVerts(dm), NULL, -1);
+ if (tree) {
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_VERTS);
}
}
BLI_rw_mutex_unlock(&cache_rwlock);
}
else {
-// printf("BVHTree is already build, using cached tree\n");
+ /* printf("BVHTree is already build, using cached tree\n"); */
}
-
/* Setup BVHTreeFromMesh */
- memset(data, 0, sizeof(*data));
- data->tree = tree;
- data->em_evil = em;
+ bvhtree_from_mesh_verts_setup_data(data, tree, true, epsilon, vert, vert_allocated);
- if (data->tree) {
- data->cached = true;
-
- if (em) {
- data->nearest_callback = editmesh_faces_nearest_point;
- data->raycast_callback = editmesh_faces_spherecast;
- }
- else {
- data->nearest_callback = mesh_faces_nearest_point;
- data->raycast_callback = mesh_faces_spherecast;
+ return data->tree;
+}
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- data->face = face;
- data->face_allocated = face_allocated;
- }
+/**
+ * Builds a bvh tree where nodes are the given vertices (note: does not copy given mverts!).
+ * \param vert_allocated if true, vert freeing will be done when freeing data.
+ * \param mask if not null, true elements give which vert to add to BVH tree.
+ * \param numVerts_active if >= 0, number of active verts to add to BVH tree (else will be computed from mask).
+ */
+BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data, MVert *vert, const int numVerts, const bool vert_allocated,
+ BLI_bitmap *mask, int numVerts_active,
+ float epsilon, int tree_type, int axis)
+{
+ BVHTree *tree = bvhtree_from_mesh_verts_create_tree(epsilon, tree_type, axis, vert, numVerts, mask, numVerts_active);
- data->sphere_radius = epsilon;
- }
- else {
- if (vert_allocated) {
- MEM_freeN(vert);
- }
- if (face_allocated) {
- MEM_freeN(face);
- }
- }
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_verts_setup_data(data, tree, false, epsilon, vert, vert_allocated);
return data->tree;
-
}
-/* Builds a bvh tree.. where nodes are the faces of the given dm. */
+/* ***** Edge ***** */
+
+/* Builds a bvh tree where nodes are the edges of the given dm */
BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
BVHTree *tree;
@@ -523,7 +475,7 @@ BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float e
BLI_bvhtree_balance(tree);
/* Save on cache for later use */
-// printf("BVHTree built and saved on cache\n");
+ /* printf("BVHTree built and saved on cache\n"); */
bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES);
}
}
@@ -531,7 +483,7 @@ BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float e
BLI_rw_mutex_unlock(&cache_rwlock);
}
else {
-// printf("BVHTree is already build, using cached tree\n");
+ /* printf("BVHTree is already build, using cached tree\n"); */
}
@@ -543,7 +495,7 @@ BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float e
data->cached = true;
data->nearest_callback = mesh_edges_nearest_point;
- data->raycast_callback = NULL;
+ data->raycast_callback = mesh_edges_spherecast;
data->vert = vert;
data->vert_allocated = vert_allocated;
@@ -561,15 +513,240 @@ BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float e
}
}
return data->tree;
+}
+
+/* ***** Tessellated face ***** */
+
+static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon, int tree_type, int axis,
+ BMEditMesh *em, MVert *vert, MFace *face, const int numFaces,
+ BLI_bitmap *mask, int numFaces_active)
+{
+ BVHTree *tree = NULL;
+ int i;
+
+ if (numFaces) {
+ if (mask && numFaces_active < 0) {
+ numFaces_active = 0;
+ for (i = 0; i < numFaces; i++) {
+ if (BLI_BITMAP_TEST_BOOL(mask, i)) {
+ numFaces_active++;
+ }
+ }
+ }
+ else if (!mask) {
+ numFaces_active = numFaces;
+ }
+
+ /* Create a bvh-tree of the given target */
+ /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
+ tree = BLI_bvhtree_new(numFaces_active, epsilon, tree_type, axis);
+ if (tree) {
+ if (em) {
+ const struct BMLoop *(*looptris)[3] = (void *)em->looptris;
+
+ /* avoid double-up on face searches for quads-ngons */
+ bool insert_prev = false;
+ BMFace *f_prev = NULL;
+
+ /* data->em_evil is only set for snapping, and only for the mesh of the object
+ * which is currently open in edit mode. When set, the bvhtree should not contain
+ * faces that will interfere with snapping (e.g. faces that are hidden/selected
+ * or faces that have selected verts). */
+
+ /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden
+ * and/or selected. Even if the faces themselves are not selected for the snapped
+ * transform, having a vertex selected means the face (and thus it's tessellated
+ * triangles) will be moving and will not be a good snap targets. */
+ for (i = 0; i < numFaces; i++) {
+ const BMLoop **ltri = looptris[i];
+ BMFace *f = ltri[0]->f;
+ bool insert = mask ? BLI_BITMAP_TEST_BOOL(mask, i) : true;
+
+ /* Start with the assumption the triangle should be included for snapping. */
+ if (f == f_prev) {
+ insert = insert_prev;
+ }
+ else if (insert) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ /* Don't insert triangles tessellated from faces that are hidden or selected */
+ insert = false;
+ }
+ else {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
+ /* Don't insert triangles tessellated from faces that have any selected verts */
+ insert = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ /* skip if face doesn't change */
+ f_prev = f;
+ insert_prev = insert;
+ }
+
+ if (insert) {
+ /* No reason found to block hit-testing the triangle for snap, so insert it now.*/
+ float co[3][3];
+ copy_v3_v3(co[0], ltri[0]->v->co);
+ copy_v3_v3(co[1], ltri[1]->v->co);
+ copy_v3_v3(co[2], ltri[2]->v->co);
+
+ BLI_bvhtree_insert(tree, i, co[0], 3);
+ }
+ }
+ }
+ else {
+ if (vert && face) {
+ for (i = 0; i < numFaces; i++) {
+ float co[4][3];
+ if (mask && !BLI_BITMAP_TEST_BOOL(mask, i)) {
+ continue;
+ }
+ copy_v3_v3(co[0], vert[face[i].v1].co);
+ copy_v3_v3(co[1], vert[face[i].v2].co);
+ copy_v3_v3(co[2], vert[face[i].v3].co);
+ if (face[i].v4)
+ copy_v3_v3(co[3], vert[face[i].v4].co);
+
+ BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
+ }
+ }
+ }
+ BLI_bvhtree_balance(tree);
+ }
+ }
+
+ return tree;
+}
+
+static void bvhtree_from_mesh_faces_setup_data(BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached,
+ float epsilon, BMEditMesh *em,
+ MVert *vert, const bool vert_allocated,
+ MFace *face, const bool face_allocated)
+{
+ memset(data, 0, sizeof(*data));
+ data->em_evil = em;
+
+ if (tree) {
+ data->tree = tree;
+ data->cached = is_cached;
+
+ if (em) {
+ data->nearest_callback = editmesh_faces_nearest_point;
+ data->raycast_callback = editmesh_faces_spherecast;
+ }
+ else {
+ data->nearest_callback = mesh_faces_nearest_point;
+ data->raycast_callback = mesh_faces_spherecast;
+
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ data->face = face;
+ data->face_allocated = face_allocated;
+ }
+
+ data->sphere_radius = epsilon;
+ }
+ else {
+ if (vert_allocated) {
+ MEM_freeN(vert);
+ }
+ if (face_allocated) {
+ MEM_freeN(face);
+ }
+ }
+}
+
+/* Builds a bvh tree where nodes are the tesselated faces of the given dm */
+BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
+{
+ BMEditMesh *em = data->em_evil;
+ const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_FACES;
+ BVHTree *tree;
+ MVert *vert = NULL;
+ MFace *face = NULL;
+ bool vert_allocated = false, face_allocated = false;
+
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
+ tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
+ BLI_rw_mutex_unlock(&cache_rwlock);
+
+ if (em == NULL) {
+ vert = DM_get_vert_array(dm, &vert_allocated);
+ face = DM_get_tessface_array(dm, &face_allocated);
+ }
+
+ /* Not in cache */
+ if (tree == NULL) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+ tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
+ if (tree == NULL) {
+ int numFaces;
+
+ /* BMESH specific check that we have tessfaces,
+ * we _could_ tessellate here but rather not - campbell
+ *
+ * this assert checks we have tessfaces,
+ * if not caller should use DM_ensure_tessface() */
+ if (em) {
+ numFaces = em->tottri;
+ }
+ else {
+ numFaces = dm->getNumTessFaces(dm);
+ BLI_assert(!(numFaces == 0 && dm->getNumPolys(dm) != 0));
+ }
+
+ tree = bvhtree_from_mesh_faces_create_tree(epsilon, tree_type, axis, em, vert, face, numFaces, NULL, -1);
+ if (tree) {
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
+ }
+ }
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ }
+ else {
+ /* printf("BVHTree is already build, using cached tree\n"); */
+ }
+
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_faces_setup_data(data, tree, true, epsilon, em, vert, vert_allocated, face, face_allocated);
+
+ return data->tree;
+}
+
+/**
+ * Builds a bvh tree where nodes are the given tessellated faces (note: does not copy given mfaces!).
+ * \param vert_allocated if true, vert freeing will be done when freeing data.
+ * \param face_allocated if true, face freeing will be done when freeing data.
+ * \param mask if not null, true elements give which faces to add to BVH tree.
+ * \param numFaces_active if >= 0, number of active faces to add to BVH tree (else will be computed from mask).
+ */
+BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data, MVert *vert, const bool vert_allocated,
+ MFace *face, const int numFaces, const bool face_allocated,
+ BLI_bitmap *mask, int numFaces_active, float epsilon, int tree_type, int axis)
+{
+ BVHTree *tree = bvhtree_from_mesh_faces_create_tree(epsilon, tree_type, axis, NULL, vert, face, numFaces,
+ mask, numFaces_active);
+
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_faces_setup_data(data, tree, false, epsilon, NULL, vert, vert_allocated, face, face_allocated);
+
+ return data->tree;
}
/* Frees data allocated by a call to bvhtree_from_mesh_*. */
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
{
if (data->tree) {
- if (!data->cached)
+ if (!data->cached) {
BLI_bvhtree_free(data->tree);
+ }
if (data->vert_allocated) {
MEM_freeN(data->vert);
@@ -586,7 +763,10 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
}
-/* BVHCache */
+/*
+ * BVHCache
+ */
+
typedef struct BVHCacheItem {
int type;
BVHTree *tree;
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 1402f62291f..e424823d8dc 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -39,6 +39,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_rect.h"
#include "BKE_animsys.h"
#include "BKE_camera.h"
@@ -77,6 +78,10 @@ Camera *BKE_camera_copy(Camera *cam)
id_lib_extern((ID *)camn->dof_ob);
+ if (cam->id.lib) {
+ BKE_id_lib_local_paths(G.main, cam->id.lib, &camn->id);
+ }
+
return camn;
}
@@ -454,17 +459,25 @@ void BKE_camera_view_frame(Scene *scene, Camera *camera, float r_vec[4][3])
float dummy_drawsize;
const float dummy_scale[3] = {1.0f, 1.0f, 1.0f};
- BKE_camera_view_frame_ex(scene, camera, false, 1.0, dummy_scale,
+ BKE_camera_view_frame_ex(scene, camera, 0.0, true, dummy_scale,
dummy_asp, dummy_shift, &dummy_drawsize, r_vec);
}
+#define CAMERA_VIEWFRAME_NUM_PLANES 4
typedef struct CameraViewFrameData {
- float plane_tx[4][4]; /* 4 planes (not 4x4 matrix)*/
- float frame_tx[4][3];
- float normal_tx[4][3];
- float dist_vals_sq[4]; /* distance squared (signed) */
+ float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][4]; /* 4 planes */
+ float normal_tx[CAMERA_VIEWFRAME_NUM_PLANES][3];
+ float dist_vals_sq[CAMERA_VIEWFRAME_NUM_PLANES]; /* distance squared (signed) */
unsigned int tot;
+
+ /* Ortho camera only. */
+ bool is_ortho;
+ float camera_no[3];
+ float dist_to_cam;
+
+ /* Not used by callbacks... */
+ float camera_rotmat[3][3];
} CameraViewFrameData;
static void camera_to_frame_view_cb(const float co[3], void *user_data)
@@ -472,67 +485,106 @@ static void camera_to_frame_view_cb(const float co[3], void *user_data)
CameraViewFrameData *data = (CameraViewFrameData *)user_data;
unsigned int i;
- for (i = 0; i < 4; 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;
- }
+ for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
+ const float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]);
+ CLAMP_MAX(data->dist_vals_sq[i], nd);
+ }
+
+ if (data->is_ortho) {
+ const float d = dot_v3v3(data->camera_no, co);
+ CLAMP_MAX(data->dist_to_cam, d);
}
data->tot++;
}
-/* don't move the camera, just yield the fit location */
-/* only valid for perspective cameras */
-bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3])
+static void camera_frame_fit_data_init(Scene *scene, Object *ob, CameraParams *params, CameraViewFrameData *data)
{
- float shift[2];
- float plane_tx[4][3];
- float rot_obmat[3][3];
- const float zero[3] = {0, 0, 0};
- CameraViewFrameData data_cb;
-
+ float camera_rotmat_transposed_inversed[4][4];
unsigned int i;
- BKE_camera_view_frame(scene, camera_ob->data, data_cb.frame_tx);
+ /* setup parameters */
+ BKE_camera_params_init(params);
+ BKE_camera_params_from_object(params, ob);
- copy_m3_m4(rot_obmat, camera_ob->obmat);
- normalize_m3(rot_obmat);
-
- for (i = 0; i < 4; i++) {
- /* normalize so Z is always 1.0f*/
- mul_v3_fl(data_cb.frame_tx[i], 1.0f / data_cb.frame_tx[i][2]);
+ /* compute matrix, viewplane, .. */
+ if (scene) {
+ BKE_camera_params_compute_viewplane(params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
}
+ else {
+ BKE_camera_params_compute_viewplane(params, 1, 1, 1.0f, 1.0f);
+ }
+ BKE_camera_params_compute_matrix(params);
- /* get the shift back out of the frame */
- shift[0] = (data_cb.frame_tx[0][0] +
- data_cb.frame_tx[1][0] +
- data_cb.frame_tx[2][0] +
- data_cb.frame_tx[3][0]) / 4.0f;
- shift[1] = (data_cb.frame_tx[0][1] +
- data_cb.frame_tx[1][1] +
- data_cb.frame_tx[2][1] +
- data_cb.frame_tx[3][1]) / 4.0f;
-
- for (i = 0; i < 4; i++) {
- mul_m3_v3(rot_obmat, data_cb.frame_tx[i]);
+ /* initialize callback data */
+ copy_m3_m4(data->camera_rotmat, ob->obmat);
+ normalize_m3(data->camera_rotmat);
+ /* To transform a plane which is in its homogeneous representation (4d vector),
+ * we need the inverse of the transpose of the transform matrix... */
+ copy_m4_m3(camera_rotmat_transposed_inversed, data->camera_rotmat);
+ transpose_m4(camera_rotmat_transposed_inversed);
+ invert_m4(camera_rotmat_transposed_inversed);
+
+ /* Extract frustum planes from projection matrix. */
+ planes_from_projmat(params->winmat,
+ /* left right top bottom near far */
+ data->plane_tx[2], data->plane_tx[0], data->plane_tx[3], data->plane_tx[1], NULL, NULL);
+
+ /* Rotate planes and get normals from them */
+ for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
+ mul_m4_v4(camera_rotmat_transposed_inversed, data->plane_tx[i]);
+ normalize_v3_v3(data->normal_tx[i], data->plane_tx[i]);
}
- for (i = 0; i < 4; i++) {
- normal_tri_v3(data_cb.normal_tx[i], zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]);
- plane_from_point_normal_v3(data_cb.plane_tx[i], data_cb.frame_tx[i], data_cb.normal_tx[i]);
+ copy_v4_fl(data->dist_vals_sq, FLT_MAX);
+ data->tot = 0;
+ data->is_ortho = params->is_ortho;
+ if (params->is_ortho) {
+ /* we want (0, 0, -1) transformed by camera_rotmat, this is a quicker shortcut. */
+ negate_v3_v3(data->camera_no, data->camera_rotmat[2]);
+ data->dist_to_cam = FLT_MAX;
}
+}
- /* initialize callback data */
- copy_v4_fl(data_cb.dist_vals_sq, FLT_MAX);
- data_cb.tot = 0;
- /* run callback on all visible points */
- BKE_scene_foreach_display_point(scene, v3d, BA_SELECT,
- camera_to_frame_view_cb, &data_cb);
+static bool camera_frame_fit_calc_from_data(
+ CameraParams *params, CameraViewFrameData *data, float r_co[3], float *r_scale)
+{
+ float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][3];
+ unsigned int i;
- if (data_cb.tot <= 1) {
+ if (data->tot <= 1) {
return false;
}
+
+ if (params->is_ortho) {
+ const float *cam_axis_x = data->camera_rotmat[0];
+ const float *cam_axis_y = data->camera_rotmat[1];
+ const float *cam_axis_z = data->camera_rotmat[2];
+ float dists[CAMERA_VIEWFRAME_NUM_PLANES];
+ float scale_diff;
+
+ /* apply the dist-from-plane's to the transformed plane points */
+ for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
+ dists[i] = sqrtf_signed(data->dist_vals_sq[i]);
+ }
+
+ if ((dists[0] + dists[2]) > (dists[1] + dists[3])) {
+ scale_diff = (dists[1] + dists[3]) *
+ (BLI_rctf_size_x(&params->viewplane) / BLI_rctf_size_y(&params->viewplane));
+ }
+ else {
+ scale_diff = (dists[0] + dists[2]) *
+ (BLI_rctf_size_y(&params->viewplane) / BLI_rctf_size_x(&params->viewplane));
+ }
+ *r_scale = params->ortho_scale - scale_diff;
+
+ zero_v3(r_co);
+ madd_v3_v3fl(r_co, cam_axis_x, (dists[2] - dists[0]) * 0.5f + params->shiftx * scale_diff);
+ madd_v3_v3fl(r_co, cam_axis_y, (dists[1] - dists[3]) * 0.5f + params->shifty * scale_diff);
+ madd_v3_v3fl(r_co, cam_axis_z, -(data->dist_to_cam - 1.0f - params->clipsta));
+
+ return true;
+ }
else {
float plane_isect_1[3], plane_isect_1_no[3], plane_isect_1_other[3];
float plane_isect_2[3], plane_isect_2_no[3], plane_isect_2_other[3];
@@ -540,16 +592,16 @@ bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object
float plane_isect_pt_1[3], plane_isect_pt_2[3];
/* apply the dist-from-plane's to the transformed plane points */
- for (i = 0; i < 4; i++) {
- mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], sqrtf_signed(data_cb.dist_vals_sq[i]));
+ for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
+ mul_v3_v3fl(plane_tx[i], data->normal_tx[i], sqrtf_signed(data->dist_vals_sq[i]));
}
if ((!isect_plane_plane_v3(plane_isect_1, plane_isect_1_no,
- plane_tx[0], data_cb.normal_tx[0],
- plane_tx[2], data_cb.normal_tx[2])) ||
+ plane_tx[0], data->normal_tx[0],
+ plane_tx[2], data->normal_tx[2])) ||
(!isect_plane_plane_v3(plane_isect_2, plane_isect_2_no,
- plane_tx[1], data_cb.normal_tx[1],
- plane_tx[3], data_cb.normal_tx[3])))
+ plane_tx[1], data->normal_tx[1],
+ plane_tx[3], data->normal_tx[3])))
{
return false;
}
@@ -559,16 +611,17 @@ bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object
if (isect_line_line_v3(plane_isect_1, plane_isect_1_other,
plane_isect_2, plane_isect_2_other,
- plane_isect_pt_1, plane_isect_pt_2) == 0)
+ plane_isect_pt_1, plane_isect_pt_2) != 0)
{
- return false;
- }
- else {
- float cam_plane_no[3] = {0.0f, 0.0f, -1.0f};
+ float cam_plane_no[3];
float plane_isect_delta[3];
float plane_isect_delta_len;
- mul_m3_v3(rot_obmat, cam_plane_no);
+ float shift_fac = BKE_camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y) /
+ params->lens;
+
+ /* we want (0, 0, -1) transformed by camera_rotmat, this is a quicker shortcut. */
+ negate_v3_v3(cam_plane_no, data->camera_rotmat[2]);
sub_v3_v3v3(plane_isect_delta, plane_isect_pt_2, plane_isect_pt_1);
plane_isect_delta_len = len_v3(plane_isect_delta);
@@ -578,18 +631,58 @@ bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object
/* offset shift */
normalize_v3(plane_isect_1_no);
- madd_v3_v3fl(r_co, plane_isect_1_no, shift[1] * -plane_isect_delta_len);
+ madd_v3_v3fl(r_co, plane_isect_1_no, params->shifty * plane_isect_delta_len * shift_fac);
}
else {
copy_v3_v3(r_co, plane_isect_pt_2);
/* offset shift */
normalize_v3(plane_isect_2_no);
- madd_v3_v3fl(r_co, plane_isect_2_no, shift[0] * -plane_isect_delta_len);
+ madd_v3_v3fl(r_co, plane_isect_2_no, params->shiftx * plane_isect_delta_len * shift_fac);
}
-
return true;
}
}
+
+ return false;
}
+
+/* don't move the camera, just yield the fit location */
+/* r_scale only valid/useful for ortho cameras */
+bool BKE_camera_view_frame_fit_to_scene(
+ Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3], float *r_scale)
+{
+ CameraParams params;
+ CameraViewFrameData data_cb;
+
+ /* just in case */
+ *r_scale = 1.0f;
+
+ camera_frame_fit_data_init(scene, camera_ob, &params, &data_cb);
+
+ /* run callback on all visible points */
+ BKE_scene_foreach_display_point(scene, v3d, BA_SELECT, camera_to_frame_view_cb, &data_cb);
+
+ return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
+}
+
+bool BKE_camera_view_frame_fit_to_coords(
+ Scene *scene, float (*cos)[3], int num_cos, Object *camera_ob, float r_co[3], float *r_scale)
+{
+ CameraParams params;
+ CameraViewFrameData data_cb;
+
+ /* just in case */
+ *r_scale = 1.0f;
+
+ camera_frame_fit_data_init(scene, camera_ob, &params, &data_cb);
+
+ /* run callback on all given coordinates */
+ while (num_cos--) {
+ camera_to_frame_view_cb(cos[num_cos], &data_cb);
+ }
+
+ return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
+}
+
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index bfc70c91181..a1bf255c239 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -35,7 +35,6 @@
*/
#include "BLI_math.h"
-#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
#include "BLI_utildefines.h"
#include "BLI_stackdefines.h"
@@ -49,7 +48,6 @@
#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"
@@ -61,7 +59,6 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
-#include "GPU_material.h"
#include <string.h>
#include <limits.h>
@@ -343,106 +340,64 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
static void cdDM_drawVerts(DerivedMesh *dm)
{
- CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MVert *mv = cddm->mvert;
- int i;
-
- if (GPU_buffer_legacy(dm)) {
- glBegin(GL_POINTS);
- for (i = 0; i < dm->numVertData; i++, mv++)
- glVertex3fv(mv->co);
- glEnd();
- }
- else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
- GPU_vertex_setup(dm);
- if (!GPU_buffer_legacy(dm)) {
- if (dm->drawObject->tot_triangle_point)
- glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_triangle_point);
- else
- glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loose_point);
- }
- GPU_buffer_unbind();
- }
+ GPU_vertex_setup(dm);
+ if (dm->drawObject->tot_triangle_point)
+ glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_triangle_point);
+ else
+ glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loose_point);
+ GPU_buffer_unbind();
}
static void cdDM_drawUVEdges(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
MFace *mf = cddm->mface;
- MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
int i;
if (mf) {
- if (GPU_buffer_legacy(dm)) {
- glBegin(GL_LINES);
- for (i = 0; i < dm->numTessFaceData; i++, mf++, tf++) {
- if (!(mf->flag & ME_HIDE)) {
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
-
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
-
- if (!mf->v4) {
- glVertex2fv(tf->uv[2]);
- glVertex2fv(tf->uv[0]);
- }
- else {
- glVertex2fv(tf->uv[2]);
- glVertex2fv(tf->uv[3]);
-
- glVertex2fv(tf->uv[3]);
- glVertex2fv(tf->uv[0]);
- }
- }
+ int prevstart = 0;
+ int prevdraw = 1;
+ int draw = 1;
+ int curpos = 0;
+
+ GPU_uvedge_setup(dm);
+ for (i = 0; i < dm->numTessFaceData; i++, mf++) {
+ if (!(mf->flag & ME_HIDE)) {
+ draw = 1;
}
- glEnd();
- }
- else {
- int prevstart = 0;
- int prevdraw = 1;
- int draw = 1;
- int curpos = 0;
-
- GPU_uvedge_setup(dm);
- if (!GPU_buffer_legacy(dm)) {
- for (i = 0; i < dm->numTessFaceData; i++, mf++) {
- if (!(mf->flag & ME_HIDE)) {
- draw = 1;
- }
- else {
- draw = 0;
- }
- if (prevdraw != draw) {
- if (prevdraw > 0 && (curpos - prevstart) > 0) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- prevstart = curpos;
- }
- if (mf->v4) {
- curpos += 8;
- }
- else {
- curpos += 6;
- }
- prevdraw = draw;
- }
+ else {
+ draw = 0;
+ }
+ if (prevdraw != draw) {
if (prevdraw > 0 && (curpos - prevstart) > 0) {
glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
}
+ prevstart = curpos;
+ }
+ if (mf->v4) {
+ curpos += 8;
}
- GPU_buffer_unbind();
+ else {
+ curpos += 6;
+ }
+ prevdraw = draw;
+ }
+ if (prevdraw > 0 && (curpos - prevstart) > 0) {
+ glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
}
+ GPU_buffer_unbind();
}
}
static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MVert *mvert = cddm->mvert;
MEdge *medge = cddm->medge;
int i;
-
+ int prevstart = 0;
+ int prevdraw = 1;
+ bool draw = true;
+
if (cddm->pbvh && cddm->pbvh_draw &&
BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH)
{
@@ -451,97 +406,60 @@ static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdg
return;
}
- if (GPU_buffer_legacy(dm)) {
- DEBUG_VBO("Using legacy code. cdDM_drawEdges\n");
- glBegin(GL_LINES);
- for (i = 0; i < dm->numEdgeData; i++, medge++) {
- if ((drawAllEdges || (medge->flag & ME_EDGEDRAW)) &&
- (drawLooseEdges || !(medge->flag & ME_LOOSEEDGE)))
- {
- glVertex3fv(mvert[medge->v1].co);
- glVertex3fv(mvert[medge->v2].co);
- }
+ GPU_edge_setup(dm);
+ for (i = 0; i < dm->numEdgeData; i++, medge++) {
+ if ((drawAllEdges || (medge->flag & ME_EDGEDRAW)) &&
+ (drawLooseEdges || !(medge->flag & ME_LOOSEEDGE)))
+ {
+ draw = true;
}
- glEnd();
- }
- else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
- int prevstart = 0;
- int prevdraw = 1;
- bool draw = true;
-
- GPU_edge_setup(dm);
- if (!GPU_buffer_legacy(dm)) {
- for (i = 0; i < dm->numEdgeData; i++, medge++) {
- if ((drawAllEdges || (medge->flag & ME_EDGEDRAW)) &&
- (drawLooseEdges || !(medge->flag & ME_LOOSEEDGE)))
- {
- draw = true;
- }
- else {
- draw = false;
- }
- if (prevdraw != draw) {
- if (prevdraw > 0 && (i - prevstart) > 0) {
- GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
- }
- prevstart = i;
- }
- prevdraw = draw;
- }
+ else {
+ draw = false;
+ }
+ if (prevdraw != draw) {
if (prevdraw > 0 && (i - prevstart) > 0) {
GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
}
+ prevstart = i;
}
- GPU_buffer_unbind();
+ prevdraw = draw;
}
+ if (prevdraw > 0 && (i - prevstart) > 0) {
+ GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
+ }
+ GPU_buffer_unbind();
}
static void cdDM_drawLooseEdges(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MVert *mvert = cddm->mvert;
MEdge *medge = cddm->medge;
int i;
-
- if (GPU_buffer_legacy(dm)) {
- DEBUG_VBO("Using legacy code. cdDM_drawLooseEdges\n");
- glBegin(GL_LINES);
- for (i = 0; i < dm->numEdgeData; i++, medge++) {
- if (medge->flag & ME_LOOSEEDGE) {
- glVertex3fv(mvert[medge->v1].co);
- glVertex3fv(mvert[medge->v2].co);
- }
+
+ int prevstart = 0;
+ int prevdraw = 1;
+ int draw = 1;
+
+ GPU_edge_setup(dm);
+ for (i = 0; i < dm->numEdgeData; i++, medge++) {
+ if (medge->flag & ME_LOOSEEDGE) {
+ draw = 1;
}
- glEnd();
- }
- else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
- int prevstart = 0;
- int prevdraw = 1;
- int draw = 1;
-
- GPU_edge_setup(dm);
- if (!GPU_buffer_legacy(dm)) {
- for (i = 0; i < dm->numEdgeData; i++, medge++) {
- if (medge->flag & ME_LOOSEEDGE) {
- draw = 1;
- }
- else {
- draw = 0;
- }
- if (prevdraw != draw) {
- if (prevdraw > 0 && (i - prevstart) > 0) {
- GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
- }
- prevstart = i;
- }
- prevdraw = draw;
- }
+ else {
+ draw = 0;
+ }
+ if (prevdraw != draw) {
if (prevdraw > 0 && (i - prevstart) > 0) {
GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
}
+ prevstart = i;
}
- GPU_buffer_unbind();
+ prevdraw = draw;
+ }
+ if (prevdraw > 0 && (i - prevstart) > 0) {
+ GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
}
+ GPU_buffer_unbind();
}
static void cdDM_drawFacesSolid(DerivedMesh *dm,
@@ -549,11 +467,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
bool UNUSED(fast), DMSetMaterial setMaterial)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MVert *mvert = cddm->mvert;
- MFace *mface = cddm->mface;
- const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
- const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
- int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
+ int a;
if (cddm->pbvh && cddm->pbvh_draw) {
if (dm->numTessFaceData) {
@@ -566,121 +480,37 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
return;
}
-
- if (GPU_buffer_legacy(dm)) {
- DEBUG_VBO("Using legacy code. cdDM_drawFacesSolid\n");
- glBegin(glmode = GL_QUADS);
- for (a = 0; a < dm->numTessFaceData; a++, mface++) {
- int new_glmode, new_matnr, new_shademodel;
-
- new_glmode = mface->v4 ? GL_QUADS : GL_TRIANGLES;
- new_matnr = mface->mat_nr + 1;
- new_shademodel = (lnors || (mface->flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT;
-
-
- if ((new_glmode != glmode) || (new_shademodel != shademodel) ||
- (setMaterial && (new_matnr != matnr)))
- {
- glEnd();
-
- if (setMaterial) {
- drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
- }
-
- glShadeModel(shademodel = new_shademodel);
- glBegin(glmode = new_glmode);
- }
-
- if (drawCurrentMat) {
- if (lnors) {
- glNormal3sv((const GLshort *)lnors[0][0]);
- glVertex3fv(mvert[mface->v1].co);
- glNormal3sv((const GLshort *)lnors[0][1]);
- glVertex3fv(mvert[mface->v2].co);
- glNormal3sv((const GLshort *)lnors[0][2]);
- glVertex3fv(mvert[mface->v3].co);
- if (mface->v4) {
- glNormal3sv((const GLshort *)lnors[0][3]);
- glVertex3fv(mvert[mface->v4].co);
- }
- }
- else if (shademodel == GL_FLAT) {
- if (nors) {
- glNormal3fv(nors);
- }
- else {
- /* TODO make this better (cache facenormals as layer?) */
- float nor[3];
- if (mface->v4) {
- normal_quad_v3(nor, mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
- }
- else {
- normal_tri_v3(nor, mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
- }
- glNormal3fv(nor);
- }
- glVertex3fv(mvert[mface->v1].co);
- glVertex3fv(mvert[mface->v2].co);
- glVertex3fv(mvert[mface->v3].co);
- if (mface->v4) {
- glVertex3fv(mvert[mface->v4].co);
- }
- }
- else { /* shademodel == GL_SMOOTH */
- glNormal3sv(mvert[mface->v1].no);
- glVertex3fv(mvert[mface->v1].co);
- glNormal3sv(mvert[mface->v2].no);
- glVertex3fv(mvert[mface->v2].co);
- glNormal3sv(mvert[mface->v3].no);
- glVertex3fv(mvert[mface->v3].co);
- if (mface->v4) {
- glNormal3sv(mvert[mface->v4].no);
- glVertex3fv(mvert[mface->v4].co);
- }
- }
- }
-
- if (nors)
- nors += 3;
- if (lnors)
- lnors++;
- }
- glEnd();
- }
- else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
- GPU_vertex_setup(dm);
- GPU_normal_setup(dm);
- if (!GPU_buffer_legacy(dm)) {
- glShadeModel(GL_SMOOTH);
- for (a = 0; a < dm->drawObject->totmaterial; a++) {
- if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
- glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start,
- dm->drawObject->materials[a].totpoint);
- }
- }
+
+ GPU_vertex_setup(dm);
+ GPU_normal_setup(dm);
+ glShadeModel(GL_SMOOTH);
+ for (a = 0; a < dm->drawObject->totmaterial; a++) {
+ if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
+ glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start,
+ dm->drawObject->materials[a].totpoint);
}
- GPU_buffer_unbind();
}
+ GPU_buffer_unbind();
glShadeModel(GL_FLAT);
}
static void cdDM_drawFacesTex_common(DerivedMesh *dm,
DMSetDrawOptionsTex drawParams,
- DMSetDrawOptions drawParamsMapped,
+ DMSetDrawOptionsMappedTex drawParamsMapped,
DMCompareDrawOptions compareDrawOptions,
void *userData, DMDrawFlag uvflag)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MVert *mv = cddm->mvert;
const MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
- const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
- const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
MCol *mcol;
int i, orig;
int colType, startFace = 0;
bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0;
+ int tottri;
+ int next_actualFace;
+
/* double lookup */
const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
@@ -717,208 +547,81 @@ 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);
+
+ GPU_vertex_setup(dm);
+ GPU_normal_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);
+ }
+
+ tottri = dm->drawObject->tot_triangle_point / 3;
+ next_actualFace = dm->drawObject->triangle_to_mface[0];
+
+ glShadeModel(GL_SMOOTH);
+ /* lastFlag = 0; */ /* UNUSED */
+ for (i = 0; i < tottri; i++) {
+ int actualFace = next_actualFace;
+ DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
+ int flush = 0;
+
+ if (i != tottri - 1)
+ next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
+
+ if (drawParams) {
+ draw_option = drawParams(use_tface && tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr);
}
-
- 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(use_tface ? tf : NULL, (mcol != NULL), mf->mat_nr);
- }
- else {
- if (index_mf_to_mpoly) {
- orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i);
- if (orig == ORIGINDEX_NONE) {
- /* XXX, this is not really correct
- * it will draw the previous faces context for this one when we don't know its settings.
- * but better then skipping it altogether. - campbell */
- draw_option = DM_DRAW_OPTION_NORMAL;
- }
- else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, orig);
- }
- else {
- if (nors) {
- nors += 3;
- }
- continue;
- }
+ else {
+ if (index_mf_to_mpoly) {
+ orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace);
+ if (orig == ORIGINDEX_NONE) {
+ /* XXX, this is not really correct
+ * it will draw the previous faces context for this one when we don't know its settings.
+ * but better then skipping it altogether. - campbell */
+ draw_option = DM_DRAW_OPTION_NORMAL;
}
else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, i);
- }
- else {
- if (nors) {
- nors += 3;
- }
- continue;
+ draw_option = drawParamsMapped(userData, orig, mf[actualFace].mat_nr);
}
}
-
- if (draw_option != DM_DRAW_OPTION_SKIP) {
- if (draw_option != DM_DRAW_OPTION_NO_MCOL && mcol)
- cp = (unsigned char *) &mcol[i * 4];
-
- if (!(lnors || (mf->flag & ME_SMOOTH))) {
- if (nors) {
- glNormal3fv(nors);
- }
- else {
- float nor[3];
- if (mf->v4) {
- normal_quad_v3(nor, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
- }
- else {
- normal_tri_v3(nor, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
- }
- glNormal3fv(nor);
- }
- }
-
- glBegin(mf->v4 ? GL_QUADS : GL_TRIANGLES);
- 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->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->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]);
- else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
- glVertex3fv(mvert->co);
-
- if (mf->v4) {
- 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]);
- else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
- glVertex3fv(mvert->co);
- }
- glEnd();
+ else if (drawParamsMapped) {
+ draw_option = drawParamsMapped(userData, actualFace, mf[actualFace].mat_nr);
}
-
- if (nors)
- nors += 3;
- if (lnors)
- lnors++;
- }
- }
- else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
- GPU_vertex_setup(dm);
- GPU_normal_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);
}
-
- if (!GPU_buffer_legacy(dm)) {
- int tottri = dm->drawObject->tot_triangle_point / 3;
- int next_actualFace = dm->drawObject->triangle_to_mface[0];
-
- glShadeModel(GL_SMOOTH);
- /* lastFlag = 0; */ /* UNUSED */
- for (i = 0; i < tottri; i++) {
- int actualFace = next_actualFace;
- DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
- int flush = 0;
-
- if (i != tottri - 1)
- next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
-
- if (drawParams) {
- draw_option = drawParams(use_tface && tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr);
- }
- else {
- if (index_mf_to_mpoly) {
- orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace);
- if (orig == ORIGINDEX_NONE) {
- /* XXX, this is not really correct
- * it will draw the previous faces context for this one when we don't know its settings.
- * but better then skipping it altogether. - campbell */
- draw_option = DM_DRAW_OPTION_NORMAL;
- }
- else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, orig);
- }
- }
- else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, actualFace);
- }
- }
-
- /* flush buffer if current triangle isn't drawable or it's last triangle */
- flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == tottri - 1);
-
- if (!flush && compareDrawOptions) {
- /* also compare draw options and flush buffer if they're different
+
+ /* flush buffer if current triangle isn't drawable or it's last triangle */
+ flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == tottri - 1);
+
+ if (!flush && compareDrawOptions) {
+ /* also compare draw options and flush buffer if they're different
* need for face selection highlight in edit mode */
- flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
- }
-
- if (flush) {
- int first = startFace * 3;
- /* Add one to the length if we're drawing at the end of the array */
- int count = (i - startFace + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3;
-
- if (count) {
- if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
- GPU_color_switch(1);
- else
- GPU_color_switch(0);
-
- glDrawArrays(GL_TRIANGLES, first, count);
- }
-
- startFace = i + 1;
- }
+ flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
+ }
+
+ if (flush) {
+ int first = startFace * 3;
+ /* Add one to the length if we're drawing at the end of the array */
+ int count = (i - startFace + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3;
+
+ if (count) {
+ if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
+ GPU_color_switch(1);
+ else
+ GPU_color_switch(0);
+
+ glDrawArrays(GL_TRIANGLES, first, count);
}
+
+ startFace = i + 1;
}
-
- GPU_buffer_unbind();
- glShadeModel(GL_FLAT);
}
+
+ GPU_buffer_unbind();
+ glShadeModel(GL_FLAT);
+
}
static void cdDM_drawFacesTex(DerivedMesh *dm,
@@ -968,7 +671,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm,
/* back-buffer always uses legacy since VBO's would need the
* color array temporarily overwritten for drawing, then reset. */
- if (GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
+ if (G.f & G_BACKBUFSEL) {
DEBUG_VBO("Using legacy code. cdDM_drawMappedFaces\n");
for (i = 0; i < dm->numTessFaceData; i++, mf++) {
int drawSmooth = ((flag & DM_DRAW_ALWAYS_SMOOTH) || lnors) ? 1 : (mf->flag & ME_SMOOTH);
@@ -1070,79 +773,85 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm,
}
else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
int prevstart = 0;
+ int tottri;
+
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
if (useColors && mcol) {
GPU_color_setup(dm, colType);
}
- if (!GPU_buffer_legacy(dm)) {
- int tottri = dm->drawObject->tot_triangle_point / 3;
- glShadeModel(GL_SMOOTH);
+ tottri = dm->drawObject->tot_triangle_point / 3;
+ glShadeModel(GL_SMOOTH);
+
+ if (tottri == 0) {
+ /* avoid buffer problems in following code */
+ }
+ if (setDrawOptions == NULL) {
+ /* just draw the entire face array */
+ glDrawArrays(GL_TRIANGLES, 0, (tottri) * 3);
+ }
+ else {
+ /* we need to check if the next material changes */
+ int next_actualFace = dm->drawObject->triangle_to_mface[0];
+ int prev_mat_nr = -1;
- if (tottri == 0) {
- /* avoid buffer problems in following code */
- }
- if (setDrawOptions == NULL) {
- /* just draw the entire face array */
- glDrawArrays(GL_TRIANGLES, 0, (tottri) * 3);
- }
- else {
- /* we need to check if the next material changes */
- int next_actualFace = dm->drawObject->triangle_to_mface[0];
+ for (i = 0; i < tottri; i++) {
+ //int actualFace = dm->drawObject->triangle_to_mface[i];
+ int actualFace = next_actualFace;
+ MFace *mface = mf + actualFace;
+ /*int drawSmooth = (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : (mface->flag & ME_SMOOTH);*/ /* UNUSED */
+ DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
+ int flush = 0;
- for (i = 0; i < tottri; i++) {
- //int actualFace = dm->drawObject->triangle_to_mface[i];
- int actualFace = next_actualFace;
- MFace *mface = mf + actualFace;
- /*int drawSmooth = (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : (mface->flag & ME_SMOOTH);*/ /* UNUSED */
- DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
- int flush = 0;
-
- if (i != tottri - 1)
- next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
-
- orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace) : actualFace;
-
- if (orig == ORIGINDEX_NONE)
+ if (i != tottri - 1)
+ next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
+
+ orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace) : actualFace;
+
+ if (mface->mat_nr != prev_mat_nr) {
+ if (setMaterial)
draw_option = setMaterial(mface->mat_nr + 1, NULL);
- else if (setDrawOptions != NULL)
- draw_option = setDrawOptions(userData, orig);
-
- if (draw_option == DM_DRAW_OPTION_STIPPLE) {
- glEnable(GL_POLYGON_STIPPLE);
- glPolygonStipple(stipple_quarttone);
- }
-
- /* Goal is to draw as long of a contiguous triangle
+
+ prev_mat_nr = mface->mat_nr;
+ }
+
+ if (setDrawOptions != NULL && (orig != ORIGINDEX_NONE))
+ draw_option = setDrawOptions(userData, orig);
+
+ if (draw_option == DM_DRAW_OPTION_STIPPLE) {
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(stipple_quarttone);
+ }
+
+ /* Goal is to draw as long of a contiguous triangle
* array as possible, so draw when we hit either an
* invisible triangle or at the end of the array */
-
- /* flush buffer if current triangle isn't drawable or it's last triangle... */
- flush = (ELEM(draw_option, DM_DRAW_OPTION_SKIP, DM_DRAW_OPTION_STIPPLE)) || (i == tottri - 1);
-
- /* ... or when material setting is dissferent */
- flush |= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr;
-
- if (!flush && compareDrawOptions) {
- flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
- }
-
- if (flush) {
- int first = prevstart * 3;
- /* Add one to the length if we're drawing at the end of the array */
- int count = (i - prevstart + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3;
-
- if (count)
- glDrawArrays(GL_TRIANGLES, first, count);
-
- prevstart = i + 1;
-
- if (draw_option == DM_DRAW_OPTION_STIPPLE)
- glDisable(GL_POLYGON_STIPPLE);
- }
+
+ /* flush buffer if current triangle isn't drawable or it's last triangle... */
+ flush = (ELEM(draw_option, DM_DRAW_OPTION_SKIP, DM_DRAW_OPTION_STIPPLE)) || (i == tottri - 1);
+
+ /* ... or when material setting is dissferent */
+ flush |= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr;
+
+ if (!flush && compareDrawOptions) {
+ flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
+ }
+
+ if (flush) {
+ int first = prevstart * 3;
+ /* Add one to the length if we're drawing at the end of the array */
+ int count = (i - prevstart + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3;
+
+ if (count)
+ glDrawArrays(GL_TRIANGLES, first, count);
+
+ prevstart = i + 1;
+
+ if (draw_option == DM_DRAW_OPTION_STIPPLE)
+ glDisable(GL_POLYGON_STIPPLE);
}
}
-
+
glShadeModel(GL_FLAT);
}
GPU_buffer_unbind();
@@ -1150,7 +859,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm,
}
static void cdDM_drawMappedFacesTex(DerivedMesh *dm,
- DMSetDrawOptions setDrawOptions,
+ DMSetDrawOptionsMappedTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData, DMDrawFlag flag)
{
@@ -1270,7 +979,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
glShadeModel(GL_SMOOTH);
- if (GPU_buffer_legacy(dm) || setDrawOptions != NULL) {
+ if (setDrawOptions != NULL) {
DEBUG_VBO("Using legacy code. cdDM_drawMappedFacesGLSL\n");
memset(&attribs, 0, sizeof(attribs));
@@ -1329,11 +1038,11 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
ln3 = &lnors[a][2];
ln4 = &lnors[a][3];
}
-
+
cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, ln1, smoothnormal);
cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, ln2, smoothnormal);
cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, ln3, smoothnormal);
-
+
if (mface->v4)
cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, ln4, smoothnormal);
else
@@ -1343,218 +1052,217 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
}
else {
GPUBuffer *buffer = NULL;
- const char *varray = NULL;
+ char *varray = NULL;
int numdata = 0, elementsize = 0, offset;
int start = 0, numfaces = 0 /* , prevdraw = 0 */ /* UNUSED */, curface = 0;
int i;
-
+
const MFace *mf = mface;
GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
memset(&attribs, 0, sizeof(attribs));
-
+
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
-
- if (!GPU_buffer_legacy(dm)) {
- for (i = 0; i < dm->drawObject->tot_triangle_point / 3; i++) {
-
- a = dm->drawObject->triangle_to_mface[i];
-
- mface = mf + a;
- new_matnr = mface->mat_nr + 1;
-
- if (new_matnr != matnr) {
- numfaces = curface - start;
- if (numfaces > 0) {
-
- if (do_draw) {
-
- if (numdata != 0) {
-
- GPU_buffer_unlock(buffer);
-
- GPU_interleaved_attrib_setup(buffer, datatypes, numdata);
- }
-
- glDrawArrays(GL_TRIANGLES, start * 3, numfaces * 3);
-
- if (numdata != 0) {
-
- GPU_buffer_free(buffer);
-
- buffer = NULL;
- }
-
+
+ for (i = 0; i < dm->drawObject->tot_triangle_point / 3; i++) {
+
+ a = dm->drawObject->triangle_to_mface[i];
+
+ mface = mf + a;
+ new_matnr = mface->mat_nr + 1;
+
+ if (new_matnr != matnr) {
+ numfaces = curface - start;
+ if (numfaces > 0) {
+
+ if (do_draw) {
+
+ if (numdata != 0) {
+
+ GPU_buffer_unlock(buffer);
+
+ GPU_interleaved_attrib_setup(buffer, datatypes, numdata);
+ }
+
+ glDrawArrays(GL_TRIANGLES, start * 3, numfaces * 3);
+
+ if (numdata != 0) {
+
+ GPU_buffer_free(buffer);
+
+ buffer = NULL;
}
+
}
- numdata = 0;
- start = curface;
- /* prevdraw = do_draw; */ /* UNUSED */
- do_draw = setMaterial(matnr = new_matnr, &gattribs);
- if (do_draw) {
- DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
-
- if (attribs.totorco && attribs.orco.array) {
- datatypes[numdata].index = attribs.orco.gl_index;
- datatypes[numdata].size = 3;
+ }
+ numdata = 0;
+ start = curface;
+ /* prevdraw = do_draw; */ /* UNUSED */
+ do_draw = setMaterial(matnr = new_matnr, &gattribs);
+ if (do_draw) {
+ DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+
+ if (attribs.totorco && attribs.orco.array) {
+ datatypes[numdata].index = attribs.orco.gl_index;
+ datatypes[numdata].size = 3;
+ datatypes[numdata].type = GL_FLOAT;
+ numdata++;
+ }
+ for (b = 0; b < attribs.tottface; b++) {
+ if (attribs.tface[b].array) {
+ datatypes[numdata].index = attribs.tface[b].gl_index;
+ datatypes[numdata].size = 2;
datatypes[numdata].type = GL_FLOAT;
numdata++;
}
- for (b = 0; b < attribs.tottface; b++) {
- if (attribs.tface[b].array) {
- datatypes[numdata].index = attribs.tface[b].gl_index;
- datatypes[numdata].size = 2;
- datatypes[numdata].type = GL_FLOAT;
- numdata++;
- }
- }
- for (b = 0; b < attribs.totmcol; b++) {
- if (attribs.mcol[b].array) {
- datatypes[numdata].index = attribs.mcol[b].gl_index;
- datatypes[numdata].size = 4;
- datatypes[numdata].type = GL_UNSIGNED_BYTE;
- numdata++;
- }
- }
- if (attribs.tottang && attribs.tang.array) {
- datatypes[numdata].index = attribs.tang.gl_index;
+ }
+ for (b = 0; b < attribs.totmcol; b++) {
+ if (attribs.mcol[b].array) {
+ datatypes[numdata].index = attribs.mcol[b].gl_index;
datatypes[numdata].size = 4;
- datatypes[numdata].type = GL_FLOAT;
+ datatypes[numdata].type = GL_UNSIGNED_BYTE;
numdata++;
}
- if (numdata != 0) {
- elementsize = GPU_attrib_element_size(datatypes, numdata);
- buffer = GPU_buffer_alloc(elementsize * dm->drawObject->tot_triangle_point);
- if (buffer == NULL) {
- GPU_buffer_unbind();
- dm->drawObject->legacy = 1;
- return;
- }
- varray = GPU_buffer_lock_stream(buffer);
- if (varray == NULL) {
- GPU_buffer_unbind();
- GPU_buffer_free(buffer);
- dm->drawObject->legacy = 1;
- return;
- }
+ }
+ if (attribs.tottang && attribs.tang.array) {
+ datatypes[numdata].index = attribs.tang.gl_index;
+ datatypes[numdata].size = 4;
+ datatypes[numdata].type = GL_FLOAT;
+ numdata++;
+ }
+ if (numdata != 0) {
+ elementsize = GPU_attrib_element_size(datatypes, numdata);
+ buffer = GPU_buffer_alloc(elementsize * dm->drawObject->tot_triangle_point, false);
+ if (buffer == NULL) {
+ GPU_buffer_unbind();
+ buffer = GPU_buffer_alloc(elementsize * dm->drawObject->tot_triangle_point, true);
+ return;
}
- else {
- /* if the buffer was set, don't use it again.
- * prevdraw was assumed true but didnt run so set to false - [#21036] */
- /* prevdraw = 0; */ /* UNUSED */
- buffer = NULL;
+ varray = GPU_buffer_lock_stream(buffer);
+ if (varray == NULL) {
+ GPU_buffer_unbind();
+ GPU_buffer_free(buffer);
+ fprintf(stderr, "Out of memory, can't draw object\n");
+ return;
}
}
+ else {
+ /* if the buffer was set, don't use it again.
+ * prevdraw was assumed true but didnt run so set to false - [#21036] */
+ /* prevdraw = 0; */ /* UNUSED */
+ buffer = NULL;
+ }
}
-
+ }
+
+ if (do_draw && numdata != 0) {
+ offset = 0;
+ if (attribs.totorco && attribs.orco.array) {
+ copy_v3_v3((float *)&varray[elementsize * curface * 3], (float *)attribs.orco.array[mface->v1]);
+ copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize], (float *)attribs.orco.array[mface->v2]);
+ copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize * 2], (float *)attribs.orco.array[mface->v3]);
+ offset += sizeof(float) * 3;
+ }
+ for (b = 0; b < attribs.tottface; b++) {
+ if (attribs.tface[b].array) {
+ MTFace *tf = &attribs.tface[b].array[a];
+ copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset], tf->uv[0]);
+ copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize], tf->uv[1]);
+
+ copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tf->uv[2]);
+ offset += sizeof(float) * 2;
+ }
+ }
+ for (b = 0; b < attribs.totmcol; b++) {
+ if (attribs.mcol[b].array) {
+ MCol *cp = &attribs.mcol[b].array[a * 4 + 0];
+ GLubyte col[4];
+ col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
+ copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset], (char *)col);
+ cp = &attribs.mcol[b].array[a * 4 + 1];
+ col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
+ copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize], (char *)col);
+ cp = &attribs.mcol[b].array[a * 4 + 2];
+ col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
+ copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize * 2], (char *)col);
+ offset += sizeof(unsigned char) * 4;
+ }
+ }
+ if (attribs.tottang && attribs.tang.array) {
+ const float *tang = attribs.tang.array[a * 4 + 0];
+ copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset], tang);
+ tang = attribs.tang.array[a * 4 + 1];
+ copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize], tang);
+ tang = attribs.tang.array[a * 4 + 2];
+ copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tang);
+ offset += sizeof(float) * 4;
+ }
+ (void)offset;
+ }
+ curface++;
+ if (mface->v4) {
if (do_draw && numdata != 0) {
offset = 0;
if (attribs.totorco && attribs.orco.array) {
- copy_v3_v3((float *)&varray[elementsize * curface * 3], (float *)attribs.orco.array[mface->v1]);
- copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize], (float *)attribs.orco.array[mface->v2]);
- copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize * 2], (float *)attribs.orco.array[mface->v3]);
+ copy_v3_v3((float *)&varray[elementsize * curface * 3], (float *)attribs.orco.array[mface->v3]);
+ copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize], (float *)attribs.orco.array[mface->v4]);
+ copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize * 2], (float *)attribs.orco.array[mface->v1]);
offset += sizeof(float) * 3;
}
for (b = 0; b < attribs.tottface; b++) {
if (attribs.tface[b].array) {
MTFace *tf = &attribs.tface[b].array[a];
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset], tf->uv[0]);
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize], tf->uv[1]);
-
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tf->uv[2]);
+ copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset], tf->uv[2]);
+ copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize], tf->uv[3]);
+ copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tf->uv[0]);
offset += sizeof(float) * 2;
}
}
for (b = 0; b < attribs.totmcol; b++) {
if (attribs.mcol[b].array) {
- MCol *cp = &attribs.mcol[b].array[a * 4 + 0];
+ MCol *cp = &attribs.mcol[b].array[a * 4 + 2];
GLubyte col[4];
col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset], (char *)col);
- cp = &attribs.mcol[b].array[a * 4 + 1];
+ cp = &attribs.mcol[b].array[a * 4 + 3];
col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize], (char *)col);
- cp = &attribs.mcol[b].array[a * 4 + 2];
+ cp = &attribs.mcol[b].array[a * 4 + 0];
col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize * 2], (char *)col);
offset += sizeof(unsigned char) * 4;
}
}
if (attribs.tottang && attribs.tang.array) {
- const float *tang = attribs.tang.array[a * 4 + 0];
+ const float *tang = attribs.tang.array[a * 4 + 2];
copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset], tang);
- tang = attribs.tang.array[a * 4 + 1];
+ tang = attribs.tang.array[a * 4 + 3];
copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize], tang);
- tang = attribs.tang.array[a * 4 + 2];
+ tang = attribs.tang.array[a * 4 + 0];
copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tang);
offset += sizeof(float) * 4;
}
(void)offset;
}
curface++;
- if (mface->v4) {
- if (do_draw && numdata != 0) {
- offset = 0;
- if (attribs.totorco && attribs.orco.array) {
- copy_v3_v3((float *)&varray[elementsize * curface * 3], (float *)attribs.orco.array[mface->v3]);
- copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize], (float *)attribs.orco.array[mface->v4]);
- copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize * 2], (float *)attribs.orco.array[mface->v1]);
- offset += sizeof(float) * 3;
- }
- for (b = 0; b < attribs.tottface; b++) {
- if (attribs.tface[b].array) {
- MTFace *tf = &attribs.tface[b].array[a];
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset], tf->uv[2]);
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize], tf->uv[3]);
- copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tf->uv[0]);
- offset += sizeof(float) * 2;
- }
- }
- for (b = 0; b < attribs.totmcol; b++) {
- if (attribs.mcol[b].array) {
- MCol *cp = &attribs.mcol[b].array[a * 4 + 2];
- GLubyte col[4];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset], (char *)col);
- cp = &attribs.mcol[b].array[a * 4 + 3];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize], (char *)col);
- cp = &attribs.mcol[b].array[a * 4 + 0];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize * 2], (char *)col);
- offset += sizeof(unsigned char) * 4;
- }
- }
- if (attribs.tottang && attribs.tang.array) {
- const float *tang = attribs.tang.array[a * 4 + 2];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset], tang);
- tang = attribs.tang.array[a * 4 + 3];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize], tang);
- tang = attribs.tang.array[a * 4 + 0];
- copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tang);
- offset += sizeof(float) * 4;
- }
- (void)offset;
- }
- curface++;
- i++;
- }
+ i++;
}
- numfaces = curface - start;
- if (numfaces > 0) {
- if (do_draw) {
- if (numdata != 0) {
- GPU_buffer_unlock(buffer);
- GPU_interleaved_attrib_setup(buffer, datatypes, numdata);
- }
- glDrawArrays(GL_TRIANGLES, start * 3, (curface - start) * 3);
+ }
+ numfaces = curface - start;
+ if (numfaces > 0) {
+ if (do_draw) {
+ if (numdata != 0) {
+ GPU_buffer_unlock(buffer);
+ GPU_interleaved_attrib_setup(buffer, datatypes, numdata);
}
+ glDrawArrays(GL_TRIANGLES, start * 3, (curface - start) * 3);
}
- GPU_buffer_unbind();
}
+ GPU_buffer_unbind();
+
GPU_buffer_free(buffer);
}
-
+
glShadeModel(GL_FLAT);
}
@@ -2725,10 +2433,10 @@ static bool poly_gset_compare_fn(const void *k1, const void *k2)
(pk1->totloops == pk2->totloops))
{
/* Equality - note that this does not mean equality of polys */
- return 0;
+ return false;
}
else {
- return 1;
+ return true;
}
}
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index a63e06c7cb8..89c3e4b0cfc 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -50,7 +50,6 @@
#include "IMB_colormanagement.h"
-#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
/* ********************************* color curve ********************* */
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 574001e2f80..f591fe857f8 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -229,7 +229,8 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob)
* of a matrix from one space to another for constraint evaluation.
* For now, this is only implemented for Objects and PoseChannels.
*/
-void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to)
+void BKE_constraint_mat_convertspace(
+ Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to, const bool keep_scale)
{
float diff_mat[4][4];
float imat[4][4];
@@ -252,7 +253,7 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[
/* use pose-space as stepping stone for other spaces... */
if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) {
/* call self with slightly different values */
- BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
}
break;
}
@@ -288,7 +289,7 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[
/* use pose-space as stepping stone for other spaces */
if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) {
/* call self with slightly different values */
- BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
}
break;
}
@@ -303,7 +304,7 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[
/* use pose-space as stepping stone for other spaces */
if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) {
/* call self with slightly different values */
- BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
}
break;
}
@@ -323,8 +324,17 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[
/* Local space in this case will have to be defined as local to the owner's
* transform-property-rotated axes. So subtract this rotation component.
*/
+ /* XXX This is actually an ugly hack, local space of a parent-less object *is* the same as
+ * global space!
+ * Think what we want actually here is some kind of 'Final Space', i.e. once transformations
+ * are applied - users are often confused about this too, this is not consistent with bones
+ * local space either... Meh :|
+ * --mont29
+ */
BKE_object_to_mat4(ob, diff_mat);
- normalize_m4(diff_mat);
+ if (!keep_scale) {
+ normalize_m4(diff_mat);
+ }
zero_v3(diff_mat[3]);
invert_m4_m4_safe(imat, diff_mat);
@@ -342,8 +352,11 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[
/* Local space in this case will have to be defined as local to the owner's
* transform-property-rotated axes. So add back this rotation component.
*/
+ /* XXX See comment above for world->local case... */
BKE_object_to_mat4(ob, diff_mat);
- normalize_m4(diff_mat);
+ if (!keep_scale) {
+ normalize_m4(diff_mat);
+ }
zero_v3(diff_mat[3]);
mul_m4_m4m4(mat, diff_mat, mat);
@@ -511,7 +524,7 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m
/* Case OBJECT */
if (!strlen(substring)) {
copy_m4_m4(mat, ob->obmat);
- BKE_constraint_mat_convertspace(ob, NULL, mat, from, to);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false);
}
/* Case VERTEXGROUP */
/* Current method just takes the average location of all the points in the
@@ -524,11 +537,11 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m
*/
else if (ob->type == OB_MESH) {
contarget_get_mesh_mat(ob, substring, mat);
- BKE_constraint_mat_convertspace(ob, NULL, mat, from, to);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false);
}
else if (ob->type == OB_LATTICE) {
contarget_get_lattice_mat(ob, substring, mat);
- BKE_constraint_mat_convertspace(ob, NULL, mat, from, to);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false);
}
/* Case BONE */
else {
@@ -561,7 +574,7 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m
copy_m4_m4(mat, ob->obmat);
/* convert matrix space as required */
- BKE_constraint_mat_convertspace(ob, pchan, mat, from, to);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, from, to, false);
}
}
@@ -1971,7 +1984,7 @@ static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTa
static void pycon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
{
#ifndef WITH_PYTHON
- (void)con; (void)cob; (void)targets; /* unused */
+ UNUSED_VARS(con, cob, targets);
return;
#else
bPythonConstraint *data = con->data;
@@ -2709,7 +2722,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
}
if (bulge < 1.0f) {
if (data->flag & STRETCHTOCON_USE_BULGE_MIN) {
- float bulge_min = CLAMPIS(data->bulge_max, 0.0f, 1.0f);
+ float bulge_min = CLAMPIS(data->bulge_min, 0.0f, 1.0f);
float hard = max_ff(bulge, bulge_min);
float range = 1.0f - bulge_min;
@@ -3461,16 +3474,13 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
}
/* transform normal into requested space */
- /* We cannot use BKE_constraint_mat_convertspace here, it does not take into account scaling...
- * In theory we would not need it, but in this case we'd have to tweak SpaceTransform to also
- * optionally ignore scaling when handling normals - simpler to directly call BKE_object_to_mat4
- * if needed! See T42447. */
- if (scon->projAxisSpace == CONSTRAINT_SPACE_WORLD) {
- BKE_object_to_mat4(cob->ob, mat);
- invert_m4(mat);
- mul_mat3_m4_v3(mat, no);
- }
- /* Else, we remain in local space, nothing to do. */
+ /* Note that in this specific case, we need to keep scaling in non-parented 'local2world' object
+ * case, because SpaceTransform also takes it into account when handling normals. See T42447. */
+ unit_m4(mat);
+ BKE_constraint_mat_convertspace(cob->ob, cob->pchan, mat,
+ CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace, true);
+ invert_m4(mat);
+ mul_mat3_m4_v3(mat, no);
if (normalize_v3(no) < FLT_EPSILON) {
fail = true;
@@ -3688,6 +3698,9 @@ static void splineik_new_data(void *cdata)
bSplineIKConstraint *data = (bSplineIKConstraint *)cdata;
data->chainlen = 1;
+ data->bulge = 1.0;
+ data->bulge_max = 1.0f;
+ data->bulge_min = 1.0f;
}
static void splineik_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
@@ -4395,10 +4408,10 @@ bool BKE_constraint_remove(ListBase *list, bConstraint *con)
if (con) {
BKE_constraint_free_data(con);
BLI_freelinkN(list, con);
- return 1;
+ return true;
}
else
- return 0;
+ return false;
}
/* ......... */
@@ -4662,15 +4675,15 @@ bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan)
/* On bone-level, check if bone is on proxy-protected layer */
if ((pchan->bone) && (pchan->bone->layer & arm->layer_protected))
- return 1;
+ return true;
}
else {
/* FIXME: constraints on object-level are not handled well yet */
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
/* -------- Target-Matrix Stuff ------- */
@@ -4816,7 +4829,7 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime)
copy_m4_m4(oldmat, cob->matrix);
/* move owner matrix into right space */
- BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace);
+ BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace, false);
/* prepare targets for constraint solving */
BKE_constraint_targets_for_solving_get(con, cob, &targets, ctime);
@@ -4834,7 +4847,7 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime)
/* move owner back into worldspace for next constraint/other business */
if ((con->flag & CONSTRAINT_SPACEONCE) == 0)
- BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD);
+ BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD, false);
/* Interpolate the enforcement, to blend result of constraint into final owner transform
* - all this happens in worldspace to prevent any weirdness creeping in ([#26014] and [#25725]),
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 4b0adafef4b..8f6c9735aaf 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -37,6 +37,7 @@
#include "DNA_windowmanager_types.h"
#include "DNA_object_types.h"
#include "DNA_linestyle_types.h"
+#include "DNA_gpencil_types.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
@@ -257,7 +258,7 @@ static void *ctx_wm_python_context_get(
}
}
#else
- (void)C, (void)member, (void)member_type;
+ UNUSED_VARS(C, member, member_type);
#endif
/* don't allow UI context access from non-main threads */
@@ -1090,3 +1091,34 @@ int CTX_data_visible_pose_bones(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "visible_pose_bones", list);
}
+
+bGPdata *CTX_data_gpencil_data(const bContext *C)
+{
+ return ctx_data_pointer_get(C, "gpencil_data");
+}
+
+bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C)
+{
+ return ctx_data_pointer_get(C, "active_gpencil_layer");
+}
+
+bGPDframe *CTX_data_active_gpencil_frame(const bContext *C)
+{
+ return ctx_data_pointer_get(C, "active_gpencil_frame");
+}
+
+int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list)
+{
+ return ctx_data_collection_get(C, "visible_gpencil_layers", list);
+}
+
+int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list)
+{
+ return ctx_data_collection_get(C, "editable_gpencil_layers", list);
+}
+
+int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list)
+{
+ return ctx_data_collection_get(C, "editable_gpencil_strokes", list);
+}
+
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 937ceffc765..3abe3c58562 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -237,6 +237,10 @@ Curve *BKE_curve_copy(Curve *cu)
id_us_plus((ID *)cun->vfonti);
id_us_plus((ID *)cun->vfontbi);
+ if (cu->id.lib) {
+ BKE_id_lib_local_paths(G.main, cu->id.lib, &cun->id);
+ }
+
return cun;
}
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 8f02ccdd8b2..89ebed258a3 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -48,6 +48,7 @@
#include "BLI_string.h"
#include "BLI_path_util.h"
#include "BLI_math.h"
+#include "BLI_math_color_blend.h"
#include "BLI_mempool.h"
#include "BLF_translation.h"
@@ -56,6 +57,8 @@
#include "BKE_customdata_file.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h"
#include "BKE_multires.h"
#include "bmesh.h"
@@ -92,7 +95,7 @@ typedef struct LayerTypeInfo {
* (deep copy if appropriate)
* if NULL, memcpy is used
*/
- void (*copy)(const void *source, void *dest, int count);
+ cd_copy copy;
/**
* a function to free any dynamically allocated components of this
@@ -117,8 +120,7 @@ typedef struct LayerTypeInfo {
* applying changes while reading from sources.
* See bug [#32395] - Campbell.
*/
- void (*interp)(void **sources, const float *weights, const float *sub_weights,
- int count, void *dest);
+ cd_interp interp;
/** a function to swap the data in corners of the element */
void (*swap)(void *data, const int *corner_indices);
@@ -134,7 +136,7 @@ typedef struct LayerTypeInfo {
void (*initminmax)(void *min, void *max);
void (*add)(void *data1, const void *data2);
void (*dominmax)(const void *data1, void *min, void *max);
- void (*copyvalue)(const void *source, void *dest);
+ void (*copyvalue)(const void *source, void *dest, const int mixmode, const float mixfactor);
/** a function to read data from a cdf file */
int (*read)(CDataFile *cdf, void *data, int count);
@@ -620,14 +622,53 @@ static void layerFree_grid_paint_mask(void *data, int count, int UNUSED(size))
}
/* --------- */
-static void layerCopyValue_mloopcol(const void *source, void *dest)
+static void layerCopyValue_mloopcol(const void *source, void *dest, const int mixmode, const float mixfactor)
{
const MLoopCol *m1 = source;
MLoopCol *m2 = dest;
-
- m2->r = m1->r;
- m2->g = m1->g;
- m2->b = m1->b;
+ unsigned char tmp_col[4];
+
+ if (ELEM(mixmode, CDT_MIX_NOMIX, CDT_MIX_REPLACE_ABOVE_THRESHOLD, CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
+ /* Modes that do a full copy or nothing. */
+ if (ELEM(mixmode, CDT_MIX_REPLACE_ABOVE_THRESHOLD, CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
+ /* TODO: Check for a real valid way to get 'factor' value of our dest color? */
+ const float f = ((float)m2->r + (float)m2->g + (float)m2->b) / 3.0f;
+ if (mixmode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && f < mixfactor) {
+ return; /* Do Nothing! */
+ }
+ else if (mixmode == CDT_MIX_REPLACE_BELOW_THRESHOLD && f > mixfactor) {
+ return; /* Do Nothing! */
+ }
+ }
+ m2->r = m1->r;
+ m2->g = m1->g;
+ m2->b = m1->b;
+ }
+ else { /* Modes that support 'real' mix factor. */
+ unsigned char src[4] = {m1->r, m1->g, m1->b, m1->a};
+ unsigned char dst[4] = {m2->r, m2->g, m2->b, m2->a};
+
+ if (mixmode == CDT_MIX_MIX) {
+ blend_color_mix_byte(tmp_col, dst, src);
+ }
+ else if (mixmode == CDT_MIX_ADD) {
+ blend_color_add_byte(tmp_col, dst, src);
+ }
+ else if (mixmode == CDT_MIX_SUB) {
+ blend_color_sub_byte(tmp_col, dst, src);
+ }
+ else if (mixmode == CDT_MIX_MUL) {
+ blend_color_mul_byte(tmp_col, dst, src);
+ }
+ else {
+ memcpy(tmp_col, src, sizeof(tmp_col));
+ }
+ blend_color_interpolate_byte(dst, dst, tmp_col, mixfactor);
+
+ m2->r = (char)dst[0];
+ m2->g = (char)dst[1];
+ m2->b = (char)dst[2];
+ }
m2->a = m1->a;
}
@@ -758,12 +799,19 @@ static int layerMaxNum_mloopcol(void)
return MAX_MCOL;
}
-static void layerCopyValue_mloopuv(const void *source, void *dest)
+static void layerCopyValue_mloopuv(const void *source, void *dest, const int mixmode, const float mixfactor)
{
const MLoopUV *luv1 = source;
MLoopUV *luv2 = dest;
- copy_v2_v2(luv2->uv, luv1->uv);
+ /* We only support a limited subset of advanced mixing here - namely the mixfactor interpolation. */
+
+ if (mixmode == CDT_MIX_NOMIX) {
+ copy_v2_v2(luv2->uv, luv1->uv);
+ }
+ else {
+ interp_v2_v2v2(luv2->uv, luv2->uv, luv1->uv, mixfactor);
+ }
}
static bool layerEqual_mloopuv(const void *data1, const void *data2)
@@ -833,7 +881,8 @@ static void layerInterp_mloopuv(void **sources, const float *weights,
}
/* origspace is almost exact copy of mloopuv's, keep in sync */
-static void layerCopyValue_mloop_origspace(const void *source, void *dest)
+static void layerCopyValue_mloop_origspace(const void *source, void *dest,
+ const int UNUSED(mixmode), const float UNUSED(mixfactor))
{
const OrigSpaceLoop *luv1 = source;
OrigSpaceLoop *luv2 = dest;
@@ -1798,7 +1847,8 @@ bool CustomData_free_layer(CustomData *data, int type, int totelem, int index)
const int n = index - CustomData_get_layer_index(data, type);
int i;
- if (index < 0) return 0;
+ if (index < 0)
+ return false;
customData_free_layer__internal(&data->layers[index], totelem);
@@ -1828,14 +1878,15 @@ bool CustomData_free_layer(CustomData *data, int type, int totelem, int index)
customData_update_offsets(data);
- return 1;
+ return true;
}
bool CustomData_free_layer_active(CustomData *data, int type, int totelem)
{
int index = 0;
index = CustomData_get_active_layer_index(data, type);
- if (index == -1) return 0;
+ if (index == -1)
+ return false;
return CustomData_free_layer(data, type, totelem, index);
}
@@ -1942,7 +1993,8 @@ bool CustomData_is_referenced_layer(struct CustomData *data, int type)
/* get the layer index of the first layer of type */
layer_index = CustomData_get_active_layer_index(data, type);
- if (layer_index == -1) return 0;
+ if (layer_index == -1)
+ return false;
layer = &data->layers[layer_index];
@@ -2258,16 +2310,23 @@ int CustomData_get_n_offset(const CustomData *data, int type, int n)
bool CustomData_set_layer_name(const CustomData *data, int type, int n, const char *name)
{
/* get the layer index of the first layer of type */
- int layer_index = CustomData_get_layer_index_n(data, type, n);
+ const int layer_index = CustomData_get_layer_index_n(data, type, n);
- if (layer_index == -1) return false;
- if (!name) return false;
+ if ((layer_index == -1) || !name)
+ return false;
BLI_strncpy(data->layers[layer_index].name, name, sizeof(data->layers[layer_index].name));
return true;
}
+const char *CustomData_get_layer_name(const CustomData *data, int type, int n)
+{
+ const int layer_index = CustomData_get_layer_index_n(data, type, n);
+
+ return (layer_index == -1) ? NULL : data->layers[layer_index].name;
+}
+
void *CustomData_set_layer(const CustomData *data, int type, void *ptr)
{
/* get the layer index of the first layer of type */
@@ -2761,11 +2820,28 @@ void CustomData_data_copy_value(int type, const void *source, void *dest)
if (!dest) return;
if (typeInfo->copyvalue)
- typeInfo->copyvalue(source, dest);
+ typeInfo->copyvalue(source, dest, CDT_MIX_NOMIX, 0.0f);
else
memcpy(dest, source, typeInfo->size);
}
+/* Mixes the "value" (e.g. mloopuv uv or mloopcol colors) from one block into
+ * another, while not overwriting anything else (e.g. flags)*/
+void CustomData_data_mix_value(int type, const void *source, void *dest, const int mixmode, const float mixfactor)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (!dest) return;
+
+ if (typeInfo->copyvalue) {
+ typeInfo->copyvalue(source, dest, mixmode, mixfactor);
+ }
+ else {
+ /* Mere copy if no advanced interpolation is supported. */
+ memcpy(dest, source, typeInfo->size);
+ }
+}
+
bool CustomData_data_equals(int type, const void *data1, const void *data2)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@@ -3461,3 +3537,233 @@ void CustomData_external_remove_object(CustomData *data, ID *id)
}
#endif
+/* ********** Mesh-to-mesh data transfer ********** */
+static void copy_bit_flag(void *dst, void *src, const size_t data_size, const uint64_t flag)
+{
+#define COPY_BIT_FLAG(_type, _dst, _src, _f) \
+{ \
+ const _type _val = *((_type *)(_src)) & ((_type)(_f)); \
+ *((_type *)(_dst)) &= ~((_type)(_f)); \
+ *((_type *)(_dst)) |= _val; \
+} (void) 0
+
+ switch (data_size) {
+ case 1:
+ COPY_BIT_FLAG(uint8_t, dst, src, flag);
+ break;
+ case 2:
+ COPY_BIT_FLAG(uint16_t, dst, src, flag);
+ break;
+ case 4:
+ COPY_BIT_FLAG(uint32_t, dst, src, flag);
+ break;
+ case 8:
+ COPY_BIT_FLAG(uint64_t, dst, src, flag);
+ break;
+ default:
+ //printf("ERROR %s: Unknown flags-container size (%zu)\n", __func__, datasize);
+ break;
+ }
+
+#undef COPY_BIT_FLAG
+}
+
+static bool check_bit_flag(void *data, const size_t data_size, const uint64_t flag)
+{
+ switch (data_size) {
+ case 1:
+ return ((*((uint8_t *)data) & ((uint8_t)flag)) != 0);
+ case 2:
+ return ((*((uint16_t *)data) & ((uint16_t)flag)) != 0);
+ case 4:
+ return ((*((uint32_t *)data) & ((uint32_t)flag)) != 0);
+ case 8:
+ return ((*((uint64_t *)data) & ((uint64_t)flag)) != 0);
+ default:
+ //printf("ERROR %s: Unknown flags-container size (%zu)\n", __func__, datasize);
+ return false;
+ }
+}
+
+static void customdata_data_transfer_interp_generic(
+ const CustomDataTransferLayerMap *laymap, void *data_dst, void **sources, const float *weights, const int count,
+ const float mix_factor)
+{
+ /* Fake interpolation, we actually copy highest weighted source to dest.
+ * Note we also handle bitflags here, in which case we rather choose to transfer value of elements totaling
+ * more than 0.5 of weight. */
+
+ int best_src_idx = 0;
+
+ const int data_type = laymap->data_type;
+ const int mix_mode = laymap->mix_mode;
+
+ size_t data_size;
+ const uint64_t data_flag = laymap->data_flag;
+
+ cd_interp interp_cd = NULL;
+ cd_copy copy_cd = NULL;
+
+ void *tmp_dst;
+
+ if (!sources) {
+ /* Not supported here, abort. */
+ return;
+ }
+
+ if (data_type & CD_FAKE) {
+ data_size = laymap->data_size;
+ }
+ else {
+ const LayerTypeInfo *type_info = layerType_getInfo(data_type);
+
+ data_size = (size_t)type_info->size;
+ interp_cd = type_info->interp;
+ copy_cd = type_info->copy;
+ }
+
+ tmp_dst = MEM_mallocN(data_size, __func__);
+
+ if (count > 1 && !interp_cd) {
+ int i;
+
+ if (data_flag) {
+ /* Boolean case, we can 'interpolate' in two groups, and choose value from highest weighted group. */
+ float tot_weight_true = 0.0f;
+ int item_true_idx = -1, item_false_idx = -1;
+
+ for (i = 0; i < count; i++) {
+ if (check_bit_flag(sources[i], data_size, data_flag)) {
+ tot_weight_true += weights[i];
+ item_true_idx = i;
+ }
+ else {
+ item_false_idx = i;
+ }
+ }
+ best_src_idx = (tot_weight_true >= 0.5f) ? item_true_idx : item_false_idx;
+ }
+ else {
+ /* We just choose highest weighted source. */
+ float max_weight = 0.0f;
+
+ for (i = 0; i < count; i++) {
+ if (weights[i] > max_weight) {
+ max_weight = weights[i];
+ best_src_idx = i;
+ }
+ }
+ }
+ }
+
+ BLI_assert(best_src_idx >= 0);
+
+ if (interp_cd) {
+ interp_cd(sources, weights, NULL, count, (char *)tmp_dst);
+ }
+ else if (data_flag) {
+ copy_bit_flag(tmp_dst, sources[best_src_idx], data_size, data_flag);
+ }
+ /* No interpolation, just copy highest weight source element's data. */
+ else if (copy_cd) {
+ copy_cd((char *)sources[best_src_idx], (char *)tmp_dst, 1);
+ }
+ else {
+ memcpy(tmp_dst, sources[best_src_idx], data_size);
+ }
+
+ if (data_flag) {
+ /* Bool flags, only copy if dest data is set (resp. unset) - only 'advanced' modes we can support here! */
+ if (mix_factor >= 0.5f &&
+ ((mix_mode == CDT_MIX_TRANSFER) ||
+ (mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && check_bit_flag(data_dst, data_size, data_flag)) ||
+ (mix_mode == CDT_MIX_REPLACE_BELOW_THRESHOLD && !check_bit_flag(data_dst, data_size, data_flag))))
+ {
+ copy_bit_flag(data_dst, tmp_dst, data_size, data_flag);
+ }
+ }
+ else if (!(data_type & CD_FAKE)) {
+ CustomData_data_mix_value(data_type, tmp_dst, data_dst, mix_mode, mix_factor);
+ }
+ /* Else we can do nothing by default, needs custom interp func!
+ * Note this is here only for sake of consistency, not expected to be used much actually? */
+ else {
+ if (mix_factor >= 0.5f) {
+ memcpy(data_dst, tmp_dst, data_size);
+ }
+ }
+
+ MEM_freeN(tmp_dst);
+}
+
+void CustomData_data_transfer(const MeshPairRemap *me_remap, const CustomDataTransferLayerMap *laymap)
+{
+ MeshPairRemapItem *mapit = me_remap->items;
+ const int totelem = me_remap->items_num;
+ int i;
+
+ const int data_type = laymap->data_type;
+ void *data_src = laymap->data_src;
+ void *data_dst = laymap->data_dst;
+
+ size_t data_step;
+ size_t data_size;
+ size_t data_offset;
+
+ cd_datatransfer_interp interp = NULL;
+
+ size_t tmp_buff_size = 32;
+ void **tmp_data_src = NULL;
+
+ /* Note: NULL data_src may happen and be valid (see vgroups...). */
+ if (!data_dst) {
+ return;
+ }
+
+ if (data_src) {
+ tmp_data_src = MEM_mallocN(sizeof(*tmp_data_src) * tmp_buff_size, __func__);
+ }
+
+ if (data_type & CD_FAKE) {
+ data_step = laymap->elem_size;
+ data_size = laymap->data_size;
+ data_offset = laymap->data_offset;
+ }
+ else {
+ const LayerTypeInfo *type_info = layerType_getInfo(data_type);
+
+ /* Note: we can use 'fake' CDLayers, like e.g. for crease, bweight, etc. :/ */
+ data_size = (size_t)type_info->size;
+ data_step = laymap->elem_size ? laymap->elem_size : data_size;
+ data_offset = laymap->data_offset;
+ }
+
+ interp = laymap->interp ? laymap->interp : customdata_data_transfer_interp_generic;
+
+ for (i = 0; i < totelem; i++, data_dst = (char *)data_dst + data_step, mapit++) {
+ const int sources_num = mapit->sources_num;
+ const float mix_factor = laymap->mix_weights ? laymap->mix_weights[i] : laymap->mix_factor;
+ int j;
+
+ if (!sources_num) {
+ /* No sources for this element, skip it. */
+ continue;
+ }
+
+ if (tmp_data_src) {
+ if (UNLIKELY(sources_num > tmp_buff_size)) {
+ tmp_buff_size = (size_t)sources_num;
+ tmp_data_src = MEM_reallocN(tmp_data_src, sizeof(*tmp_data_src) * tmp_buff_size);
+ }
+
+ for (j = 0; j < sources_num; j++) {
+ const size_t src_idx = (size_t)mapit->indices_src[j];
+ tmp_data_src[j] = (char *)data_src + data_step * src_idx + data_offset;
+ }
+ }
+
+ interp(laymap, (char *)data_dst + data_offset, tmp_data_src, mapit->weights_src, sources_num, mix_factor);
+ }
+
+ MEM_SAFE_FREE(tmp_data_src);
+}
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
new file mode 100644
index 00000000000..d41c74770f1
--- /dev/null
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -0,0 +1,1241 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Bastien Montagne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/data_transfer.c
+ * \ingroup bke
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_customdata_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_array.h"
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_data_transfer.h"
+#include "BKE_deform.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h"
+#include "BKE_object.h"
+#include "BKE_object_deform.h"
+#include "BKE_report.h"
+
+#include "data_transfer_intern.h"
+
+
+CustomDataMask BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types)
+{
+ CustomDataMask cddata_mask = 0;
+ int i;
+
+ for (i = 0; i < DT_TYPE_MAX; i++) {
+ const int dtdata_type = 1 << i;
+ int cddata_type;
+
+ if (!(dtdata_types & dtdata_type)) {
+ continue;
+ }
+
+ cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type);
+ if (!(cddata_type & CD_FAKE)) {
+ cddata_mask |= 1LL << cddata_type;
+ }
+ else if (cddata_type == CD_FAKE_MDEFORMVERT) {
+ cddata_mask |= CD_MASK_MDEFORMVERT; /* Exception for vgroups :/ */
+ }
+ else if (cddata_type == CD_FAKE_UV) {
+ cddata_mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV;
+ }
+ }
+
+ return cddata_mask;
+}
+
+/* Check what can do each layer type (if it is actually handled by transferdata, if it supports advanced mixing... */
+bool BKE_object_data_transfer_get_dttypes_capacity(
+ const int dtdata_types, bool *r_advanced_mixing, bool *r_threshold)
+{
+ int i;
+ bool ret = false;
+
+ *r_advanced_mixing = false;
+ *r_threshold = false;
+
+ for (i = 0; (i < DT_TYPE_MAX) && !(ret && *r_advanced_mixing && *r_threshold); i++) {
+ const int dtdata_type = 1 << i;
+
+ if (!(dtdata_types & dtdata_type)) {
+ continue;
+ }
+
+ switch (dtdata_type) {
+ /* Vertex data */
+ case DT_TYPE_MDEFORMVERT:
+ *r_advanced_mixing = true;
+ *r_threshold = true;
+ ret = true;
+ break;
+ case DT_TYPE_SKIN:
+ *r_threshold = true;
+ ret = true;
+ break;
+ case DT_TYPE_BWEIGHT_VERT:
+ ret = true;
+ break;
+ /* Edge data */
+ case DT_TYPE_SHARP_EDGE:
+ *r_threshold = true;
+ ret = true;
+ break;
+ case DT_TYPE_SEAM:
+ *r_threshold = true;
+ ret = true;
+ break;
+ case DT_TYPE_CREASE:
+ ret = true;
+ break;
+ case DT_TYPE_BWEIGHT_EDGE:
+ ret = true;
+ break;
+ case DT_TYPE_FREESTYLE_EDGE:
+ *r_threshold = true;
+ ret = true;
+ break;
+ /* Loop/Poly data */
+ case DT_TYPE_UV:
+ ret = true;
+ break;
+ case DT_TYPE_VCOL:
+ *r_advanced_mixing = true;
+ *r_threshold = true;
+ ret = true;
+ break;
+ case DT_TYPE_SHARP_FACE:
+ *r_threshold = true;
+ ret = true;
+ break;
+ case DT_TYPE_FREESTYLE_FACE:
+ *r_threshold = true;
+ ret = true;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int BKE_object_data_transfer_get_dttypes_item_types(const int dtdata_types)
+{
+ int i, ret = 0;
+
+ for (i = 0; (i < DT_TYPE_MAX) && (ret ^ (ME_VERT | ME_EDGE | ME_LOOP | ME_POLY)); i++) {
+ const int dtdata_type = 1 << i;
+
+ if (!(dtdata_types & dtdata_type)) {
+ continue;
+ }
+
+ if (DT_DATATYPE_IS_VERT(dtdata_type)) {
+ ret |= ME_VERT;
+ }
+ if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
+ ret |= ME_EDGE;
+ }
+ if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
+ ret |= ME_LOOP;
+ }
+ if (DT_DATATYPE_IS_POLY(dtdata_type)) {
+ ret |= ME_POLY;
+ }
+ }
+
+ return ret;
+}
+
+int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type)
+{
+ switch (dtdata_type) {
+ case DT_TYPE_MDEFORMVERT:
+ return CD_FAKE_MDEFORMVERT;
+ case DT_TYPE_SHAPEKEY:
+ return CD_FAKE_SHAPEKEY;
+ case DT_TYPE_SKIN:
+ return CD_MVERT_SKIN;
+ case DT_TYPE_BWEIGHT_VERT:
+ return CD_FAKE_BWEIGHT;
+
+ case DT_TYPE_SHARP_EDGE:
+ return CD_FAKE_SHARP;
+ case DT_TYPE_SEAM:
+ return CD_FAKE_SEAM;
+ case DT_TYPE_CREASE:
+ return CD_FAKE_CREASE;
+ case DT_TYPE_BWEIGHT_EDGE:
+ return CD_FAKE_BWEIGHT;
+ case DT_TYPE_FREESTYLE_EDGE:
+ return CD_FREESTYLE_EDGE;
+
+ case DT_TYPE_UV:
+ return CD_FAKE_UV;
+ case DT_TYPE_SHARP_FACE:
+ return CD_FAKE_SHARP;
+ case DT_TYPE_FREESTYLE_FACE:
+ return CD_FREESTYLE_FACE;
+
+ case DT_TYPE_VCOL:
+ return CD_MLOOPCOL;
+
+ default:
+ BLI_assert(0);
+ }
+ return 0; /* Should never be reached! */
+}
+
+int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type)
+{
+ switch (dtdata_type) {
+ case DT_TYPE_MDEFORMVERT:
+ return DT_MULTILAYER_INDEX_MDEFORMVERT;
+ case DT_TYPE_SHAPEKEY:
+ return DT_MULTILAYER_INDEX_SHAPEKEY;
+ case DT_TYPE_UV:
+ return DT_MULTILAYER_INDEX_UV;
+ case DT_TYPE_VCOL:
+ return DT_MULTILAYER_INDEX_VCOL;
+ default:
+ return DT_MULTILAYER_INDEX_INVALID;
+ }
+}
+
+/* ********** */
+
+static MeshRemapIslandsCalc data_transfer_get_loop_islands_generator(const int cddata_type)
+{
+ switch (cddata_type) {
+ case CD_FAKE_UV:
+ return BKE_mesh_calc_islands_loop_poly_uv;
+ break;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+float data_transfer_interp_float_do(
+ const int mix_mode, const float val_dst, const float val_src, const float mix_factor)
+{
+ float val_ret;
+
+ if (((mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && (val_dst < mix_factor)) ||
+ (mix_mode == CDT_MIX_REPLACE_BELOW_THRESHOLD && (val_dst > mix_factor))))
+ {
+ return val_dst; /* Do not affect destination. */
+ }
+
+ switch (mix_mode) {
+ case CDT_MIX_REPLACE_ABOVE_THRESHOLD:
+ case CDT_MIX_REPLACE_BELOW_THRESHOLD:
+ return val_src;
+ case CDT_MIX_MIX:
+ val_ret = (val_dst + val_src) * 0.5f;
+ break;
+ case CDT_MIX_ADD:
+ val_ret = val_dst + val_src;
+ break;
+ case CDT_MIX_SUB:
+ val_ret = val_dst - val_src;
+ break;
+ case CDT_MIX_MUL:
+ val_ret = val_dst * val_src;
+ break;
+ case CDT_MIX_TRANSFER:
+ default:
+ val_ret = val_src;
+ break;
+ }
+ return interpf(val_ret, val_dst, mix_factor);
+}
+
+static void data_transfer_interp_char(const CustomDataTransferLayerMap *laymap, void *dest,
+ void **sources, const float *weights, const int count, const float mix_factor)
+{
+ char **data_src = (char **)sources;
+ char *data_dst = (char *)dest;
+
+ const int mix_mode = laymap->mix_mode;
+ float val_src = 0.0f;
+ const float val_dst = (float)(*data_dst) / 255.0f;
+
+ int i;
+
+ for (i = count; i--;) {
+ val_src += ((float)(*data_src[i]) / 255.0f) * weights[i];
+ }
+
+ val_src = data_transfer_interp_float_do(mix_mode, val_dst, val_src, mix_factor);
+
+ CLAMP(val_src, 0.0f, 1.0f);
+
+ *data_dst = (char)(val_src * 255.0f);
+}
+
+/* Helpers to match sources and destinations data layers (also handles 'conversions' in CD_FAKE cases). */
+
+void data_transfer_layersmapping_add_item(
+ ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights,
+ void *data_src, void *data_dst, const int data_src_n, const int data_dst_n,
+ const size_t elem_size, const size_t data_size, const size_t data_offset, const uint64_t data_flag,
+ cd_datatransfer_interp interp)
+{
+ CustomDataTransferLayerMap *item = MEM_mallocN(sizeof(*item), __func__);
+
+ BLI_assert(data_dst != NULL);
+
+ item->data_type = cddata_type;
+ item->mix_mode = mix_mode;
+ item->mix_factor = mix_factor;
+ item->mix_weights = mix_weights;
+
+ item->data_src = data_src;
+ item->data_dst = data_dst;
+ item->data_src_n = data_src_n;
+ item->data_dst_n = data_dst_n;
+ item->elem_size = elem_size;
+
+ item->data_size = data_size;
+ item->data_offset = data_offset;
+ item->data_flag = data_flag;
+
+ item->interp = interp;
+
+ BLI_addtail(r_map, item);
+}
+
+static void data_transfer_layersmapping_add_item_cd(
+ ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights,
+ void *data_src, void *data_dst)
+{
+ data_transfer_layersmapping_add_item(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst,
+ 0, 0, 0, 0, 0, 0, NULL);
+}
+
+/* Note: All those layer mapping handlers return false *only* if they were given invalid parameters.
+ * This means that even if they do nothing, they will return true if all given parameters were OK.
+ * Also, r_map may be NULL, in which case they will 'only' create/delete destination layers according
+ * to given parameters.
+ */
+
+static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(
+ ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights,
+ const int num_elem_dst, const bool use_create, const bool use_delete,
+ CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst,
+ const int tolayers, bool *use_layers_src, const int num_layers_src)
+{
+ void *data_src, *data_dst = NULL;
+ int idx_src = num_layers_src;
+ int idx_dst, tot_dst = CustomData_number_of_layers(cd_dst, cddata_type);
+ bool *data_dst_to_delete = NULL;
+
+ if (!use_layers_src) {
+ /* No source at all, we can only delete all dest if requested... */
+ if (use_delete) {
+ idx_dst = tot_dst;
+ while (idx_dst--) {
+ CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst);
+ }
+ }
+ return true;
+ }
+
+ switch (tolayers) {
+ case DT_LAYERS_INDEX_DST:
+ idx_dst = tot_dst;
+
+ /* Find last source actually used! */
+ while (idx_src-- && !use_layers_src[idx_src]);
+ idx_src++;
+
+ if (idx_dst < idx_src) {
+ if (!use_create) {
+ return true;
+ }
+ /* Create as much data layers as necessary! */
+ for (; idx_dst < idx_src; idx_dst++) {
+ CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst);
+ }
+ }
+ else if (use_delete && idx_dst > idx_src) {
+ while (idx_dst-- > idx_src) {
+ CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst);
+ }
+ }
+ if (r_map) {
+ while (idx_src--) {
+ if (!use_layers_src[idx_src]) {
+ continue;
+ }
+ data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src);
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ if (use_dupref_dst) {
+ data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_src, num_elem_dst);
+ }
+ else {
+ data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_src);
+ }
+ data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ data_src, data_dst);
+ }
+ }
+ break;
+ case DT_LAYERS_NAME_DST:
+ if (use_delete) {
+ if (tot_dst) {
+ data_dst_to_delete = MEM_mallocN(sizeof(*data_dst_to_delete) * (size_t)tot_dst, __func__);
+ memset(data_dst_to_delete, true, sizeof(*data_dst_to_delete) * (size_t)tot_dst);
+ }
+ }
+
+ while (idx_src--) {
+ const char *name;
+
+ if (!use_layers_src[idx_src]) {
+ continue;
+ }
+
+ name = CustomData_get_layer_name(cd_src, cddata_type, idx_src);
+ data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src);
+
+ if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) {
+ if (!use_create) {
+ if (r_map) {
+ BLI_freelistN(r_map);
+ }
+ return true;
+ }
+ CustomData_add_layer_named(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst, name);
+ idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name);
+ }
+ else if (data_dst_to_delete) {
+ data_dst_to_delete[idx_dst] = false;
+ }
+ if (r_map) {
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ if (use_dupref_dst) {
+ data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst);
+ }
+ else {
+ data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst);
+ }
+ data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ data_src, data_dst);
+ }
+ }
+
+ if (data_dst_to_delete) {
+ /* Note: This won't affect newly created layers, if any, since tot_dst has not been updated!
+ * Also, looping backward ensures us we do not suffer from index shifting when deleting a layer.
+ */
+ for (idx_dst = tot_dst; idx_dst--;) {
+ if (data_dst_to_delete[idx_dst]) {
+ CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst);
+ }
+ }
+
+ MEM_freeN(data_dst_to_delete);
+ }
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+static bool data_transfer_layersmapping_cdlayers(
+ ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights,
+ const int num_elem_dst, const bool use_create, const bool use_delete,
+ CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst,
+ const int fromlayers, const int tolayers)
+{
+ int idx_src, idx_dst;
+ void *data_src, *data_dst = NULL;
+
+ if (CustomData_layertype_is_singleton(cddata_type)) {
+ if (!(data_src = CustomData_get_layer(cd_src, cddata_type))) {
+ if (use_delete) {
+ CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, 0);
+ }
+ return true;
+ }
+
+ data_dst = CustomData_get_layer(cd_dst, cddata_type);
+ if (!data_dst) {
+ if (!use_create) {
+ return true;
+ }
+ data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst);
+ }
+ else if (use_dupref_dst && r_map) {
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ data_dst = CustomData_duplicate_referenced_layer(cd_dst, cddata_type, num_elem_dst);
+ }
+
+ if (r_map) {
+ data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ data_src, data_dst);
+ }
+ }
+ else if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) {
+ /* Note: use_delete has not much meaning in this case, ignored. */
+
+ if (fromlayers >= 0) { /* Real-layer index */
+ idx_src = fromlayers;
+ }
+ else {
+ if ((idx_src = CustomData_get_active_layer(cd_src, cddata_type)) == -1) {
+ return true;
+ }
+ }
+ data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src);
+ if (!data_src) {
+ return true;
+ }
+
+ if (tolayers >= 0) { /* Real-layer index */
+ idx_dst = tolayers;
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ if (use_dupref_dst && r_map) {
+ data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst);
+ }
+ else {
+ data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst);
+ }
+ }
+ else if (tolayers == DT_LAYERS_ACTIVE_DST) {
+ if ((idx_dst = CustomData_get_active_layer(cd_dst, cddata_type)) == -1) {
+ if (!use_create) {
+ return true;
+ }
+ data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst);
+ }
+ else {
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ if (use_dupref_dst && r_map) {
+ data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst);
+ }
+ else {
+ data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst);
+ }
+ }
+ }
+ else if (tolayers == DT_LAYERS_INDEX_DST) {
+ int num = CustomData_number_of_layers(cd_dst, cddata_type);
+ idx_dst = idx_src;
+ if (num <= idx_dst) {
+ if (!use_create) {
+ return true;
+ }
+ /* Create as much data layers as necessary! */
+ for (; num <= idx_dst; num++) {
+ CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst);
+ }
+ }
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ if (use_dupref_dst && r_map) {
+ data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst);
+ }
+ else {
+ data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst);
+ }
+ }
+ else if (tolayers == DT_LAYERS_NAME_DST) {
+ const char *name = CustomData_get_layer_name(cd_src, cddata_type, idx_src);
+ if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) {
+ if (!use_create) {
+ return true;
+ }
+ CustomData_add_layer_named(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst, name);
+ idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name);
+ }
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ if (use_dupref_dst && r_map) {
+ data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst);
+ }
+ else {
+ data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst);
+ }
+ }
+ else {
+ return false;
+ }
+
+ if (!data_dst) {
+ return false;
+ }
+
+ if (r_map) {
+ data_transfer_layersmapping_add_item_cd(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst);
+ }
+ }
+ else if (fromlayers == DT_LAYERS_ALL_SRC) {
+ int num_src = CustomData_number_of_layers(cd_src, cddata_type);
+ bool *use_layers_src = num_src ? MEM_mallocN(sizeof(*use_layers_src) * (size_t)num_src, __func__) : NULL;
+ bool ret;
+
+ if (use_layers_src) {
+ memset(use_layers_src, true, sizeof(*use_layers_src) * num_src);
+ }
+
+ ret = data_transfer_layersmapping_cdlayers_multisrc_to_dst(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ num_elem_dst, use_create, use_delete, cd_src, cd_dst, use_dupref_dst,
+ tolayers, use_layers_src, num_src);
+
+ if (use_layers_src) {
+ MEM_freeN(use_layers_src);
+ }
+ return ret;
+ }
+ else {
+ return false;
+ }
+
+ return true;
+}
+
+static bool data_transfer_layersmapping_generate(
+ ListBase *r_map, Object *ob_src, Object *ob_dst, DerivedMesh *dm_src, DerivedMesh *dm_dst, Mesh *me_dst,
+ const int elem_type, int cddata_type, int mix_mode, float mix_factor, const float *mix_weights,
+ const int num_elem_dst, const bool use_create, const bool use_delete, const int fromlayers, const int tolayers)
+{
+ CustomData *cd_src, *cd_dst;
+
+ if (elem_type == ME_VERT) {
+ if (!(cddata_type & CD_FAKE)) {
+ cd_src = dm_src->getVertDataLayout(dm_src);
+ cd_dst = dm_dst ? dm_dst->getVertDataLayout(dm_dst) : &me_dst->vdata;
+
+ if (!data_transfer_layersmapping_cdlayers(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ num_elem_dst, use_create, use_delete,
+ cd_src, cd_dst, dm_dst != NULL,
+ fromlayers, tolayers))
+ {
+ /* We handle specific source selection cases here. */
+ return false;
+ }
+ return true;
+ }
+ else if (cddata_type == CD_FAKE_BWEIGHT) {
+ const size_t elem_size = sizeof(*((MVert *)NULL));
+ const size_t data_size = sizeof(((MVert *)NULL)->bweight);
+ const size_t data_offset = offsetof(MVert, bweight);
+ const uint64_t data_flag = 0;
+
+ if (!(dm_src->cd_flag & ME_CDFLAG_VERT_BWEIGHT)) {
+ if (use_delete && !dm_dst) {
+ me_dst->cd_flag &= ~ME_CDFLAG_VERT_BWEIGHT;
+ }
+ return true;
+ }
+ if (dm_dst) {
+ dm_dst->cd_flag |= ME_CDFLAG_VERT_BWEIGHT;
+ }
+ else {
+ me_dst->cd_flag |= ME_CDFLAG_VERT_BWEIGHT;
+ }
+ if (r_map) {
+ data_transfer_layersmapping_add_item(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ dm_src->getVertArray(dm_src),
+ dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert,
+ dm_src->getNumVerts(dm_src),
+ dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert,
+ elem_size, data_size, data_offset, data_flag,
+ data_transfer_interp_char);
+ }
+ return true;
+ }
+ else if (cddata_type == CD_FAKE_MDEFORMVERT) {
+ cd_src = dm_src->getVertDataLayout(dm_src);
+ cd_dst = dm_dst ? dm_dst->getVertDataLayout(dm_dst) : &me_dst->vdata;
+
+ return data_transfer_layersmapping_vgroups(r_map, mix_mode, mix_factor, mix_weights,
+ num_elem_dst, use_create, use_delete,
+ ob_src, ob_dst, cd_src, cd_dst, dm_dst != NULL,
+ fromlayers, tolayers);
+ }
+ else if (cddata_type == CD_FAKE_SHAPEKEY) {
+ /* TODO: leaving shapekeys asside for now, quite specific case, since we can't access them from MVert :/ */
+ return false;
+ }
+ }
+ else if (elem_type == ME_EDGE) {
+ if (!(cddata_type & CD_FAKE)) { /* Unused for edges, currently... */
+ cd_src = dm_src->getEdgeDataLayout(dm_src);
+ cd_dst = dm_dst ? dm_dst->getEdgeDataLayout(dm_dst) : &me_dst->edata;
+
+ if (!data_transfer_layersmapping_cdlayers(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ num_elem_dst, use_create, use_delete,
+ cd_src, cd_dst, dm_dst != NULL,
+ fromlayers, tolayers))
+ {
+ /* We handle specific source selection cases here. */
+ return false;
+ }
+ return true;
+ }
+ else if (cddata_type == CD_FAKE_CREASE) {
+ const size_t elem_size = sizeof(*((MEdge *)NULL));
+ const size_t data_size = sizeof(((MEdge *)NULL)->crease);
+ const size_t data_offset = offsetof(MEdge, crease);
+ const uint64_t data_flag = 0;
+
+ if (!(dm_src->cd_flag & ME_CDFLAG_EDGE_CREASE)) {
+ if (use_delete && !dm_dst) {
+ me_dst->cd_flag &= ~ME_CDFLAG_EDGE_CREASE;
+ }
+ return true;
+ }
+ if (dm_dst) {
+ dm_dst->cd_flag |= ME_CDFLAG_EDGE_CREASE;
+ }
+ else {
+ me_dst->cd_flag |= ME_CDFLAG_EDGE_CREASE;
+ }
+ if (r_map) {
+ data_transfer_layersmapping_add_item(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ dm_src->getEdgeArray(dm_src),
+ dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge,
+ dm_src->getNumEdges(dm_src),
+ dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge,
+ elem_size, data_size, data_offset, data_flag,
+ data_transfer_interp_char);
+ }
+ return true;
+ }
+ else if (cddata_type == CD_FAKE_BWEIGHT) {
+ const size_t elem_size = sizeof(*((MEdge *)NULL));
+ const size_t data_size = sizeof(((MEdge *)NULL)->bweight);
+ const size_t data_offset = offsetof(MEdge, bweight);
+ const uint64_t data_flag = 0;
+
+ if (!(dm_src->cd_flag & ME_CDFLAG_EDGE_BWEIGHT)) {
+ if (use_delete && !dm_dst) {
+ me_dst->cd_flag &= ~ME_CDFLAG_EDGE_BWEIGHT;
+ }
+ return true;
+ }
+ if (dm_dst) {
+ dm_dst->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT;
+ }
+ else {
+ me_dst->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT;
+ }
+ if (r_map) {
+ data_transfer_layersmapping_add_item(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ dm_src->getEdgeArray(dm_src),
+ dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge,
+ dm_src->getNumEdges(dm_src),
+ dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge,
+ elem_size, data_size, data_offset, data_flag,
+ data_transfer_interp_char);
+ }
+ return true;
+ }
+ else if (r_map && ELEM(cddata_type, CD_FAKE_SHARP, CD_FAKE_SEAM)) {
+ const size_t elem_size = sizeof(*((MEdge *)NULL));
+ const size_t data_size = sizeof(((MEdge *)NULL)->flag);
+ const size_t data_offset = offsetof(MEdge, flag);
+ const uint64_t data_flag = (cddata_type == CD_FAKE_SHARP) ? ME_SHARP : ME_SEAM;
+
+ data_transfer_layersmapping_add_item(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ dm_src->getEdgeArray(dm_src),
+ dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge,
+ dm_src->getNumEdges(dm_src),
+ dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge,
+ elem_size, data_size, data_offset, data_flag, NULL);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else if (elem_type == ME_LOOP) {
+ if (cddata_type == CD_FAKE_UV) {
+ cddata_type = CD_MLOOPUV;
+ }
+
+ if (!(cddata_type & CD_FAKE)) {
+ cd_src = dm_src->getLoopDataLayout(dm_src);
+ cd_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata;
+
+ if (!data_transfer_layersmapping_cdlayers(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ num_elem_dst, use_create, use_delete, cd_src, cd_dst, dm_dst != NULL,
+ fromlayers, tolayers))
+ {
+ /* We handle specific source selection cases here. */
+ return false;
+ }
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else if (elem_type == ME_POLY) {
+ if (cddata_type == CD_FAKE_UV) {
+ cddata_type = CD_MTEXPOLY;
+ }
+
+ if (!(cddata_type & CD_FAKE)) {
+ cd_src = dm_src->getPolyDataLayout(dm_src);
+ cd_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
+
+ if (!data_transfer_layersmapping_cdlayers(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ num_elem_dst, use_create, use_delete, cd_src, cd_dst, dm_dst != NULL,
+ fromlayers, tolayers))
+ {
+ /* We handle specific source selection cases here. */
+ return false;
+ }
+ return true;
+ }
+ else if (r_map && cddata_type == CD_FAKE_SHARP) {
+ const size_t elem_size = sizeof(*((MPoly *)NULL));
+ const size_t data_size = sizeof(((MPoly *)NULL)->flag);
+ const size_t data_offset = offsetof(MPoly, flag);
+ const uint64_t data_flag = ME_SMOOTH;
+
+ data_transfer_layersmapping_add_item(
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights,
+ dm_src->getPolyArray(dm_src),
+ dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly,
+ dm_src->getNumPolys(dm_src),
+ dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly,
+ elem_size, data_size, data_offset, data_flag, NULL);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Transfer data *layout* of selected types from source to destination object.
+ * By default, it only creates new data layers if needed on \a ob_dst.
+ * If \a use_delete is true, it will also delete data layers on \a ob_dst that do not match those from \a ob_src,
+ * to get (as much as possible) exact copy of source data layout.
+ */
+void BKE_object_data_transfer_layout(
+ Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, const bool use_delete,
+ const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX])
+{
+ DerivedMesh *dm_src;
+ Mesh *me_dst;
+ int i;
+
+ const bool use_create = true; /* We always create needed layers here. */
+
+ CustomDataMask dm_src_mask = CD_MASK_BAREMESH;
+
+ BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH));
+
+ me_dst = ob_dst->data;
+
+ /* Get source DM.*/
+ dm_src_mask |= BKE_object_data_transfer_dttypes_to_cdmask(data_types);
+ dm_src = mesh_get_derived_final(scene, ob_src, dm_src_mask);
+ if (!dm_src) {
+ return;
+ }
+
+ /* Check all possible data types. */
+ for (i = 0; i < DT_TYPE_MAX; i++) {
+ const int dtdata_type = 1 << i;
+ int cddata_type;
+ int fromlayers, tolayers, fromto_idx;
+
+ if (!(data_types & dtdata_type)) {
+ continue;
+ }
+
+ cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type);
+
+ fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type);
+ if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
+ fromlayers = fromlayers_select[fromto_idx];
+ tolayers = tolayers_select[fromto_idx];
+ }
+ else {
+ fromlayers = tolayers = 0;
+ }
+
+ if (DT_DATATYPE_IS_VERT(dtdata_type)) {
+ const int num_elem_dst = me_dst->totvert;
+
+ data_transfer_layersmapping_generate(
+ NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_VERT, cddata_type, 0, 0.0f, NULL,
+ num_elem_dst, use_create, use_delete, fromlayers, tolayers);
+ }
+ if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
+ const int num_elem_dst = me_dst->totedge;
+
+ data_transfer_layersmapping_generate(
+ NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_EDGE, cddata_type, 0, 0.0f, NULL,
+ num_elem_dst, use_create, use_delete, fromlayers, tolayers);
+ }
+ if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
+ const int num_elem_dst = me_dst->totloop;
+
+ data_transfer_layersmapping_generate(
+ NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_LOOP, cddata_type, 0, 0.0f, NULL,
+ num_elem_dst, use_create, use_delete, fromlayers, tolayers);
+ }
+ if (DT_DATATYPE_IS_POLY(dtdata_type)) {
+ const int num_elem_dst = me_dst->totpoly;
+
+ data_transfer_layersmapping_generate(
+ NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_POLY, cddata_type, 0, 0.0f, NULL,
+ num_elem_dst, use_create, use_delete, fromlayers, tolayers);
+ }
+ }
+}
+
+bool BKE_object_data_transfer_dm(
+ Scene *scene, Object *ob_src, Object *ob_dst, DerivedMesh *dm_dst, const int data_types, bool use_create,
+ const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
+ SpaceTransform *space_transform, const float max_distance, const float ray_radius,
+ const float islands_handling_precision,
+ const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
+ const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
+ ReportList *reports)
+{
+#define VDATA 0
+#define EDATA 1
+#define LDATA 2
+#define PDATA 3
+#define DATAMAX 4
+
+ DerivedMesh *dm_src;
+ Mesh *me_dst;
+ bool dirty_nors_dst = true; /* Assumed always true if not using a dm as destination. */
+ int i;
+
+ MDeformVert *mdef = NULL;
+ int vg_idx = -1;
+ float *weights[DATAMAX] = {NULL};
+
+ MeshPairRemap geom_map[DATAMAX] = {{0}};
+ bool geom_map_init[DATAMAX] = {0};
+ ListBase lay_map = {0};
+ bool changed = false;
+
+ const bool use_delete = false; /* We never delete data layers from destination here. */
+
+ CustomDataMask dm_src_mask = CD_MASK_BAREMESH;
+
+ BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH));
+
+ me_dst = ob_dst->data;
+ if (dm_dst) {
+ dirty_nors_dst = (dm_dst->dirty & DM_DIRTY_NORMALS) != 0;
+ use_create = false; /* Never create needed custom layers on DM (modifier case). */
+ }
+
+ if (vgroup_name) {
+ if (dm_dst) {
+ mdef = dm_dst->getVertDataArray(dm_dst, CD_MDEFORMVERT);
+ }
+ else {
+ mdef = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT);
+ }
+ if (mdef) {
+ vg_idx = defgroup_name_index(ob_dst, vgroup_name);
+ }
+ }
+
+ /* Get source DM.*/
+ dm_src_mask |= BKE_object_data_transfer_dttypes_to_cdmask(data_types);
+ /* XXX Hack! In case this is being evaluated from dm stack, we cannot compute final dm,
+ * can lead to infinite recursion in case of dependency cycles of DataTransfer modifiers...
+ * Issue is, this means we cannot be sure to have requested cd layers in source.
+ */
+ dm_src = dm_dst ? ob_src->derivedFinal : mesh_get_derived_final(scene, ob_src, dm_src_mask);
+ if (!dm_src) {
+ return changed;
+ }
+
+ /* Check all possible data types.
+ * Note item mappings and dest mix weights are cached. */
+ for (i = 0; i < DT_TYPE_MAX; i++) {
+ const int dtdata_type = 1 << i;
+ int cddata_type;
+ int fromlayers, tolayers, fromto_idx;
+
+ if (!(data_types & dtdata_type)) {
+ continue;
+ }
+
+ cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type);
+
+ fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type);
+ if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
+ fromlayers = fromlayers_select[fromto_idx];
+ tolayers = tolayers_select[fromto_idx];
+ }
+ else {
+ fromlayers = tolayers = 0;
+ }
+
+ if (DT_DATATYPE_IS_VERT(dtdata_type)) {
+ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+ const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+
+ if (!geom_map_init[VDATA]) {
+ if ((map_vert_mode == MREMAP_MODE_TOPOLOGY) && (num_verts_dst != dm_src->getNumVerts(dm_src))) {
+ BKE_report(reports, RPT_ERROR,
+ "Source and destination meshes do not have the same amount of vertices, "
+ "'Topology' mapping cannot be used in this case");
+ return changed;
+ }
+ BKE_mesh_remap_calc_verts_from_dm(
+ map_vert_mode, space_transform, max_distance, ray_radius,
+ verts_dst, num_verts_dst, dirty_nors_dst, dm_src, &geom_map[VDATA]);
+ geom_map_init[VDATA] = true;
+ }
+
+ if (mdef && vg_idx != -1 && !weights[VDATA]) {
+ weights[VDATA] = MEM_mallocN(sizeof(*(weights[VDATA])) * (size_t)num_verts_dst, __func__);
+ BKE_defvert_extract_vgroup_to_vertweights(mdef, vg_idx, num_verts_dst, weights[VDATA], invert_vgroup);
+ }
+
+ if (data_transfer_layersmapping_generate(
+ &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_VERT,
+ cddata_type, mix_mode, mix_factor, weights[VDATA],
+ num_verts_dst, use_create, use_delete, fromlayers, tolayers))
+ {
+ CustomDataTransferLayerMap *lay_mapit;
+
+ changed = (lay_map.first != NULL);
+
+ for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) {
+ CustomData_data_transfer(&geom_map[VDATA], lay_mapit);
+ }
+
+ BLI_freelistN(&lay_map);
+ }
+ }
+ if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
+ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+ const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+ MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
+ const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;
+
+ if (!geom_map_init[EDATA]) {
+ if ((map_edge_mode == MREMAP_MODE_TOPOLOGY) && (num_edges_dst != dm_src->getNumEdges(dm_src))) {
+ BKE_report(reports, RPT_ERROR,
+ "Source and destination meshes do not have the same amount of edges, "
+ "'Topology' mapping cannot be used in this case");
+ return changed;
+ }
+ BKE_mesh_remap_calc_edges_from_dm(
+ map_edge_mode, space_transform, max_distance, ray_radius,
+ verts_dst, num_verts_dst, edges_dst, num_edges_dst, dirty_nors_dst,
+ dm_src, &geom_map[EDATA]);
+ geom_map_init[EDATA] = true;
+ }
+
+ if (mdef && vg_idx != -1 && !weights[EDATA]) {
+ weights[EDATA] = MEM_mallocN(sizeof(*weights[EDATA]) * (size_t)num_edges_dst, __func__);
+ BKE_defvert_extract_vgroup_to_edgeweights(
+ mdef, vg_idx, num_verts_dst, edges_dst, num_edges_dst,
+ weights[EDATA], invert_vgroup);
+ }
+
+ if (data_transfer_layersmapping_generate(
+ &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_EDGE,
+ cddata_type, mix_mode, mix_factor, weights[EDATA],
+ num_edges_dst, use_create, use_delete, fromlayers, tolayers))
+ {
+ CustomDataTransferLayerMap *lay_mapit;
+
+ changed = (lay_map.first != NULL);
+
+ for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) {
+ CustomData_data_transfer(&geom_map[EDATA], lay_mapit);
+ }
+
+ BLI_freelistN(&lay_map);
+ }
+ }
+ if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
+ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+ const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+ MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
+ const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;
+ MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
+ const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
+ MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
+ const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
+ CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
+ CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata;
+
+ MeshRemapIslandsCalc island_callback = data_transfer_get_loop_islands_generator(cddata_type);
+
+ if (!geom_map_init[LDATA]) {
+ if ((map_loop_mode == MREMAP_MODE_TOPOLOGY) && (num_loops_dst != dm_src->getNumLoops(dm_src))) {
+ BKE_report(reports, RPT_ERROR,
+ "Source and destination meshes do not have the same amount of face corners, "
+ "'Topology' mapping cannot be used in this case");
+ return changed;
+ }
+ BKE_mesh_remap_calc_loops_from_dm(
+ map_loop_mode, space_transform, max_distance, ray_radius,
+ verts_dst, num_verts_dst, edges_dst, num_edges_dst,
+ loops_dst, num_loops_dst, polys_dst, num_polys_dst,
+ ldata_dst, pdata_dst, me_dst->smoothresh, dirty_nors_dst,
+ dm_src, island_callback, islands_handling_precision, &geom_map[LDATA]);
+ geom_map_init[LDATA] = true;
+ }
+
+ if (mdef && vg_idx != -1 && !weights[LDATA]) {
+ weights[LDATA] = MEM_mallocN(sizeof(*weights[LDATA]) * (size_t)num_loops_dst, __func__);
+ BKE_defvert_extract_vgroup_to_loopweights(
+ mdef, vg_idx, num_verts_dst, loops_dst, num_loops_dst,
+ weights[LDATA], invert_vgroup);
+ }
+
+ if (data_transfer_layersmapping_generate(
+ &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_LOOP,
+ cddata_type, mix_mode, mix_factor, weights[LDATA],
+ num_loops_dst, use_create, use_delete, fromlayers, tolayers))
+ {
+ CustomDataTransferLayerMap *lay_mapit;
+
+ changed = (lay_map.first != NULL);
+
+ for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) {
+ CustomData_data_transfer(&geom_map[LDATA], lay_mapit);
+ }
+
+ BLI_freelistN(&lay_map);
+ }
+ }
+ if (DT_DATATYPE_IS_POLY(dtdata_type)) {
+ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+ const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+ MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
+ const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
+ MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
+ const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
+ CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
+
+ if (!geom_map_init[PDATA]) {
+ if ((map_poly_mode == MREMAP_MODE_TOPOLOGY) && (num_polys_dst != dm_src->getNumPolys(dm_src))) {
+ BKE_report(reports, RPT_ERROR,
+ "Source and destination meshes do not have the same amount of faces, "
+ "'Topology' mapping cannot be used in this case");
+ return changed;
+ }
+ BKE_mesh_remap_calc_polys_from_dm(
+ map_poly_mode, space_transform, max_distance, ray_radius,
+ verts_dst, num_verts_dst, loops_dst, num_loops_dst,
+ polys_dst, num_polys_dst, pdata_dst, dirty_nors_dst,
+ dm_src, &geom_map[PDATA]);
+ geom_map_init[PDATA] = true;
+ }
+
+ if (mdef && vg_idx != -1 && !weights[PDATA]) {
+ weights[PDATA] = MEM_mallocN(sizeof(*weights[PDATA]) * (size_t)num_polys_dst, __func__);
+ BKE_defvert_extract_vgroup_to_polyweights(
+ mdef, vg_idx, num_verts_dst, loops_dst, num_loops_dst,
+ polys_dst, num_polys_dst, weights[PDATA], invert_vgroup);
+ }
+
+ if (data_transfer_layersmapping_generate(
+ &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_POLY,
+ cddata_type, mix_mode, mix_factor, weights[PDATA],
+ num_polys_dst, use_create, use_delete, fromlayers, tolayers))
+ {
+ CustomDataTransferLayerMap *lay_mapit;
+
+ changed = (lay_map.first != NULL);
+
+ for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) {
+ CustomData_data_transfer(&geom_map[PDATA], lay_mapit);
+ }
+
+ BLI_freelistN(&lay_map);
+ }
+ }
+ }
+
+ for (i = 0; i < DATAMAX; i++) {
+ BKE_mesh_remap_free(&geom_map[i]);
+ MEM_SAFE_FREE(weights[i]);
+ }
+
+ return changed;
+
+#undef VDATA
+#undef EDATA
+#undef LDATA
+#undef PDATA
+#undef DATAMAX
+}
+
+bool BKE_object_data_transfer_mesh(
+ Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, const bool use_create,
+ const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
+ SpaceTransform *space_transform, const float max_distance, const float ray_radius,
+ const float islands_handling_precision,
+ const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
+ const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
+ ReportList *reports)
+{
+ return BKE_object_data_transfer_dm(
+ scene, ob_src, ob_dst, NULL, data_types, use_create,
+ map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode, space_transform,
+ max_distance, ray_radius, islands_handling_precision, fromlayers_select, tolayers_select,
+ mix_mode, mix_factor, vgroup_name, invert_vgroup, reports);
+}
diff --git a/source/blender/blenkernel/intern/data_transfer_intern.h b/source/blender/blenkernel/intern/data_transfer_intern.h
new file mode 100644
index 00000000000..913325afce0
--- /dev/null
+++ b/source/blender/blenkernel/intern/data_transfer_intern.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/data_transfer_intern.h
+ * \ingroup bke
+ */
+
+#ifndef __DATA_TRANSFER_INTERN_H__
+#define __DATA_TRANSFER_INTERN_H__
+
+struct CustomDataTransferLayerMap;
+struct CustomData;
+struct ListBase;
+
+float data_transfer_interp_float_do(
+ const int mix_mode, const float val_dst, const float val_src, const float mix_factor);
+
+/* Copied from BKE_customdata.h :( */
+typedef void (*cd_datatransfer_interp)(const struct CustomDataTransferLayerMap *laymap, void *dest,
+ void **sources, const float *weights, const int count, const float mix_factor);
+
+void data_transfer_layersmapping_add_item(
+ struct ListBase *r_map, const int data_type, const int mix_mode,
+ const float mix_factor, const float *mix_weights,
+ void *data_src, void *data_dst, const int data_src_n, const int data_dst_n,
+ const size_t elem_size, const size_t data_size, const size_t data_offset, const uint64_t data_flag,
+ cd_datatransfer_interp interp);
+
+/* Type-specific. */
+
+bool data_transfer_layersmapping_vgroups(
+ struct ListBase *r_map, const int mix_mode, const float mix_factor, const float *mix_weights,
+ const int num_elem_dst, const bool use_create, const bool use_delete,
+ struct Object *ob_src, struct Object *ob_dst, struct CustomData *cd_src, struct CustomData *cd_dst,
+ const bool use_dupref_dst, const int fromlayers, const int tolayers);
+
+#endif /* __DATA_TRANSFER_INTERN_H__ */
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index d3148dbc8e9..80db62801d6 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -39,7 +39,9 @@
#include "MEM_guardedalloc.h"
#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
@@ -49,7 +51,14 @@
#include "BLF_translation.h"
+#include "BKE_customdata.h"
+#include "BKE_data_transfer.h"
#include "BKE_deform.h" /* own include */
+#include "BKE_mesh_mapping.h"
+#include "BKE_object_deform.h"
+
+#include "data_transfer_intern.h"
+
bDeformGroup *BKE_defgroup_new(Object *ob, const char *name)
{
@@ -960,3 +969,385 @@ void BKE_defvert_array_free(MDeformVert *dvert, int totvert)
MEM_freeN(dvert);
}
+
+void BKE_defvert_extract_vgroup_to_vertweights(
+ MDeformVert *dvert, const int defgroup, const int num_verts, float *r_weights, const bool invert_vgroup)
+{
+ if (dvert && defgroup != -1) {
+ int i = num_verts;
+
+ while (i--) {
+ const float w = defvert_find_weight(&dvert[i], defgroup);
+ r_weights[i] = invert_vgroup ? (1.0f - w) : w;
+ }
+ }
+ else {
+ fill_vn_fl(r_weights, invert_vgroup ? 1.0f : 0.0f, num_verts);
+ }
+}
+
+/* The following three make basic interpolation, using temp vert_weights array to avoid looking up same weight
+ * several times. */
+
+void BKE_defvert_extract_vgroup_to_edgeweights(
+ MDeformVert *dvert, const int defgroup, const int num_verts, MEdge *edges, const int num_edges,
+ float *r_weights, const bool invert_vgroup)
+{
+ if (dvert && defgroup != -1) {
+ int i = num_edges;
+ float *tmp_weights = MEM_mallocN(sizeof(*tmp_weights) * (size_t)num_verts, __func__);
+
+ BKE_defvert_extract_vgroup_to_vertweights(dvert, defgroup, num_verts, tmp_weights, invert_vgroup);
+
+ while (i--) {
+ MEdge *me = &edges[i];
+
+ r_weights[i] = (tmp_weights[me->v1] + tmp_weights[me->v2]) * 0.5f;
+ }
+
+ MEM_freeN(tmp_weights);
+ }
+ else {
+ fill_vn_fl(r_weights, 0.0f, num_edges);
+ }
+}
+
+void BKE_defvert_extract_vgroup_to_loopweights(
+ MDeformVert *dvert, const int defgroup, const int num_verts, MLoop *loops, const int num_loops,
+ float *r_weights, const bool invert_vgroup)
+{
+ if (dvert && defgroup != -1) {
+ int i = num_loops;
+ float *tmp_weights = MEM_mallocN(sizeof(*tmp_weights) * (size_t)num_verts, __func__);
+
+ BKE_defvert_extract_vgroup_to_vertweights(dvert, defgroup, num_verts, tmp_weights, invert_vgroup);
+
+ while (i--) {
+ MLoop *ml = &loops[i];
+
+ r_weights[i] = tmp_weights[ml->v];
+ }
+
+ MEM_freeN(tmp_weights);
+ }
+ else {
+ fill_vn_fl(r_weights, 0.0f, num_loops);
+ }
+}
+
+void BKE_defvert_extract_vgroup_to_polyweights(
+ MDeformVert *dvert, const int defgroup, const int num_verts, MLoop *loops, const int UNUSED(num_loops),
+ MPoly *polys, const int num_polys, float *r_weights, const bool invert_vgroup)
+{
+ if (dvert && defgroup != -1) {
+ int i = num_polys;
+ float *tmp_weights = MEM_mallocN(sizeof(*tmp_weights) * (size_t)num_verts, __func__);
+
+ BKE_defvert_extract_vgroup_to_vertweights(dvert, defgroup, num_verts, tmp_weights, invert_vgroup);
+
+ while (i--) {
+ MPoly *mp = &polys[i];
+ MLoop *ml = &loops[mp->loopstart];
+ int j = mp->totloop;
+ float w = 0.0f;
+
+ for (; j--; ml++) {
+ w += tmp_weights[ml->v];
+ }
+ r_weights[i] = w / (float)mp->totloop;
+ }
+
+ MEM_freeN(tmp_weights);
+ }
+ else {
+ fill_vn_fl(r_weights, 0.0f, num_polys);
+ }
+}
+
+/*********** Data Transfer **********/
+
+static void vgroups_datatransfer_interp(const CustomDataTransferLayerMap *laymap, void *dest,
+ void **sources, const float *weights, const int count, const float mix_factor)
+{
+ MDeformVert **data_src = (MDeformVert **)sources;
+ MDeformVert *data_dst = (MDeformVert *)dest;
+ const int idx_src = laymap->data_src_n;
+ const int idx_dst = laymap->data_dst_n;
+
+ const int mix_mode = laymap->mix_mode;
+
+ int i, j;
+
+ MDeformWeight *dw_src;
+ MDeformWeight *dw_dst = defvert_find_index(data_dst, idx_dst);
+ float weight_src = 0.0f, weight_dst = 0.0f;
+
+ if (sources) {
+ for (i = count; i--;) {
+ for (j = data_src[i]->totweight; j--;) {
+ if ((dw_src = &data_src[i]->dw[j])->def_nr == idx_src) {
+ weight_src += dw_src->weight * weights[i];
+ break;
+ }
+ }
+ }
+ }
+
+ if (dw_dst) {
+ weight_dst = dw_dst->weight;
+ }
+ else if (mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD) {
+ return; /* Do not affect destination. */
+ }
+
+ weight_src = data_transfer_interp_float_do(mix_mode, weight_dst, weight_src, mix_factor);
+
+ CLAMP(weight_src, 0.0f, 1.0f);
+
+ if (!dw_dst) {
+ defvert_add_index_notest(data_dst, idx_dst, weight_src);
+ }
+ else {
+ dw_dst->weight = weight_src;
+ }
+}
+
+static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(
+ ListBase *r_map, const int mix_mode, const float mix_factor, const float *mix_weights,
+ const int num_elem_dst, const bool use_create, const bool use_delete,
+ Object *ob_src, Object *ob_dst, MDeformVert *data_src, MDeformVert *data_dst,
+ CustomData *UNUSED(cd_src), CustomData *cd_dst, const bool UNUSED(use_dupref_dst),
+ const int tolayers, bool *use_layers_src, const int num_layers_src)
+{
+ int idx_src;
+ int idx_dst;
+ int tot_dst = BLI_listbase_count(&ob_dst->defbase);
+
+ const size_t elem_size = sizeof(*((MDeformVert *)NULL));
+
+ switch (tolayers) {
+ case DT_LAYERS_INDEX_DST:
+ idx_dst = tot_dst;
+
+ /* Find last source actually used! */
+ idx_src = num_layers_src;
+ while (idx_src-- && !use_layers_src[idx_src]);
+ idx_src++;
+
+ if (idx_dst < idx_src) {
+ if (!use_create) {
+ return false;
+ }
+ /* Create as much vgroups as necessary! */
+ for (; idx_dst < idx_src; idx_dst++) {
+ BKE_object_defgroup_add(ob_dst);
+ }
+ }
+ else if (use_delete && idx_dst > idx_src) {
+ while (idx_dst-- > idx_src) {
+ BKE_object_defgroup_remove(ob_dst, ob_dst->defbase.last);
+ }
+ }
+ if (r_map) {
+ /* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest!
+ * Again, use_create is not relevant in this case */
+ if (!data_dst) {
+ data_dst = CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_CALLOC, NULL, num_elem_dst);
+ }
+
+ while (idx_src--) {
+ if (!use_layers_src[idx_src]) {
+ continue;
+ }
+ data_transfer_layersmapping_add_item(r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights,
+ data_src, data_dst, idx_src, idx_src,
+ elem_size, 0, 0, 0, vgroups_datatransfer_interp);
+ }
+ }
+ break;
+ case DT_LAYERS_NAME_DST:
+ {
+ bDeformGroup *dg_src, *dg_dst;
+
+ if (use_delete) {
+ /* Remove all unused dst vgroups first, simpler in this case. */
+ for (dg_dst = ob_dst->defbase.first; dg_dst;) {
+ bDeformGroup *dg_dst_next = dg_dst->next;
+
+ if (defgroup_name_index(ob_src, dg_dst->name) == -1) {
+ BKE_object_defgroup_remove(ob_dst, dg_dst);
+ }
+ dg_dst = dg_dst_next;
+ }
+ }
+
+ for (idx_src = 0, dg_src = ob_src->defbase.first;
+ idx_src < num_layers_src;
+ idx_src++, dg_src = dg_src->next)
+ {
+ if (!use_layers_src[idx_src]) {
+ continue;
+ }
+
+ if ((idx_dst = defgroup_name_index(ob_dst, dg_src->name)) == -1) {
+ if (!use_create) {
+ if (r_map) {
+ BLI_freelistN(r_map);
+ }
+ return false;
+ }
+ BKE_object_defgroup_add_name(ob_dst, dg_src->name);
+ idx_dst = ob_dst->actdef - 1;
+ }
+ if (r_map) {
+ /* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest!
+ * use_create is not relevant in this case */
+ if (!data_dst) {
+ data_dst = CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_CALLOC, NULL, num_elem_dst);
+ }
+
+ data_transfer_layersmapping_add_item(
+ r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights,
+ data_src, data_dst, idx_src, idx_dst,
+ elem_size, 0, 0, 0, vgroups_datatransfer_interp);
+ }
+ }
+ break;
+ }
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool data_transfer_layersmapping_vgroups(
+ ListBase *r_map, const int mix_mode, const float mix_factor, const float *mix_weights,
+ const int num_elem_dst, const bool use_create, const bool use_delete, Object *ob_src, Object *ob_dst,
+ CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst, const int fromlayers, const int tolayers)
+{
+ int idx_src, idx_dst;
+ MDeformVert *data_src, *data_dst = NULL;
+
+ const size_t elem_size = sizeof(*((MDeformVert *)NULL));
+
+ /* Note: VGroups are a bit hairy, since their layout is defined on object level (ob->defbase), while their actual
+ * data is a (mesh) CD layer.
+ * This implies we may have to handle data layout itself while having NULL data itself,
+ * and even have to support NULL data_src in transfer data code (we always create a data_dst, though).
+ */
+
+ if (BLI_listbase_is_empty(&ob_src->defbase)) {
+ if (use_delete) {
+ BKE_object_defgroup_remove_all(ob_dst);
+ }
+ return true;
+ }
+
+ data_src = CustomData_get_layer(cd_src, CD_MDEFORMVERT);
+
+ data_dst = CustomData_get_layer(cd_dst, CD_MDEFORMVERT);
+ if (data_dst && use_dupref_dst && r_map) {
+ /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
+ data_dst = CustomData_duplicate_referenced_layer(cd_dst, CD_MDEFORMVERT, num_elem_dst);
+ }
+
+ if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) {
+ /* Note: use_delete has not much meaning in this case, ignored. */
+
+ if (fromlayers >= 0) {
+ idx_src = fromlayers;
+ BLI_assert(idx_src < BLI_listbase_count(&ob_src->defbase));
+ }
+ else if ((idx_src = ob_src->actdef - 1) == -1) {
+ return false;
+ }
+
+ if (tolayers >= 0) {
+ /* Note: in this case we assume layer exists! */
+ idx_dst = tolayers;
+ BLI_assert(idx_dst < BLI_listbase_count(&ob_dst->defbase));
+ }
+ else if (tolayers == DT_LAYERS_ACTIVE_DST) {
+ if ((idx_dst = ob_dst->actdef - 1) == -1) {
+ bDeformGroup *dg_src;
+ if (!use_create) {
+ return true;
+ }
+ dg_src = BLI_findlink(&ob_src->defbase, idx_src);
+ BKE_object_defgroup_add_name(ob_dst, dg_src->name);
+ idx_dst = ob_dst->actdef - 1;
+ }
+ }
+ else if (tolayers == DT_LAYERS_INDEX_DST) {
+ int num = BLI_listbase_count(&ob_src->defbase);
+ idx_dst = idx_src;
+ if (num <= idx_dst) {
+ if (!use_create) {
+ return true;
+ }
+ /* Create as much vgroups as necessary! */
+ for (; num <= idx_dst; num++) {
+ BKE_object_defgroup_add(ob_dst);
+ }
+ }
+ }
+ else if (tolayers == DT_LAYERS_NAME_DST) {
+ bDeformGroup *dg_src = BLI_findlink(&ob_src->defbase, idx_src);
+ if ((idx_dst = defgroup_name_index(ob_dst, dg_src->name)) == -1) {
+ if (!use_create) {
+ return true;
+ }
+ BKE_object_defgroup_add_name(ob_dst, dg_src->name);
+ idx_dst = ob_dst->actdef - 1;
+ }
+ }
+ else {
+ return false;
+ }
+
+ if (r_map) {
+ /* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest!
+ * use_create is not relevant in this case */
+ if (!data_dst) {
+ data_dst = CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_CALLOC, NULL, num_elem_dst);
+ }
+
+ data_transfer_layersmapping_add_item(r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights,
+ data_src, data_dst, idx_src, idx_dst,
+ elem_size, 0, 0, 0, vgroups_datatransfer_interp);
+ }
+ }
+ else {
+ int num_src, num_sel_unused;
+ bool *use_layers_src = NULL;
+ bool ret = false;
+
+ switch (fromlayers) {
+ case DT_LAYERS_ALL_SRC:
+ use_layers_src = BKE_object_defgroup_subset_from_select_type(ob_src, WT_VGROUP_ALL,
+ &num_src, &num_sel_unused);
+ break;
+ case DT_LAYERS_VGROUP_SRC_BONE_SELECT:
+ use_layers_src = BKE_object_defgroup_subset_from_select_type(ob_src, WT_VGROUP_BONE_SELECT,
+ &num_src, &num_sel_unused);
+ break;
+ case DT_LAYERS_VGROUP_SRC_BONE_DEFORM:
+ use_layers_src = BKE_object_defgroup_subset_from_select_type(ob_src, WT_VGROUP_BONE_DEFORM,
+ &num_src, &num_sel_unused);
+ break;
+ }
+
+ if (use_layers_src) {
+ ret = data_transfer_layersmapping_vgroups_multisrc_to_dst(
+ r_map, mix_mode, mix_factor, mix_weights, num_elem_dst, use_create, use_delete,
+ ob_src, ob_dst, data_src, data_dst, cd_src, cd_dst, use_dupref_dst,
+ tolayers, use_layers_src, num_src);
+ }
+
+ MEM_SAFE_FREE(use_layers_src);
+ return ret;
+ }
+
+ return true;
+}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index cf425afe5db..1f3f31c3220 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -2359,6 +2359,15 @@ void DAG_on_visible_update(Main *bmain, const bool do_time)
ob->recalc |= OB_RECALC_DATA;
lib_id_recalc_tag(bmain, &ob->id);
}
+ /* This should not be needed here, but in some cases, like after a redo, we can end up with
+ * a wrong final matrix (see T42472).
+ * Quoting Sergey, this comes from BKE_object_handle_update_ex, which is calling
+ * BKE_object_where_is_calc_ex when it shouldn't, but that issue is not easily fixable.
+ */
+ else {
+ ob->recalc |= OB_RECALC_OB;
+ lib_id_recalc_tag(bmain, &ob->id);
+ }
if (ob->proxy && (ob->proxy_group == NULL)) {
ob->proxy->recalc |= OB_RECALC_DATA;
lib_id_recalc_tag(bmain, &ob->id);
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 893c69741cd..9ea5a5638b9 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -37,7 +37,6 @@
#include "MEM_guardedalloc.h"
#include "DNA_curve_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_vfont_types.h"
@@ -814,7 +813,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb,
required_mode |= eModifierMode_Editmode;
if (cu->editnurb == NULL) {
- keyVerts = BKE_key_evaluate_object(scene, ob, &numVerts);
+ keyVerts = BKE_key_evaluate_object(ob, &numVerts);
if (keyVerts) {
/* split coords from key data, the latter also includes
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index c4f91f0ba89..58a7702828c 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -73,10 +73,6 @@
#include "BKE_scene.h"
#include "BKE_texture.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
/* for image output */
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -259,20 +255,20 @@ static int dynamicPaint_surfaceNumOfPoints(DynamicPaintSurface *surface)
bool dynamicPaint_surfaceHasColorPreview(DynamicPaintSurface *surface)
{
if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
- return 0;
+ return false;
}
else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
surface->type == MOD_DPAINT_SURFACE_T_WAVE)
{
- return 0;
+ return false;
}
else {
- return 1;
+ return true;
}
}
else {
- return 1;
+ return true;
}
}
@@ -327,7 +323,7 @@ bool dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, Object
else if (output == 1)
name = surface->output_name2;
else
- return 0;
+ return false;
if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
@@ -338,7 +334,7 @@ bool dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, Object
return (defgroup_name_index(ob, surface->output_name) != -1);
}
- return 0;
+ return false;
}
static bool surface_duplicateOutputExists(void *arg, const char *name)
@@ -1106,13 +1102,13 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str
canvas = pmd->canvas = MEM_callocN(sizeof(DynamicPaintCanvasSettings), "DynamicPaint Canvas");
if (!canvas)
- return 0;
+ return false;
canvas->pmd = pmd;
canvas->dm = NULL;
/* Create one surface */
if (!dynamicPaint_createNewSurface(canvas, scene))
- return 0;
+ return false;
}
else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH) {
@@ -1122,7 +1118,7 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str
brush = pmd->brush = MEM_callocN(sizeof(DynamicPaintBrushSettings), "DynamicPaint Paint");
if (!brush)
- return 0;
+ return false;
brush->pmd = pmd;
brush->psys = NULL;
@@ -1157,7 +1153,7 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str
brush->paint_ramp = add_colorband(false);
if (!brush->paint_ramp)
- return 0;
+ return false;
ramp = brush->paint_ramp->data;
/* Add default smooth-falloff ramp. */
ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = 1.0f;
@@ -1173,7 +1169,7 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str
brush->vel_ramp = add_colorband(false);
if (!brush->vel_ramp)
- return 0;
+ return false;
ramp = brush->vel_ramp->data;
ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = ramp[0].pos = 0.0f;
ramp[1].r = ramp[1].g = ramp[1].b = ramp[1].a = ramp[1].pos = 1.0f;
@@ -1181,10 +1177,11 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str
}
}
}
- else
- return 0;
+ else {
+ return false;
+ }
- return 1;
+ return true;
}
void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct DynamicPaintModifierData *tpmd)
@@ -1630,12 +1627,12 @@ bool dynamicPaint_resetSurface(Scene *scene, DynamicPaintSurface *surface)
if (surface->data) dynamicPaint_freeSurfaceData(surface);
/* don't reallocate for image sequence types. they get handled only on bake */
- if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return 1;
- if (numOfPoints < 1) return 0;
+ if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return true;
+ if (numOfPoints < 1) return false;
/* allocate memory */
surface->data = MEM_callocN(sizeof(PaintSurfaceData), "PaintSurfaceData");
- if (!surface->data) return 0;
+ if (!surface->data) return false;
/* allocate data depending on surface type and format */
surface->data->total_points = numOfPoints;
@@ -1646,7 +1643,7 @@ bool dynamicPaint_resetSurface(Scene *scene, DynamicPaintSurface *surface)
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
dynamicPaint_setInitialColor(scene, surface);
- return 1;
+ return true;
}
/* make sure allocated surface size matches current requirements */
@@ -1655,7 +1652,7 @@ static bool dynamicPaint_checkSurfaceData(Scene *scene, DynamicPaintSurface *sur
if (!surface->data || ((dynamicPaint_surfaceNumOfPoints(surface) != surface->data->total_points))) {
return dynamicPaint_resetSurface(scene, surface);
}
- return 1;
+ return true;
}
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 7d64892d6b4..eb7c78c2760 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -526,6 +526,8 @@ static void emDM_drawMappedFaces(DerivedMesh *dm,
setDrawOptions(userData, BM_elem_index_get(efa)));
if (draw_option != DM_DRAW_OPTION_SKIP) {
const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
+ if (setMaterial)
+ setMaterial(efa->mat_nr + 1, NULL);
if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
if (poly_prev != GL_ZERO) glEnd();
@@ -608,12 +610,17 @@ static void emDM_drawMappedFaces(DerivedMesh *dm,
efa = ltri[0]->f;
drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH));
+
+ draw_option = (setDrawOptions ?
+ setDrawOptions(userData, BM_elem_index_get(efa)) :
+ DM_DRAW_OPTION_NORMAL);
- draw_option = (!setDrawOptions ?
- DM_DRAW_OPTION_NORMAL :
- setDrawOptions(userData, BM_elem_index_get(efa)));
if (draw_option != DM_DRAW_OPTION_SKIP) {
const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
+
+ if (setMaterial)
+ setMaterial(efa->mat_nr + 1, NULL);
+
if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
if (poly_prev != GL_ZERO) glEnd();
@@ -717,7 +724,7 @@ static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned c
static void emDM_drawFacesTex_common(DerivedMesh *dm,
DMSetDrawOptionsTex drawParams,
- DMSetDrawOptions drawParamsMapped,
+ DMSetDrawOptionsMappedTex drawParamsMapped,
DMCompareDrawOptions compareDrawOptions,
void *userData)
{
@@ -785,7 +792,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
if (drawParams)
draw_option = drawParams(&mtf, has_vcol, efa->mat_nr);
else if (drawParamsMapped)
- draw_option = drawParamsMapped(userData, BM_elem_index_get(efa));
+ draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr);
else
draw_option = DM_DRAW_OPTION_NORMAL;
@@ -854,7 +861,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
if (drawParams)
draw_option = drawParams(&mtf, has_vcol, efa->mat_nr);
else if (drawParamsMapped)
- draw_option = drawParamsMapped(userData, BM_elem_index_get(efa));
+ draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr);
else
draw_option = DM_DRAW_OPTION_NORMAL;
@@ -916,7 +923,7 @@ static void emDM_drawFacesTex(DerivedMesh *dm,
}
static void emDM_drawMappedFacesTex(DerivedMesh *dm,
- DMSetDrawOptions setDrawOptions,
+ DMSetDrawOptionsMappedTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData, DMDrawFlag UNUSED(flag))
{
@@ -1555,7 +1562,8 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
if (type == CD_MTFACE || type == CD_MCOL) {
const int type_from = (type == CD_MTFACE) ? CD_MTEXPOLY : CD_MLOOPCOL;
int index;
- const char *data, *bmdata;
+ const char *bmdata;
+ char *data;
index = CustomData_get_layer_index(&bm->pdata, type_from);
if (index != -1) {
@@ -1580,11 +1588,11 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
// bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
bmdata = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- ME_MTEXFACE_CPY(((MTFace *)data), ((MTexPoly *)bmdata));
+ ME_MTEXFACE_CPY(((MTFace *)data), ((const MTexPoly *)bmdata));
for (j = 0; j < 3; j++) {
// bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPUV);
bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_uv_offset);
- copy_v2_v2(((MTFace *)data)->uv[j], ((MLoopUV *)bmdata)->uv);
+ copy_v2_v2(((MTFace *)data)->uv[j], ((const MLoopUV *)bmdata)->uv);
}
}
}
@@ -1594,7 +1602,7 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
for (j = 0; j < 3; j++) {
// bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPCOL);
bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_color_offset);
- MESH_MLOOPCOL_TO_MCOL(((MLoopCol *)bmdata), (((MCol *)data) + j));
+ MESH_MLOOPCOL_TO_MCOL(((const MLoopCol *)bmdata), (((MCol *)data) + j));
}
}
}
diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c
index 442ab26ffc8..5f2660b5365 100644
--- a/source/blender/blenkernel/intern/editmesh_bvh.c
+++ b/source/blender/blenkernel/intern/editmesh_bvh.c
@@ -239,6 +239,32 @@ struct RayCastUserData {
float uv[2];
};
+
+static BMFace *bmbvh_ray_cast_handle_hit(
+ BMBVHTree *bmtree, struct RayCastUserData *bmcb_data, const BVHTreeRayHit *hit,
+ float *r_dist, float r_hitout[3], float r_cagehit[3])
+{
+ if (r_hitout) {
+ if (bmtree->flag & BMBVH_RETURN_ORIG) {
+ BMLoop **ltri = bmtree->looptris[hit->index];
+ interp_v3_v3v3v3_uv(r_hitout, ltri[0]->v->co, ltri[1]->v->co, ltri[2]->v->co, bmcb_data->uv);
+ }
+ else {
+ copy_v3_v3(r_hitout, hit->co);
+ }
+
+ if (r_cagehit) {
+ copy_v3_v3(r_cagehit, hit->co);
+ }
+ }
+
+ if (r_dist) {
+ *r_dist = hit->dist;
+ }
+
+ return bmtree->looptris[hit->index][0]->f;
+}
+
static void bmbvh_ray_cast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
struct RayCastUserData *bmcb_data = userdata;
@@ -284,32 +310,68 @@ BMFace *BKE_bmbvh_ray_cast(BMBVHTree *bmtree, const float co[3], const float dir
bmcb_data.cos_cage = (const float (*)[3])bmtree->cos_cage;
BLI_bvhtree_ray_cast(bmtree->tree, co, dir, radius, &hit, bmbvh_ray_cast_cb, &bmcb_data);
+
if (hit.index != -1 && hit.dist != dist) {
- if (r_hitout) {
- if (bmtree->flag & BMBVH_RETURN_ORIG) {
- BMLoop **ltri = bmtree->looptris[hit.index];
- interp_v3_v3v3v3_uv(r_hitout, ltri[0]->v->co, ltri[1]->v->co, ltri[2]->v->co, bmcb_data.uv);
- }
- else {
- copy_v3_v3(r_hitout, hit.co);
- }
+ return bmbvh_ray_cast_handle_hit(bmtree, &bmcb_data, &hit, r_dist, r_hitout, r_cagehit);
+ }
- if (r_cagehit) {
- copy_v3_v3(r_cagehit, hit.co);
- }
- }
+ return NULL;
+}
- if (r_dist) {
- *r_dist = hit.dist;
- }
+/* -------------------------------------------------------------------- */
+/* bmbvh_ray_cast_cb_filter */
- return bmtree->looptris[hit.index][0]->f;
+/* Same as BKE_bmbvh_ray_cast but takes a callback to filter out faces.
+ */
+
+struct RayCastUserData_Filter {
+ struct RayCastUserData bmcb_data;
+
+ BMBVHTree_FaceFilter filter_cb;
+ void *filter_userdata;
+};
+
+static void bmbvh_ray_cast_cb_filter(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ struct RayCastUserData_Filter *bmcb_data_filter = userdata;
+ struct RayCastUserData *bmcb_data = &bmcb_data_filter->bmcb_data;
+ const BMLoop **ltri = bmcb_data->looptris[index];
+ if (bmcb_data_filter->filter_cb(ltri[0]->f, bmcb_data_filter->filter_userdata)) {
+ bmbvh_ray_cast_cb(bmcb_data, index, ray, hit);
+ }
+}
+
+BMFace *BKE_bmbvh_ray_cast_filter(
+ BMBVHTree *bmtree, const float co[3], const float dir[3], const float radius,
+ float *r_dist, float r_hitout[3], float r_cagehit[3],
+ BMBVHTree_FaceFilter filter_cb, void *filter_userdata)
+{
+ BVHTreeRayHit hit;
+ struct RayCastUserData_Filter bmcb_data_filter;
+ struct RayCastUserData *bmcb_data = &bmcb_data_filter.bmcb_data;
+
+ const float dist = r_dist ? *r_dist : FLT_MAX;
+
+ bmcb_data_filter.filter_cb = filter_cb;
+ bmcb_data_filter.filter_userdata = filter_userdata;
+
+ if (bmtree->cos_cage) BLI_assert(!(bmtree->bm->elem_index_dirty & BM_VERT));
+
+ hit.dist = dist;
+ hit.index = -1;
+
+ /* ok to leave 'uv' uninitialized */
+ bmcb_data->looptris = (const BMLoop *(*)[3])bmtree->looptris;
+ bmcb_data->cos_cage = (const float (*)[3])bmtree->cos_cage;
+
+ BLI_bvhtree_ray_cast(bmtree->tree, co, dir, radius, &hit, bmbvh_ray_cast_cb_filter, &bmcb_data_filter);
+ if (hit.index != -1 && hit.dist != dist) {
+ return bmbvh_ray_cast_handle_hit(bmtree, bmcb_data, &hit, r_dist, r_hitout, r_cagehit);
}
return NULL;
}
-
/* -------------------------------------------------------------------- */
/* BKE_bmbvh_find_face_segment */
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 88d70691120..b50e563775e 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -687,11 +687,11 @@ bool fcurve_are_keyframes_usable(FCurve *fcu)
{
/* F-Curve must exist */
if (fcu == NULL)
- return 0;
+ return false;
/* F-Curve must not have samples - samples are mutually exclusive of keyframes */
if (fcu->fpt)
- return 0;
+ return false;
/* if it has modifiers, none of these should "drastically" alter the curve */
if (fcu->modifiers.first) {
@@ -718,7 +718,7 @@ bool fcurve_are_keyframes_usable(FCurve *fcu)
FMod_Generator *data = (FMod_Generator *)fcm->data;
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
- return 0;
+ return false;
break;
}
case FMODIFIER_TYPE_FN_GENERATOR:
@@ -726,18 +726,18 @@ bool fcurve_are_keyframes_usable(FCurve *fcu)
FMod_FunctionGenerator *data = (FMod_FunctionGenerator *)fcm->data;
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
- return 0;
+ return false;
break;
}
/* always harmful - cannot allow */
default:
- return 0;
+ return false;
}
}
}
/* keyframes are usable */
- return 1;
+ return true;
}
bool BKE_fcurve_is_protected(FCurve *fcu)
@@ -1283,7 +1283,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
/* extract transform just like how the constraints do it! */
copy_m4_m4(mat, pchan->pose_mat);
- BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false);
/* ... and from that, we get our transform */
copy_v3_v3(tmp_loc, mat[3]);
@@ -1308,7 +1308,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
/* extract transform just like how the constraints do it! */
copy_m4_m4(mat, ob->obmat);
- BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false);
/* ... and from that, we get our transform */
copy_v3_v3(tmp_loc, mat[3]);
@@ -1385,7 +1385,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
/* just like how the constraints do it! */
copy_m4_m4(mat, pchan->pose_mat);
- BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false);
}
else {
/* specially calculate local matrix, since chan_mat is not valid
@@ -1412,7 +1412,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
/* just like how the constraints do it! */
copy_m4_m4(mat, ob->obmat);
- BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false);
}
else {
/* transforms to matrix */
@@ -2165,8 +2165,8 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime
* the value is simply the shared value (see T40372 -> F91346)
*/
cvalue = v1[1];
- }
- else {
+ }
+ else {
/* adjust handles so that they don't overlap (forming a loop) */
correct_bezpart(v1, v2, v3, v4);
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 56b087e7eb6..af0db5e1c47 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -27,8 +27,6 @@
* \ingroup bke
*/
-
-
#include <math.h>
#include <stdio.h>
#include <stddef.h>
@@ -1173,7 +1171,7 @@ bool remove_fmodifier(ListBase *modifiers, FModifier *fcm)
/* sanity check */
if (fcm == NULL)
- return 0;
+ return false;
/* free modifier's special data (stored inside fcm->data) */
if (fcm->data) {
@@ -1187,13 +1185,13 @@ bool remove_fmodifier(ListBase *modifiers, FModifier *fcm)
/* remove modifier from stack */
if (modifiers) {
BLI_freelinkN(modifiers, fcm);
- return 1;
+ return true;
}
else {
/* XXX this case can probably be removed some day, as it shouldn't happen... */
printf("remove_fmodifier() - no modifier stack given\n");
MEM_freeN(fcm);
- return 0;
+ return false;
}
}
@@ -1264,7 +1262,7 @@ bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype)
/* sanity checks */
if (ELEM(NULL, modifiers, modifiers->first))
- return 0;
+ return false;
/* find the first mdifier fitting these criteria */
for (fcm = modifiers->first; fcm; fcm = fcm->next) {
@@ -1279,11 +1277,11 @@ bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype)
/* if both are ok, we've found a hit */
if (mOk && aOk)
- return 1;
+ return true;
}
/* no matches */
- return 0;
+ return false;
}
/* Evaluation API --------------------------- */
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index e226e9d9797..dd2155505fb 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -45,6 +45,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_userdef_types.h"
+#include "BKE_animsys.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_library.h"
@@ -115,6 +116,12 @@ void BKE_gpencil_free(bGPdata *gpd)
{
/* free layers */
free_gpencil_layers(&gpd->layers);
+
+ /* free animation data */
+ if (gpd->adt) {
+ BKE_free_animdata(&gpd->id);
+ gpd->adt = NULL;
+ }
}
/* -------- Container Creation ---------- */
@@ -276,7 +283,7 @@ bGPDlayer *gpencil_layer_duplicate(bGPDlayer *src)
}
/* make a copy of a given gpencil datablock */
-bGPdata *gpencil_data_duplicate(bGPdata *src)
+bGPdata *gpencil_data_duplicate(bGPdata *src, bool internal_copy)
{
bGPDlayer *gpl, *gpld;
bGPdata *dst;
@@ -286,7 +293,14 @@ bGPdata *gpencil_data_duplicate(bGPdata *src)
return NULL;
/* make a copy of the base-data */
- dst = MEM_dupallocN(src);
+ if (internal_copy) {
+ /* make a straight copy for undo buffers used during stroke drawing */
+ dst = MEM_dupallocN(src);
+ }
+ else {
+ /* make a copy when others use this */
+ dst = BKE_libblock_copy(&src->id);
+ }
/* copy layers */
BLI_listbase_clear(&dst->layers);
@@ -300,6 +314,31 @@ bGPdata *gpencil_data_duplicate(bGPdata *src)
return dst;
}
+/* -------- GP-Stroke API --------- */
+
+/* ensure selection status of stroke is in sync with its points */
+void gpencil_stroke_sync_selection(bGPDstroke *gps)
+{
+ bGPDspoint *pt;
+ int i;
+
+ /* error checking */
+ if (gps == NULL)
+ return;
+
+ /* we'll stop when we find the first selected point,
+ * so initially, we must deselect
+ */
+ gps->flag &= ~GP_STROKE_SELECT;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ gps->flag |= GP_STROKE_SELECT;
+ break;
+ }
+ }
+}
+
/* -------- GP-Frame API ---------- */
/* delete the last stroke of the given frame */
@@ -359,7 +398,7 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, short addnew)
/* do not allow any changes to layer's active frame if layer is locked from changes
* or if the layer has been set to stay on the current frame
*/
- if (gpl->flag & (GP_LAYER_LOCKED | GP_LAYER_FRAMELOCK))
+ if (gpl->flag & GP_LAYER_FRAMELOCK)
return gpf;
/* do not allow any changes to actframe if frame has painting tag attached to it */
if (gpf->flag & GP_FRAME_PAINT)
@@ -468,16 +507,23 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, short addnew)
bool gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
{
bool changed = false;
-
+
/* error checking */
if (ELEM(NULL, gpl, gpf))
return false;
-
+
+ /* if this frame was active, make the previous frame active instead
+ * since it's tricky to set active frame otherwise
+ */
+ if (gpl->actframe == gpf)
+ gpl->actframe = gpf->prev;
+ else
+ gpl->actframe = NULL;
+
/* free the frame and its data */
changed = free_gpencil_strokes(gpf);
BLI_freelinkN(&gpl->frames, gpf);
- gpl->actframe = NULL;
-
+
return changed;
}
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 6ea6bafaa14..1f9cf2e11b7 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -149,6 +149,10 @@ Group *BKE_group_copy(Group *group)
groupn = BKE_libblock_copy(&group->id);
BLI_duplicatelist(&groupn->gobject, &group->gobject);
+ if (group->id.lib) {
+ BKE_id_lib_local_paths(G.main, group->id.lib, &groupn->id);
+ }
+
return groupn;
}
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index a7c76acedbb..2b99b5f4620 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -42,10 +42,18 @@
#include "MEM_guardedalloc.h"
+#include "BLI_strict_flags.h"
+
/* IDPropertyTemplate is a union in DNA_ID.h */
+/**
+ * if the new is 'IDP_ARRAY_REALLOC_LIMIT' items less,
+ * than #IDProperty.totallen, reallocate anyway.
+ */
+#define IDP_ARRAY_REALLOC_LIMIT 200
+
/*local size table.*/
-static char idp_size_table[] = {
+static size_t idp_size_table[] = {
1, /*strings*/
sizeof(int),
sizeof(float),
@@ -158,9 +166,8 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
BLI_assert(prop->type == IDP_IDPARRAY);
/* first check if the array buffer size has room */
- /* if newlen is 200 items less then totallen, reallocate anyway */
if (newlen <= prop->totallen) {
- if (newlen < prop->len && prop->totallen - newlen < 200) {
+ if (newlen < prop->len && prop->totallen - newlen < IDP_ARRAY_REALLOC_LIMIT) {
int i;
for (i = newlen; i < prop->len; i++)
@@ -194,7 +201,7 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
*/
newsize = newlen;
newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
- prop->data.pointer = MEM_recallocN(prop->data.pointer, sizeof(IDProperty) * newsize);
+ prop->data.pointer = MEM_recallocN(prop->data.pointer, sizeof(IDProperty) * (size_t)newsize);
prop->len = newlen;
prop->totallen = newsize;
}
@@ -235,8 +242,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen)
const bool is_grow = newlen >= prop->len;
/* first check if the array buffer size has room */
- /* if newlen is 200 chars less then totallen, reallocate anyway */
- if (newlen <= prop->totallen && prop->totallen - newlen < 200) {
+ if (newlen <= prop->totallen && prop->totallen - newlen < IDP_ARRAY_REALLOC_LIMIT) {
idp_resize_group_array(prop, newlen, prop->data.pointer);
prop->len = newlen;
return;
@@ -256,7 +262,8 @@ void IDP_ResizeArray(IDProperty *prop, int newlen)
if (is_grow == false)
idp_resize_group_array(prop, newlen, prop->data.pointer);
- prop->data.pointer = MEM_recallocN(prop->data.pointer, idp_size_table[(int)prop->subtype] * newsize);
+ prop->data.pointer = MEM_recallocN(
+ prop->data.pointer, idp_size_table[(int)prop->subtype] * (size_t)newsize);
if (is_grow == true)
idp_resize_group_array(prop, newlen, prop->data.pointer);
@@ -336,14 +343,14 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen)
}
else {
/* include null terminator '\0' */
- int stlen = strlen(st) + 1;
+ int stlen = (int)strlen(st) + 1;
if (maxlen > 0 && maxlen < stlen)
stlen = maxlen;
- prop->data.pointer = MEM_mallocN(stlen, "id property string 2");
+ prop->data.pointer = MEM_mallocN((size_t)stlen, "id property string 2");
prop->len = prop->totallen = stlen;
- BLI_strncpy(prop->data.pointer, st, stlen);
+ BLI_strncpy(prop->data.pointer, st, (size_t)stlen);
}
prop->type = IDP_STRING;
@@ -374,18 +381,18 @@ void IDP_AssignString(IDProperty *prop, const char *st, int maxlen)
int stlen;
BLI_assert(prop->type == IDP_STRING);
- stlen = strlen(st);
+ stlen = (int)strlen(st);
if (maxlen > 0 && maxlen < stlen)
stlen = maxlen;
if (prop->subtype == IDP_STRING_SUB_BYTE) {
IDP_ResizeArray(prop, stlen);
- memcpy(prop->data.pointer, st, stlen);
+ memcpy(prop->data.pointer, st, (size_t)stlen);
}
else {
stlen++;
IDP_ResizeArray(prop, stlen);
- BLI_strncpy(prop->data.pointer, st, stlen);
+ BLI_strncpy(prop->data.pointer, st, (size_t)stlen);
}
}
@@ -395,7 +402,7 @@ void IDP_ConcatStringC(IDProperty *prop, const char *st)
BLI_assert(prop->type == IDP_STRING);
- newlen = prop->len + strlen(st);
+ newlen = prop->len + (int)strlen(st);
/* we have to remember that prop->len includes the null byte for strings.
* so there's no need to add +1 to the resize function.*/
IDP_ResizeArray(prop, newlen);
@@ -795,10 +802,15 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
case IDP_DOUBLE:
return (IDP_Double(prop1) == IDP_Double(prop2));
case IDP_STRING:
- return ((prop1->len == prop2->len) && strncmp(IDP_String(prop1), IDP_String(prop2), prop1->len) == 0);
+ {
+ return (((prop1->len == prop2->len) &&
+ strncmp(IDP_String(prop1), IDP_String(prop2), (size_t)prop1->len) == 0));
+ }
case IDP_ARRAY:
if (prop1->len == prop2->len && prop1->subtype == prop2->subtype) {
- return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[(int)prop1->subtype] * prop1->len);
+ return (memcmp(IDP_Array(prop1),
+ IDP_Array(prop2),
+ idp_size_table[(int)prop1->subtype] * (size_t)prop1->len) == 0);
}
return false;
case IDP_GROUP:
@@ -870,7 +882,7 @@ bool IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2)
* IDP_AddToGroup or MEM_freeN the property, doing anything else might result in
* a memory leak.
*/
-IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name)
+IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *name)
{
IDProperty *prop = NULL;
@@ -897,8 +909,10 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n
{
prop = MEM_callocN(sizeof(IDProperty), "IDProperty array");
prop->subtype = val->array.type;
- if (val->array.len)
- prop->data.pointer = MEM_callocN(idp_size_table[val->array.type] * val->array.len, "id property array");
+ if (val->array.len) {
+ prop->data.pointer = MEM_callocN(
+ idp_size_table[val->array.type] * (size_t)val->array.len, "id property array");
+ }
prop->len = prop->totallen = val->array.len;
break;
}
@@ -918,9 +932,9 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n
prop->len = 0;
}
else {
- prop->data.pointer = MEM_mallocN(val->string.len, "id property string 2");
+ prop->data.pointer = MEM_mallocN((size_t)val->string.len, "id property string 2");
prop->len = prop->totallen = val->string.len;
- memcpy(prop->data.pointer, st, val->string.len);
+ memcpy(prop->data.pointer, st, (size_t)val->string.len);
}
prop->subtype = IDP_STRING_SUB_BYTE;
}
@@ -932,10 +946,10 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n
prop->len = 1; /*NULL string, has len of 1 to account for null byte.*/
}
else {
- int stlen = strlen(st) + 1;
- prop->data.pointer = MEM_mallocN(stlen, "id property string 3");
+ int stlen = (int)strlen(st) + 1;
+ prop->data.pointer = MEM_mallocN((size_t)stlen, "id property string 3");
prop->len = prop->totallen = stlen;
- memcpy(prop->data.pointer, st, stlen);
+ memcpy(prop->data.pointer, st, (size_t)stlen);
}
prop->subtype = IDP_STRING_SUB_UTF8;
}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 54f5cb7a68e..870c077ff78 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -117,21 +117,21 @@ typedef struct ImageCacheKey {
static unsigned int imagecache_hashhash(const void *key_v)
{
- const ImageCacheKey *key = (ImageCacheKey *) key_v;
+ const ImageCacheKey *key = key_v;
return key->index;
}
static bool imagecache_hashcmp(const void *a_v, const void *b_v)
{
- const ImageCacheKey *a = (ImageCacheKey *) a_v;
- const ImageCacheKey *b = (ImageCacheKey *) b_v;
+ const ImageCacheKey *a = a_v;
+ const ImageCacheKey *b = b_v;
return (a->index != b->index);
}
static void imagecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
{
- ImageCacheKey *key = (ImageCacheKey *)userkey;
+ ImageCacheKey *key = userkey;
*framenr = IMA_INDEX_FRAME(key->index);
*proxy = IMB_PROXY_NONE;
@@ -273,7 +273,13 @@ void BKE_image_free_buffers(Image *ima)
ima->rr = NULL;
}
- GPU_free_image(ima);
+ if (!G.background) {
+ /* Background mode doesn't use opnegl,
+ * so we can avoid freeing GPU images and save some
+ * time by skipping mutex lock.
+ */
+ GPU_free_image(ima);
+ }
ima->ok = IMA_OK;
}
@@ -378,6 +384,10 @@ Image *BKE_image_copy(Main *bmain, Image *ima)
if (ima->packedfile)
nima->packedfile = dupPackedFile(ima->packedfile);
+ if (ima->id.lib) {
+ BKE_id_lib_local_paths(bmain, ima->id.lib, &nima->id);
+ }
+
return nima;
}
@@ -661,7 +671,7 @@ Image *BKE_image_load(Main *bmain, const char *filepath)
/* otherwise creates new. */
/* does not load ibuf itself */
/* pass on optional frame for #name images */
-Image *BKE_image_load_exists(const char *filepath)
+Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists)
{
Image *ima;
char str[FILE_MAX], strtest[FILE_MAX];
@@ -681,16 +691,24 @@ Image *BKE_image_load_exists(const char *filepath)
ima->id.us++; /* officially should not, it doesn't link here! */
if (ima->ok == 0)
ima->ok = IMA_OK;
- /* RETURN! */
+ if (r_exists)
+ *r_exists = true;
return ima;
}
}
}
}
+ if (r_exists)
+ *r_exists = false;
return BKE_image_load(G.main, filepath);
}
+Image *BKE_image_load_exists(const char *filepath)
+{
+ return BKE_image_load_exists_ex(filepath, NULL);
+}
+
static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type,
const float color[4], ColorManagedColorspaceSettings *colorspace_settings)
{
@@ -3393,9 +3411,9 @@ bool BKE_image_has_alpha(struct Image *image)
BKE_image_release_ibuf(image, ibuf, lock);
if (planes == 32)
- return 1;
+ return true;
else
- return 0;
+ return false;
}
void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height)
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 3ba0c6e5ffa..560a3c0726b 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -73,10 +73,6 @@
#define IPO_BEZTRIPLE 100
#define IPO_BPOINT 101
-/* extern, not threadsafe */
-int slurph_opt = 1;
-
-
void BKE_key_free(Key *key)
{
KeyBlock *kb;
@@ -171,7 +167,11 @@ Key *BKE_key_copy(Key *key)
kbn = kbn->next;
kb = kb->next;
}
-
+
+ if (key->id.lib) {
+ BKE_id_lib_local_paths(G.main, key->id.lib, &keyn->id);
+ }
+
return keyn;
}
@@ -607,7 +607,7 @@ static void cp_key(const int start, int end, const int tot, char *poin, Key *key
k1 = key_block_get_data(key, actkb, kb, &freek1);
kref = key_block_get_data(key, actkb, key->refkey, &freekref);
- /* this exception is needed for slurphing */
+ /* this exception is needed curves with multiple splines */
if (start != 0) {
poin += poinsize * start;
@@ -891,7 +891,7 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
}
}
- /* this exception needed for slurphing */
+ /* this exception is needed for curves with multiple splines */
if (start != 0) {
poin += poinsize * start;
@@ -1168,53 +1168,29 @@ void BKE_keyblock_free_per_block_weights(Key *key, float **per_keyblock_weights,
MEM_freeN(per_keyblock_weights);
}
-static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
+static void do_mesh_key(Object *ob, Key *key, char *out, const int tot)
{
KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
float t[4];
int flag = 0;
- if (key->slurph && key->type != KEY_RELATIVE) {
+ if (key->type == KEY_RELATIVE) {
+ WeightsArrayCache cache = {0, NULL};
+ float **per_keyblock_weights;
+ per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, &cache);
+ BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
+ BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, &cache);
+ }
+ else {
const float ctime_scaled = key->ctime / 100.0f;
- float delta = (float)key->slurph / tot;
- float cfra = BKE_scene_frame_get(scene);
- int step, a;
- if (tot > 100 && slurph_opt) {
- step = tot / 50;
- delta *= step;
- /* in do_key and cp_key the case a>tot is handled */
- }
- else {
- step = 1;
- }
+ flag = setkeys(ctime_scaled, &key->block, k, t, 0);
- for (a = 0; a < tot; a += step, cfra += delta) {
- flag = setkeys(ctime_scaled, &key->block, k, t, 0);
-
- if (flag == 0)
- do_key(a, a + step, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
- else
- cp_key(a, a + step, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
- }
- }
- else {
- if (key->type == KEY_RELATIVE) {
- WeightsArrayCache cache = {0, NULL};
- float **per_keyblock_weights;
- per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, &cache);
- BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
- BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, &cache);
+ if (flag == 0) {
+ do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
}
else {
- const float ctime_scaled = key->ctime / 100.0f;
-
- flag = setkeys(ctime_scaled, &key->block, k, t, 0);
-
- if (flag == 0)
- do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
- else
- cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
+ cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
}
}
}
@@ -1259,135 +1235,63 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const
}
}
-static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
+static void do_curve_key(Object *ob, Key *key, char *out, const int tot)
{
Curve *cu = ob->data;
KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
float t[4];
int flag = 0;
- if (key->slurph && key->type != KEY_RELATIVE) {
+ if (key->type == KEY_RELATIVE) {
+ do_rel_cu_key(cu, cu->key, actkb, out, tot);
+ }
+ else {
const float ctime_scaled = key->ctime / 100.0f;
- float delta = (float)key->slurph / tot;
- float cfra = BKE_scene_frame_get(scene);
- Nurb *nu;
- int i = 0, remain = 0;
- int step, a;
- if (tot > 100 && slurph_opt) {
- step = tot / 50;
- delta *= step;
- /* in do_key and cp_key the case a>tot has been handled */
- }
- else {
- step = 1;
- }
+ flag = setkeys(ctime_scaled, &key->block, k, t, 0);
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- int estep, mode;
-
- if (nu->bp) {
- mode = KEY_MODE_BPOINT;
- estep = nu->pntsu * nu->pntsv;
- }
- else if (nu->bezt) {
- mode = KEY_MODE_BEZTRIPLE;
- estep = 3 * nu->pntsu;
- }
- else {
- mode = 0;
- estep = 0;
- }
-
- a = 0;
- while (a < estep) {
- int count;
-
- if (remain <= 0) {
- cfra += delta;
- flag = setkeys(ctime_scaled, &key->block, k, t, 0);
-
- remain = step;
- }
-
- count = min_ii(remain, estep);
- if (mode == KEY_MODE_BEZTRIPLE) {
- count += 3 - count % 3;
- }
-
- if (flag == 0)
- do_key(i, i + count, tot, (char *)out, key, actkb, k, t, mode);
- else
- cp_key(i, i + count, tot, (char *)out, key, actkb, k[2], NULL, mode);
-
- a += count;
- i += count;
- remain -= count;
- }
- }
- }
- else {
- if (key->type == KEY_RELATIVE) {
- do_rel_cu_key(cu, cu->key, actkb, out, tot);
+ if (flag == 0) {
+ do_cu_key(cu, key, actkb, k, t, out, tot);
}
else {
- const float ctime_scaled = key->ctime / 100.0f;
-
- flag = setkeys(ctime_scaled, &key->block, k, t, 0);
-
- if (flag == 0) do_cu_key(cu, key, actkb, k, t, out, tot);
- else cp_cu_key(cu, key, actkb, k[2], 0, tot, out, tot);
+ cp_cu_key(cu, key, actkb, k[2], 0, tot, out, tot);
}
}
}
-static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
+static void do_latt_key(Object *ob, Key *key, char *out, const int tot)
{
Lattice *lt = ob->data;
KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
float t[4];
int flag;
- if (key->slurph && key->type != KEY_RELATIVE) {
- const float ctime_scaled = key->ctime / 100.0f;
- float delta = (float)key->slurph / tot;
- float cfra = BKE_scene_frame_get(scene);
- int a;
-
- for (a = 0; a < tot; a++, cfra += delta) {
- flag = setkeys(ctime_scaled, &key->block, k, t, 0);
-
- if (flag == 0)
- do_key(a, a + 1, tot, out, key, actkb, k, t, KEY_MODE_DUMMY);
- else
- cp_key(a, a + 1, tot, out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
- }
+ if (key->type == KEY_RELATIVE) {
+ float **per_keyblock_weights;
+ per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, NULL);
+ BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
+ BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, NULL);
}
else {
- if (key->type == KEY_RELATIVE) {
- float **per_keyblock_weights;
- per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, NULL);
- BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
- BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, NULL);
+ const float ctime_scaled = key->ctime / 100.0f;
+
+ flag = setkeys(ctime_scaled, &key->block, k, t, 0);
+
+ if (flag == 0) {
+ do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
}
else {
- const float ctime_scaled = key->ctime / 100.0f;
-
- flag = setkeys(ctime_scaled, &key->block, k, t, 0);
-
- if (flag == 0)
- do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
- else
- cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
+ cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
}
}
-
+
if (lt->flag & LT_OUTSIDE) outside_lattice(lt);
}
/* returns key coordinates (+ tilt) when key applied, NULL otherwise */
-float *BKE_key_evaluate_object_ex(Scene *scene, Object *ob, int *r_totelem,
- float *arr, size_t arr_size)
+float *BKE_key_evaluate_object_ex(
+ Object *ob, int *r_totelem,
+ float *arr, size_t arr_size)
{
Key *key = BKE_key_from_object(ob);
KeyBlock *actkb = BKE_keyblock_from_object(ob);
@@ -1469,10 +1373,10 @@ float *BKE_key_evaluate_object_ex(Scene *scene, Object *ob, int *r_totelem,
}
else {
- if (ob->type == OB_MESH) do_mesh_key(scene, ob, key, out, tot);
- else if (ob->type == OB_LATTICE) do_latt_key(scene, ob, key, out, tot);
- else if (ob->type == OB_CURVE) do_curve_key(scene, ob, key, out, tot);
- else if (ob->type == OB_SURF) do_curve_key(scene, ob, key, out, tot);
+ if (ob->type == OB_MESH) do_mesh_key(ob, key, out, tot);
+ else if (ob->type == OB_LATTICE) do_latt_key(ob, key, out, tot);
+ else if (ob->type == OB_CURVE) do_curve_key(ob, key, out, tot);
+ else if (ob->type == OB_SURF) do_curve_key(ob, key, out, tot);
}
if (r_totelem) {
@@ -1481,9 +1385,9 @@ float *BKE_key_evaluate_object_ex(Scene *scene, Object *ob, int *r_totelem,
return (float *)out;
}
-float *BKE_key_evaluate_object(Scene *scene, Object *ob, int *r_totelem)
+float *BKE_key_evaluate_object(Object *ob, int *r_totelem)
{
- return BKE_key_evaluate_object_ex(scene, ob, r_totelem, NULL, 0);
+ return BKE_key_evaluate_object_ex(ob, r_totelem, NULL, 0);
}
Key *BKE_key_from_object(Object *ob)
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 4a413850ec0..93b9c22566d 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -41,7 +41,6 @@
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
-#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -127,6 +126,10 @@ Lamp *BKE_lamp_copy(Lamp *la)
if (la->preview)
lan->preview = BKE_previewimg_copy(la->preview);
+ if (la->id.lib) {
+ BKE_id_lib_local_paths(G.main, la->id.lib, &lan->id);
+ }
+
return lan;
}
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 3f12e3efcc7..fa62308ec53 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -284,6 +284,10 @@ Lattice *BKE_lattice_copy(Lattice *lt)
ltn->editlatt = NULL;
+ if (lt->id.lib) {
+ BKE_id_lib_local_paths(G.main, lt->id.lib, &ltn->id);
+ }
+
return ltn;
}
@@ -575,7 +579,7 @@ static bool where_on_path_deform(Object *ob, float ctime, float vec[4], float di
/* test for cyclic */
bl = ob->curve_cache->bev.first;
- if (!bl->nr) return 0;
+ if (!bl->nr) return false;
if (bl->poly > -1) cycl = 1;
if (cycl == 0) {
@@ -608,9 +612,9 @@ static bool where_on_path_deform(Object *ob, float ctime, float vec[4], float di
/* weight - not used but could be added */
}
}
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* for each point, rotate & translate to curve */
@@ -634,9 +638,7 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3],
#endif
if (par->curve_cache->path == NULL) {
- return 0; /* happens on append, cyclic dependencies
- * and empty curves
- */
+ return false; /* happens on append, cyclic dependencies and empty curves */
}
/* options */
@@ -718,9 +720,9 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3],
if (r_quat)
copy_qt_qt(r_quat, quat);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3],
@@ -939,10 +941,10 @@ bool object_deform_mball(Object *ob, ListBase *dispbase)
(float(*)[3])dl->verts, dl->nr, NULL, 1.0f);
}
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index b49eee3ea22..752c2961f28 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -139,7 +139,7 @@ void BKE_id_lib_local_paths(Main *bmain, Library *lib, ID *id)
BKE_bpath_traverse_id(bmain, id,
BKE_bpath_relocate_visitor,
BKE_BPATH_TRAVERSE_SKIP_MULTIFILE,
- bpath_user_data);
+ (void *)bpath_user_data);
}
void id_lib_extern(ID *id)
@@ -351,7 +351,7 @@ bool id_copy(ID *id, ID **newid, bool test)
case ID_VF:
return false; /* not implemented */
case ID_TXT:
- if (!test) *newid = (ID *)BKE_text_copy((Text *)id);
+ if (!test) *newid = (ID *)BKE_text_copy(G.main, (Text *)id);
return true;
case ID_SCRIPT:
return false; /* deprecated */
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index bcdaf9b7af0..d244e9d79d2 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -53,8 +53,6 @@
#include "BKE_colortools.h"
#include "BKE_animsys.h"
-#include "RNA_access.h"
-
static const char *modifier_name[LS_MODIFIER_NUM] = {
NULL,
"Along Stroke",
@@ -212,6 +210,10 @@ FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle)
for (m = (LineStyleModifier *)linestyle->geometry_modifiers.first; m; m = m->next)
BKE_linestyle_geometry_modifier_copy(new_linestyle, m);
+ if (linestyle->id.lib) {
+ BKE_id_lib_local_paths(G.main, linestyle->id.lib, &new_linestyle->id);
+ }
+
return new_linestyle;
}
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index b05634f5fe5..83ca6cd8d72 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -50,6 +50,7 @@
#include "DNA_sequence_types.h"
#include "BKE_curve.h"
+#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_mask.h"
@@ -59,8 +60,6 @@
#include "BKE_movieclip.h"
#include "BKE_image.h"
-#include "NOD_composite.h"
-
static struct {
ListBase splines;
struct GHash *id_hash;
@@ -857,6 +856,10 @@ Mask *BKE_mask_copy(Mask *mask)
mask_new->id.us++;
}
+ if (mask->id.lib) {
+ BKE_id_lib_local_paths(G.main, mask->id.lib, &mask_new->id);
+ }
+
return mask_new;
}
@@ -1187,11 +1190,12 @@ void BKE_mask_point_parent_matrix_get(MaskSplinePoint *point, float ctime, float
MovieTrackingPlaneTrack *plane_track = BKE_tracking_plane_track_get_named(tracking, ob, parent->sub_parent);
if (plane_track) {
- MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
+ float corners[4][2];
float aspx, aspy;
float frame_size[2], H[3][3], mask_from_clip_matrix[3][3], mask_to_clip_matrix[3][3];
- BKE_tracking_homography_between_two_quads(parent->parent_corners_orig, plane_marker->corners, H);
+ BKE_tracking_plane_marker_get_subframe_corners(plane_track, ctime, corners);
+ BKE_tracking_homography_between_two_quads(parent->parent_corners_orig, corners, H);
unit_m3(mask_from_clip_matrix);
diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c
index 3ed6148054c..5517fc36bc1 100644
--- a/source/blender/blenkernel/intern/mask_evaluate.c
+++ b/source/blender/blenkernel/intern/mask_evaluate.c
@@ -40,8 +40,6 @@
#include "BLI_math.h"
#include "DNA_mask_types.h"
-#include "DNA_node_types.h"
-#include "DNA_scene_types.h"
#include "BKE_curve.h"
#include "BKE_mask.h"
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index ea1b9a3f13d..981064bb22a 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -116,7 +116,7 @@ void BKE_material_free_ex(Material *ma, bool do_id_user)
MEM_freeN(ma->texpaintslot);
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
}
void init_material(Material *ma)
@@ -252,6 +252,10 @@ Material *BKE_material_copy(Material *ma)
BLI_listbase_clear(&man->gpumaterial);
+ if (ma->id.lib) {
+ BKE_id_lib_local_paths(G.main, ma->id.lib, &man->id);
+ }
+
return man;
}
@@ -681,16 +685,16 @@ Material *give_current_material(Object *ob, short act)
/* if object cannot have material, (totcolp == NULL) */
totcolp = give_totcolp(ob);
if (totcolp == NULL || ob->totcol == 0) return NULL;
-
- if (act < 0) {
- printf("Negative material index!\n");
- }
-
+
/* return NULL for invalid 'act', can happen for mesh face indices */
if (act > ob->totcol)
return NULL;
- else if (act <= 0)
+ else if (act <= 0) {
+ if (act < 0) {
+ printf("Negative material index!\n");
+ }
return NULL;
+ }
if (ob->matbits && ob->matbits[act - 1]) { /* in object */
ma = ob->mat[act - 1];
@@ -1137,28 +1141,28 @@ static bool material_in_nodetree(bNodeTree *ntree, Material *mat)
if (node->id) {
if (GS(node->id->name) == ID_MA) {
if (node->id == (ID *)mat) {
- return 1;
+ return true;
}
}
else if (node->type == NODE_GROUP) {
if (material_in_nodetree((bNodeTree *)node->id, mat)) {
- return 1;
+ return true;
}
}
}
}
- return 0;
+ return false;
}
bool material_in_material(Material *parmat, Material *mat)
{
if (parmat == mat)
- return 1;
+ return true;
else if (parmat->nodetree && parmat->use_nodes)
return material_in_nodetree(parmat->nodetree, mat);
else
- return 0;
+ return false;
}
@@ -1724,7 +1728,7 @@ void paste_matcopybuf(Material *ma)
MEM_freeN(ma->nodetree);
}
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
id = (ma->id);
memcpy(ma, &matcopybuf, sizeof(Material));
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 453c6df6e3b..34ab2a85593 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -238,6 +238,10 @@ MetaBall *BKE_mball_copy(MetaBall *mb)
mbn->editelems = NULL;
mbn->lastelem = NULL;
+ if (mb->id.lib) {
+ BKE_id_lib_local_paths(G.main, mb->id.lib, &mbn->id);
+ }
+
return mbn;
}
@@ -2436,10 +2440,10 @@ bool BKE_mball_center_bounds(MetaBall *mb, float r_cent[3])
if (BKE_mball_minmax(mb, min, max)) {
mid_v3_v3v3(r_cent, min, max);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
void BKE_mball_transform(MetaBall *mb, float mat[4][4])
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 2e80379522c..c47d294cfb2 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -562,6 +562,10 @@ Mesh *BKE_mesh_copy_ex(Main *bmain, Mesh *me)
men->key = BKE_key_copy(me->key);
if (men->key) men->key->from = (ID *)men;
+ if (me->id.lib) {
+ BKE_id_lib_local_paths(bmain, me->id.lib, &men->id);
+ }
+
return men;
}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 4c9e44682c3..915abdb6766 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -896,13 +896,6 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart,
mvarray[loopstart[2].v].co
);
}
- else if (mpoly->totloop == 4) {
- return area_quad_v3(mvarray[loopstart[0].v].co,
- mvarray[loopstart[1].v].co,
- mvarray[loopstart[2].v].co,
- mvarray[loopstart[3].v].co
- );
- }
else {
int i;
MLoop *l_iter = loopstart;
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index 53d1aae104c..9e490ae6766 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -32,10 +32,12 @@
#include "DNA_meshdata_types.h"
#include "BLI_utildefines.h"
+#include "BLI_bitmap.h"
#include "BLI_math.h"
#include "BKE_mesh_mapping.h"
#include "BKE_customdata.h"
+#include "BLI_memarena.h"
#include "BLI_strict_flags.h"
@@ -156,18 +158,25 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
}
}
-/* Generates a map where the key is the vertex and the value is a list
- * of polys that use that vertex as a corner. The lists are allocated
- * from one memory pool. */
-void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem,
- const MPoly *mpoly, const MLoop *mloop,
- int totvert, int totpoly, int totloop)
+/**
+
+
+ * Generates a map where the key is the vertex and the value is a list
+ * of polys or loops that use that vertex as a corner. The lists are allocated
+ * from one memory pool.
+ *
+ * Wrapped by #BKE_mesh_vert_poly_map_create & BKE_mesh_vert_loop_map_create
+ */
+static void mesh_vert_poly_or_loop_map_create(
+ MeshElemMap **r_map, int **r_mem,
+ const MPoly *mpoly, const MLoop *mloop,
+ int totvert, int totpoly, int totloop, const bool do_loops)
{
- MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, "vert poly map");
+ MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, __func__);
int *indices, *index_iter;
int i, j;
- indices = index_iter = MEM_mallocN(sizeof(int) * (size_t)totloop, "vert poly map mem");
+ indices = index_iter = MEM_mallocN(sizeof(int) * (size_t)totloop, __func__);
/* Count number of polys for each vertex */
for (i = 0; i < totpoly; i++) {
@@ -193,7 +202,7 @@ void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem,
for (j = 0; j < p->totloop; j++) {
unsigned int v = mloop[p->loopstart + j].v;
- map[v].indices[map[v].count] = i;
+ map[v].indices[map[v].count] = do_loops ? p->loopstart + j : i;
map[v].count++;
}
}
@@ -202,6 +211,28 @@ void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem,
*r_mem = indices;
}
+/**
+ * Generates a map where the key is the vertex and the value is a list of polys that use that vertex as a corner.
+ * The lists are allocated from one memory pool.
+ */
+void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem,
+ const MPoly *mpoly, const MLoop *mloop,
+ int totvert, int totpoly, int totloop)
+{
+ mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, false);
+}
+
+/**
+ * Generates a map where the key is the vertex and the value is a list of loops that use that vertex as a corner.
+ * The lists are allocated from one memory pool.
+ */
+void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem,
+ const MPoly *mpoly, const MLoop *mloop,
+ int totvert, int totpoly, int totloop)
+{
+ mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, true);
+}
+
/* Generates a map where the key is the vertex and the value is a list
* of edges that use that vertex as an endpoint. The lists are allocated
* from one memory pool. */
@@ -345,26 +376,30 @@ void BKE_mesh_origindex_map_create(MeshElemMap **r_map, int **r_mem,
/** \} */
-
/* -------------------------------------------------------------------- */
-/** \name Mesh Smooth Groups
+/** \name Mesh loops/poly islands.
+ * Used currently for UVs and 'smooth groups'.
* \{ */
-/**
- * Calculate smooth groups from sharp edges.
- *
- * \param r_totgroup The total number of groups, 1 or more.
- * \return Polygon aligned array of group index values (bitflags if use_bitflags is true), starting at 1.
+/** Callback deciding whether the given poly/loop/edge define an island boundary or not.
*/
-int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
- const MPoly *mpoly, const int totpoly,
- const MLoop *mloop, const int totloop,
- int *r_totgroup, const bool use_bitflags)
+typedef bool (*MeshRemap_CheckIslandBoundary)(
+ const struct MPoly *mpoly, const struct MLoop *mloop, const struct MEdge *medge,
+ const int nbr_egde_users);
+
+static void poly_edge_loop_islands_calc(
+ const MEdge *medge, const int totedge, const MPoly *mpoly, const int totpoly,
+ const MLoop *mloop, const int totloop, MeshElemMap *edge_poly_map,
+ const bool use_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check,
+ int **r_poly_groups, int *r_totgroup, BLI_bitmap **r_edge_borders, int *r_totedgeborder)
{
int *poly_groups;
int *poly_stack;
+ BLI_bitmap *edge_borders = NULL;
+ int num_edgeborders = 0;
+
int poly_prev = 0;
const int temp_poly_group_id = 3; /* Placeholder value. */
const int poly_group_id_overflowed = 5; /* Group we could not find any available bit, will be reset to 0 at end */
@@ -372,18 +407,27 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
bool group_id_overflow = false;
/* map vars */
- MeshElemMap *edge_poly_map;
- int *edge_poly_mem;
+ int *edge_poly_mem = NULL;
if (totpoly == 0) {
*r_totgroup = 0;
- return NULL;
+ *r_poly_groups = NULL;
+ if (r_edge_borders) {
+ *r_edge_borders = NULL;
+ *r_totedgeborder = 0;
+ }
+ return;
}
- BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem,
- medge, totedge,
- mpoly, totpoly,
- mloop, totloop);
+ if (r_edge_borders) {
+ edge_borders = BLI_BITMAP_NEW(totedge, __func__);
+ *r_totedgeborder = 0;
+ }
+
+ if (!edge_poly_map) {
+ BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem,
+ medge, totedge, mpoly, totpoly, mloop, totloop);
+ }
poly_groups = MEM_callocN(sizeof(int) * (size_t)totpoly, __func__);
poly_stack = MEM_mallocN(sizeof(int) * (size_t)totpoly, __func__);
@@ -416,22 +460,20 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
while (ps_curr_idx != ps_end_idx) {
const MPoly *mp;
const MLoop *ml;
- bool sharp_poly;
int j;
poly = poly_stack[ps_curr_idx++];
BLI_assert(poly_groups[poly] == poly_group_id);
mp = &mpoly[poly];
- sharp_poly = !(mp->flag & ME_SMOOTH);
for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) {
/* loop over poly users */
- const MeshElemMap *map_ele = &edge_poly_map[ml->e];
+ const int me_idx = (int)ml->e;
+ const MEdge *me = &medge[me_idx];
+ const MeshElemMap *map_ele = &edge_poly_map[me_idx];
const int *p = map_ele->indices;
int i = map_ele->count;
- /* Edge is smooth only if its poly is not sharp, edge is not sharp,
- * and edge is used by exactly two polygons. */
- if (!sharp_poly && !(medge[ml->e].flag & ME_SHARP) && i == 2) {
+ if (!edge_boundary_check(mp, ml, me, i)) {
for (; i--; p++) {
/* if we meet other non initialized its a bug */
BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id));
@@ -442,14 +484,20 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
}
}
}
- else if (use_bitflags) {
- /* Find contiguous smooth groups already assigned, these are the values we can't reuse! */
- for (; i--; p++) {
- int bit = poly_groups[*p];
- if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) &&
- !(bit_poly_group_mask & bit))
- {
- bit_poly_group_mask |= bit;
+ else {
+ if (edge_borders && !BLI_BITMAP_TEST(edge_borders, me_idx)) {
+ BLI_BITMAP_ENABLE(edge_borders, me_idx);
+ num_edgeborders++;
+ }
+ if (use_bitflags) {
+ /* Find contiguous smooth groups already assigned, these are the values we can't reuse! */
+ for (; i--; p++) {
+ int bit = poly_groups[*p];
+ if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) &&
+ !(bit_poly_group_mask & bit))
+ {
+ bit_poly_group_mask |= bit;
+ }
}
}
}
@@ -502,12 +550,255 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
tot_group++;
}
- MEM_freeN(edge_poly_map);
- MEM_freeN(edge_poly_mem);
+ if (edge_poly_mem) {
+ MEM_freeN(edge_poly_map);
+ MEM_freeN(edge_poly_mem);
+ }
MEM_freeN(poly_stack);
*r_totgroup = tot_group;
+ *r_poly_groups = poly_groups;
+ if (r_edge_borders) {
+ *r_edge_borders = edge_borders;
+ *r_totedgeborder = num_edgeborders;
+ }
+}
+
+static bool poly_is_island_boundary_smooth_cb(
+ const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me,
+ const int nbr_egde_users)
+{
+ /* Edge is sharp if its poly is sharp, or edge itself is sharp, or edge is not used by exactly two polygons. */
+ return (!(mp->flag & ME_SMOOTH) || (me->flag & ME_SHARP) || (nbr_egde_users != 2));
+}
+
+/**
+ * Calculate smooth groups from sharp edges.
+ *
+ * \param r_totgroup The total number of groups, 1 or more.
+ * \return Polygon aligned array of group index values (bitflags if use_bitflags is true), starting at 1
+ * (0 being used as 'invalid' flag).
+ * Note it's callers's responsibility to MEM_freeN returned array.
+ */
+int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
+ const MPoly *mpoly, const int totpoly,
+ const MLoop *mloop, const int totloop,
+ int *r_totgroup, const bool use_bitflags)
+{
+ int *poly_groups = NULL;
+
+ poly_edge_loop_islands_calc(
+ medge, totedge, mpoly, totpoly, mloop, totloop, NULL, use_bitflags,
+ poly_is_island_boundary_smooth_cb, &poly_groups, r_totgroup, NULL, NULL);
return poly_groups;
}
+
+#define MISLAND_DEFAULT_BUFSIZE 64
+
+void BKE_mesh_loop_islands_init(
+ MeshIslandStore *island_store,
+ const short item_type, const int items_num, const short island_type, const short innercut_type)
+{
+ MemArena *mem = island_store->mem;
+
+ if (mem == NULL) {
+ mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ island_store->mem = mem;
+ }
+ /* else memarena should be cleared */
+
+ BLI_assert(ELEM(item_type, MISLAND_TYPE_VERT, MISLAND_TYPE_EDGE, MISLAND_TYPE_POLY, MISLAND_TYPE_LOOP));
+ BLI_assert(ELEM(island_type, MISLAND_TYPE_VERT, MISLAND_TYPE_EDGE, MISLAND_TYPE_POLY, MISLAND_TYPE_LOOP));
+
+ island_store->item_type = item_type;
+ island_store->items_to_islands_num = items_num;
+ island_store->items_to_islands = BLI_memarena_alloc(mem, sizeof(*island_store->items_to_islands) * (size_t)items_num);
+
+ island_store->island_type = island_type;
+ island_store->islands_num_alloc = MISLAND_DEFAULT_BUFSIZE;
+ island_store->islands = BLI_memarena_alloc(mem, sizeof(*island_store->islands) * island_store->islands_num_alloc);
+
+ island_store->innercut_type = innercut_type;
+ island_store->innercuts = BLI_memarena_alloc(mem, sizeof(*island_store->innercuts) * island_store->islands_num_alloc);
+}
+
+void BKE_mesh_loop_islands_clear(MeshIslandStore *island_store)
+{
+ island_store->item_type = MISLAND_TYPE_NONE;
+ island_store->items_to_islands_num = 0;
+ island_store->items_to_islands = NULL;
+
+ island_store->island_type = MISLAND_TYPE_NONE;
+ island_store->islands_num = 0;
+ island_store->islands = NULL;
+
+ island_store->innercut_type = MISLAND_TYPE_NONE;
+ island_store->innercuts = NULL;
+
+ if (island_store->mem) {
+ BLI_memarena_clear(island_store->mem);
+ }
+
+ island_store->islands_num_alloc = 0;
+}
+
+void BKE_mesh_loop_islands_free(MeshIslandStore *island_store)
+{
+ if (island_store->mem) {
+ BLI_memarena_free(island_store->mem);
+ island_store->mem = NULL;
+ }
+}
+
+void BKE_mesh_loop_islands_add(
+ MeshIslandStore *island_store, const int item_num, int *items_indices,
+ const int num_island_items, int *island_item_indices,
+ const int num_innercut_items, int *innercut_item_indices)
+{
+ MemArena *mem = island_store->mem;
+
+ MeshElemMap *isld, *innrcut;
+ const int curr_island_idx = island_store->islands_num++;
+ const size_t curr_num_islands = (size_t)island_store->islands_num;
+ int i = item_num;
+
+ island_store->items_to_islands_num = item_num;
+ while (i--) {
+ island_store->items_to_islands[items_indices[i]] = curr_island_idx;
+ }
+
+ if (UNLIKELY(curr_num_islands > island_store->islands_num_alloc)) {
+ MeshElemMap **islds, **innrcuts;
+
+ island_store->islands_num_alloc *= 2;
+ islds = BLI_memarena_alloc(mem, sizeof(*islds) * island_store->islands_num_alloc);
+ memcpy(islds, island_store->islands, sizeof(*islds) * (curr_num_islands - 1));
+ island_store->islands = islds;
+
+ innrcuts = BLI_memarena_alloc(mem, sizeof(*innrcuts) * island_store->islands_num_alloc);
+ memcpy(innrcuts, island_store->innercuts, sizeof(*innrcuts) * (curr_num_islands - 1));
+ island_store->innercuts = innrcuts;
+ }
+
+ island_store->islands[curr_island_idx] = isld = BLI_memarena_alloc(mem, sizeof(*isld));
+ isld->count = num_island_items;
+ isld->indices = BLI_memarena_alloc(mem, sizeof(*isld->indices) * (size_t)num_island_items);
+ memcpy(isld->indices, island_item_indices, sizeof(*isld->indices) * (size_t)num_island_items);
+
+ island_store->innercuts[curr_island_idx] = innrcut = BLI_memarena_alloc(mem, sizeof(*innrcut));
+ innrcut->count = num_innercut_items;
+ innrcut->indices = BLI_memarena_alloc(mem, sizeof(*innrcut->indices) * (size_t)num_innercut_items);
+ memcpy(innrcut->indices, innercut_item_indices, sizeof(*innrcut->indices) * (size_t)num_innercut_items);
+}
+
+/* TODO: I'm not sure edge seam flag is enough to define UV islands? Maybe we should also consider UVmaps values
+ * themselves (i.e. different UV-edges for a same mesh-edge => boundary edge too?).
+ * Would make things much more complex though, and each UVMap would then need its own mesh mapping,
+ * not sure we want that at all!
+ */
+static bool mesh_check_island_boundary_uv(
+ const MPoly *UNUSED(mp), const MLoop *UNUSED(ml), const MEdge *me,
+ const int UNUSED(nbr_egde_users))
+{
+ /* Edge is UV boundary if tagged as seam. */
+ return (me->flag & ME_SEAM) != 0;
+}
+
+/**
+ * \note all this could be optimized...
+ * Not sure it would be worth the more complex code, though, those loops
+ * are supposed to be really quick to do...
+ */
+bool BKE_mesh_calc_islands_loop_poly_uv(
+ MVert *UNUSED(verts), const int UNUSED(totvert),
+ MEdge *edges, const int totedge,
+ MPoly *polys, const int totpoly,
+ MLoop *loops, const int totloop,
+ MeshIslandStore *r_island_store)
+{
+ int *poly_groups = NULL;
+ int num_poly_groups;
+
+ /* map vars */
+ MeshElemMap *edge_poly_map;
+ int *edge_poly_mem;
+
+ int *poly_indices = MEM_mallocN(sizeof(*poly_indices) * (size_t)totpoly, __func__);
+ int *loop_indices = MEM_mallocN(sizeof(*loop_indices) * (size_t)totloop, __func__);
+ int num_pidx, num_lidx;
+
+ /* Those are used to detect 'inner cuts', i.e. edges that are borders, and yet have two or more polys of
+ * a same group using them (typical case: seam used to unwrap properly a cylinder). */
+ BLI_bitmap *edge_borders;
+ int num_edge_borders;
+ char *edge_border_count = NULL;
+ int *edge_innercut_indices = NULL;
+ int num_einnercuts = 0;
+
+ int grp_idx, p_idx, pl_idx, l_idx;
+
+ BKE_mesh_loop_islands_clear(r_island_store);
+ BKE_mesh_loop_islands_init(r_island_store, MISLAND_TYPE_LOOP, totloop, MISLAND_TYPE_POLY, MISLAND_TYPE_EDGE);
+
+ BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem,
+ edges, totedge, polys, totpoly, loops, totloop);
+
+ poly_edge_loop_islands_calc(
+ edges, totedge, polys, totpoly, loops, totloop, edge_poly_map, false,
+ mesh_check_island_boundary_uv, &poly_groups, &num_poly_groups, &edge_borders, &num_edge_borders);
+
+ if (!num_poly_groups) {
+ /* Should never happen... */
+ return false;
+ }
+
+ if (num_edge_borders) {
+ edge_border_count = MEM_mallocN(sizeof(*edge_border_count) * (size_t)totedge, __func__);
+ edge_innercut_indices = MEM_mallocN(sizeof(*edge_innercut_indices) * (size_t)num_edge_borders, __func__);
+ }
+
+ /* Note: here we ignore '0' invalid group - this should *never* happen in this case anyway? */
+ for (grp_idx = 1; grp_idx <= num_poly_groups; grp_idx++) {
+ num_pidx = num_lidx = 0;
+ if (num_edge_borders) {
+ num_einnercuts = 0;
+ memset(edge_border_count, 0, sizeof(*edge_border_count) * (size_t)totedge);
+ }
+
+ for (p_idx = 0; p_idx < totpoly; p_idx++) {
+ MPoly *mp;
+
+ if (poly_groups[p_idx] != grp_idx) {
+ continue;
+ }
+
+ mp = &polys[p_idx];
+ poly_indices[num_pidx++] = p_idx;
+ for (l_idx = mp->loopstart, pl_idx = 0; pl_idx < mp->totloop; l_idx++, pl_idx++) {
+ MLoop *ml = &loops[l_idx];
+ loop_indices[num_lidx++] = l_idx;
+ if (num_edge_borders && BLI_BITMAP_TEST(edge_borders, ml->e) && (edge_border_count[ml->e] < 2)) {
+ edge_border_count[ml->e]++;
+ if (edge_border_count[ml->e] == 2) {
+ edge_innercut_indices[num_einnercuts++] = (int)ml->e;
+ }
+ }
+ }
+ }
+
+ BKE_mesh_loop_islands_add(r_island_store, num_lidx, loop_indices, num_pidx, poly_indices,
+ num_einnercuts, edge_innercut_indices);
+ }
+
+ MEM_freeN(poly_indices);
+ MEM_freeN(loop_indices);
+ MEM_freeN(poly_groups);
+ if (num_edge_borders) {
+ MEM_freeN(edge_border_count);
+ MEM_freeN(edge_innercut_indices);
+ }
+ return true;
+}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
new file mode 100644
index 00000000000..1deb7cfdd7f
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -0,0 +1,1988 @@
+/*
+ * ***** 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/blenkernel/intern/mesh_remap.c
+ * \ingroup bke
+ *
+ * Functions for mapping data between meshes.
+ */
+
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_meshdata_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
+#include "BLI_astar.h"
+#include "BLI_bitmap.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+#include "BLI_polyfill2d.h"
+#include "BLI_rand.h"
+
+#include "BKE_bvhutils.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h" /* own include */
+
+#include "BLI_strict_flags.h"
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh to mesh mapping
+ * \{ */
+
+void BKE_mesh_remap_init(MeshPairRemap *map, const int items_num)
+{
+ MemArena *mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ BKE_mesh_remap_free(map);
+
+ map->items = BLI_memarena_alloc(mem, sizeof(*map->items) * (size_t)items_num);
+ map->items_num = items_num;
+
+ map->mem = mem;
+}
+
+void BKE_mesh_remap_free(MeshPairRemap *map)
+{
+ if (map->mem) {
+ BLI_memarena_free((MemArena *)map->mem);
+ }
+
+ map->items_num = 0;
+ map->items = NULL;
+ map->mem = NULL;
+}
+
+static void mesh_remap_item_define(
+ MeshPairRemap *map, const int index, const float UNUSED(hit_dist), const int island,
+ const int sources_num, const int *indices_src, const float *weights_src)
+{
+ MeshPairRemapItem *mapit = &map->items[index];
+ MemArena *mem = map->mem;
+
+ if (sources_num) {
+ mapit->sources_num = sources_num;
+ mapit->indices_src = BLI_memarena_alloc(mem, sizeof(*mapit->indices_src) * (size_t)sources_num);
+ memcpy(mapit->indices_src, indices_src, sizeof(*mapit->indices_src) * (size_t)sources_num);
+ mapit->weights_src = BLI_memarena_alloc(mem, sizeof(*mapit->weights_src) * (size_t)sources_num);
+ memcpy(mapit->weights_src, weights_src, sizeof(*mapit->weights_src) * (size_t)sources_num);
+ }
+ else {
+ mapit->sources_num = 0;
+ mapit->indices_src = NULL;
+ mapit->weights_src = NULL;
+ }
+ /* UNUSED */
+ // mapit->hit_dist = hit_dist;
+ mapit->island = island;
+}
+
+void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, const int index)
+{
+ mesh_remap_item_define(map, index, FLT_MAX, 0, 0, NULL, NULL);
+}
+
+static int mesh_remap_interp_poly_data_get(
+ const MPoly *mp, MLoop *mloops, const float (*vcos_src)[3], const float point[3],
+ size_t *buff_size, float (**vcos)[3], const bool use_loops, int **indices, float **weights,
+ const bool do_weights, int *r_closest_index)
+{
+ MLoop *ml;
+ float (*vco)[3];
+ float ref_dist_sq = FLT_MAX;
+ int *index;
+ const int sources_num = mp->totloop;
+ int i;
+
+ if ((size_t)sources_num > *buff_size) {
+ *buff_size = (size_t)sources_num;
+ *vcos = MEM_reallocN(*vcos, sizeof(**vcos) * *buff_size);
+ *indices = MEM_reallocN(*indices, sizeof(**indices) * *buff_size);
+ if (do_weights) {
+ *weights = MEM_reallocN(*weights, sizeof(**weights) * *buff_size);
+ }
+ }
+
+ for (i = 0, ml = &mloops[mp->loopstart], vco = *vcos, index = *indices; i < sources_num; i++, ml++, vco++, index++) {
+ *index = use_loops ? (int)mp->loopstart + i : (int)ml->v;
+ copy_v3_v3(*vco, vcos_src[ml->v]);
+ if (r_closest_index) {
+ /* Find closest vert/loop in this case. */
+ const float dist_sq = len_squared_v3v3(point, *vco);
+ if (dist_sq < ref_dist_sq) {
+ ref_dist_sq = dist_sq;
+ *r_closest_index = *index;
+ }
+ }
+ }
+
+ if (do_weights) {
+ interp_weights_poly_v3(*weights, *vcos, sources_num, point);
+ }
+
+ return sources_num;
+}
+
+static bool mesh_remap_bvhtree_query_nearest(
+ BVHTreeFromMesh *treedata, BVHTreeNearest *nearest, const SpaceTransform *space_transform,
+ const float in_co[3], const float max_dist_sq,
+ float *r_hit_dist)
+{
+ float co[3];
+
+ copy_v3_v3(co, in_co);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, co);
+ }
+
+ /* Use local proximity heuristics (to reduce the nearest search). */
+ if (nearest->index != -1) {
+ nearest->dist_sq = min_ff(len_squared_v3v3(co, nearest->co), max_dist_sq);
+ }
+ else {
+ nearest->dist_sq = max_dist_sq;
+ }
+ /* Compute and store result. If invalid (-1 index), keep FLT_MAX dist. */
+ BLI_bvhtree_find_nearest(treedata->tree, co, nearest, treedata->nearest_callback, treedata);
+
+ if ((nearest->index != -1) && (nearest->dist_sq <= max_dist_sq)) {
+ *r_hit_dist = sqrtf(nearest->dist_sq);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+static bool mesh_remap_bvhtree_query_raycast(
+ BVHTreeFromMesh *treedata, BVHTreeRayHit *rayhit, const SpaceTransform *space_transform,
+ const float in_co[3], const float in_no[3], const float radius, const float max_dist,
+ float *r_hit_dist)
+{
+ BVHTreeRayHit rayhit_tmp;
+ float co[3], no[3];
+
+ copy_v3_v3(co, in_co);
+ copy_v3_v3(no, in_no);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, co);
+ BLI_space_transform_apply_normal(space_transform, no);
+ }
+
+ rayhit->index = -1;
+ rayhit->dist = max_dist;
+ BLI_bvhtree_ray_cast(treedata->tree, co, no, radius, rayhit, treedata->raycast_callback, treedata);
+
+ /* Also cast in the other direction! */
+ rayhit_tmp = *rayhit;
+ negate_v3(no);
+ BLI_bvhtree_ray_cast(treedata->tree, co, no, radius, &rayhit_tmp, treedata->raycast_callback, treedata);
+ if (rayhit_tmp.dist < rayhit->dist) {
+ *rayhit = rayhit_tmp;
+ }
+
+ if ((rayhit->index != -1) && (rayhit->dist <= max_dist)) {
+ *r_hit_dist = rayhit->dist;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/* Little helper when dealing with source islands */
+typedef struct IslandResult {
+ float factor; /* A factor, based on which best island for a given set of elements will be selected. */
+ int index_src; /* Index of the source. */
+ float hit_dist; /* The actual hit distance. */
+ float hit_point[3]; /* The hit point, if relevant. */
+} IslandResult;
+
+/* Note about all bvh/raycasting stuff below:
+ * * We must use our ray radius as BVH epsilon too, else rays not hitting anything but 'passing near' an item
+ * would be missed (since BVH handling would not detect them, 'refining' callbacks won't be executed,
+ * even though they would return a valid hit).
+ * * However, in 'islands' case where each hit gets a weight, 'precise' hits should have a better weight than
+ * 'approximate' hits. To address that, we simplify things with:
+ * ** A first raycast with default, given rayradius;
+ * ** If first one fails, we do more raycasting with bigger radius, but if hit is found
+ * it will get smaller weight.
+ * This only concerns loops, currently (because of islands), and 'sampled' edges/polys norproj.
+ */
+
+/* At most n raycasts per 'real' ray. */
+#define MREMAP_RAYCAST_APPROXIMATE_NR 3
+/* Each approximated raycasts will have n times bigger radius than previous one. */
+#define MREMAP_RAYCAST_APPROXIMATE_FAC 5.0f
+/* BVH epsilon value we have to give to bvh 'constructor' when doing approximated raycasting. */
+#define MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON(_ray_radius) \
+ ((float)MREMAP_RAYCAST_APPROXIMATE_NR * MREMAP_RAYCAST_APPROXIMATE_FAC * (_ray_radius))
+
+/* min 16 rays/face, max 400. */
+#define MREMAP_RAYCAST_TRI_SAMPLES_MIN 4
+#define MREMAP_RAYCAST_TRI_SAMPLES_MAX 20
+
+/* Will be enough in 99% of cases. */
+#define MREMAP_DEFAULT_BUFSIZE 32
+
+void BKE_mesh_remap_calc_verts_from_dm(
+ const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ const MVert *verts_dst, const int numverts_dst, const bool UNUSED(dirty_nors_dst), DerivedMesh *dm_src,
+ MeshPairRemap *r_map)
+{
+ const float full_weight = 1.0f;
+ const float max_dist_sq = max_dist * max_dist;
+ int i;
+
+ BLI_assert(mode & MREMAP_MODE_VERT);
+
+ BKE_mesh_remap_init(r_map, numverts_dst);
+
+ if (mode == MREMAP_MODE_TOPOLOGY) {
+ BLI_assert(numverts_dst == dm_src->getNumVerts(dm_src));
+ for (i = 0; i < numverts_dst; i++) {
+ mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
+ }
+ }
+ else {
+ BVHTreeFromMesh treedata = {NULL};
+ BVHTreeNearest nearest = {0};
+ BVHTreeRayHit rayhit = {0};
+ float hit_dist;
+
+ if (mode == MREMAP_MODE_VERT_NEAREST) {
+ bvhtree_from_mesh_verts(&treedata, dm_src, 0.0f, 2, 6);
+ nearest.index = -1;
+
+ for (i = 0; i < numverts_dst; i++) {
+ float tmp_co[3];
+
+ copy_v3_v3(tmp_co, verts_dst[i].co);
+
+ if (mesh_remap_bvhtree_query_nearest(
+ &treedata, &nearest, space_transform,
+ tmp_co, max_dist_sq, &hit_dist))
+ {
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &nearest.index, &full_weight);
+ }
+ else {
+ /* No source for this dest vertex! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+ }
+ else if (ELEM(mode, MREMAP_MODE_VERT_EDGE_NEAREST, MREMAP_MODE_VERT_EDGEINTERP_NEAREST)) {
+ MEdge *edges_src = dm_src->getEdgeArray(dm_src);
+ float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)dm_src->getNumVerts(dm_src), __func__);
+ dm_src->getVertCos(dm_src, vcos_src);
+
+ bvhtree_from_mesh_edges(&treedata, dm_src, 0.0f, 2, 6);
+ nearest.index = -1;
+
+ for (i = 0; i < numverts_dst; i++) {
+ float tmp_co[3];
+
+ copy_v3_v3(tmp_co, verts_dst[i].co);
+
+ if (mesh_remap_bvhtree_query_nearest(
+ &treedata, &nearest, space_transform,
+ tmp_co, max_dist_sq, &hit_dist))
+ {
+ MEdge *me = &edges_src[nearest.index];
+ const float *v1cos = vcos_src[me->v1];
+ const float *v2cos = vcos_src[me->v2];
+
+ if (mode == MREMAP_MODE_VERT_EDGE_NEAREST) {
+ const float dist_v1 = len_squared_v3v3(tmp_co, v1cos);
+ const float dist_v2 = len_squared_v3v3(tmp_co, v2cos);
+ const int index = (int)((dist_v1 > dist_v2) ? me->v2 : me->v1);
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &index, &full_weight);
+ }
+ else if (mode == MREMAP_MODE_VERT_EDGEINTERP_NEAREST) {
+ int indices[2];
+ float weights[2];
+
+ indices[0] = (int)me->v1;
+ indices[1] = (int)me->v2;
+
+ /* Weight is inverse of point factor here... */
+ weights[0] = line_point_factor_v3(tmp_co, v2cos, v1cos);
+ CLAMP(weights[0], 0.0f, 1.0f);
+ weights[1] = 1.0f - weights[0];
+
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 2, indices, weights);
+ }
+ }
+ else {
+ /* No source for this dest vertex! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+
+ MEM_freeN(vcos_src);
+ }
+ else if (ELEM(mode, MREMAP_MODE_VERT_POLY_NEAREST, MREMAP_MODE_VERT_POLYINTERP_NEAREST,
+ MREMAP_MODE_VERT_POLYINTERP_VNORPROJ))
+ {
+ MPoly *polys_src = dm_src->getPolyArray(dm_src);
+ MLoop *loops_src = dm_src->getLoopArray(dm_src);
+ float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)dm_src->getNumVerts(dm_src), __func__);
+ int *tessface_to_poly_map_src;
+
+ size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE;
+ float (*vcos)[3] = MEM_mallocN(sizeof(*vcos) * tmp_buff_size, __func__);
+ int *indices = MEM_mallocN(sizeof(*indices) * tmp_buff_size, __func__);
+ float *weights = MEM_mallocN(sizeof(*weights) * tmp_buff_size, __func__);
+
+ dm_src->getVertCos(dm_src, vcos_src);
+ bvhtree_from_mesh_faces(&treedata, dm_src, (mode & MREMAP_USE_NORPROJ) ? ray_radius : 0.0f, 2, 6);
+ /* bvhtree here uses tesselated faces... */
+ tessface_to_poly_map_src = dm_src->getTessFaceDataArray(dm_src, CD_ORIGINDEX);
+
+ if (mode == MREMAP_MODE_VERT_POLYINTERP_VNORPROJ) {
+ for (i = 0; i < numverts_dst; i++) {
+ float tmp_co[3], tmp_no[3];
+
+ copy_v3_v3(tmp_co, verts_dst[i].co);
+ normal_short_to_float_v3(tmp_no, verts_dst[i].no);
+
+ if (mesh_remap_bvhtree_query_raycast(
+ &treedata, &rayhit, space_transform,
+ tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
+ {
+ MPoly *mp_src = &polys_src[tessface_to_poly_map_src[rayhit.index]];
+ const int sources_num = mesh_remap_interp_poly_data_get(
+ mp_src, loops_src, (const float (*)[3])vcos_src, rayhit.co,
+ &tmp_buff_size, &vcos, false, &indices, &weights, true, NULL);
+
+ mesh_remap_item_define(r_map, i, hit_dist, 0, sources_num, indices, weights);
+ }
+ else {
+ /* No source for this dest vertex! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+ }
+ else {
+ nearest.index = -1;
+
+ for (i = 0; i < numverts_dst; i++) {
+ float tmp_co[3];
+
+ /* Convert the vertex to tree coordinates. */
+ copy_v3_v3(tmp_co, verts_dst[i].co);
+
+ if (mesh_remap_bvhtree_query_nearest(
+ &treedata, &nearest, space_transform,
+ tmp_co, max_dist_sq, &hit_dist))
+ {
+ MPoly *mp = &polys_src[tessface_to_poly_map_src[nearest.index]];
+
+ if (mode == MREMAP_MODE_VERT_POLY_NEAREST) {
+ int index;
+ mesh_remap_interp_poly_data_get(
+ mp, loops_src, (const float (*)[3])vcos_src, nearest.co,
+ &tmp_buff_size, &vcos, false, &indices, &weights, false,
+ &index);
+
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &index, &full_weight);
+ }
+ else if (mode == MREMAP_MODE_VERT_POLYINTERP_NEAREST) {
+ const int sources_num = mesh_remap_interp_poly_data_get(
+ mp, loops_src, (const float (*)[3])vcos_src, nearest.co,
+ &tmp_buff_size, &vcos, false, &indices, &weights, true,
+ NULL);
+
+ mesh_remap_item_define(r_map, i, hit_dist, 0, sources_num, indices, weights);
+ }
+ }
+ else {
+ /* No source for this dest vertex! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+ }
+
+ MEM_freeN(vcos_src);
+ MEM_freeN(vcos);
+ MEM_freeN(indices);
+ MEM_freeN(weights);
+ }
+ else {
+ printf("WARNING! Unsupported mesh-to-mesh vertex mapping mode (%d)!\n", mode);
+ memset(r_map->items, 0, sizeof(*r_map->items) * (size_t)numverts_dst);
+ }
+
+ free_bvhtree_from_mesh(&treedata);
+ }
+}
+
+void BKE_mesh_remap_calc_edges_from_dm(
+ const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ const MVert *verts_dst, const int numverts_dst, const MEdge *edges_dst, const int numedges_dst,
+ const bool UNUSED(dirty_nors_dst), DerivedMesh *dm_src, MeshPairRemap *r_map)
+{
+ const float full_weight = 1.0f;
+ const float max_dist_sq = max_dist * max_dist;
+ int i;
+
+ BLI_assert(mode & MREMAP_MODE_EDGE);
+
+ BKE_mesh_remap_init(r_map, numedges_dst);
+
+ if (mode == MREMAP_MODE_TOPOLOGY) {
+ BLI_assert(numedges_dst == dm_src->getNumEdges(dm_src));
+ for (i = 0; i < numedges_dst; i++) {
+ mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
+ }
+ }
+ else {
+ BVHTreeFromMesh treedata = {NULL};
+ BVHTreeNearest nearest = {0};
+ BVHTreeRayHit rayhit = {0};
+ float hit_dist;
+
+ if (mode == MREMAP_MODE_EDGE_VERT_NEAREST) {
+ const int num_verts_src = dm_src->getNumVerts(dm_src);
+ const int num_edges_src = dm_src->getNumEdges(dm_src);
+ MEdge *edges_src = dm_src->getEdgeArray(dm_src);
+ float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)dm_src->getNumVerts(dm_src), __func__);
+
+ MeshElemMap *vert_to_edge_src_map;
+ int *vert_to_edge_src_map_mem;
+
+ struct {
+ float hit_dist;
+ int index;
+ } *v_dst_to_src_map = MEM_mallocN(sizeof(*v_dst_to_src_map) * (size_t)numverts_dst, __func__);
+
+ for (i = 0; i < numverts_dst; i++) {
+ v_dst_to_src_map[i].hit_dist = -1.0f;
+ }
+
+ BKE_mesh_vert_edge_map_create(&vert_to_edge_src_map, &vert_to_edge_src_map_mem,
+ edges_src, num_verts_src, num_edges_src);
+
+ dm_src->getVertCos(dm_src, vcos_src);
+
+ bvhtree_from_mesh_verts(&treedata, dm_src, 0.0f, 2, 6);
+ nearest.index = -1;
+
+ for (i = 0; i < numedges_dst; i++) {
+ const MEdge *e_dst = &edges_dst[i];
+ float best_totdist = FLT_MAX;
+ int best_eidx_src = -1;
+ int j = 2;
+
+ while (j--) {
+ const unsigned int vidx_dst = j ? e_dst->v1 : e_dst->v2;
+
+ /* Compute closest verts only once! */
+ if (v_dst_to_src_map[vidx_dst].hit_dist == -1.0f) {
+ float tmp_co[3];
+
+ copy_v3_v3(tmp_co, verts_dst[vidx_dst].co);
+
+ if (mesh_remap_bvhtree_query_nearest(
+ &treedata, &nearest, space_transform,
+ tmp_co, max_dist_sq, &hit_dist))
+ {
+ v_dst_to_src_map[vidx_dst].hit_dist = hit_dist;
+ v_dst_to_src_map[vidx_dst].index = nearest.index;
+ }
+ else {
+ /* No source for this dest vert! */
+ v_dst_to_src_map[vidx_dst].hit_dist = FLT_MAX;
+ }
+ }
+ }
+
+ /* Now, check all source edges of closest sources vertices, and select the one giving the smallest
+ * total verts-to-verts distance. */
+ for (j = 2; j--;) {
+ const unsigned int vidx_dst = j ? e_dst->v1 : e_dst->v2;
+ const float first_dist = v_dst_to_src_map[vidx_dst].hit_dist;
+ const int vidx_src = v_dst_to_src_map[vidx_dst].index;
+ int *eidx_src, k;
+
+ if (vidx_src < 0) {
+ continue;
+ }
+
+ eidx_src = vert_to_edge_src_map[vidx_src].indices;
+ k = vert_to_edge_src_map[vidx_src].count;
+
+ for (; k--; eidx_src++) {
+ MEdge *e_src = &edges_src[*eidx_src];
+ const float *other_co_src = vcos_src[BKE_mesh_edge_other_vert(e_src, vidx_src)];
+ const float *other_co_dst = verts_dst[BKE_mesh_edge_other_vert(e_dst, (int)vidx_dst)].co;
+ const float totdist = first_dist + len_v3v3(other_co_src, other_co_dst);
+
+ if (totdist < best_totdist) {
+ best_totdist = totdist;
+ best_eidx_src = *eidx_src;
+ }
+ }
+ }
+
+ if (best_eidx_src >= 0) {
+ const float *co1_src = vcos_src[edges_src[best_eidx_src].v1];
+ const float *co2_src = vcos_src[edges_src[best_eidx_src].v2];
+ const float *co1_dst = verts_dst[e_dst->v1].co;
+ const float *co2_dst = verts_dst[e_dst->v2].co;
+ float co_src[3], co_dst[3];
+
+ /* TODO: would need an isect_seg_seg_v3(), actually! */
+ const int isect_type = isect_line_line_v3(co1_src, co2_src, co1_dst, co2_dst, co_src, co_dst);
+ if (isect_type != 0) {
+ const float fac_src = line_point_factor_v3(co_src, co1_src, co2_src);
+ const float fac_dst = line_point_factor_v3(co_dst, co1_dst, co2_dst);
+ if (fac_src < 0.0f) {
+ copy_v3_v3(co_src, co1_src);
+ }
+ else if (fac_src > 1.0f) {
+ copy_v3_v3(co_src, co2_src);
+ }
+ if (fac_dst < 0.0f) {
+ copy_v3_v3(co_dst, co1_dst);
+ }
+ else if (fac_dst > 1.0f) {
+ copy_v3_v3(co_dst, co2_dst);
+ }
+ }
+ hit_dist = len_v3v3(co_dst, co_src);
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &best_eidx_src, &full_weight);
+ }
+ else {
+ /* No source for this dest edge! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+
+ MEM_freeN(vcos_src);
+ MEM_freeN(v_dst_to_src_map);
+ MEM_freeN(vert_to_edge_src_map);
+ MEM_freeN(vert_to_edge_src_map_mem);
+ }
+ else if (mode == MREMAP_MODE_EDGE_NEAREST) {
+ bvhtree_from_mesh_edges(&treedata, dm_src, 0.0f, 2, 6);
+ nearest.index = -1;
+
+ for (i = 0; i < numedges_dst; i++) {
+ float tmp_co[3];
+
+ interp_v3_v3v3(tmp_co, verts_dst[edges_dst[i].v1].co, verts_dst[edges_dst[i].v2].co, 0.5f);
+
+ if (mesh_remap_bvhtree_query_nearest(
+ &treedata, &nearest, space_transform,
+ tmp_co, max_dist_sq, &hit_dist))
+ {
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &nearest.index, &full_weight);
+ }
+ else {
+ /* No source for this dest edge! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+ }
+ else if (mode == MREMAP_MODE_EDGE_POLY_NEAREST) {
+ MEdge *edges_src = dm_src->getEdgeArray(dm_src);
+ MPoly *polys_src = dm_src->getPolyArray(dm_src);
+ MLoop *loops_src = dm_src->getLoopArray(dm_src);
+ float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)dm_src->getNumVerts(dm_src), __func__);
+ int *tessface_to_poly_map_src;
+
+ dm_src->getVertCos(dm_src, vcos_src);
+ bvhtree_from_mesh_faces(&treedata, dm_src, 0.0f, 2, 6);
+ /* bvhtree here uses tesselated faces... */
+ tessface_to_poly_map_src = dm_src->getTessFaceDataArray(dm_src, CD_ORIGINDEX);
+
+ for (i = 0; i < numedges_dst; i++) {
+ float tmp_co[3];
+
+ interp_v3_v3v3(tmp_co, verts_dst[edges_dst[i].v1].co, verts_dst[edges_dst[i].v2].co, 0.5f);
+
+ if (mesh_remap_bvhtree_query_nearest(
+ &treedata, &nearest, space_transform,
+ tmp_co, max_dist_sq, &hit_dist))
+ {
+ MPoly *mp_src = &polys_src[tessface_to_poly_map_src[nearest.index]];
+ MLoop *ml_src = &loops_src[mp_src->loopstart];
+ int nloops = mp_src->totloop;
+ float best_dist_sq = FLT_MAX;
+ int best_eidx_src = -1;
+
+ for (; nloops--; ml_src++) {
+ MEdge *me_src = &edges_src[ml_src->e];
+ float *co1_src = vcos_src[me_src->v1];
+ float *co2_src = vcos_src[me_src->v2];
+ float co_src[3];
+ float dist_sq;
+
+ interp_v3_v3v3(co_src, co1_src, co2_src, 0.5f);
+ dist_sq = len_squared_v3v3(tmp_co, co_src);
+ if (dist_sq < best_dist_sq) {
+ best_dist_sq = dist_sq;
+ best_eidx_src = (int)ml_src->e;
+ }
+ }
+ if (best_eidx_src >= 0) {
+ mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &best_eidx_src, &full_weight);
+ }
+ }
+ else {
+ /* No source for this dest edge! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+
+ MEM_freeN(vcos_src);
+ }
+ else if (mode == MREMAP_MODE_EDGE_EDGEINTERP_VNORPROJ) {
+ const int num_rays_min = 5, num_rays_max = 100;
+ const int numedges_src = dm_src->getNumEdges(dm_src);
+
+ /* Subtleness - this one we can allocate only max number of cast rays per edges! */
+ int *indices = MEM_mallocN(sizeof(*indices) * (size_t)min_ii(numedges_src, num_rays_max), __func__);
+ /* Here it's simpler to just allocate for all edges :/ */
+ float *weights = MEM_mallocN(sizeof(*weights) * (size_t)numedges_src, __func__);
+
+ bvhtree_from_mesh_edges(&treedata, dm_src, MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON(ray_radius), 2, 6);
+
+ for (i = 0; i < numedges_dst; i++) {
+ /* For each dst edge, we sample some rays from it (interpolated from its vertices)
+ * and use their hits to interpolate from source edges. */
+ const MEdge *me = &edges_dst[i];
+ float tmp_co[3], v1_co[3], v2_co[3];
+ float tmp_no[3], v1_no[3], v2_no[3];
+
+ int grid_size;
+ float edge_dst_len;
+ float grid_step;
+
+ float totweights = 0.0f;
+ float hit_dist_accum = 0.0f;
+ int sources_num = 0;
+ int j;
+
+ copy_v3_v3(v1_co, verts_dst[me->v1].co);
+ copy_v3_v3(v2_co, verts_dst[me->v2].co);
+
+ normal_short_to_float_v3(v1_no, verts_dst[me->v1].no);
+ normal_short_to_float_v3(v2_no, verts_dst[me->v2].no);
+
+ /* We do our transform here, allows to interpolate from normals already in src space. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, v1_co);
+ BLI_space_transform_apply(space_transform, v2_co);
+ BLI_space_transform_apply_normal(space_transform, v1_no);
+ BLI_space_transform_apply_normal(space_transform, v2_no);
+ }
+
+ fill_vn_fl(weights, (int)numedges_src, 0.0f);
+
+ /* We adjust our ray-casting grid to ray_radius (the smaller, the more rays are cast),
+ * with lower/upper bounds. */
+ edge_dst_len = len_v3v3(v1_co, v2_co);
+
+ grid_size = (int)((edge_dst_len / ray_radius) + 0.5f);
+ CLAMP(grid_size, num_rays_min, num_rays_max); /* min 5 rays/edge, max 100. */
+
+ grid_step = 1.0f / (float)grid_size; /* Not actual distance here, rather an interp fac... */
+
+ /* And now we can cast all our rays, and see what we get! */
+ for (j = 0; j < grid_size; j++) {
+ const float fac = grid_step * (float)j;
+
+ int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1;
+ float w = 1.0f;
+
+ interp_v3_v3v3(tmp_co, v1_co, v2_co, fac);
+ interp_v3_v3v3_slerp_safe(tmp_no, v1_no, v2_no, fac);
+
+ while (n--) {
+ /* Note we handle dest to src space conversion ourself, here! */
+ if (mesh_remap_bvhtree_query_raycast(
+ &treedata, &rayhit, NULL,
+ tmp_co, tmp_no, ray_radius / w, max_dist, &hit_dist))
+ {
+ weights[rayhit.index] += w;
+ totweights += w;
+ hit_dist_accum += hit_dist;
+ break;
+ }
+ /* Next iteration will get bigger radius but smaller weight! */
+ w /= MREMAP_RAYCAST_APPROXIMATE_FAC;
+ }
+ }
+ /* A sampling is valid (as in, its result can be considered as valid sources) only if at least
+ * half of the rays found a source! */
+ if (totweights > ((float)grid_size / 2.0f)) {
+ for (j = 0; j < (int)numedges_src; j++) {
+ if (!weights[j]) {
+ continue;
+ }
+ /* Note: sources_num is always <= j! */
+ weights[sources_num] = weights[j] / totweights;
+ indices[sources_num] = j;
+ sources_num++;
+ }
+ mesh_remap_item_define(r_map, i, hit_dist_accum / totweights, 0,
+ sources_num, indices, weights);
+ }
+ else {
+ /* No source for this dest edge! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+
+ MEM_freeN(indices);
+ MEM_freeN(weights);
+ }
+ else {
+ printf("WARNING! Unsupported mesh-to-mesh edge mapping mode (%d)!\n", mode);
+ memset(r_map->items, 0, sizeof(*r_map->items) * (size_t)numedges_dst);
+ }
+
+ free_bvhtree_from_mesh(&treedata);
+ }
+}
+
+#define POLY_UNSET 0
+#define POLY_CENTER_INIT 1
+#define POLY_COMPLETE 2
+
+static void mesh_island_to_astar_graph_edge_process(
+ MeshIslandStore *islands, const int island_index, BLI_AStarGraph *as_graph,
+ MVert *verts, MPoly *polys, MLoop *loops,
+ const int edge_idx, BLI_bitmap *done_edges, MeshElemMap *edge_to_poly_map, const bool is_edge_innercut,
+ int *poly_island_index_map, float (*poly_centers)[3], unsigned char *poly_status)
+{
+ int *poly_island_indices = BLI_array_alloca(poly_island_indices, (size_t)edge_to_poly_map[edge_idx].count);
+ int i, j;
+
+ for (i = 0; i < edge_to_poly_map[edge_idx].count; i++) {
+ const int pidx = edge_to_poly_map[edge_idx].indices[i];
+ MPoly *mp = &polys[pidx];
+ const int pidx_isld = islands ? poly_island_index_map[pidx] : pidx;
+ void *custom_data = is_edge_innercut ? SET_INT_IN_POINTER(edge_idx) : SET_INT_IN_POINTER(-1);
+
+ if (UNLIKELY(islands && (islands->items_to_islands[mp->loopstart] != island_index))) {
+ /* poly not in current island, happens with border edges... */
+ poly_island_indices[i] = -1;
+ continue;
+ }
+
+ if (poly_status[pidx_isld] == POLY_COMPLETE) {
+ poly_island_indices[i] = pidx_isld;
+ continue;
+ }
+
+ if (poly_status[pidx_isld] == POLY_UNSET) {
+ BKE_mesh_calc_poly_center(mp, &loops[mp->loopstart], verts, poly_centers[pidx_isld]);
+ BLI_astar_node_init(as_graph, pidx_isld, poly_centers[pidx_isld]);
+ poly_status[pidx_isld] = POLY_CENTER_INIT;
+ }
+
+ for (j = i; j--;) {
+ float dist_cost;
+ const int pidx_isld_other = poly_island_indices[j];
+
+ if (pidx_isld_other == -1 || poly_status[pidx_isld_other] == POLY_COMPLETE) {
+ /* If the other poly is complete, that link has already been added! */
+ continue;
+ }
+ dist_cost = len_v3v3(poly_centers[pidx_isld_other], poly_centers[pidx_isld]);
+ BLI_astar_node_link_add(as_graph, pidx_isld_other, pidx_isld, dist_cost, custom_data);
+ }
+
+ poly_island_indices[i] = pidx_isld;
+ }
+
+ BLI_BITMAP_ENABLE(done_edges, edge_idx);
+}
+
+static void mesh_island_to_astar_graph(
+ MeshIslandStore *islands, const int island_index,
+ MVert *verts, MeshElemMap *edge_to_poly_map, const int numedges, MLoop *loops, MPoly *polys, const int numpolys,
+ BLI_AStarGraph *r_as_graph)
+{
+ MeshElemMap *island_poly_map = islands ? islands->islands[island_index] : NULL;
+ MeshElemMap *island_einnercut_map = islands ? islands->innercuts[island_index] : NULL;
+
+ int *poly_island_index_map = NULL;
+ BLI_bitmap *done_edges = BLI_BITMAP_NEW(numedges, __func__);
+
+ const int node_num = islands ? island_poly_map->count : numpolys;
+ unsigned char *poly_status = MEM_callocN(sizeof(*poly_status) * (size_t)node_num, __func__);
+ float (*poly_centers)[3];
+
+ int pidx_isld;
+ int i;
+
+ BLI_astar_graph_init(r_as_graph, node_num, NULL);
+ /* poly_centers is owned by graph memarena. */
+ poly_centers = BLI_memarena_calloc(r_as_graph->mem, sizeof(*poly_centers) * (size_t)node_num);
+
+ if (islands) {
+ /* poly_island_index_map is owned by graph memarena. */
+ poly_island_index_map = BLI_memarena_calloc(r_as_graph->mem, sizeof(*poly_island_index_map) * (size_t)numpolys);
+ for (i = island_poly_map->count; i--;) {
+ poly_island_index_map[island_poly_map->indices[i]] = i;
+ }
+
+ r_as_graph->custom_data = poly_island_index_map;
+
+ for (i = island_einnercut_map->count; i--;) {
+ mesh_island_to_astar_graph_edge_process(
+ islands, island_index, r_as_graph, verts, polys, loops,
+ island_einnercut_map->indices[i], done_edges, edge_to_poly_map, true,
+ poly_island_index_map, poly_centers, poly_status);
+ }
+ }
+
+ for (pidx_isld = node_num; pidx_isld--;) {
+ const int pidx = islands ? island_poly_map->indices[pidx_isld] : pidx_isld;
+ MPoly *mp = &polys[pidx];
+ int pl_idx, l_idx;
+
+ if (poly_status[pidx_isld] == POLY_COMPLETE) {
+ continue;
+ }
+
+ for (pl_idx = 0, l_idx = mp->loopstart; pl_idx < mp->totloop; pl_idx++, l_idx++) {
+ MLoop *ml = &loops[l_idx];
+
+ if (BLI_BITMAP_TEST(done_edges, ml->e)) {
+ continue;
+ }
+
+ mesh_island_to_astar_graph_edge_process(
+ islands, island_index, r_as_graph, verts, polys, loops,
+ (int)ml->e, done_edges, edge_to_poly_map, false,
+ poly_island_index_map, poly_centers, poly_status);
+ }
+ poly_status[pidx_isld] = POLY_COMPLETE;
+ }
+
+ MEM_freeN(done_edges);
+ MEM_freeN(poly_status);
+}
+
+#undef POLY_UNSET
+#undef POLY_CENTER_INIT
+#undef POLY_COMPLETE
+
+/* Our 'f_cost' callback func, to find shortest poly-path between two remapped-loops.
+ * Note we do not want to make innercuts 'walls' here, just detect when the shortest path goes by those. */
+static float mesh_remap_calc_loops_astar_f_cost(
+ BLI_AStarGraph *as_graph, BLI_AStarSolution *as_solution, BLI_AStarGNLink *link,
+ const int node_idx_curr, const int node_idx_next, const int node_idx_dst)
+{
+ float *co_next, *co_dest;
+
+ if (link && (GET_INT_FROM_POINTER(link->custom_data) != -1)) {
+ /* An innercut edge... We tag our solution as potentially crossing innercuts.
+ * Note it might not be the case in the end (AStar will explore around optimal path), but helps
+ * trimming off some processing later... */
+ if (!GET_INT_FROM_POINTER(as_solution->custom_data)) {
+ as_solution->custom_data = SET_INT_IN_POINTER(true);
+ }
+ }
+
+ /* Our heuristic part of current f_cost is distance from next node to destination one.
+ * It is guaranteed to be less than (or equal to) actual shortest poly-path between next node and destination one.
+ */
+ co_next = (float *)as_graph->nodes[node_idx_next].custom_data;
+ co_dest = (float *)as_graph->nodes[node_idx_dst].custom_data;
+ return (link ? (as_solution->g_costs[node_idx_curr] + link->cost) : 0.0f) + len_v3v3(co_next, co_dest);
+}
+
+#define ASTAR_STEPS_MAX 64
+
+
+void BKE_mesh_remap_calc_loops_from_dm(
+ const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ MVert *verts_dst, const int numverts_dst, MEdge *edges_dst, const int numedges_dst,
+ MLoop *loops_dst, const int numloops_dst, MPoly *polys_dst, const int numpolys_dst,
+ CustomData *ldata_dst, CustomData *pdata_dst, const float split_angle_dst, const bool dirty_nors_dst,
+ DerivedMesh *dm_src,
+ MeshRemapIslandsCalc gen_islands_src, const float islands_precision_src, MeshPairRemap *r_map)
+{
+ const float full_weight = 1.0f;
+ const float max_dist_sq = max_dist * max_dist;
+
+ int i;
+
+ BLI_assert(mode & MREMAP_MODE_LOOP);
+ BLI_assert((islands_precision_src >= 0.0f) && (islands_precision_src <= 1.0f));
+
+ BKE_mesh_remap_init(r_map, numloops_dst);
+
+ if (mode == MREMAP_MODE_TOPOLOGY) {
+ /* In topology mapping, we assume meshes are identical, islands included! */
+ BLI_assert(numloops_dst == dm_src->getNumLoops(dm_src));
+ for (i = 0; i < numloops_dst; i++) {
+ mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
+ }
+ }
+ else {
+ BVHTreeFromMesh *treedata = NULL;
+ BVHTreeNearest nearest = {0};
+ BVHTreeRayHit rayhit = {0};
+ int num_trees = 0;
+ float hit_dist;
+
+ const bool use_from_vert = (mode & MREMAP_USE_VERT);
+
+ MeshIslandStore island_store = {0};
+ bool use_islands = false;
+
+ BLI_AStarGraph *as_graphdata = NULL;
+ BLI_AStarSolution as_solution = {0};
+ const int isld_steps_src = islands_precision_src ?
+ max_ii((int)(ASTAR_STEPS_MAX * islands_precision_src + 0.499f), 1) : 0;
+
+ float (*poly_nors_src)[3] = NULL;
+ float (*loop_nors_src)[3] = NULL;
+ float (*poly_nors_dst)[3] = NULL;
+ float (*loop_nors_dst)[3] = NULL;
+
+ MeshElemMap *vert_to_loop_map_src = NULL;
+ int *vert_to_loop_map_src_buff = NULL;
+ MeshElemMap *vert_to_poly_map_src = NULL;
+ int *vert_to_poly_map_src_buff = NULL;
+ MeshElemMap *edge_to_poly_map_src = NULL;
+ int *edge_to_poly_map_src_buff = NULL;
+ MeshElemMap *poly_to_tessface_map_src = NULL;
+ int *poly_to_tessface_map_src_buff = NULL;
+
+ /* Unlike above, those are one-to-one mappings, simpler! */
+ int *loop_to_poly_map_src = NULL;
+ int *tessface_to_poly_map_src = NULL;
+
+ bool verts_allocated_src;
+ MVert *verts_src = DM_get_vert_array(dm_src, &verts_allocated_src);
+ const int num_verts_src = dm_src->getNumVerts(dm_src);
+ float (*vcos_src)[3] = NULL;
+ bool edges_allocated_src;
+ MEdge *edges_src = DM_get_edge_array(dm_src, &edges_allocated_src);
+ const int num_edges_src = dm_src->getNumEdges(dm_src);
+ bool loops_allocated_src;
+ MLoop *loops_src = DM_get_loop_array(dm_src, &loops_allocated_src);
+ const int num_loops_src = dm_src->getNumLoops(dm_src);
+ bool polys_allocated_src;
+ MPoly *polys_src = DM_get_poly_array(dm_src, &polys_allocated_src);
+ const int num_polys_src = dm_src->getNumPolys(dm_src);
+ bool faces_allocated_src = false;
+ MFace *faces_src = NULL;
+ int num_faces_src = 0;
+
+ size_t buff_size_interp = MREMAP_DEFAULT_BUFSIZE;
+ float (*vcos_interp)[3] = NULL;
+ int *indices_interp = NULL;
+ float *weights_interp = NULL;
+
+ int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src;
+
+ IslandResult **islands_res;
+ size_t islands_res_buff_size = MREMAP_DEFAULT_BUFSIZE;
+
+ const float bvh_epsilon = (mode & MREMAP_USE_NORPROJ) ? MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON(ray_radius) : 0.0f;
+
+ if (!use_from_vert) {
+ vcos_src = MEM_mallocN(sizeof(*vcos_src) * (size_t)num_verts_src, __func__);
+ dm_src->getVertCos(dm_src, vcos_src);
+
+ vcos_interp = MEM_mallocN(sizeof(*vcos_interp) * buff_size_interp, __func__);
+ indices_interp = MEM_mallocN(sizeof(*indices_interp) * buff_size_interp, __func__);
+ weights_interp = MEM_mallocN(sizeof(*weights_interp) * buff_size_interp, __func__);
+ }
+
+ {
+ const bool need_lnors_src = (mode & MREMAP_USE_LOOP) && (mode & MREMAP_USE_NORMAL);
+ const bool need_lnors_dst = need_lnors_src || (mode & MREMAP_USE_NORPROJ);
+ const bool need_pnors_src = need_lnors_src || ((mode & MREMAP_USE_POLY) && (mode & MREMAP_USE_NORMAL));
+ const bool need_pnors_dst = need_lnors_dst || need_pnors_src;
+
+ if (need_pnors_dst) {
+ /* Cache poly nors into a temp CDLayer. */
+ poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL);
+ if (!poly_nors_dst) {
+ poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, numpolys_dst);
+ CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
+ }
+ if (dirty_nors_dst) {
+ BKE_mesh_calc_normals_poly(verts_dst, numverts_dst, loops_dst, polys_dst,
+ numloops_dst, numpolys_dst, poly_nors_dst, true);
+ }
+ }
+ if (need_lnors_dst) {
+ /* Cache poly nors into a temp CDLayer. */
+ loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL);
+ if (!loop_nors_dst) {
+ loop_nors_dst = CustomData_add_layer(ldata_dst, CD_NORMAL, CD_CALLOC, NULL, numloops_dst);
+ CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
+ }
+ if (dirty_nors_dst) {
+ BKE_mesh_normals_loop_split(verts_dst, numverts_dst, edges_dst, numedges_dst,
+ loops_dst, loop_nors_dst, numloops_dst,
+ polys_dst, poly_nors_dst, numpolys_dst, split_angle_dst);
+ }
+ }
+ if (need_pnors_src || need_lnors_src) {
+ /* Simpler for now, calcNormals never stores pnors :( */
+ dm_src->calcLoopNormals(dm_src, /* TODO */ (float)M_PI);
+
+ if (need_pnors_src) {
+ poly_nors_src = dm_src->getPolyDataArray(dm_src, CD_NORMAL);
+ }
+ if (need_lnors_src) {
+ loop_nors_src = dm_src->getLoopDataArray(dm_src, CD_NORMAL);
+ }
+ }
+ }
+
+ if (use_from_vert) {
+ BKE_mesh_vert_loop_map_create(&vert_to_loop_map_src, &vert_to_loop_map_src_buff,
+ polys_src, loops_src, num_verts_src, num_polys_src, num_loops_src);
+ if (mode & MREMAP_USE_POLY) {
+ BKE_mesh_vert_poly_map_create(&vert_to_poly_map_src, &vert_to_poly_map_src_buff,
+ polys_src, loops_src, num_verts_src, num_polys_src, num_loops_src);
+ }
+ }
+
+ /* Needed for islands (or plain mesh) to AStar graph conversion. */
+ BKE_mesh_edge_poly_map_create(&edge_to_poly_map_src, &edge_to_poly_map_src_buff,
+ edges_src, num_edges_src, polys_src, num_polys_src, loops_src, num_loops_src);
+ if (use_from_vert) {
+ loop_to_poly_map_src = MEM_mallocN(sizeof(*loop_to_poly_map_src) * (size_t)num_loops_src, __func__);
+ for (pidx_src = 0; pidx_src < num_polys_src; pidx_src++) {
+ MPoly *mp = &polys_src[pidx_src];
+ for (plidx_src = 0, lidx_src = mp->loopstart; plidx_src < mp->totloop; plidx_src++, lidx_src++) {
+ loop_to_poly_map_src[lidx_src] = pidx_src;
+ }
+ }
+ }
+
+ /* Island makes things slightly more complex here.
+ * Basically, we:
+ * * Make one treedata for each island's elements.
+ * * Check all loops of a same dest poly against all treedata.
+ * * Choose the island's elements giving the best results.
+ */
+
+ /* First, generate the islands, if possible. */
+ if (gen_islands_src) {
+ use_islands = gen_islands_src(
+ verts_src, num_verts_src,
+ edges_src, num_edges_src,
+ polys_src, num_polys_src,
+ loops_src, num_loops_src,
+ &island_store);
+
+ num_trees = use_islands ? island_store.islands_num : 1;
+ treedata = MEM_callocN(sizeof(*treedata) * (size_t)num_trees, __func__);
+ if (isld_steps_src) {
+ as_graphdata = MEM_callocN(sizeof(*as_graphdata) * (size_t)num_trees, __func__);
+ }
+
+ if (use_islands) {
+ /* We expect our islands to contain poly indices, with edge indices of 'inner cuts',
+ * and a mapping loops -> islands indices.
+ * This implies all loops of a same poly are in the same island. */
+ BLI_assert((island_store.item_type == MISLAND_TYPE_LOOP) &&
+ (island_store.island_type == MISLAND_TYPE_POLY) &&
+ (island_store.innercut_type == MISLAND_TYPE_EDGE));
+ }
+ }
+ else {
+ num_trees = 1;
+ treedata = MEM_callocN(sizeof(*treedata), __func__);
+ if (isld_steps_src) {
+ as_graphdata = MEM_callocN(sizeof(*as_graphdata), __func__);
+ }
+ }
+
+ /* Build our AStar graphs. */
+ if (isld_steps_src) {
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ mesh_island_to_astar_graph(
+ use_islands ? &island_store : NULL, tindex, verts_src, edge_to_poly_map_src, num_edges_src,
+ loops_src, polys_src, num_polys_src, &as_graphdata[tindex]);
+ }
+ }
+
+ /* Build our BVHtrees, either from verts or tessfaces. */
+ if (use_from_vert) {
+ if (use_islands) {
+ BLI_bitmap *verts_active = BLI_BITMAP_NEW((size_t)num_verts_src, __func__);
+
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ MeshElemMap *isld = island_store.islands[tindex];
+ int num_verts_active = 0;
+ BLI_BITMAP_SET_ALL(verts_active, false, (size_t)num_verts_src);
+ for (i = 0; i < isld->count; i++) {
+ MPoly *mp_src = &polys_src[isld->indices[i]];
+ for (lidx_src = mp_src->loopstart; lidx_src < mp_src->loopstart + mp_src->totloop; lidx_src++) {
+ BLI_BITMAP_ENABLE(verts_active, loops_src[lidx_src].v);
+ num_verts_active++;
+ }
+ }
+ /* verts 'ownership' is transfered to treedata here, which will handle its freeing. */
+ bvhtree_from_mesh_verts_ex(&treedata[tindex], verts_src, num_verts_src, verts_allocated_src,
+ verts_active, num_verts_active, bvh_epsilon, 2, 6);
+ if (verts_allocated_src) {
+ verts_allocated_src = false; /* Only 'give' our verts once, to first tree! */
+ }
+ }
+
+ MEM_freeN(verts_active);
+ }
+ else {
+ BLI_assert(num_trees == 1);
+ bvhtree_from_mesh_verts(&treedata[0], dm_src, bvh_epsilon, 2, 6);
+ }
+ }
+ else { /* We use polygons. */
+ if (use_islands) {
+ /* bvhtree here uses tesselated faces... */
+ const unsigned int dirty_tess_flag = dm_src->dirty & DM_DIRTY_TESS_CDLAYERS;
+ BLI_bitmap *faces_active;
+
+ /* We do not care about tessellated data here, only geometry itself is important. */
+ if (dirty_tess_flag) {
+ dm_src->dirty &= ~dirty_tess_flag;
+ }
+ DM_ensure_tessface(dm_src);
+ if (dirty_tess_flag) {
+ dm_src->dirty |= dirty_tess_flag;
+ }
+ faces_src = DM_get_tessface_array(dm_src, &faces_allocated_src);
+ num_faces_src = dm_src->getNumTessFaces(dm_src);
+ tessface_to_poly_map_src = dm_src->getTessFaceDataArray(dm_src, CD_ORIGINDEX);
+ faces_active = BLI_BITMAP_NEW((size_t)num_faces_src, __func__);
+
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ int num_faces_active = 0;
+ BLI_BITMAP_SET_ALL(faces_active, false, (size_t)num_faces_src);
+ for (i = 0; i < num_faces_src; i++) {
+ MPoly *mp_src = &polys_src[tessface_to_poly_map_src[i]];
+ if (island_store.items_to_islands[mp_src->loopstart] == tindex) {
+ BLI_BITMAP_ENABLE(faces_active, i);
+ num_faces_active++;
+ }
+ }
+ /* verts 'ownership' is transfered to treedata here, which will handle its freeing. */
+ bvhtree_from_mesh_faces_ex(
+ &treedata[tindex], verts_src, verts_allocated_src,
+ faces_src, num_faces_src, faces_allocated_src,
+ faces_active, num_faces_active, bvh_epsilon, 2, 6);
+ if (verts_allocated_src) {
+ verts_allocated_src = false; /* Only 'give' our verts once, to first tree! */
+ }
+ if (faces_allocated_src) {
+ faces_allocated_src = false; /* Only 'give' our faces once, to first tree! */
+ }
+ }
+
+ MEM_freeN(faces_active);
+ }
+ else {
+ BLI_assert(num_trees == 1);
+ bvhtree_from_mesh_faces(&treedata[0], dm_src, bvh_epsilon, 2, 6);
+ tessface_to_poly_map_src = dm_src->getTessFaceDataArray(dm_src, CD_ORIGINDEX);
+ }
+ }
+
+ /* And check each dest poly! */
+ islands_res = MEM_mallocN(sizeof(*islands_res) * (size_t)num_trees, __func__);
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ islands_res[tindex] = MEM_mallocN(sizeof(**islands_res) * islands_res_buff_size, __func__);
+ }
+
+ for (pidx_dst = 0; pidx_dst < numpolys_dst; pidx_dst++) {
+ MPoly *mp_dst = &polys_dst[pidx_dst];
+ float (*pnor_dst)[3] = &poly_nors_dst[pidx_dst];
+
+ if ((size_t)mp_dst->totloop > islands_res_buff_size) {
+ islands_res_buff_size = (size_t)mp_dst->totloop;
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ islands_res[tindex] = MEM_reallocN(islands_res[tindex], sizeof(**islands_res) * islands_res_buff_size);
+ }
+ }
+
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ BVHTreeFromMesh *tdata = &treedata[tindex];
+ MLoop *ml_dst = &loops_dst[mp_dst->loopstart];
+
+ for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++, ml_dst++) {
+ if (use_from_vert) {
+ float tmp_co[3];
+ MeshElemMap *vert_to_refelem_map_src = NULL;
+
+ copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
+ nearest.index = -1;
+
+ if (mesh_remap_bvhtree_query_nearest(
+ tdata, &nearest, space_transform,
+ tmp_co, max_dist_sq, &hit_dist))
+ {
+ float (*nor_dst)[3];
+ float (*nors_src)[3];
+ float best_nor_dot = -2.0f;
+ int best_index_src = -1;
+
+ if (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) {
+ nor_dst = &loop_nors_dst[plidx_dst + mp_dst->loopstart];
+ nors_src = loop_nors_src;
+ vert_to_refelem_map_src = vert_to_loop_map_src;
+ }
+ else { /* if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { */
+ nor_dst = pnor_dst;
+ nors_src = poly_nors_src;
+ vert_to_refelem_map_src = vert_to_poly_map_src;
+ }
+
+ for (i = vert_to_refelem_map_src[nearest.index].count; i--;) {
+ const int index_src = vert_to_refelem_map_src[nearest.index].indices[i];
+ const float dot = dot_v3v3(nors_src[index_src], *nor_dst);
+ if (dot > best_nor_dot) {
+ best_nor_dot = dot;
+ best_index_src = index_src;
+ }
+ }
+ if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) {
+ /* Our best_index_src is a poly one for now!
+ * Have to find its loop matching our closest vertex. */
+ MPoly *mp_src = &polys_src[best_index_src];
+ MLoop *ml_src = &loops_src[mp_src->loopstart];
+ for (plidx_src = 0; plidx_src < mp_src->totloop; plidx_src++, ml_src++) {
+ if ((int)ml_src->v == nearest.index) {
+ best_index_src = plidx_src + mp_src->loopstart;
+ break;
+ }
+ }
+ }
+ islands_res[tindex][plidx_dst].factor = hit_dist ? (1.0f / (hit_dist * best_nor_dot)) : 1e18f;
+ islands_res[tindex][plidx_dst].hit_dist = hit_dist;
+ islands_res[tindex][plidx_dst].index_src = best_index_src;
+ }
+ else {
+ /* No source for this dest loop! */
+ islands_res[tindex][plidx_dst].factor = 0.0f;
+ islands_res[tindex][plidx_dst].hit_dist = FLT_MAX;
+ islands_res[tindex][plidx_dst].index_src = -1;
+ }
+ }
+ else if (mode & MREMAP_USE_NORPROJ) {
+ float tmp_co[3], tmp_no[3];
+
+ int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1;
+ float w = 1.0f;
+
+ copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
+ copy_v3_v3(tmp_no, loop_nors_dst[plidx_dst + mp_dst->loopstart]);
+
+ /* We do our transform here, since we may do several raycast/nearest queries. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ BLI_space_transform_apply_normal(space_transform, tmp_no);
+ }
+
+ while (n--) {
+ /* Note we handle dest to src space conversion ourself, here! */
+ if (mesh_remap_bvhtree_query_raycast(
+ tdata, &rayhit, NULL,
+ tmp_co, tmp_no, ray_radius / w, max_dist, &hit_dist))
+ {
+ islands_res[tindex][plidx_dst].factor = (hit_dist ? (1.0f / hit_dist) : 1e18f) * w;
+ islands_res[tindex][plidx_dst].hit_dist = hit_dist;
+ islands_res[tindex][plidx_dst].index_src = tessface_to_poly_map_src[rayhit.index];
+ copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, rayhit.co);
+ break;
+ }
+ /* Next iteration will get bigger radius but smaller weight! */
+ w /= MREMAP_RAYCAST_APPROXIMATE_FAC;
+ }
+ if (n == -1) {
+ /* Fallback to 'nearest' hit here, loops usually comes in 'face group', not good to
+ * have only part of one dest face's loops to map to source.
+ * Note that since we give this a null weight, if whole weight for a given face
+ * is null, it means none of its loop mapped to this source island, hence we can skip it
+ * later.
+ */
+ copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
+ nearest.index = -1;
+
+ /* In any case, this fallback nearest hit should have no weight at all
+ * in 'best island' decision! */
+ islands_res[tindex][plidx_dst].factor = 0.0f;
+
+ /* Note we handle dest to src space conversion ourself, here! */
+ if (mesh_remap_bvhtree_query_nearest(
+ tdata, &nearest, NULL,
+ tmp_co, max_dist_sq, &hit_dist))
+ {
+ islands_res[tindex][plidx_dst].hit_dist = hit_dist;
+ islands_res[tindex][plidx_dst].index_src = tessface_to_poly_map_src[nearest.index];
+ copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.co);
+ }
+ else {
+ /* No source for this dest loop! */
+ islands_res[tindex][plidx_dst].hit_dist = FLT_MAX;
+ islands_res[tindex][plidx_dst].index_src = -1;
+ }
+ }
+ }
+ else { /* Nearest poly either to use all its loops/verts or just closest one. */
+ float tmp_co[3];
+
+ copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
+ nearest.index = -1;
+
+ if (mesh_remap_bvhtree_query_nearest(
+ tdata, &nearest, space_transform,
+ tmp_co, max_dist_sq, &hit_dist))
+ {
+ islands_res[tindex][plidx_dst].factor = hit_dist ? (1.0f / hit_dist) : 1e18f;
+ islands_res[tindex][plidx_dst].hit_dist = hit_dist;
+ islands_res[tindex][plidx_dst].index_src = tessface_to_poly_map_src[nearest.index];
+ copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.co);
+ }
+ else {
+ /* No source for this dest loop! */
+ islands_res[tindex][plidx_dst].factor = 0.0f;
+ islands_res[tindex][plidx_dst].hit_dist = FLT_MAX;
+ islands_res[tindex][plidx_dst].index_src = -1;
+ }
+ }
+ }
+ }
+
+ /* And now, find best island to use! */
+ /* We have to first select the 'best source island' for given dst poly and its loops.
+ * Then, we have to check that poly does not 'spread' across some island's limits
+ * (like inner seams for UVs, etc.).
+ * Note we only still partially support that kind of situation here, i.e. polys spreading over actual cracks
+ * (like a narrow space without faces on src, splitting a 'tube-like' geometry). That kind of situation
+ * should be relatively rare, though.
+ */
+ /* XXX This block in itself is big and complex enough to be a separate function but... it uses a bunch
+ * of locale vars. Not worth sending all that through parameters (for now at least). */
+ {
+ BLI_AStarGraph *as_graph = NULL;
+ int *poly_island_index_map = NULL;
+ int pidx_src_prev = -1;
+
+ MeshElemMap *best_island = NULL;
+ float best_island_fac = 0.0f;
+ int best_island_index = -1;
+
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ float island_fac = 0.0f;
+
+ for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++) {
+ island_fac += islands_res[tindex][plidx_dst].factor;
+ }
+ island_fac /= (float)mp_dst->totloop;
+
+ if (island_fac > best_island_fac) {
+ best_island_fac = island_fac;
+ best_island_index = tindex;
+ }
+ }
+
+ if (best_island_index != -1 && isld_steps_src) {
+ best_island = use_islands ? island_store.islands[best_island_index] : NULL;
+ as_graph = &as_graphdata[best_island_index];
+ poly_island_index_map = (int *)as_graph->custom_data;
+ BLI_astar_solution_init(as_graph, &as_solution, false);
+ }
+
+ for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++) {
+ IslandResult *isld_res;
+ lidx_dst = plidx_dst + mp_dst->loopstart;
+
+ if (best_island_index == -1) {
+ /* No source for any loops of our dest poly in any source islands. */
+ BKE_mesh_remap_item_define_invalid(r_map, lidx_dst);
+ continue;
+ }
+
+ as_solution.custom_data = SET_INT_IN_POINTER(false);
+
+ isld_res = &islands_res[best_island_index][plidx_dst];
+ if (use_from_vert) {
+ /* Indices stored in islands_res are those of loops, one per dest loop. */
+ lidx_src = isld_res->index_src;
+ if (lidx_src >= 0) {
+ pidx_src = loop_to_poly_map_src[lidx_src];
+ /* If prev and curr poly are the same, no need to do anything more!!! */
+ if (!ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
+ BLI_astar_graph_solve(
+ as_graph, poly_island_index_map[pidx_src_prev], poly_island_index_map[pidx_src],
+ mesh_remap_calc_loops_astar_f_cost, &as_solution, isld_steps_src);
+ if (GET_INT_FROM_POINTER(as_solution.custom_data) && (as_solution.steps > 0)) {
+ /* Find first 'cutting edge' on path, and bring back lidx_src on poly just
+ * before that edge.
+ * Note we could try to be much smarter (like e.g. storing a whole poly's indices,
+ * and making decision (on which side of cutting edge(s!) to be) on the end,
+ * but this is one more level of complexity, better to first see if
+ * simple solution works!
+ */
+ int pidx_isld_src = poly_island_index_map[pidx_src];
+ int last_valid_pidx_isld_src = -1;
+ /* Note we go backward here, from dest to src poly. */
+ for (i = as_solution.steps - 1; i--;) {
+ BLI_AStarGNLink *as_link = as_solution.prev_links[pidx_isld_src];
+ const int eidx = GET_INT_FROM_POINTER(as_link->custom_data);
+ pidx_isld_src = as_solution.prev_nodes[pidx_isld_src];
+ BLI_assert(pidx_isld_src != -1);
+ if (eidx != -1) {
+ /* we are 'crossing' a cutting edge. */
+ last_valid_pidx_isld_src = pidx_isld_src;
+ }
+ }
+ if (last_valid_pidx_isld_src != -1) {
+ /* Find a new valid loop in that new poly (nearest one for now).
+ * Note we could be much more subtle here, again that's for later... */
+ MPoly *mp_src;
+ MLoop *ml_src, *ml_dst = &loops_dst[lidx_dst];
+ int j;
+ float best_dist_sq = FLT_MAX;
+ float tmp_co[3];
+
+ copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
+
+ /* We do our transform here, since we may do several raycast/nearest queries. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ pidx_src = use_islands ? best_island->indices[last_valid_pidx_isld_src] :
+ last_valid_pidx_isld_src;
+ mp_src = &polys_src[pidx_src];
+ ml_src = &loops_src[mp_src->loopstart];
+ for (j = 0; j < mp_src->totloop; j++, ml_src++) {
+ const float dist_sq = len_squared_v3v3(verts_src[ml_src->v].co, tmp_co);
+ if (dist_sq < best_dist_sq) {
+ best_dist_sq = dist_sq;
+ lidx_src = mp_src->loopstart + j;
+ }
+ }
+ }
+ }
+ }
+ mesh_remap_item_define(
+ r_map, lidx_dst, isld_res->hit_dist,
+ best_island_index, 1, &lidx_src, &full_weight);
+ pidx_src_prev = pidx_src;
+ }
+ else {
+ /* No source for this loop in this island. */
+ /* TODO: would probably be better to get a source at all cost in best island anyway? */
+ mesh_remap_item_define(
+ r_map, lidx_dst, FLT_MAX,
+ best_island_index, 0, NULL, NULL);
+ }
+ }
+ else {
+ /* Else, we use source poly, indices stored in islands_res are those of polygons. */
+ pidx_src = isld_res->index_src;
+ if (pidx_src >= 0) {
+ MPoly *mp_src = &polys_src[pidx_src];
+ float *hit_co = isld_res->hit_point;
+ int best_loop_index_src;
+
+ /* If prev and curr poly are the same, no need to do anything more!!! */
+ if (!ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
+ BLI_astar_graph_solve(
+ as_graph, poly_island_index_map[pidx_src_prev], poly_island_index_map[pidx_src],
+ mesh_remap_calc_loops_astar_f_cost, &as_solution, isld_steps_src);
+ if (GET_INT_FROM_POINTER(as_solution.custom_data) && (as_solution.steps > 0)) {
+ /* Find first 'cutting edge' on path, and bring back lidx_src on poly just
+ * before that edge.
+ * Note we could try to be much smarter (like e.g. storing a whole poly's indices,
+ * and making decision (one which side of cutting edge(s!) to be on the end,
+ * but this is one more level of complexity, better to first see if
+ * simple solution works!
+ */
+ int pidx_isld_src = poly_island_index_map[pidx_src];
+ int last_valid_pidx_isld_src = -1;
+ /* Note we go backward here, from dest to src poly. */
+ for (i = as_solution.steps - 1; i--;) {
+ BLI_AStarGNLink *as_link = as_solution.prev_links[pidx_isld_src];
+ int eidx = GET_INT_FROM_POINTER(as_link->custom_data);
+
+ pidx_isld_src = as_solution.prev_nodes[pidx_isld_src];
+ BLI_assert(pidx_isld_src != -1);
+ if (eidx != -1) {
+ /* we are 'crossing' a cutting edge. */
+ last_valid_pidx_isld_src = pidx_isld_src;
+ }
+ }
+ if (last_valid_pidx_isld_src != -1) {
+ /* Find a new valid loop in that new poly (nearest point on poly for now).
+ * Note we could be much more subtle here, again that's for later... */
+ MLoop *ml_dst = &loops_dst[lidx_dst];
+ float best_dist_sq = FLT_MAX;
+ float tmp_co[3];
+ int j;
+
+ copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
+
+ /* We do our transform here, since we may do several raycast/nearest queries. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ pidx_src = use_islands ? best_island->indices[last_valid_pidx_isld_src] :
+ last_valid_pidx_isld_src;
+ mp_src = &polys_src[pidx_src];
+
+ /* Create that one on demand. */
+ if (poly_to_tessface_map_src == NULL) {
+ BKE_mesh_origindex_map_create(
+ &poly_to_tessface_map_src, &poly_to_tessface_map_src_buff,
+ num_faces_src, tessface_to_poly_map_src, num_polys_src);
+ }
+
+ for (j = poly_to_tessface_map_src[pidx_src].count; j--;) {
+ float h[3];
+ MFace *mf = &faces_src[poly_to_tessface_map_src[pidx_src].indices[j]];
+ float dist_sq;
+
+ closest_on_tri_to_point_v3(
+ h, tmp_co,
+ vcos_src[mf->v1], vcos_src[mf->v2], vcos_src[mf->v3]);
+ dist_sq = len_squared_v3v3(tmp_co, h);
+ if (dist_sq < best_dist_sq) {
+ copy_v3_v3(hit_co, h);
+ best_dist_sq = dist_sq;
+ }
+ if (mf->v4) {
+ closest_on_tri_to_point_v3(
+ h, tmp_co,
+ vcos_src[mf->v1], vcos_src[mf->v3], vcos_src[mf->v4]);
+ dist_sq = len_squared_v3v3(tmp_co, h);
+ if (dist_sq < best_dist_sq) {
+ copy_v3_v3(hit_co, h);
+ best_dist_sq = dist_sq;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (mode == MREMAP_MODE_LOOP_POLY_NEAREST) {
+ mesh_remap_interp_poly_data_get(
+ mp_src, loops_src, (const float (*)[3])vcos_src, hit_co,
+ &buff_size_interp, &vcos_interp, true, &indices_interp,
+ &weights_interp, false, &best_loop_index_src);
+
+ mesh_remap_item_define(
+ r_map, lidx_dst, isld_res->hit_dist,
+ best_island_index, 1, &best_loop_index_src, &full_weight);
+ }
+ else {
+ const int sources_num = mesh_remap_interp_poly_data_get(
+ mp_src, loops_src, (const float (*)[3])vcos_src, hit_co,
+ &buff_size_interp, &vcos_interp, true, &indices_interp,
+ &weights_interp, true, NULL);
+
+ mesh_remap_item_define(
+ r_map, lidx_dst,
+ isld_res->hit_dist, best_island_index,
+ sources_num, indices_interp, weights_interp);
+ }
+
+ pidx_src_prev = pidx_src;
+ }
+ else {
+ /* No source for this loop in this island. */
+ /* TODO: would probably be better to get a source at all cost in best island anyway? */
+ mesh_remap_item_define(r_map, lidx_dst, FLT_MAX, best_island_index, 0, NULL, NULL);
+ }
+ }
+ }
+
+ BLI_astar_solution_clear(&as_solution);
+ }
+ }
+
+ for (tindex = 0; tindex < num_trees; tindex++) {
+ MEM_freeN(islands_res[tindex]);
+ free_bvhtree_from_mesh(&treedata[tindex]);
+ if (isld_steps_src) {
+ BLI_astar_graph_free(&as_graphdata[tindex]);
+ }
+ }
+ MEM_freeN(islands_res);
+ BKE_mesh_loop_islands_free(&island_store);
+ MEM_freeN(treedata);
+ if (isld_steps_src) {
+ MEM_freeN(as_graphdata);
+ BLI_astar_solution_free(&as_solution);
+ }
+
+ if (verts_allocated_src) {
+ MEM_freeN(verts_src);
+ }
+ if (vcos_src) {
+ MEM_freeN(vcos_src);
+ }
+ if (edges_allocated_src) {
+ MEM_freeN(edges_src);
+ }
+ if (loops_allocated_src) {
+ MEM_freeN(loops_src);
+ }
+ if (polys_allocated_src) {
+ MEM_freeN(polys_src);
+ }
+ if (faces_allocated_src) {
+ MEM_freeN(faces_src);
+ }
+ if (vert_to_loop_map_src_buff) {
+ MEM_freeN(vert_to_loop_map_src_buff);
+ }
+ if (vert_to_poly_map_src_buff) {
+ MEM_freeN(vert_to_poly_map_src_buff);
+ }
+ if (edge_to_poly_map_src_buff) {
+ MEM_freeN(edge_to_poly_map_src_buff);
+ }
+ if (poly_to_tessface_map_src_buff) {
+ MEM_freeN(poly_to_tessface_map_src_buff);
+ }
+ if (loop_to_poly_map_src) {
+ MEM_freeN(loop_to_poly_map_src);
+ }
+ if (vcos_interp) {
+ MEM_freeN(vcos_interp);
+ }
+ if (indices_interp) {
+ MEM_freeN(indices_interp);
+ }
+ if (weights_interp) {
+ MEM_freeN(weights_interp);
+ }
+ }
+}
+
+void BKE_mesh_remap_calc_polys_from_dm(
+ const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius,
+ MVert *verts_dst, const int numverts_dst, MLoop *loops_dst, const int numloops_dst,
+ MPoly *polys_dst, const int numpolys_dst, CustomData *pdata_dst, const bool dirty_nors_dst,
+ DerivedMesh *dm_src, MeshPairRemap *r_map)
+{
+ const float full_weight = 1.0f;
+ const float max_dist_sq = max_dist * max_dist;
+ float (*poly_nors_dst)[3] = NULL;
+ int i;
+
+ BLI_assert(mode & MREMAP_MODE_POLY);
+
+ if (mode & (MREMAP_USE_NORMAL | MREMAP_USE_NORPROJ)) {
+ /* Cache poly nors into a temp CDLayer. */
+ poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL);
+ if (!poly_nors_dst) {
+ poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, numpolys_dst);
+ CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
+ }
+ if (dirty_nors_dst) {
+ BKE_mesh_calc_normals_poly(verts_dst, numverts_dst, loops_dst, polys_dst, numloops_dst, numpolys_dst,
+ poly_nors_dst, true);
+ }
+ }
+
+ BKE_mesh_remap_init(r_map, numpolys_dst);
+
+ if (mode == MREMAP_MODE_TOPOLOGY) {
+ BLI_assert(numpolys_dst == dm_src->getNumPolys(dm_src));
+ for (i = 0; i < numpolys_dst; i++) {
+ mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
+ }
+ }
+ else {
+ BVHTreeFromMesh treedata = {NULL};
+ BVHTreeNearest nearest = {0};
+ BVHTreeRayHit rayhit = {0};
+ float hit_dist;
+
+ int *tessface_to_poly_map_src;
+
+ bvhtree_from_mesh_faces(
+ &treedata, dm_src,
+ (mode & MREMAP_USE_NORPROJ) ? MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON(ray_radius) : 0.0f,
+ 2, 6);
+ /* bvhtree here uses tesselated faces... */
+ tessface_to_poly_map_src = dm_src->getTessFaceDataArray(dm_src, CD_ORIGINDEX);
+
+ if (mode == MREMAP_MODE_POLY_NEAREST) {
+ nearest.index = -1;
+
+ for (i = 0; i < numpolys_dst; i++) {
+ MPoly *mp = &polys_dst[i];
+ float tmp_co[3];
+
+ BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], verts_dst, tmp_co);
+
+ if (mesh_remap_bvhtree_query_nearest(
+ &treedata, &nearest, space_transform,
+ tmp_co, max_dist_sq, &hit_dist))
+ {
+ mesh_remap_item_define(
+ r_map, i, hit_dist, 0,
+ 1, &tessface_to_poly_map_src[nearest.index], &full_weight);
+ }
+ else {
+ /* No source for this dest poly! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+ }
+ else if (mode == MREMAP_MODE_POLY_NOR) {
+ BLI_assert(poly_nors_dst);
+
+ for (i = 0; i < numpolys_dst; i++) {
+ MPoly *mp = &polys_dst[i];
+ float tmp_co[3], tmp_no[3];
+
+ BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], verts_dst, tmp_co);
+ copy_v3_v3(tmp_no, poly_nors_dst[i]);
+
+ if (mesh_remap_bvhtree_query_raycast(
+ &treedata, &rayhit, space_transform,
+ tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
+ {
+ mesh_remap_item_define(
+ r_map, i, hit_dist, 0,
+ 1, &tessface_to_poly_map_src[rayhit.index], &full_weight);
+ }
+ else {
+ /* No source for this dest poly! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+ }
+ else if (mode == MREMAP_MODE_POLY_POLYINTERP_PNORPROJ) {
+ /* We cast our rays randomly, with a pseudo-even distribution (since we spread across tessellated tris,
+ * with additional weighting based on each tri's relative area).
+ */
+ RNG *rng = BLI_rng_new(0);
+
+ const size_t numpolys_src = (size_t)dm_src->getNumPolys(dm_src);
+
+ /* Here it's simpler to just allocate for all polys :/ */
+ int *indices = MEM_mallocN(sizeof(*indices) * numpolys_src, __func__);
+ float *weights = MEM_mallocN(sizeof(*weights) * numpolys_src, __func__);
+
+ size_t tmp_poly_size = MREMAP_DEFAULT_BUFSIZE;
+ float (*poly_vcos_2d)[2] = MEM_mallocN(sizeof(*poly_vcos_2d) * tmp_poly_size, __func__);
+ /* Tessellated 2D poly, always (num_loops - 2) triangles. */
+ int (*tri_vidx_2d)[3] = MEM_mallocN(sizeof(*tri_vidx_2d) * (tmp_poly_size - 2), __func__);
+
+ for (i = 0; i < numpolys_dst; i++) {
+ /* For each dst poly, we sample some rays from it (2D grid in pnor space)
+ * and use their hits to interpolate from source polys. */
+ /* Note: dst poly is early-converted into src space! */
+ MPoly *mp = &polys_dst[i];
+ float tmp_co[3], tmp_no[3];
+
+ int tot_rays, done_rays = 0;
+ float poly_area_2d_inv, done_area = 0.0f;
+
+ const float zvec[3] = {0.0f, 0.0f, 1.0f};
+ float pcent_dst[3];
+ float to_pnor_2d_mat[3][3], from_pnor_2d_mat[3][3];
+ float poly_dst_2d_min[2], poly_dst_2d_max[2], poly_dst_2d_z;
+ float poly_dst_2d_size[2];
+
+ float totweights = 0.0f;
+ float hit_dist_accum = 0.0f;
+ int sources_num = 0;
+ const int tris_num = mp->totloop - 2;
+ int j;
+
+ BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], verts_dst, pcent_dst);
+ copy_v3_v3(tmp_no, poly_nors_dst[i]);
+ /* We do our transform here, else it'd be redone by raycast helper for each ray, ugh! */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, pcent_dst);
+ BLI_space_transform_apply_normal(space_transform, tmp_no);
+ }
+
+ fill_vn_fl(weights, (int)numpolys_src, 0.0f);
+
+ if (UNLIKELY((size_t)mp->totloop > tmp_poly_size)) {
+ tmp_poly_size = (size_t)mp->totloop;
+ poly_vcos_2d = MEM_reallocN(poly_vcos_2d, sizeof(*poly_vcos_2d) * tmp_poly_size);
+ tri_vidx_2d = MEM_reallocN(tri_vidx_2d, sizeof(*tri_vidx_2d) * (tmp_poly_size - 2));
+ }
+
+ rotation_between_vecs_to_mat3(to_pnor_2d_mat, tmp_no, zvec);
+ invert_m3_m3(from_pnor_2d_mat, to_pnor_2d_mat);
+
+ mul_m3_v3(to_pnor_2d_mat, pcent_dst);
+ poly_dst_2d_z = pcent_dst[2];
+
+ /* Get (2D) bounding square of our poly. */
+ INIT_MINMAX2(poly_dst_2d_min, poly_dst_2d_max);
+
+ for (j = 0; j < mp->totloop; j++) {
+ MLoop *ml = &loops_dst[j + mp->loopstart];
+ copy_v3_v3(tmp_co, verts_dst[ml->v].co);
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+ mul_v2_m3v3(poly_vcos_2d[j], to_pnor_2d_mat, tmp_co);
+ minmax_v2v2_v2(poly_dst_2d_min, poly_dst_2d_max, poly_vcos_2d[j]);
+ }
+
+ /* We adjust our ray-casting grid to ray_radius (the smaller, the more rays are cast),
+ * with lower/upper bounds. */
+ sub_v2_v2v2(poly_dst_2d_size, poly_dst_2d_max, poly_dst_2d_min);
+
+ if (ray_radius) {
+ tot_rays = (int)((max_ff(poly_dst_2d_size[0], poly_dst_2d_size[1]) / ray_radius) + 0.5f);
+ CLAMP(tot_rays, MREMAP_RAYCAST_TRI_SAMPLES_MIN, MREMAP_RAYCAST_TRI_SAMPLES_MAX);
+ }
+ else {
+ /* If no radius (pure rays), give max number of rays! */
+ tot_rays = MREMAP_RAYCAST_TRI_SAMPLES_MIN;
+ }
+ tot_rays *= tot_rays;
+
+ poly_area_2d_inv = 1.0f / area_poly_v2((const float(*)[2])poly_vcos_2d, (unsigned int)mp->totloop);
+
+ /* Tessellate our poly. */
+ if (mp->totloop == 3) {
+ tri_vidx_2d[0][0] = 0;
+ tri_vidx_2d[0][1] = 1;
+ tri_vidx_2d[0][2] = 2;
+ }
+ if (mp->totloop == 4) {
+ tri_vidx_2d[0][0] = 0;
+ tri_vidx_2d[0][1] = 1;
+ tri_vidx_2d[0][2] = 2;
+ tri_vidx_2d[1][0] = 0;
+ tri_vidx_2d[1][1] = 2;
+ tri_vidx_2d[1][2] = 3;
+ }
+ else {
+ BLI_polyfill_calc((const float(*)[2])poly_vcos_2d, (unsigned int)mp->totloop, -1,
+ (unsigned int (*)[3])tri_vidx_2d);
+ }
+
+ for (j = 0; j < tris_num; j++) {
+ float *v1 = poly_vcos_2d[tri_vidx_2d[j][0]];
+ float *v2 = poly_vcos_2d[tri_vidx_2d[j][1]];
+ float *v3 = poly_vcos_2d[tri_vidx_2d[j][2]];
+ int rays_num;
+
+ /* All this allows us to get 'absolute' number of rays for each tri, avoiding accumulating
+ * errors over iterations, and helping better even distribution. */
+ done_area += area_tri_v2(v1, v2, v3);
+ rays_num = (int)((float)tot_rays * done_area * poly_area_2d_inv + 0.5f) - done_rays;
+ done_rays += rays_num;
+
+ while (rays_num--) {
+ int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1;
+ float w = 1.0f;
+
+ BLI_rng_get_tri_sample_float_v2(rng, v1, v2, v3, tmp_co);
+
+ tmp_co[2] = poly_dst_2d_z;
+ mul_m3_v3(from_pnor_2d_mat, tmp_co);
+
+ /* At this point, tmp_co is a point on our poly surface, in mesh_src space! */
+ while (n--) {
+ /* Note we handle dest to src space conversion ourself, here! */
+
+ if (mesh_remap_bvhtree_query_raycast(
+ &treedata, &rayhit, NULL,
+ tmp_co, tmp_no, ray_radius / w, max_dist, &hit_dist))
+ {
+ weights[tessface_to_poly_map_src[rayhit.index]] += w;
+ totweights += w;
+ hit_dist_accum += hit_dist;
+ break;
+ }
+ /* Next iteration will get bigger radius but smaller weight! */
+ w /= MREMAP_RAYCAST_APPROXIMATE_FAC;
+ }
+ }
+ }
+
+ if (totweights > 0.0f) {
+ for (j = 0; j < (int)numpolys_src; j++) {
+ if (!weights[j]) {
+ continue;
+ }
+ /* Note: sources_num is always <= j! */
+ weights[sources_num] = weights[j] / totweights;
+ indices[sources_num] = j;
+ sources_num++;
+ }
+ mesh_remap_item_define(r_map, i, hit_dist_accum / totweights, 0, sources_num, indices, weights);
+ }
+ else {
+ /* No source for this dest poly! */
+ BKE_mesh_remap_item_define_invalid(r_map, i);
+ }
+ }
+
+ MEM_freeN(tri_vidx_2d);
+ MEM_freeN(poly_vcos_2d);
+ MEM_freeN(indices);
+ MEM_freeN(weights);
+ BLI_rng_free(rng);
+ }
+ else {
+ printf("WARNING! Unsupported mesh-to-mesh poly mapping mode (%d)!\n", mode);
+ memset(r_map->items, 0, sizeof(*r_map->items) * (size_t)numpolys_dst);
+ }
+
+ free_bvhtree_from_mesh(&treedata);
+ }
+}
+
+#undef MREMAP_RAYCAST_APPROXIMATE_NR
+#undef MREMAP_RAYCAST_APPROXIMATE_FAC
+#undef MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON
+#undef MREMAP_RAYCAST_TRI_SAMPLES_MIN
+#undef MREMAP_RAYCAST_TRI_SAMPLES_MAX
+#undef MREMAP_DEFAULT_BUFSIZE
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index f3a9e894eb3..3a6c949fe9c 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -755,7 +755,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
MDeformWeight *dw;
for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
- /* note, greater then max defgroups is accounted for in our code, but not < 0 */
+ /* note, greater than max defgroups is accounted for in our code, but not < 0 */
if (!finite(dw->weight)) {
PRINT_ERR("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
if (do_fixes) {
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index a9e853c873e..021e564ef95 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -47,7 +47,6 @@
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
-#include "DNA_meshdata_types.h"
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
@@ -57,6 +56,7 @@
#include "BLF_translation.h"
+#include "BKE_appdir.h"
#include "BKE_key.h"
#include "BKE_multires.h"
#include "BKE_DerivedMesh.h"
@@ -262,8 +262,8 @@ void modifier_copyData_generic(const ModifierData *md_src, ModifierData *md_dst)
{
ModifierTypeInfo *mti = modifierType_getInfo(md_src->type);
const size_t data_size = sizeof(ModifierData);
- const char *md_src_data = ((char *)md_src) + data_size;
- char *md_dst_data = ((char *)md_dst) + data_size;
+ const char *md_src_data = ((const char *)md_src) + data_size;
+ char *md_dst_data = ((char *)md_dst) + data_size;
BLI_assert(data_size <= (size_t)mti->structSize);
memcpy(md_dst_data, md_src_data, (size_t)mti->structSize - data_size);
}
@@ -713,7 +713,7 @@ const char *modifier_path_relbase(Object *ob)
else {
/* last resort, better then using "" which resolves to the current
* working directory */
- return BLI_temp_dir_session();
+ return BKE_tempdir_session();
}
}
@@ -723,7 +723,7 @@ void modifier_path_init(char *path, int path_maxlen, const char *name)
/* elubie: changed this to default to the same dir as the render output
* to prevent saving to C:\ on Windows */
BLI_join_dirfile(path, path_maxlen,
- G.relbase_valid ? "//" : BLI_temp_dir_session(),
+ G.relbase_valid ? "//" : BKE_tempdir_session(),
name);
}
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index b387c7d2d1b..fe38fedd7aa 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -69,7 +69,6 @@
#include "BKE_image.h" /* openanim */
#include "BKE_tracking.h"
-#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
@@ -78,8 +77,6 @@
# include "intern/openexr/openexr_multi.h"
#endif
-#include "NOD_composite.h"
-
/*********************** movieclip buffer loaders *************************/
static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen)
@@ -391,7 +388,7 @@ static int user_frame_to_cache_frame(MovieClip *clip, int framenr)
static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
{
- MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)userkey;
+ const MovieClipImBufCacheKey *key = userkey;
*framenr = key->framenr;
*proxy = key->proxy;
@@ -400,7 +397,7 @@ static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *ren
static unsigned int moviecache_hashhash(const void *keyv)
{
- MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)keyv;
+ const MovieClipImBufCacheKey *key = keyv;
int rval = key->framenr;
return rval;
@@ -408,8 +405,8 @@ static unsigned int moviecache_hashhash(const void *keyv)
static bool moviecache_hashcmp(const void *av, const void *bv)
{
- const MovieClipImBufCacheKey *a = (MovieClipImBufCacheKey *)av;
- const MovieClipImBufCacheKey *b = (MovieClipImBufCacheKey *)bv;
+ const MovieClipImBufCacheKey *a = av;
+ const MovieClipImBufCacheKey *b = bv;
return ((a->framenr != b->framenr) ||
(a->proxy != b->proxy) ||
@@ -528,6 +525,15 @@ static bool put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, i
}
}
+static bool moviecache_check_free_proxy(ImBuf *UNUSED(ibuf),
+ void *userkey,
+ void *UNUSED(userdata))
+{
+ MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)userkey;
+
+ return !(key->proxy == IMB_PROXY_NONE && key->render_flag == 0);
+}
+
/*********************** common functions *************************/
/* only image block itself */
@@ -1170,6 +1176,15 @@ void BKE_movieclip_clear_cache(MovieClip *clip)
free_buffers(clip);
}
+void BKE_movieclip_clear_proxy_cache(MovieClip *clip)
+{
+ if (clip->cache && clip->cache->moviecache) {
+ IMB_moviecache_cleanup(clip->cache->moviecache,
+ moviecache_check_free_proxy,
+ NULL);
+ }
+}
+
void BKE_movieclip_reload(MovieClip *clip)
{
/* clear cache */
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index d89c4877dea..8e9f86d7c19 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -567,7 +567,7 @@ bool BKE_nlastrips_has_space(ListBase *strips, float start, float end)
/* sanity checks */
if ((strips == NULL) || IS_EQF(start, end))
- return 0;
+ return false;
if (start > end) {
puts("BKE_nlastrips_has_space() error... start and end arguments swapped");
SWAP(float, start, end);
@@ -579,17 +579,17 @@ bool BKE_nlastrips_has_space(ListBase *strips, float start, float end)
* we've gone past the window we need to check for, so things are fine
*/
if (strip->start >= end)
- return 1;
+ return true;
/* if the end of the strip is greater than either of the boundaries, the range
* must fall within the extents of the strip
*/
if ((strip->end > start) || (strip->end > end))
- return 0;
+ return false;
}
/* if we are still here, we haven't encountered any overlapping strips */
- return 1;
+ return true;
}
/* Rearrange the strips in the track so that they are always in order
@@ -646,11 +646,11 @@ bool BKE_nlastrips_add_strip(ListBase *strips, NlaStrip *strip)
/* sanity checks */
if (ELEM(NULL, strips, strip))
- return 0;
+ return false;
/* check if any space to add */
if (BKE_nlastrips_has_space(strips, strip->start, strip->end) == 0)
- return 0;
+ return false;
/* find the right place to add the strip to the nominated track */
for (ns = strips->first; ns; ns = ns->next) {
@@ -667,7 +667,7 @@ bool BKE_nlastrips_add_strip(ListBase *strips, NlaStrip *strip)
}
/* added... */
- return 1;
+ return true;
}
@@ -785,11 +785,11 @@ bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip)
{
/* sanity checks */
if (ELEM(NULL, mstrip, strip))
- return 0;
+ return false;
/* firstly, check if the meta-strip has space for this */
if (BKE_nlastrips_has_space(&mstrip->strips, strip->start, strip->end) == 0)
- return 0;
+ return false;
/* check if this would need to be added to the ends of the meta,
* and subsequently, if the neighboring strips allow us enough room
@@ -803,10 +803,10 @@ bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip)
BLI_addhead(&mstrip->strips, strip);
mstrip->start = strip->start;
- return 1;
+ return true;
}
else /* failed... no room before */
- return 0;
+ return false;
}
else if (strip->end > mstrip->end) {
/* check if strip to the right (if it exists) starts before the
@@ -817,10 +817,10 @@ bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip)
BLI_addtail(&mstrip->strips, strip);
mstrip->end = strip->end;
- return 1;
+ return true;
}
else /* failed... no room after */
- return 0;
+ return false;
}
else {
/* just try to add to the meta-strip (no dimension changes needed) */
@@ -988,7 +988,7 @@ bool BKE_nlatrack_has_space(NlaTrack *nlt, float start, float end)
* - bounds cannot be equal (0-length is nasty)
*/
if ((nlt == NULL) || (nlt->flag & NLATRACK_PROTECTED) || IS_EQF(start, end))
- return 0;
+ return false;
if (start > end) {
puts("BKE_nlatrack_has_space() error... start and end arguments swapped");
@@ -1019,7 +1019,7 @@ bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip)
{
/* sanity checks */
if (ELEM(NULL, nlt, strip))
- return 0;
+ return false;
/* try to add the strip to the track using a more generic function */
return BKE_nlastrips_add_strip(&nlt->strips, strip);
@@ -1036,11 +1036,11 @@ bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2])
if (bounds)
bounds[0] = bounds[1] = 0.0f;
else
- return 0;
+ return false;
/* sanity checks */
if (ELEM(NULL, nlt, nlt->strips.first))
- return 0;
+ return false;
/* lower bound is first strip's start frame */
strip = nlt->strips.first;
@@ -1051,7 +1051,7 @@ bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2])
bounds[1] = strip->end;
/* done */
- return 1;
+ return true;
}
/* NLA Strips -------------------------------------- */
@@ -1105,7 +1105,7 @@ bool BKE_nlastrip_within_bounds(NlaStrip *strip, float min, float max)
/* sanity checks */
if ((strip == NULL) || IS_EQF(stripLen, 0.0f) || IS_EQF(boundsLen, 0.0f))
- return 0;
+ return false;
/* only ok if at least part of the strip is within the bounding window
* - first 2 cases cover when the strip length is less than the bounding area
@@ -1115,17 +1115,17 @@ bool BKE_nlastrip_within_bounds(NlaStrip *strip, float min, float max)
!(IN_RANGE(strip->start, min, max) ||
IN_RANGE(strip->end, min, max)))
{
- return 0;
+ return false;
}
if ((stripLen > boundsLen) &&
!(IN_RANGE(min, strip->start, strip->end) ||
IN_RANGE(max, strip->start, strip->end)) )
{
- return 0;
+ return false;
}
/* should be ok! */
- return 1;
+ return true;
}
@@ -1209,11 +1209,11 @@ static bool nlastrip_is_first(AnimData *adt, NlaStrip *strip)
/* sanity checks */
if (ELEM(NULL, adt, strip))
- return 0;
+ return false;
/* check if strip has any strips before it */
if (strip->prev)
- return 0;
+ return false;
/* check other tracks to see if they have a strip that's earlier */
/* TODO: or should we check that the strip's track is also the first? */
@@ -1222,12 +1222,12 @@ static bool nlastrip_is_first(AnimData *adt, NlaStrip *strip)
ns = nlt->strips.first;
if (ns) {
if (ns->start < strip->start)
- return 0;
+ return false;
}
}
/* should be first now */
- return 1;
+ return true;
}
/* Animated Strips ------------------------------------------- */
@@ -1239,16 +1239,16 @@ bool BKE_nlatrack_has_animated_strips(NlaTrack *nlt)
/* sanity checks */
if (ELEM(NULL, nlt, nlt->strips.first))
- return 0;
+ return false;
/* check each strip for F-Curves only (don't care about whether the flags are set) */
for (strip = nlt->strips.first; strip; strip = strip->next) {
if (strip->fcurves.first)
- return 1;
+ return true;
}
/* none found */
- return 0;
+ return false;
}
/* Check if given NLA-Tracks have any strips with own F-Curves */
@@ -1258,16 +1258,16 @@ bool BKE_nlatracks_have_animated_strips(ListBase *tracks)
/* sanity checks */
if (ELEM(NULL, tracks, tracks->first))
- return 0;
+ return false;
/* check each track, stopping on the first hit */
for (nlt = tracks->first; nlt; nlt = nlt->next) {
if (BKE_nlatrack_has_animated_strips(nlt))
- return 1;
+ return true;
}
/* none found */
- return 0;
+ return false;
}
/* Validate the NLA-Strips 'control' F-Curves based on the flags set*/
@@ -1326,7 +1326,7 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
static bool nla_editbone_name_check(void *arg, const char *name)
{
- return BLI_ghash_haskey((GHash *)arg, (void *)name);
+ return BLI_ghash_haskey((GHash *)arg, (const void *)name);
}
/* Find (and set) a unique name for a strip from the whole AnimData block
@@ -1587,13 +1587,13 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
/* verify that data is valid */
if (ELEM(NULL, adt, adt->nla_tracks.first))
- return 0;
+ return false;
/* if block is already in tweakmode, just leave, but we should report
* that this block is in tweakmode (as our returncode)
*/
if (adt->flag & ADT_NLA_EDIT_ON)
- return 1;
+ return true;
/* go over the tracks, finding the active one, and its active strip
* - if we cannot find both, then there's nothing to do
@@ -1642,7 +1642,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
printf("NLA tweakmode enter - neither active requirement found\n");
printf("\tactiveTrack = %p, activeStrip = %p\n", (void *)activeTrack, (void *)activeStrip);
}
- return 0;
+ return false;
}
/* go over all the tracks up to the active one, tagging each strip that uses the same
@@ -1677,7 +1677,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
adt->flag |= ADT_NLA_EDIT_ON;
/* done! */
- return 1;
+ return true;
}
/* Exit tweakmode for this AnimData block */
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index db27e559a4f..039af949d81 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1202,6 +1202,10 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool do_
/* node tree will generate its own interface type */
newtree->interface_type = NULL;
+ if (ntree->id.lib) {
+ BKE_id_lib_local_paths(bmain, ntree->id.lib, &newtree->id);
+ }
+
return newtree;
}
@@ -2293,8 +2297,8 @@ bool ntreeHasType(const bNodeTree *ntree, int type)
if (ntree)
for (node = ntree->nodes.first; node; node = node->next)
if (node->type == type)
- return 1;
- return 0;
+ return true;
+ return false;
}
bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup)
@@ -2877,7 +2881,7 @@ static void ntree_update_node_level(bNodeTree *ntree)
}
}
-static void ntree_update_link_pointers(bNodeTree *ntree)
+void ntreeTagUsedSockets(bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
@@ -2886,22 +2890,43 @@ static void ntree_update_link_pointers(bNodeTree *ntree)
/* first clear data */
for (node = ntree->nodes.first; node; node = node->next) {
for (sock = node->inputs.first; sock; sock = sock->next) {
- sock->link = NULL;
sock->flag &= ~SOCK_IN_USE;
}
for (sock = node->outputs.first; sock; sock = sock->next) {
sock->flag &= ~SOCK_IN_USE;
}
}
-
+
for (link = ntree->links.first; link; link = link->next) {
- link->tosock->link = link;
+ /* link is unused if either side is disabled */
+ if ((link->fromsock->flag & SOCK_UNAVAIL) || (link->tosock->flag & SOCK_UNAVAIL))
+ continue;
link->fromsock->flag |= SOCK_IN_USE;
link->tosock->flag |= SOCK_IN_USE;
}
}
+static void ntree_update_link_pointers(bNodeTree *ntree)
+{
+ bNode *node;
+ bNodeSocket *sock;
+ bNodeLink *link;
+
+ /* first clear data */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ sock->link = NULL;
+ }
+ }
+
+ for (link = ntree->links.first; link; link = link->next) {
+ link->tosock->link = link;
+ }
+
+ ntreeTagUsedSockets(ntree);
+}
+
static void ntree_validate_links(bNodeTree *ntree)
{
bNodeLink *link;
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index f8e883b03dd..41f7721d59f 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1137,7 +1137,7 @@ static LodLevel *lod_level_select(Object *ob, const float camera_position[3])
bool BKE_object_lod_is_usable(Object *ob, Scene *scene)
{
- bool active = (scene) ? ob == OBACT : 0;
+ bool active = (scene) ? ob == OBACT : false;
return (ob->mode == OB_MODE_OBJECT || !active);
}
@@ -1403,10 +1403,10 @@ bool BKE_object_pose_context_check(Object *ob)
(ob->pose) &&
(ob->mode & OB_MODE_POSE))
{
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
@@ -1519,6 +1519,10 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
/* Copy runtime surve data. */
obn->curve_cache = NULL;
+ if (ob->id.lib) {
+ BKE_id_lib_local_paths(bmain, ob->id.lib, &obn->id);
+ }
+
return obn;
}
@@ -2020,12 +2024,16 @@ void BKE_object_to_mat4(Object *ob, float mat[4][4])
add_v3_v3v3(mat[3], ob->loc, ob->dloc);
}
+static void ob_get_parent_matrix(Scene *scene, Object *ob, Object *par, float parentmat[4][4]);
+
void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4])
{
if (ob->parent) {
- float invmat[4][4]; /* for inverse of parent's matrix */
- invert_m4_m4(invmat, ob->parent->obmat);
- mul_m4_m4m4(mat, invmat, ob->obmat);
+ float par_imat[4][4];
+
+ ob_get_parent_matrix(NULL, ob, ob->parent, par_imat);
+ invert_m4(par_imat);
+ mul_m4_m4m4(mat, par_imat, ob->obmat);
}
else {
copy_m4_m4(mat, ob->obmat);
@@ -2402,7 +2410,7 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat
/* include framerate */
fac1 = (1.0f / (1.0f + fabsf(ob->sf)));
- if (fac1 >= 1.0f) return 0;
+ if (fac1 >= 1.0f) return false;
fac2 = 1.0f - fac1;
fp1 = obmat[0];
@@ -2411,7 +2419,7 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat
fp1[0] = fac1 * fp1[0] + fac2 * fp2[0];
}
- return 1;
+ return true;
}
/* note, scene is the active scene while actual_scene is the scene the object resides in */
@@ -2535,17 +2543,16 @@ void BKE_object_apply_mat4(Object *ob, float mat[4][4], const bool use_compat, c
mul_m4_m4m4(diff_mat, parent_mat, ob->parentinv);
invert_m4_m4(imat, diff_mat);
mul_m4_m4m4(rmat, imat, mat); /* get the parent relative matrix */
- BKE_object_apply_mat4(ob, rmat, use_compat, false);
/* same as below, use rmat rather than mat */
mat4_to_loc_rot_size(ob->loc, rot, ob->size, rmat);
- BKE_object_mat3_to_rot(ob, rot, use_compat);
}
else {
mat4_to_loc_rot_size(ob->loc, rot, ob->size, mat);
- BKE_object_mat3_to_rot(ob, rot, use_compat);
}
+ BKE_object_mat3_to_rot(ob, rot, use_compat);
+
sub_v3_v3(ob->loc, ob->dloc);
if (ob->dscale[0] != 0.0f) ob->size[0] /= ob->dscale[0];
@@ -3345,7 +3352,7 @@ void BKE_object_delete_ptcache(Object *ob, int index)
/* shape key utility function */
/************************* Mesh ************************/
-static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, const bool from_mix)
+static KeyBlock *insert_meshkey(Object *ob, const char *name, const bool from_mix)
{
Mesh *me = ob->data;
Key *key = me->key;
@@ -3366,7 +3373,7 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, cons
else {
/* copy from current values */
int totelem;
- float *data = BKE_key_evaluate_object(scene, ob, &totelem);
+ float *data = BKE_key_evaluate_object(ob, &totelem);
/* create new block with prepared data */
kb = BKE_keyblock_add_ctime(key, name, false);
@@ -3377,7 +3384,7 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, cons
return kb;
}
/************************* Lattice ************************/
-static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, const bool from_mix)
+static KeyBlock *insert_lattkey(Object *ob, const char *name, const bool from_mix)
{
Lattice *lt = ob->data;
Key *key = lt->key;
@@ -3404,7 +3411,7 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, cons
else {
/* copy from current values */
int totelem;
- float *data = BKE_key_evaluate_object(scene, ob, &totelem);
+ float *data = BKE_key_evaluate_object(ob, &totelem);
/* create new block with prepared data */
kb = BKE_keyblock_add_ctime(key, name, false);
@@ -3415,7 +3422,7 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, cons
return kb;
}
/************************* Curve ************************/
-static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, const bool from_mix)
+static KeyBlock *insert_curvekey(Object *ob, const char *name, const bool from_mix)
{
Curve *cu = ob->data;
Key *key = cu->key;
@@ -3444,7 +3451,7 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, con
else {
/* copy from current values */
int totelem;
- float *data = BKE_key_evaluate_object(scene, ob, &totelem);
+ float *data = BKE_key_evaluate_object(ob, &totelem);
/* create new block with prepared data */
kb = BKE_keyblock_add_ctime(key, name, false);
@@ -3455,16 +3462,16 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, con
return kb;
}
-KeyBlock *BKE_object_insert_shape_key(Scene *scene, Object *ob, const char *name, const bool from_mix)
+KeyBlock *BKE_object_insert_shape_key(Object *ob, const char *name, const bool from_mix)
{
switch (ob->type) {
case OB_MESH:
- return insert_meshkey(scene, ob, name, from_mix);
+ return insert_meshkey(ob, name, from_mix);
case OB_CURVE:
case OB_SURF:
- return insert_curvekey(scene, ob, name, from_mix);
+ return insert_curvekey(ob, name, from_mix);
case OB_LATTICE:
- return insert_lattkey(scene, ob, name, from_mix);
+ return insert_lattkey(ob, name, from_mix);
default:
return NULL;
}
@@ -3509,6 +3516,88 @@ int BKE_object_is_modified(Scene *scene, Object *ob)
return flag;
}
+/* Check of objects moves in time. */
+/* NOTE: This function is currently optimized for usage in combination
+ * with mti->canDeform, so modifiers can quickly check if their target
+ * objects moves (causing deformation motion blur) or not.
+ *
+ * This makes it possible to give some degree of false-positives here,
+ * but it's currently an acceptable tradeoff between complexity and check
+ * speed. In combination with checks of modifier stack and real life usage
+ * percentage of false-positives shouldn't be that hight.
+ */
+static bool object_moves_in_time(Object *object)
+{
+ AnimData *adt = object->adt;
+ if (adt != NULL) {
+ /* If object has any sort of animation data assume it is moving. */
+ if (adt->action != NULL ||
+ !BLI_listbase_is_empty(&adt->nla_tracks) ||
+ !BLI_listbase_is_empty(&adt->drivers) ||
+ !BLI_listbase_is_empty(&adt->overrides))
+ {
+ return true;
+ }
+ }
+ if (!BLI_listbase_is_empty(&object->constraints)) {
+ return true;
+ }
+ if (object->parent != NULL) {
+ /* TODO(sergey): Do recursive check here? */
+ return true;
+ }
+ return false;
+}
+
+static bool constructive_modifier_is_deform_modified(ModifierData *md)
+{
+ /* TODO(sergey): Consider generalizing this a bit so all modifier logic
+ * is concentrated in MOD_{modifier}.c file,
+ */
+ if (md->type == eModifierType_Array) {
+ ArrayModifierData *amd = (ArrayModifierData *)md;
+ /* TODO(sergey): Check if curve is deformed. */
+ return (amd->start_cap != NULL && object_moves_in_time(amd->start_cap)) ||
+ (amd->end_cap != NULL && object_moves_in_time(amd->end_cap)) ||
+ (amd->curve_ob != NULL && object_moves_in_time(amd->curve_ob)) ||
+ (amd->offset_ob != NULL && object_moves_in_time(amd->offset_ob));
+ }
+ else if (md->type == eModifierType_Mirror) {
+ MirrorModifierData *mmd = (MirrorModifierData *)md;
+ return mmd->mirror_ob != NULL && object_moves_in_time(mmd->mirror_ob);
+ }
+ else if (md->type == eModifierType_Screw) {
+ ScrewModifierData *smd = (ScrewModifierData *)md;
+ return smd->ob_axis != NULL && object_moves_in_time(smd->ob_axis);
+ }
+ return false;
+}
+
+static bool modifiers_has_animation_check(Object *ob)
+{
+ /* TODO(sergey): This is a bit code duplication with depsgraph, but
+ * would be nicer to solve this as a part of new dependency graph
+ * work, so we avoid conflicts and so.
+ */
+ if (ob->adt != NULL) {
+ AnimData *adt = ob->adt;
+ FCurve *fcu;
+ if (adt->action != NULL) {
+ for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
+ if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) {
+ return true;
+ }
+ }
+ }
+ for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
+ if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
/* test if object is affected by deforming modifiers (for motion blur). again
* most important is to avoid false positives, this is to skip computations
* and we can still if there was actual deformation afterwards */
@@ -3517,6 +3606,7 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob)
ModifierData *md;
VirtualModifierData virtualModifierData;
int flag = 0;
+ const bool is_modifier_animated = modifiers_has_animation_check(ob);
if (BKE_key_from_object(ob))
flag |= eModifierMode_Realtime | eModifierMode_Render;
@@ -3527,8 +3617,14 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob)
md = md->next)
{
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ bool can_deform = mti->type == eModifierTypeType_OnlyDeform ||
+ is_modifier_animated;
+
+ if (!can_deform) {
+ can_deform = constructive_modifier_is_deform_modified(md);
+ }
- if (mti->type == eModifierTypeType_OnlyDeform) {
+ if (can_deform) {
if (!(flag & eModifierMode_Render) && modifier_isEnabled(scene, md, eModifierMode_Render))
flag |= eModifierMode_Render;
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index a3f5e56f4dc..e46929dde4a 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -27,18 +27,457 @@
#include "MEM_guardedalloc.h"
+#include "BLF_translation.h"
+
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
+#include "DNA_armature_types.h"
+#include "DNA_cloth_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
+
#include "BKE_action.h"
+#include "BKE_deform.h"
+#include "BKE_editmesh.h"
#include "BKE_object_deform.h" /* own include */
#include "BKE_object.h"
#include "BKE_modifier.h"
-#include "DNA_armature_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_types.h"
+/** \name Misc helpers
+ * \{ */
+
+static Lattice *object_defgroup_lattice_get(ID *id)
+{
+ Lattice *lt = (Lattice *)id;
+ BLI_assert(GS(id->name) == ID_LT);
+ return (lt->editlatt) ? lt->editlatt->latt : lt;
+}
+
+/**
+ * Update users of vgroups from this object, according to given map.
+ *
+ * Use it when you remove or reorder vgroups in the object.
+ *
+ * \param map an array mapping old indices to new indices.
+ */
+void BKE_object_defgroup_remap_update_users(Object *ob, int *map)
+{
+ ModifierData *md;
+ ParticleSystem *psys;
+ int a;
+
+ /* these cases don't use names to refer to vertex groups, so when
+ * they get removed the numbers get out of sync, this corrects that */
+
+ if (ob->soft) {
+ ob->soft->vertgroup = map[ob->soft->vertgroup];
+ }
+
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Explode) {
+ ExplodeModifierData *emd = (ExplodeModifierData *)md;
+ emd->vgroup = map[emd->vgroup];
+ }
+ else if (md->type == eModifierType_Cloth) {
+ ClothModifierData *clmd = (ClothModifierData *)md;
+ ClothSimSettings *clsim = clmd->sim_parms;
+
+ if (clsim) {
+ clsim->vgroup_mass = map[clsim->vgroup_mass];
+ clsim->vgroup_bend = map[clsim->vgroup_bend];
+ clsim->vgroup_struct = map[clsim->vgroup_struct];
+ }
+ }
+ }
+
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ for (a = 0; a < PSYS_TOT_VG; a++) {
+ psys->vgroup[a] = map[psys->vgroup[a]];
+ }
+ }
+}
+/** \} */
+
+
+/** \name Group creation
+ * \{ */
+
+/**
+ * Add a vgroup of given name to object. *Does not* handle MDeformVert data at all!
+ */
+bDeformGroup *BKE_object_defgroup_add_name(Object *ob, const char *name)
+{
+ bDeformGroup *defgroup;
+
+ if (!ob || !OB_TYPE_SUPPORT_VGROUP(ob->type))
+ return NULL;
+
+ defgroup = BKE_defgroup_new(ob, name);
+
+ ob->actdef = BLI_listbase_count(&ob->defbase);
+
+ return defgroup;
+}
+
+/**
+ * Add a vgroup of default name to object. *Does not* handle MDeformVert data at all!
+ */
+bDeformGroup *BKE_object_defgroup_add(Object *ob)
+{
+ return BKE_object_defgroup_add_name(ob, DATA_("Group"));
+}
+
+/**
+ * Create MDeformVert data for given ID. Work in Object mode only.
+ */
+MDeformVert *BKE_object_defgroup_data_create(ID *id)
+{
+ if (GS(id->name) == ID_ME) {
+ Mesh *me = (Mesh *)id;
+ me->dvert = CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
+ return me->dvert;
+ }
+ else if (GS(id->name) == ID_LT) {
+ Lattice *lt = (Lattice *)id;
+ lt->dvert = MEM_callocN(sizeof(MDeformVert) * lt->pntsu * lt->pntsv * lt->pntsw, "lattice deformVert");
+ return lt->dvert;
+ }
+
+ return NULL;
+}
+/** \} */
+
+
+/** \name Group clearing
+ * \{ */
+
+/**
+ * Remove all verts (or only selected ones) from given vgroup. Work in Object and Edit modes.
+ *
+ * \param allverts If true, remove all vertices, else only selected ones.
+ * \return True if any vertex was removed, false otherwise.
+ */
+bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_selection)
+{
+ MDeformVert *dv;
+ const int def_nr = BLI_findindex(&ob->defbase, dg);
+ bool changed = false;
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_btmesh) {
+ BMEditMesh *em = me->edit_btmesh;
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ if (cd_dvert_offset != -1) {
+ BMVert *eve;
+ BMIter iter;
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+
+ if (dv && dv->dw && (!use_selection || BM_elem_flag_test(eve, BM_ELEM_SELECT))) {
+ MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ defvert_remove_group(dv, dw); /* dw can be NULL */
+ changed = true;
+ }
+ }
+ }
+ }
+ else {
+ if (me->dvert) {
+ MVert *mv;
+ int i;
+
+ mv = me->mvert;
+ dv = me->dvert;
+
+ for (i = 0; i < me->totvert; i++, mv++, dv++) {
+ if (mv->flag & SELECT) {
+ if (dv->dw && (!use_selection || (mv->flag & SELECT))) {
+ MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ defvert_remove_group(dv, dw); /* dw can be NULL */
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
+
+ if (lt->dvert) {
+ BPoint *bp;
+ int i, tot = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ for (i = 0, bp = lt->def; i < tot; i++, bp++) {
+ if (!use_selection || (bp->f1 & SELECT)) {
+ MDeformWeight *dw;
+
+ dv = &lt->dvert[i];
+
+ dw = defvert_find_index(dv, def_nr);
+ defvert_remove_group(dv, dw); /* dw can be NULL */
+ changed = true;
+ }
+ }
+ }
+ }
+
+ return changed;
+}
+
+/**
+ * Remove all verts (or only selected ones) from all vgroups. Work in Object and Edit modes.
+ *
+ * \param allverts If true, remove all vertices, else only selected ones.
+ * \return True if any vertex was removed, false otherwise.
+ */
+bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection)
+{
+ bDeformGroup *dg;
+ bool changed = false;
+
+ for (dg = ob->defbase.first; dg; dg = dg->next) {
+ if (BKE_object_defgroup_clear(ob, dg, use_selection)) {
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+/** \} */
+
+
+/** \name Group removal
+ * \{ */
+
+static void object_defgroup_remove_update_users(Object *ob, const int idx)
+{
+ int i, defbase_tot = BLI_listbase_count(&ob->defbase) + 1;
+ int *map = MEM_mallocN(sizeof(int) * defbase_tot, "vgroup del");
+
+ map[idx] = map[0] = 0;
+ for (i = 1; i < idx; i++) {
+ map[i] = i;
+ }
+ for (i = idx + 1; i < defbase_tot; i++) {
+ map[i] = i - 1;
+ }
+
+ BKE_object_defgroup_remap_update_users(ob, map);
+ MEM_freeN(map);
+}
+
+static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const int def_nr)
+{
+ object_defgroup_remove_update_users(ob, def_nr + 1);
+
+ /* Remove the group */
+ BLI_freelinkN(&ob->defbase, dg);
+
+ /* Update the active deform index if necessary */
+ if (ob->actdef > def_nr)
+ ob->actdef--;
+
+ /* remove all dverts */
+ if (BLI_listbase_is_empty(&ob->defbase)) {
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
+ me->dvert = NULL;
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
+ if (lt->dvert) {
+ MEM_freeN(lt->dvert);
+ lt->dvert = NULL;
+ }
+ }
+ }
+ else if (ob->actdef < 1) { /* Keep a valid active index if we still have some vgroups. */
+ ob->actdef = 1;
+ }
+}
+
+static void object_defgroup_remove_object_mode(Object *ob, bDeformGroup *dg)
+{
+ MDeformVert *dvert_array = NULL;
+ int dvert_tot = 0;
+ const int def_nr = BLI_findindex(&ob->defbase, dg);
+
+ BLI_assert(def_nr != -1);
+
+ BKE_object_defgroup_array_get(ob->data, &dvert_array, &dvert_tot);
+
+ if (dvert_array) {
+ int i, j;
+ MDeformVert *dv;
+ for (i = 0, dv = dvert_array; i < dvert_tot; i++, dv++) {
+ MDeformWeight *dw;
+
+ dw = defvert_find_index(dv, def_nr);
+ defvert_remove_group(dv, dw); /* dw can be NULL */
+
+ /* inline, make into a function if anything else needs to do this */
+ for (j = 0; j < dv->totweight; j++) {
+ if (dv->dw[j].def_nr > def_nr) {
+ dv->dw[j].def_nr--;
+ }
+ }
+ /* done */
+ }
+ }
+
+ object_defgroup_remove_common(ob, dg, def_nr);
+}
+
+static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg)
+{
+ int i;
+ const int def_nr = BLI_findindex(&ob->defbase, dg);
+
+ BLI_assert(def_nr != -1);
+
+ /* Make sure that no verts are using this group - if none were removed, we can skip next per-vert update. */
+ if (!BKE_object_defgroup_clear(ob, dg, false)) {
+ /* Nothing to do. */
+ }
+ /* Else, make sure that any groups with higher indices are adjusted accordingly */
+ else if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ BMIter iter;
+ BMVert *eve;
+ MDeformVert *dvert;
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+
+ if (dvert) {
+ for (i = 0; i < dvert->totweight; i++) {
+ if (dvert->dw[i].def_nr > def_nr) {
+ dvert->dw[i].def_nr--;
+ }
+ }
+ }
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ((Lattice *)(ob->data))->editlatt->latt;
+ BPoint *bp;
+ MDeformVert *dvert = lt->dvert;
+ int a, tot;
+
+ if (dvert) {
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ for (a = 0, bp = lt->def; a < tot; a++, bp++, dvert++) {
+ for (i = 0; i < dvert->totweight; i++) {
+ if (dvert->dw[i].def_nr > def_nr) {
+ dvert->dw[i].def_nr--;
+ }
+ }
+ }
+ }
+ }
+
+ object_defgroup_remove_common(ob, dg, def_nr);
+}
+
+/**
+ * Remove given vgroup from object. Work in Object and Edit modes.
+ */
+void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
+{
+ if (BKE_object_is_in_editmode_vgroup(ob))
+ object_defgroup_remove_edit_mode(ob, defgroup);
+ else
+ object_defgroup_remove_object_mode(ob, defgroup);
+}
+
+/**
+ * Remove all vgroups from object. Work in Object and Edit modes.
+ */
+void BKE_object_defgroup_remove_all(Object *ob)
+{
+ bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
+ const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
+
+ if (dg) {
+ while (dg) {
+ bDeformGroup *next_dg = dg->next;
+
+ if (edit_mode)
+ object_defgroup_remove_edit_mode(ob, dg);
+ else
+ object_defgroup_remove_object_mode(ob, dg);
+
+ dg = next_dg;
+ }
+ }
+ else { /* ob->defbase is empty... */
+ /* remove all dverts */
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
+ me->dvert = NULL;
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
+ if (lt->dvert) {
+ MEM_freeN(lt->dvert);
+ lt->dvert = NULL;
+ }
+ }
+ /* Fix counters/indices */
+ ob->actdef = 0;
+ }
+}
+
+/**
+ * Get MDeformVert vgroup data from given object. Should only be used in Object mode.
+ *
+ * \return True if the id type supports weights.
+ */
+bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
+{
+ if (id) {
+ switch (GS(id->name)) {
+ case ID_ME:
+ {
+ Mesh *me = (Mesh *)id;
+ *dvert_arr = me->dvert;
+ *dvert_tot = me->totvert;
+ return true;
+ }
+ case ID_LT:
+ {
+ Lattice *lt = object_defgroup_lattice_get(id);
+ *dvert_arr = lt->dvert;
+ *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ return true;
+ }
+ }
+ }
+
+ *dvert_arr = NULL;
+ *dvert_tot = 0;
+ return false;
+}
+/** \} */
/* --- functions for getting vgroup aligned maps --- */
@@ -46,7 +485,7 @@
* gets the status of "flag" for each bDeformGroup
* in ob->defbase and returns an array containing them
*/
-bool *BKE_objdef_lock_flags_get(Object *ob, const int defbase_tot)
+bool *BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot)
{
bool is_locked = false;
int i;
@@ -66,11 +505,11 @@ bool *BKE_objdef_lock_flags_get(Object *ob, const int defbase_tot)
return NULL;
}
-bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
+bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
{
bDeformGroup *dg;
ModifierData *md;
- bool *vgroup_validmap;
+ bool *defgroup_validmap;
GHash *gh;
int i, step1 = 1;
//int defbase_tot = BLI_listbase_count(&ob->defbase);
@@ -80,7 +519,7 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
return NULL;
}
- gh = BLI_ghash_str_new_ex("BKE_objdef_validmap_get gh", defbase_tot);
+ gh = BLI_ghash_str_new_ex(__func__, defbase_tot);
/* add all names to a hash table */
for (dg = ob->defbase.first; dg; dg = dg->next) {
@@ -115,23 +554,23 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
}
}
- vgroup_validmap = MEM_mallocN(sizeof(*vgroup_validmap) * defbase_tot, "wpaint valid map");
+ defgroup_validmap = MEM_mallocN(sizeof(*defgroup_validmap) * defbase_tot, "wpaint valid map");
/* add all names to a hash table */
for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
- vgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL);
+ defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL);
}
BLI_assert(i == BLI_ghash_size(gh));
BLI_ghash_free(gh, NULL, NULL);
- return vgroup_validmap;
+ return defgroup_validmap;
}
/* Returns total selected vgroups,
* wpi.defbase_sel is assumed malloc'd, all values are set */
-bool *BKE_objdef_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
+bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
{
bool *dg_selection = MEM_mallocN(defbase_tot * sizeof(bool), __func__);
bDeformGroup *defgroup;
@@ -158,3 +597,86 @@ bool *BKE_objdef_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_t
return dg_selection;
}
+
+
+/**
+ * Return the subset type of the Vertex Group Selection
+ */
+bool *BKE_object_defgroup_subset_from_select_type(
+ Object *ob, eVGroupSelect subset_type, int *r_defgroup_tot, int *r_subset_count)
+{
+ bool *defgroup_validmap = NULL;
+ *r_defgroup_tot = BLI_listbase_count(&ob->defbase);
+
+ switch (subset_type) {
+ case WT_VGROUP_ACTIVE:
+ {
+ const int def_nr_active = ob->actdef - 1;
+ defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
+ memset(defgroup_validmap, false, *r_defgroup_tot * sizeof(*defgroup_validmap));
+ if ((def_nr_active >= 0) && (def_nr_active < *r_defgroup_tot)) {
+ *r_subset_count = 1;
+ defgroup_validmap[def_nr_active] = true;
+ }
+ else {
+ *r_subset_count = 0;
+ }
+ break;
+ }
+ case WT_VGROUP_BONE_SELECT:
+ {
+ defgroup_validmap = BKE_object_defgroup_selected_get(ob, *r_defgroup_tot, r_subset_count);
+ break;
+ }
+ case WT_VGROUP_BONE_DEFORM:
+ {
+ int i;
+ defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
+ *r_subset_count = 0;
+ for (i = 0; i < *r_defgroup_tot; i++) {
+ if (defgroup_validmap[i] == true) {
+ *r_subset_count += 1;
+ }
+ }
+ break;
+ }
+ case WT_VGROUP_BONE_DEFORM_OFF:
+ {
+ int i;
+ defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
+ *r_subset_count = 0;
+ for (i = 0; i < *r_defgroup_tot; i++) {
+ defgroup_validmap[i] = !defgroup_validmap[i];
+ if (defgroup_validmap[i] == true) {
+ *r_subset_count += 1;
+ }
+ }
+ break;
+ }
+ case WT_VGROUP_ALL:
+ default:
+ {
+ defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
+ memset(defgroup_validmap, true, *r_defgroup_tot * sizeof(*defgroup_validmap));
+ *r_subset_count = *r_defgroup_tot;
+ break;
+ }
+ }
+
+ return defgroup_validmap;
+}
+
+/**
+ * store indices from the defgroup_validmap (faster lookups in some cases)
+ */
+void BKE_object_defgroup_subset_to_index_array(
+ const bool *defgroup_validmap, const int defgroup_tot, int *r_defgroup_subset_map)
+{
+ int i, j = 0;
+ for (i = 0; i < defgroup_tot; i++) {
+ if (defgroup_validmap[i]) {
+ r_defgroup_subset_map[j++] = i;
+ }
+ }
+}
+
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index ea81d1609d9..58591242e5b 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -395,7 +395,7 @@ bool BKE_paint_select_elem_test(Object *ob)
BKE_paint_select_face_test(ob));
}
-void BKE_paint_init(Paint *p, const char col[3])
+void BKE_paint_init(UnifiedPaintSettings *ups, Paint *p, const char col[3])
{
Brush *brush;
@@ -407,6 +407,9 @@ void BKE_paint_init(Paint *p, const char col[3])
memcpy(p->paint_cursor_col, col, 3);
p->paint_cursor_col[3] = 128;
+ ups->last_stroke_valid = false;
+ zero_v3(ups->average_stroke_accum);
+ ups->average_stroke_counter = 0;
}
void BKE_paint_free(Paint *paint)
@@ -426,6 +429,18 @@ void BKE_paint_copy(Paint *src, Paint *tar)
id_us_plus((ID *)tar->palette);
}
+void BKE_paint_stroke_get_average(Scene *scene, Object *ob, float stroke[3])
+{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ if (ups->last_stroke_valid && ups->average_stroke_counter > 0) {
+ float fac = 1.0f / ups->average_stroke_counter;
+ mul_v3_v3fl(stroke, ups->average_stroke_accum, fac);
+ }
+ else {
+ copy_v3_v3(stroke, ob->obmat[3]);
+ }
+}
+
/* returns non-zero if any of the face's vertices
* are hidden, zero otherwise */
bool paint_is_face_hidden(const MFace *f, const MVert *mvert)
@@ -477,19 +492,48 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level,
/* threshold to move before updating the brush rotation */
#define RAKE_THRESHHOLD 20
-void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_pos[2])
+static void update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, float rotation)
+{
+ if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE)
+ ups->brush_rotation = rotation;
+ else
+ ups->brush_rotation = 0.0f;
+
+ if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)
+ /* here, translation contains the mouse coordinates. */
+ ups->brush_rotation_sec = rotation;
+ else
+ ups->brush_rotation_sec = 0.0f;
+}
+
+void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, const float mouse_pos[2])
{
- const float u = 0.5f;
- const float r = RAKE_THRESHHOLD;
+ if ((brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
+ const float u = 0.5f;
+ const float r = RAKE_THRESHHOLD;
+ float rotation;
+
+ float dpos[2];
+ sub_v2_v2v2(dpos, ups->last_rake, mouse_pos);
+
+ if (len_squared_v2(dpos) >= r * r) {
+ rotation = atan2f(dpos[0], dpos[1]);
- float dpos[2];
- sub_v2_v2v2(dpos, ups->last_rake, mouse_pos);
+ interp_v2_v2v2(ups->last_rake, ups->last_rake,
+ mouse_pos, u);
- if (len_squared_v2(dpos) >= r * r) {
- ups->brush_rotation = atan2f(dpos[0], dpos[1]);
+ ups->last_rake_angle = rotation;
- interp_v2_v2v2(ups->last_rake, ups->last_rake,
- mouse_pos, u);
+ update_brush_rake_rotation(ups, brush, rotation);
+ }
+ /* make sure we reset here to the last rotation to avoid accumulating
+ * values in case a random rotation is also added */
+ else {
+ update_brush_rake_rotation(ups, brush, ups->last_rake_angle);
+ }
+ }
+ else {
+ ups->brush_rotation = ups->brush_rotation_sec = 0.0f;
}
}
@@ -644,11 +688,11 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
VirtualModifierData virtualModifierData;
if (mmd || ob->sculpt->bm)
- return 0;
+ return false;
/* non-locked shape keys could be handled in the same way as deformed mesh */
if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr)
- return 1;
+ return true;
md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
@@ -658,11 +702,11 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue;
if (ELEM(md->type, eModifierType_ShapeKey, eModifierType_Multires)) continue;
- if (mti->type == eModifierTypeType_OnlyDeform) return 1;
- else if ((sd->flags & SCULPT_ONLY_DEFORM) == 0) return 1;
+ if (mti->type == eModifierTypeType_OnlyDeform) return true;
+ else if ((sd->flags & SCULPT_ONLY_DEFORM) == 0) return true;
}
- return 0;
+ return false;
}
/**
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 0b108210929..78a54e5c6ac 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -981,14 +981,14 @@ bool psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float
int b;
if (!(psys->renderdata && (psys->part->simplify_flag & PART_SIMPLIFY_ENABLE)))
- return 0;
+ return false;
data = psys->renderdata;
if (!data->do_simplify)
- return 0;
+ return false;
b = (data->index_mf_to_mpoly) ? DM_origindex_mface_mpoly(data->index_mf_to_mpoly, data->index_mp_to_orig, cpa->num) : cpa->num;
if (b == ORIGINDEX_NONE) {
- return 0;
+ return false;
}
elem = &data->elems[b];
@@ -1568,12 +1568,13 @@ void psys_interpolate_uvs(const MTFace *tface, int quad, const float w[4], float
void psys_interpolate_mcol(const MCol *mcol, int quad, const float w[4], MCol *mc)
{
- char *cp, *cp1, *cp2, *cp3, *cp4;
+ const char *cp1, *cp2, *cp3, *cp4;
+ char *cp;
cp = (char *)mc;
- cp1 = (char *)&mcol[0];
- cp2 = (char *)&mcol[1];
- cp3 = (char *)&mcol[2];
+ cp1 = (const char *)&mcol[0];
+ cp2 = (const char *)&mcol[1];
+ cp3 = (const char *)&mcol[2];
if (quad) {
cp4 = (char *)&mcol[3];
@@ -2999,7 +3000,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
}
/*---first main loop: create all actual particles' paths---*/
- LOOP_SHOWN_PARTICLES {
+ LOOP_PARTICLES {
if (!psys->totchild) {
psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f);
pa_length = ptex.length * (1.0f - part->randlength * psys_frand(psys, psys->seed + p));
@@ -3700,6 +3701,10 @@ ParticleSettings *BKE_particlesettings_copy(ParticleSettings *part)
BLI_duplicatelist(&partn->dupliweights, &part->dupliweights);
+ if (part->id.lib) {
+ BKE_id_lib_local_paths(G.main, part->id.lib, &partn->id);
+ }
+
return partn;
}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 9fe5ba6707f..2a71cf2780f 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -1667,7 +1667,7 @@ static void get_angular_velocity_vector(short avemode, ParticleKey *state, float
}
}
-void psys_get_birth_coordinates(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, float dtime, float cfra)
+void psys_get_birth_coords(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, float dtime, float cfra)
{
Object *ob = sim->ob;
ParticleSystem *psys = sim->psys;
@@ -1999,7 +1999,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
psys->flag |= PSYS_OB_ANIM_RESTORE;
}
- psys_get_birth_coordinates(sim, pa, &pa->state, dtime, cfra);
+ psys_get_birth_coords(sim, pa, &pa->state, dtime, cfra);
/* Initialize particle settings which depends on texture.
*
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index ff6fae08460..bd953890443 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -943,7 +943,7 @@ static bool update_search_cb(PBVHNode *node, void *data_v)
if (node->flag & PBVH_Leaf)
return (node->flag & flag) != 0;
- return 1;
+ return true;
}
static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
@@ -1474,10 +1474,10 @@ bool ray_face_intersection(const float ray_start[3],
(t3 && isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2, t3, &dist, NULL, 0.1f) && dist < *fdist))
{
*fdist = dist;
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index c2f71d729bb..75301471fca 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -50,7 +50,6 @@
#include "BLI_threads.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_system.h"
#include "BLF_translation.h"
@@ -58,6 +57,7 @@
#include "WM_api.h"
+#include "BKE_appdir.h"
#include "BKE_anim.h"
#include "BKE_blender.h"
#include "BKE_cloth.h"
@@ -1461,7 +1461,7 @@ static int ptcache_path(PointCache *cache, Object *ob, char *filename)
/* use the temp path. this is weak but better then not using point cache at all */
/* temporary directory is assumed to exist and ALWAYS has a trailing slash */
- BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH, BLI_temp_dir_session());
+ BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH, BKE_tempdir_session());
return BLI_add_slash(filename); /* new strlen() */
}
@@ -2495,11 +2495,18 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
case PTCACHE_CLEAR_AFTER:
ptcache_path(pid->cache, pid->ob, path);
- len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */
-
dir = opendir(path);
if (dir==NULL)
return;
+
+ len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */
+ /* append underscore terminator to ensure we don't match similar names
+ * from objects whose names start with the same prefix
+ */
+ if (len < sizeof(filename) - 2) {
+ BLI_strncpy(filename + len, "_", sizeof(filename) - 2 - len);
+ len += 1;
+ }
BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 9b5d6699cb1..4bd3b6bd8dd 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -62,8 +62,6 @@
#include "BKE_pointcache.h"
#include "BKE_rigidbody.h"
-#include "RNA_access.h"
-
#ifdef WITH_BULLET
/* ************************************** */
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 168fa9ad120..13e9b7fb0c4 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -70,6 +70,7 @@
#include "BKE_fcurve.h"
#include "BKE_freestyle.h"
#include "BKE_global.h"
+#include "BKE_gpencil.h"
#include "BKE_group.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
@@ -308,6 +309,19 @@ Scene *BKE_scene_copy(Scene *sce, int type)
BKE_sequence_base_dupli_recursive(sce, scen, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL);
}
}
+
+ /* grease pencil */
+ if (scen->gpd) {
+ if (type == SCE_COPY_FULL) {
+ scen->gpd = gpencil_data_duplicate(scen->gpd, false);
+ }
+ else if (type == SCE_COPY_EMPTY) {
+ scen->gpd = NULL;
+ }
+ else {
+ id_us_plus((ID *)scen->gpd);
+ }
+ }
return scen;
}
@@ -1102,7 +1116,7 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce)
Scene *sce_iter;
int a, totscene;
- if (sce->set == NULL) return 1;
+ if (sce->set == NULL) return true;
totscene = BLI_listbase_count(&bmain->scene);
for (a = 0, sce_iter = sce; sce_iter->set; sce_iter = sce_iter->set, a++) {
@@ -1110,11 +1124,11 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce)
if (a > totscene) {
/* the tested scene gets zero'ed, that's typically current scene */
sce->set = NULL;
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
/* This function is needed to cope with fractional frames - including two Blender rendering features
@@ -1838,13 +1852,13 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *
Scene *sce;
if (act == -1) {
- return 0;
+ return false;
}
else if ( (scene->r.layers.first == scene->r.layers.last) &&
(scene->r.layers.first == srl))
{
/* ensure 1 layer is kept */
- return 0;
+ return false;
}
BLI_remlink(&scene->r.layers, srl);
@@ -1866,7 +1880,7 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *
}
}
- return 1;
+ return true;
}
/* render simplification */
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index b2296151cf7..ad4ed5a0b99 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -402,6 +402,23 @@ ARegion *BKE_area_find_region_active_win(ScrArea *sa)
return NULL;
}
+/**
+ * \note, ideally we can get the area from the context,
+ * there are a few places however where this isn't practical.
+ */
+ScrArea *BKE_screen_find_area_from_space(struct bScreen *sc, SpaceLink *sl)
+{
+ ScrArea *sa;
+
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ if (BLI_findindex(&sa->spacedata, sl) != -1) {
+ break;
+ }
+ }
+
+ return sa;
+}
+
/* note, using this function is generally a last resort, you really want to be
* using the context when you can - campbell
* -1 for any type */
diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c
index 4268b33cb14..a1135bfc54b 100644
--- a/source/blender/blenkernel/intern/seqcache.c
+++ b/source/blender/blenkernel/intern/seqcache.c
@@ -95,10 +95,10 @@ static unsigned int seq_hash_render_data(const SeqRenderData *a)
static unsigned int seqcache_hashhash(const void *key_)
{
- const SeqCacheKey *key = (SeqCacheKey *) key_;
+ const SeqCacheKey *key = key_;
unsigned int rval = seq_hash_render_data(&key->context);
- rval ^= *(unsigned int *) &key->cfra;
+ rval ^= *(const unsigned int *) &key->cfra;
rval += key->type;
rval ^= ((intptr_t) key->seq) << 6;
@@ -107,8 +107,8 @@ static unsigned int seqcache_hashhash(const void *key_)
static bool seqcache_hashcmp(const void *a_, const void *b_)
{
- const SeqCacheKey *a = (SeqCacheKey *) a_;
- const SeqCacheKey *b = (SeqCacheKey *) b_;
+ const SeqCacheKey *a = a_;
+ const SeqCacheKey *b = b_;
return ((a->seq != b->seq) ||
(a->cfra != b->cfra) ||
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 9a144ec8e44..b43e481d97d 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -515,24 +515,22 @@ void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixe
/*********************** sequencer pipeline functions *************************/
-SeqRenderData BKE_sequencer_new_render_data(EvaluationContext *eval_ctx,
- Main *bmain, Scene *scene, int rectx, int recty,
- int preview_render_size)
-{
- SeqRenderData rval;
-
- rval.bmain = bmain;
- rval.scene = scene;
- rval.rectx = rectx;
- rval.recty = recty;
- rval.preview_render_size = preview_render_size;
- rval.motion_blur_samples = 0;
- rval.motion_blur_shutter = 0;
- rval.eval_ctx = eval_ctx;
- rval.skip_cache = false;
- rval.is_proxy_render = false;
-
- return rval;
+void BKE_sequencer_new_render_data(
+ EvaluationContext *eval_ctx,
+ Main *bmain, Scene *scene, int rectx, int recty,
+ int preview_render_size,
+ SeqRenderData *r_context)
+{
+ r_context->eval_ctx = eval_ctx;
+ r_context->bmain = bmain;
+ r_context->scene = scene;
+ r_context->rectx = rectx;
+ r_context->recty = recty;
+ r_context->preview_render_size = preview_render_size;
+ r_context->motion_blur_samples = 0;
+ r_context->motion_blur_shutter = 0;
+ r_context->skip_cache = false;
+ r_context->is_proxy_render = false;
}
/* ************************* iterator ************************** */
@@ -892,7 +890,6 @@ void BKE_sequencer_sort(Scene *scene)
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq, *seqt;
-
if (ed == NULL)
return;
@@ -1453,8 +1450,8 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c
return NULL;
}
- /* proxies are generated in default color space */
- seq->strip->proxy->anim = openanim(name, IB_rect, 0, NULL);
+ seq->strip->proxy->anim = openanim(name, IB_rect, 0,
+ seq->strip->colorspace_settings.name);
}
if (seq->strip->proxy->anim == NULL) {
return NULL;
@@ -1490,20 +1487,25 @@ static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, i
int quality;
int rectx, recty;
int ok;
- ImBuf *ibuf;
+ ImBuf *ibuf_tmp, *ibuf;
if (!seq_proxy_get_fname(seq, cfra, proxy_render_size, name)) {
return;
}
- ibuf = seq_render_strip(context, seq, cfra);
+ ibuf_tmp = seq_render_strip(context, seq, cfra);
- rectx = (proxy_render_size * ibuf->x) / 100;
- recty = (proxy_render_size * ibuf->y) / 100;
+ rectx = (proxy_render_size * ibuf_tmp->x) / 100;
+ recty = (proxy_render_size * ibuf_tmp->y) / 100;
- if (ibuf->x != rectx || ibuf->y != recty) {
+ if (ibuf_tmp->x != rectx || ibuf_tmp->y != recty) {
+ ibuf = IMB_dupImBuf(ibuf_tmp);
+ IMB_freeImBuf(ibuf_tmp);
IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty);
}
+ else {
+ ibuf = ibuf_tmp;
+ }
/* depth = 32 is intentionally left in, otherwise ALPHA channels
* won't work... */
@@ -1589,9 +1591,12 @@ void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, sho
/* fail safe code */
- render_context = BKE_sequencer_new_render_data(bmain->eval_ctx, bmain, context->scene,
- (scene->r.size * (float) scene->r.xsch) / 100.0f + 0.5f,
- (scene->r.size * (float) scene->r.ysch) / 100.0f + 0.5f, 100);
+ BKE_sequencer_new_render_data(
+ bmain->eval_ctx, bmain, context->scene,
+ (scene->r.size * (float) scene->r.xsch) / 100.0f + 0.5f,
+ (scene->r.size * (float) scene->r.ysch) / 100.0f + 0.5f, 100,
+ &render_context);
+
render_context.skip_cache = true;
render_context.is_proxy_render = true;
@@ -2525,6 +2530,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
int do_seq;
// bool have_seq = false; /* UNUSED */
bool have_comp = false;
+ bool use_gpencil = true;
Scene *scene;
int is_thread_main = BLI_thread_is_main();
@@ -2549,6 +2555,10 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
BKE_scene_camera_switch_update(scene);
camera = scene->camera;
}
+
+ if (seq->flag & SEQ_SCENE_NO_GPENCIL) {
+ use_gpencil = false;
+ }
if (have_comp == false && camera == NULL) {
scene->r.cfra = oldcfra;
@@ -2582,7 +2592,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
ibuf = sequencer_view3d_cb(scene, camera, width, height, IB_rect,
context->scene->r.seq_prev_type,
(context->scene->r.seq_flag & R_SEQ_SOLID_TEX) != 0,
- true, scene->r.alphamode, err_out);
+ use_gpencil, true, scene->r.alphamode, err_out);
if (ibuf == NULL) {
fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
}
@@ -3411,7 +3421,7 @@ static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *cha
/* recurs downwards to see if this seq depends on the changed seq */
if (seq == NULL)
- return 0;
+ return false;
if (seq == changed_seq)
free_imbuf = true;
@@ -4675,3 +4685,70 @@ bool BKE_sequence_is_valid_check(Sequence *seq)
return true;
}
+int BKE_sequencer_find_next_prev_edit(
+ Scene *scene, int cfra, const short side,
+ const bool do_skip_mute, const bool do_center, const bool do_unselected)
+{
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+
+ int dist, best_dist, best_frame = cfra;
+ int seq_frames[2], seq_frames_tot;
+
+ /* in case where both is passed, frame just finds the nearest end while frame_left the nearest start */
+
+ best_dist = MAXFRAME * 2;
+
+ if (ed == NULL) return cfra;
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ int i;
+
+ if (do_skip_mute && (seq->flag & SEQ_MUTE)) {
+ continue;
+ }
+
+ if (do_unselected && (seq->flag & SELECT))
+ continue;
+
+ if (do_center) {
+ seq_frames[0] = (seq->startdisp + seq->enddisp) / 2;
+ seq_frames_tot = 1;
+ }
+ else {
+ seq_frames[0] = seq->startdisp;
+ seq_frames[1] = seq->enddisp;
+
+ seq_frames_tot = 2;
+ }
+
+ for (i = 0; i < seq_frames_tot; i++) {
+ const int seq_frame = seq_frames[i];
+
+ dist = MAXFRAME * 2;
+
+ switch (side) {
+ case SEQ_SIDE_LEFT:
+ if (seq_frame < cfra) {
+ dist = cfra - seq_frame;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if (seq_frame > cfra) {
+ dist = seq_frame - cfra;
+ }
+ break;
+ case SEQ_SIDE_BOTH:
+ dist = abs(seq_frame - cfra);
+ break;
+ }
+
+ if (dist < best_dist) {
+ best_frame = seq_frame;
+ best_dist = dist;
+ }
+ }
+ }
+
+ return best_frame;
+}
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index d2a4d15a2c6..d91818615f3 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -52,7 +52,6 @@
#include "BKE_deform.h"
#include "BKE_mesh.h" /* for OMP limits. */
#include "BKE_subsurf.h"
-#include "BKE_editmesh.h"
#include "BLI_strict_flags.h"
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index cf3dc67e7bd..a996da5915e 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -62,6 +62,7 @@
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
+#include "BKE_appdir.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_bvhutils.h"
@@ -207,7 +208,7 @@ void smoke_reallocate_highres_fluid(SmokeDomainSettings *sds, float dx, int res[
/* smoke_turbulence_init uses non-threadsafe functions from fftw3 lib (like fftw_plan & co). */
BLI_lock_thread(LOCK_FFTW);
- sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, BLI_temp_dir_session(), use_fire, use_colors);
+ sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, BKE_tempdir_session(), use_fire, use_colors);
BLI_unlock_thread(LOCK_FFTW);
@@ -953,7 +954,7 @@ static bool subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int
/* if other is dynamic paint canvas, don't update */
if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN))
- return 1;
+ return true;
/* if object has parents, update them too */
if (parent_recursion) {
@@ -965,7 +966,7 @@ static bool subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int
/* skip subframe if object is parented
* to vertex of a dynamic paint canvas */
if (is_domain && (ob->partype == PARVERT1 || ob->partype == PARVERT3))
- return 0;
+ return false;
/* also update constraint targets */
for (con = ob->constraints.first; con; con = con->next) {
@@ -1011,7 +1012,7 @@ static bool subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int
BKE_pose_where_is(scene, ob);
}
- return 0;
+ return false;
}
/**********************************************************
@@ -1424,7 +1425,7 @@ static void emit_from_particles(Object *flow_ob, SmokeDomainSettings *sds, Smoke
static void sample_derivedmesh(
SmokeFlowSettings *sfs, MVert *mvert, MTFace *tface, MFace *mface,
- float *influence_map, float *velocity_map, int index, int base_res[3], float flow_center[3],
+ float *influence_map, float *velocity_map, int index, const int base_res[3], float flow_center[3],
BVHTreeFromMesh *treeData, const float ray_start[3], const float *vert_vel,
bool has_velocity, int defgrp_index, MDeformVert *dvert, float x, float y, float z)
{
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index da6ead06d98..88720d5fcb7 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -36,6 +36,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_threads.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
@@ -116,6 +117,12 @@ void BKE_sound_free(bSound *sound)
}
sound_free_waveform(sound);
+
+ if (sound->mutex) {
+ BLI_mutex_free(sound->mutex);
+ sound->mutex = NULL;
+ }
+
#endif /* WITH_AUDASPACE */
}
@@ -296,12 +303,6 @@ void sound_cache(bSound *sound)
sound->playback_handle = sound->handle;
}
-void sound_cache_notifying(struct Main *main, bSound *sound)
-{
- sound_cache(sound);
- sound_update_sequencer(main, sound);
-}
-
void sound_delete_cache(bSound *sound)
{
sound->flags &= ~SOUND_FLAGS_CACHING;
@@ -672,30 +673,55 @@ int sound_scene_playing(struct Scene *scene)
void sound_free_waveform(bSound *sound)
{
- if (sound->waveform) {
- MEM_freeN(((SoundWaveform *)sound->waveform)->data);
- MEM_freeN(sound->waveform);
+ SoundWaveform *waveform = sound->waveform;
+ if (waveform) {
+ if (waveform->data) {
+ MEM_freeN(waveform->data);
+ }
+ MEM_freeN(waveform);
}
sound->waveform = NULL;
}
-void sound_read_waveform(bSound *sound)
+void sound_read_waveform(bSound *sound, short *stop)
{
- AUD_SoundInfo info;
-
- info = AUD_getInfo(sound->playback_handle);
+ AUD_SoundInfo info = AUD_getInfo(sound->playback_handle);
+ SoundWaveform *waveform = MEM_mallocN(sizeof(SoundWaveform),
+ "SoundWaveform");
if (info.length > 0) {
- SoundWaveform *waveform = MEM_mallocN(sizeof(SoundWaveform), "SoundWaveform");
int length = info.length * SOUND_WAVE_SAMPLES_PER_SECOND;
-
+
waveform->data = MEM_mallocN(length * sizeof(float) * 3, "SoundWaveform.samples");
- waveform->length = AUD_readSound(sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND);
+ waveform->length = AUD_readSound(sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND, stop);
+ }
+ else {
+ /* Create an empty waveform here if the sound couldn't be
+ * read. This indicates that reading the waveform is "done",
+ * whereas just setting sound->waveform to NULL causes other
+ * code to think the waveform still needs to be created. */
+ waveform->data = NULL;
+ waveform->length = 0;
+ }
- sound_free_waveform(sound);
- sound->waveform = waveform;
+ if (*stop) {
+ if (waveform->data) {
+ MEM_freeN(waveform->data);
+ }
+ MEM_freeN(waveform);
+ BLI_mutex_lock(sound->mutex);
+ sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+ BLI_mutex_unlock(sound->mutex);
+ return;
}
+
+ sound_free_waveform(sound);
+
+ BLI_mutex_lock(sound->mutex);
+ sound->waveform = waveform;
+ sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+ BLI_mutex_unlock(sound->mutex);
}
void sound_update_scene(Main *bmain, struct Scene *scene)
@@ -830,7 +856,7 @@ void sound_stop_scene(struct Scene *UNUSED(scene)) {}
void sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {}
float sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; }
int sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; }
-void sound_read_waveform(struct bSound *UNUSED(sound)) {}
+void sound_read_waveform(struct bSound *sound, short *stop) { UNUSED_VARS(sound, stop); }
void sound_init_main(struct Main *UNUSED(bmain)) {}
void sound_set_cfra(int UNUSED(cfra)) {}
void sound_update_sequencer(struct Main *UNUSED(main), struct bSound *UNUSED(sound)) {}
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index 08daa09cc85..b11d0ae03b0 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -67,6 +67,10 @@ Speaker *BKE_speaker_copy(Speaker *spk)
if (spkn->sound)
spkn->sound->id.us++;
+ if (spk->id.lib) {
+ BKE_id_lib_local_paths(G.main, spk->id.lib, &spkn->id);
+ }
+
return spkn;
}
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index f03e2eaff4a..961a66f853b 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -41,7 +41,6 @@
#include "MEM_guardedalloc.h"
-#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@@ -66,8 +65,6 @@
#include "BKE_scene.h"
#include "BKE_subsurf.h"
-#include "PIL_time.h"
-
#ifndef USE_DYNSIZE
# include "BLI_array.h"
#endif
@@ -75,7 +72,6 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
-#include "GPU_material.h"
#include "CCGSubSurf.h"
@@ -411,7 +407,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
CCGFace **faceMap;
MTFace *tf;
MLoopUV *mluv;
- CCGFaceIterator *fi;
+ CCGFaceIterator fi;
int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S;
MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, n);
/* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with
@@ -438,11 +434,10 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
/* make a map from original faces to CCGFaces */
faceMap = MEM_mallocN(totface * sizeof(*faceMap), "facemapuv");
- for (fi = ccgSubSurf_getFaceIterator(uvss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ for (ccgSubSurf_initFaceIterator(uvss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))] = f;
}
- ccgFaceIterator_free(fi);
/* load coordinates from uvss into tface */
tf = tface;
@@ -699,9 +694,9 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
- CCGVertIterator *vi;
- CCGEdgeIterator *ei;
- CCGFaceIterator *fi;
+ CCGVertIterator vi;
+ CCGEdgeIterator ei;
+ CCGFaceIterator fi;
CCGKey key;
int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
int gridSize = ccgSubSurf_getGridSize(ss);
@@ -711,25 +706,23 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
if (!ccgSubSurf_getNumVerts(ss))
r_min[0] = r_min[1] = r_min[2] = r_max[0] = r_max[1] = r_max[2] = 0.0;
- for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(&vi);
float *co = ccgSubSurf_getVertData(ss, v);
minmax_v3_v3v3(co, r_min, r_max);
}
- ccgVertIterator_free(vi);
- for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
for (i = 0; i < edgeSize; i++)
minmax_v3_v3v3(CCG_elem_offset_co(&key, edgeData, i), r_min, r_max);
}
- ccgEdgeIterator_free(ei);
- for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
for (S = 0; S < numVerts; S++) {
@@ -740,7 +733,6 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
minmax_v3_v3v3(CCG_grid_elem_co(&key, faceGridData, x, y), r_min, r_max);
}
}
- ccgFaceIterator_free(fi);
}
static int ccgDM_getNumVerts(DerivedMesh *dm)
@@ -1067,8 +1059,9 @@ void subsurf_copy_grid_hidden(DerivedMesh *dm, const MPoly *mpoly,
const MDisps *md = &mdisps[mpoly[i].loopstart + j];
int hidden_gridsize = BKE_ccg_gridsize(md->level);
int factor = BKE_ccg_factor(level, md->level);
+ BLI_bitmap *hidden = md->hidden;
- if (!md->hidden)
+ if (!hidden)
continue;
for (y = 0; y < gridSize; y++) {
@@ -1077,7 +1070,7 @@ void subsurf_copy_grid_hidden(DerivedMesh *dm, const MPoly *mpoly,
vndx = getFaceIndex(ss, f, j, x, y, edgeSize, gridSize);
offset = (y * factor) * hidden_gridsize + (x * factor);
- if (BLI_BITMAP_TEST(md->hidden, offset))
+ if (BLI_BITMAP_TEST(hidden, offset))
mvert[vndx].flag |= ME_HIDE;
}
}
@@ -1433,9 +1426,9 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3])
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int gridSize = ccgSubSurf_getGridSize(ss);
int i;
- CCGVertIterator *vi;
- CCGEdgeIterator *ei;
- CCGFaceIterator *fi;
+ CCGVertIterator vi;
+ CCGEdgeIterator ei;
+ CCGFaceIterator fi;
CCGFace **faceMap2;
CCGEdge **edgeMap2;
CCGVert **vertMap2;
@@ -1443,30 +1436,27 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3])
totvert = ccgSubSurf_getNumVerts(ss);
vertMap2 = MEM_mallocN(totvert * sizeof(*vertMap2), "vertmap");
- for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(&vi);
vertMap2[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))] = v;
}
- ccgVertIterator_free(vi);
totedge = ccgSubSurf_getNumEdges(ss);
edgeMap2 = MEM_mallocN(totedge * sizeof(*edgeMap2), "edgemap");
- for (ei = ccgSubSurf_getEdgeIterator(ss), i = 0; !ccgEdgeIterator_isStopped(ei); i++, ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei), i = 0; !ccgEdgeIterator_isStopped(&ei); i++, ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
}
- ccgEdgeIterator_free(ei);
totface = ccgSubSurf_getNumFaces(ss);
faceMap2 = MEM_mallocN(totface * sizeof(*faceMap2), "facemap");
- for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
faceMap2[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))] = f;
}
- ccgFaceIterator_free(fi);
i = 0;
for (index = 0; index < totface; index++) {
@@ -1516,12 +1506,12 @@ static void ccgDM_foreachMappedVert(
DMForeachFlag flag)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
- CCGVertIterator *vi;
+ CCGVertIterator vi;
CCGKey key;
CCG_key_top_level(&key, ccgdm->ss);
- for (vi = ccgSubSurf_getVertIterator(ccgdm->ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ for (ccgSubSurf_initVertIterator(ccgdm->ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(&vi);
const int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
if (index != -1) {
@@ -1530,8 +1520,6 @@ static void ccgDM_foreachMappedVert(
func(userData, index, CCG_elem_co(&key, vd), no, NULL);
}
}
-
- ccgVertIterator_free(vi);
}
static void ccgDM_foreachMappedEdge(
@@ -1541,14 +1529,14 @@ static void ccgDM_foreachMappedEdge(
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
- CCGEdgeIterator *ei;
+ CCGEdgeIterator ei;
CCGKey key;
int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
CCG_key_top_level(&key, ss);
- for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
const int index = ccgDM_getEdgeMapIndex(ss, e);
if (index != -1) {
@@ -1558,8 +1546,6 @@ static void ccgDM_foreachMappedEdge(
}
}
}
-
- ccgEdgeIterator_free(ei);
}
static void ccgDM_foreachMappedLoop(
@@ -1597,28 +1583,26 @@ static void ccgDM_drawVerts(DerivedMesh *dm)
CCGSubSurf *ss = ccgdm->ss;
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int gridSize = ccgSubSurf_getGridSize(ss);
- CCGVertIterator *vi;
- CCGEdgeIterator *ei;
- CCGFaceIterator *fi;
+ CCGVertIterator vi;
+ CCGEdgeIterator ei;
+ CCGFaceIterator fi;
glBegin(GL_POINTS);
- for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(&vi);
glVertex3fv(ccgSubSurf_getVertData(ss, v));
}
- ccgVertIterator_free(vi);
- for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
int x;
for (x = 1; x < edgeSize - 1; x++)
glVertex3fv(ccgSubSurf_getEdgeData(ss, e, x));
}
- ccgEdgeIterator_free(ei);
- for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
glVertex3fv(ccgSubSurf_getFaceCenterData(f));
@@ -1630,7 +1614,6 @@ static void ccgDM_drawVerts(DerivedMesh *dm)
for (x = 1; x < gridSize - 1; x++)
glVertex3fv(ccgSubSurf_getFaceGridData(ss, f, S, x, y));
}
- ccgFaceIterator_free(fi);
glEnd();
}
@@ -2289,7 +2272,7 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
DMSetDrawOptionsTex drawParams,
- DMSetDrawOptions drawParamsMapped,
+ DMSetDrawOptionsMappedTex drawParamsMapped,
DMCompareDrawOptions compareDrawOptions,
void *userData, DMDrawFlag flag)
{
@@ -2361,7 +2344,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
if (drawParams)
draw_option = drawParams(tf, (mcol != NULL), mat_nr);
else if (index != ORIGINDEX_NONE)
- draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index) : DM_DRAW_OPTION_NORMAL;
+ draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index, mat_nr) : DM_DRAW_OPTION_NORMAL;
else
draw_option = GPU_enable_material(mat_nr, NULL) ? DM_DRAW_OPTION_NORMAL : DM_DRAW_OPTION_SKIP;
@@ -2530,7 +2513,7 @@ static void ccgDM_drawFacesTex(DerivedMesh *dm,
}
static void ccgDM_drawMappedFacesTex(DerivedMesh *dm,
- DMSetDrawOptions setDrawOptions,
+ DMSetDrawOptionsMappedTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData, DMDrawFlag flag)
{
@@ -2586,6 +2569,7 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
DMFlagMat *faceFlags = ccgdm->faceFlags;
int useColors = flag & DM_DRAW_USE_COLORS;
int gridFaces = gridSize - 1, totface;
+ int prev_mat_nr = -1;
CCG_key_top_level(&key, ss);
@@ -2626,9 +2610,16 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
{
DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
- if (index == ORIGINDEX_NONE)
- draw_option = setMaterial(faceFlags ? faceFlags[origIndex].mat_nr + 1 : 1, NULL); /* XXX, no faceFlags no material */
- else if (setDrawOptions)
+ if (setMaterial) {
+ int mat_nr = faceFlags ? faceFlags[origIndex].mat_nr + 1 : 1;
+
+ if (mat_nr != prev_mat_nr) {
+ setMaterial(mat_nr, NULL); /* XXX, no faceFlags no material */
+ prev_mat_nr = mat_nr;
+ }
+ }
+
+ if (setDrawOptions && (index != ORIGINDEX_NONE))
draw_option = setDrawOptions(userData, index);
if (draw_option != DM_DRAW_OPTION_SKIP) {
@@ -2745,15 +2736,15 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm,
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
- CCGEdgeIterator *ei;
+ CCGEdgeIterator ei;
CCGKey key;
int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
CCG_key_top_level(&key, ss);
ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
- for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
int index = ccgDM_getEdgeMapIndex(ss, e);
@@ -2771,8 +2762,6 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm,
}
glEnd();
}
-
- ccgEdgeIterator_free(ei);
}
static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm,
@@ -2783,14 +2772,14 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm,
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- CCGEdgeIterator *ei;
+ CCGEdgeIterator ei;
int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
CCG_key_top_level(&key, ss);
ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
- for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
int index = ccgDM_getEdgeMapIndex(ss, e);
@@ -2809,8 +2798,6 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm,
}
glEnd();
}
-
- ccgEdgeIterator_free(ei);
}
static void ccgDM_foreachMappedFaceCenter(
@@ -2822,12 +2809,12 @@ static void ccgDM_foreachMappedFaceCenter(
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- CCGFaceIterator *fi;
+ CCGFaceIterator fi;
CCG_key_top_level(&key, ss);
- for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
const int index = ccgDM_getFaceMapIndex(ss, f);
if (index != -1) {
@@ -2837,8 +2824,6 @@ static void ccgDM_foreachMappedFaceCenter(
func(userData, index, CCG_elem_co(&key, vd), no);
}
}
-
- ccgFaceIterator_free(fi);
}
static void ccgDM_release(DerivedMesh *dm)
@@ -3434,9 +3419,9 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
DerivedMesh *dm)
{
CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
- CCGVertIterator *vi;
- CCGEdgeIterator *ei;
- CCGFaceIterator *fi;
+ CCGVertIterator vi;
+ CCGEdgeIterator ei;
+ CCGFaceIterator fi;
int index, totvert, totedge, totface;
int i;
int vertNum, edgeNum, faceNum;
@@ -3569,30 +3554,27 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
totvert = ccgSubSurf_getNumVerts(ss);
ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
- for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(&vi);
ccgdm->vertMap[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))].vert = v;
}
- ccgVertIterator_free(vi);
totedge = ccgSubSurf_getNumEdges(ss);
ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
- for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
ccgdm->edgeMap[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))].edge = e;
}
- ccgEdgeIterator_free(ei);
totface = ccgSubSurf_getNumFaces(ss);
ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
- for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(&fi);
ccgdm->faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))].face = f;
}
- ccgFaceIterator_free(fi);
ccgdm->reverseFaceMap = MEM_callocN(sizeof(int) * ccgSubSurf_getNumFinalFaces(ss), "reverseFaceMap");
@@ -3997,13 +3979,13 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*r_positions)[3])
*/
CCGSubSurf *ss = _getSubSurf(NULL, 1, 3, CCG_USE_ARENA);
float edge_sum[3], face_sum[3];
- CCGVertIterator *vi;
+ CCGVertIterator vi;
DerivedMesh *dm = CDDM_from_mesh(me);
ss_sync_from_derivedmesh(ss, dm, NULL, 0);
- for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(&vi);
int idx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
int N = ccgSubSurf_getVertNumEdges(v);
int numFaces = ccgSubSurf_getVertNumFaces(v);
@@ -4032,7 +4014,6 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*r_positions)[3])
r_positions[idx][1] = (co[1] * N * N + edge_sum[1] * 4 + face_sum[1]) / (N * (N + 5));
r_positions[idx][2] = (co[2] * N * N + edge_sum[2] * 4 + face_sum[2]) / (N * (N + 5));
}
- ccgVertIterator_free(vi);
ccgSubSurf_free(ss);
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index b45d9b418ed..3a311bfb23b 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -369,8 +369,8 @@ int BKE_text_reload(Text *text)
buffer = MEM_mallocN(len, "text_buffer");
- // under windows fread can return less then len bytes because
- // of CR stripping
+ /* under windows fread can return less than len bytes because
+ * of CR stripping */
len = fread(buffer, 1, len, fp);
fclose(fp);
@@ -425,8 +425,8 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const
fseek(fp, 0L, SEEK_SET);
buffer = MEM_mallocN(len, "text_buffer");
- // under windows fread can return less then len bytes because
- // of CR stripping
+ /* under windows fread can return less than len bytes because
+ * of CR stripping */
len = fread(buffer, 1, len, fp);
fclose(fp);
@@ -446,7 +446,7 @@ Text *BKE_text_load(Main *bmain, const char *file, const char *relpath)
return BKE_text_load_ex(bmain, file, relpath, false);
}
-Text *BKE_text_copy(Text *ta)
+Text *BKE_text_copy(Main *bmain, Text *ta)
{
Text *tan;
TextLine *line, *tmp;
@@ -455,8 +455,7 @@ Text *BKE_text_copy(Text *ta)
/* file name can be NULL */
if (ta->name) {
- tan->name = MEM_mallocN(strlen(ta->name) + 1, "text_name");
- strcpy(tan->name, ta->name);
+ tan->name = BLI_strdup(ta->name);
}
else {
tan->name = NULL;
@@ -490,6 +489,10 @@ Text *BKE_text_copy(Text *ta)
init_undo_text(tan);
+ if (ta->id.lib) {
+ BKE_id_lib_local_paths(bmain, ta->id.lib, &tan->id);
+ }
+
return tan;
}
@@ -1515,7 +1518,7 @@ static bool max_undo_test(Text *text, int x)
/* XXX error("Undo limit reached, buffer cleared\n"); */
MEM_freeN(text->undo_buf);
init_undo_text(text);
- return 0;
+ return false;
}
else {
void *tmp = text->undo_buf;
@@ -1526,7 +1529,7 @@ static bool max_undo_test(Text *text, int x)
}
}
- return 1;
+ return true;
}
#if 0 /* UNUSED */
@@ -2550,13 +2553,13 @@ static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs)
if (add == '\n') {
txt_split_curline(text);
- return 1;
+ return true;
}
/* insert spaces rather than tabs */
if (add == '\t' && replace_tabs) {
txt_convert_tab_to_spaces(text);
- return 1;
+ return true;
}
txt_delete_sel(text);
@@ -2605,7 +2608,7 @@ bool txt_replace_char(Text *text, unsigned int add)
size_t del_size = 0, add_size;
char ch[BLI_UTF8_MAX];
- if (!text->curl) return 0;
+ if (!text->curl) return false;
/* If text is selected or we're at the end of the line just use txt_add_char */
if (text->curc == text->curl->len || txt_has_sel(text) || add == '\n') {
@@ -2644,7 +2647,7 @@ bool txt_replace_char(Text *text, unsigned int add)
text->curc += add_size;
txt_pop_sel(text);
}
- return 1;
+ return true;
}
void txt_indent(Text *text)
@@ -2979,37 +2982,37 @@ bool text_check_delim(const char ch)
for (a = 0; a < (sizeof(delims) - 1); a++) {
if (ch == delims[a])
- return 1;
+ return true;
}
- return 0;
+ return false;
}
bool text_check_digit(const char ch)
{
- if (ch < '0') return 0;
- if (ch <= '9') return 1;
- return 0;
+ if (ch < '0') return false;
+ if (ch <= '9') return true;
+ return false;
}
bool text_check_identifier(const char ch)
{
- if (ch < '0') return 0;
- if (ch <= '9') return 1;
- if (ch < 'A') return 0;
- if (ch <= 'Z' || ch == '_') return 1;
- if (ch < 'a') return 0;
- if (ch <= 'z') return 1;
- return 0;
+ if (ch < '0') return false;
+ if (ch <= '9') return true;
+ if (ch < 'A') return false;
+ if (ch <= 'Z' || ch == '_') return true;
+ if (ch < 'a') return false;
+ if (ch <= 'z') return true;
+ return false;
}
bool text_check_identifier_nodigit(const char ch)
{
- if (ch <= '9') return 0;
- if (ch < 'A') return 0;
- if (ch <= 'Z' || ch == '_') return 1;
- if (ch < 'a') return 0;
- if (ch <= 'z') return 1;
- return 0;
+ if (ch <= '9') return false;
+ if (ch < 'A') return false;
+ if (ch <= 'Z' || ch == '_') return true;
+ if (ch < 'a') return false;
+ if (ch <= 'z') return true;
+ return false;
}
#ifndef WITH_PYTHON
@@ -3027,8 +3030,8 @@ int text_check_identifier_nodigit_unicode(const unsigned int ch)
bool text_check_whitespace(const char ch)
{
if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
- return 1;
- return 0;
+ return true;
+ return false;
}
int text_find_identifier_start(const char *str, int i)
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index b1981a3a804..dce6584bdfe 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -37,7 +37,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
@@ -328,7 +327,7 @@ bool do_colorband(const ColorBand *coba, float in, float out[4])
int ipotype;
int a;
- if (coba == NULL || coba->tot == 0) return 0;
+ if (coba == NULL || coba->tot == 0) return false;
cbd1 = coba->data;
@@ -464,7 +463,7 @@ bool do_colorband(const ColorBand *coba, float in, float out[4])
}
}
}
- return 1; /* OK */
+ return true; /* OK */
}
void colorband_table_RGBA(ColorBand *coba, float **array, int *size)
@@ -756,6 +755,8 @@ void default_mtex(MTex *mtex)
mtex->fieldfac = 1.0f;
mtex->normapspace = MTEX_NSPACE_TANGENT;
mtex->brush_map_mode = MTEX_MAP_MODE_TILED;
+ mtex->random_angle = 2.0f * M_PI;
+ mtex->brush_angle_mode = 0;
}
@@ -843,6 +844,10 @@ Tex *BKE_texture_copy(Tex *tex)
texn->nodetree = ntreeCopyTree(tex->nodetree);
}
+ if (tex->id.lib) {
+ BKE_id_lib_local_paths(G.main, tex->id.lib, &texn->id);
+ }
+
return texn;
}
@@ -1305,7 +1310,7 @@ bool has_current_material_texture(Material *ma)
node = nodeGetActiveID(ma->nodetree, ID_TE);
if (node)
- return 1;
+ return true;
}
return (ma != NULL);
@@ -1599,17 +1604,17 @@ void BKE_free_oceantex(struct OceanTex *ot)
bool BKE_texture_dependsOnTime(const struct Tex *texture)
{
if (texture->ima && BKE_image_is_animated(texture->ima)) {
- return 1;
+ return true;
}
else if (texture->adt) {
/* assume anything in adt means the texture is animated */
- return 1;
+ return true;
}
else if (texture->type == TEX_NOISE) {
/* noise always varies with time */
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 1613b0c5a78..d580c184a8b 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -1456,6 +1456,35 @@ MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(MovieTrackingPlaneTra
return plane_marker;
}
+void BKE_tracking_plane_marker_get_subframe_corners(MovieTrackingPlaneTrack *plane_track,
+ float framenr,
+ float corners[4][2])
+{
+ MovieTrackingPlaneMarker *marker = BKE_tracking_plane_marker_get(plane_track, (int)framenr);
+ MovieTrackingPlaneMarker *marker_last = plane_track->markers + (plane_track->markersnr - 1);
+ int i;
+ if (marker != marker_last) {
+ MovieTrackingPlaneMarker *marker_next = marker + 1;
+ if (marker_next->framenr == marker->framenr + 1) {
+ float fac = (framenr - (int) framenr) / (marker_next->framenr - marker->framenr);
+ for (i = 0; i < 4; ++i) {
+ interp_v2_v2v2(corners[i], marker->corners[i],
+ marker_next->corners[i], fac);
+ }
+ }
+ else {
+ for (i = 0; i < 4; ++i) {
+ copy_v2_v2(corners[i], marker->corners[i]);
+ }
+ }
+ }
+ else {
+ for (i = 0; i < 4; ++i) {
+ copy_v2_v2(corners[i], marker->corners[i]);
+ }
+ }
+}
+
/*********************** Object *************************/
MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char *name)
diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c
index 55b8f0bd3ab..22a380ea835 100644
--- a/source/blender/blenkernel/intern/tracking_auto.c
+++ b/source/blender/blenkernel/intern/tracking_auto.c
@@ -383,13 +383,17 @@ bool BKE_autotrack_context_step(AutoTrackContext *context)
int frame = BKE_movieclip_remap_scene_to_clip_frame(
context->clips[options->clip_index],
context->user.framenr);
+ bool has_marker;
- if (libmv_autoTrackGetMarker(context->autotrack,
- options->clip_index,
- frame,
- options->track_index,
- &libmv_current_marker))
- {
+ BLI_spin_lock(&context->spin_lock);
+ has_marker = libmv_autoTrackGetMarker(context->autotrack,
+ options->clip_index,
+ frame,
+ options->track_index,
+ &libmv_current_marker);
+ BLI_spin_unlock(&context->spin_lock);
+
+ if (has_marker) {
if (!tracking_check_marker_margin(&libmv_current_marker,
options->track->margin,
context->frame_width,
@@ -427,7 +431,7 @@ bool BKE_autotrack_context_step(AutoTrackContext *context)
}
else {
options->is_failed = true;
- options->failed_frame = frame;
+ options->failed_frame = frame + frame_delta;
}
ok = true;
}
@@ -442,11 +446,11 @@ bool BKE_autotrack_context_step(AutoTrackContext *context)
void BKE_autotrack_context_sync(AutoTrackContext *context)
{
- int newframe = context->user.framenr,
- frame_delta = context->backwards ? -1 : 1;
+ int newframe, frame_delta = context->backwards ? -1 : 1;
int clip, frame;
BLI_spin_lock(&context->spin_lock);
+ newframe = context->user.framenr;
for (frame = context->sync_frame;
frame != (context->backwards ? newframe - 1 : newframe + 1);
frame += frame_delta)
@@ -459,22 +463,18 @@ void BKE_autotrack_context_sync(AutoTrackContext *context)
AutoTrackOptions *options = &context->options[track];
int track_frame = BKE_movieclip_remap_scene_to_clip_frame(
context->clips[options->clip_index], frame);
- if (options->is_failed) {
- if (options->failed_frame == track_frame) {
- MovieTrackingMarker *prev_marker =
- BKE_tracking_marker_get_exact(
- options->track,
- frame);
- if (prev_marker) {
- marker = *prev_marker;
- marker.framenr = context->backwards ?
- track_frame - 1 :
- track_frame + 1;
- marker.flag |= MARKER_DISABLED;
- BKE_tracking_marker_insert(options->track, &marker);
- }
+ if (options->is_failed && options->failed_frame == track_frame) {
+ MovieTrackingMarker *prev_marker =
+ BKE_tracking_marker_get_exact(options->track, frame);
+ if (prev_marker) {
+ marker = *prev_marker;
+ marker.framenr = context->backwards ?
+ track_frame - 1 :
+ track_frame + 1;
+ marker.flag |= MARKER_DISABLED;
+ BKE_tracking_marker_insert(options->track, &marker);
+ continue;
}
- continue;
}
if (libmv_autoTrackGetMarker(context->autotrack,
clip,
diff --git a/source/blender/blenkernel/intern/tracking_detect.c b/source/blender/blenkernel/intern/tracking_detect.c
index 62039b761e8..6df51b5441a 100644
--- a/source/blender/blenkernel/intern/tracking_detect.c
+++ b/source/blender/blenkernel/intern/tracking_detect.c
@@ -40,7 +40,6 @@
#include "BKE_tracking.h"
#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "libmv-capi.h"
diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c
index 09c95ae4321..dd7def16ca8 100644
--- a/source/blender/blenkernel/intern/tracking_region_tracker.c
+++ b/source/blender/blenkernel/intern/tracking_region_tracker.c
@@ -35,11 +35,8 @@
#include "MEM_guardedalloc.h"
#include "DNA_movieclip_types.h"
-#include "DNA_object_types.h" /* SELECT */
#include "BLI_utildefines.h"
-#include "BLI_math.h"
-#include "BLI_ghash.h"
#include "BLI_threads.h"
#include "BKE_tracking.h"
@@ -116,7 +113,7 @@ static float *track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track,
return gray_pixels;
}
-/* Get image boffer for a given frame
+/* Get image buffer for a given frame
*
* Frame is in clip space.
*/
diff --git a/source/blender/blenkernel/intern/tracking_solver.c b/source/blender/blenkernel/intern/tracking_solver.c
index 6d4e7efa815..d5e2f24e9ed 100644
--- a/source/blender/blenkernel/intern/tracking_solver.c
+++ b/source/blender/blenkernel/intern/tracking_solver.c
@@ -391,7 +391,7 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieClip *clip
last_marker--;
}
- if (first < track->markersnr - 1)
+ if (first <= track->markersnr - 1)
sfra = min_ii(sfra, first_marker->framenr);
if (last >= 0)
@@ -509,6 +509,11 @@ bool BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieT
MovieTrackingReconstruction *reconstruction;
MovieTrackingObject *object;
+ if (!libmv_reconstructionIsValid(context->reconstruction)) {
+ printf("Failed solve the motion: most likely there are no good keyframes\n");
+ return false;
+ }
+
tracks_map_merge(context->tracks_map, tracking);
BKE_tracking_dopesheet_tag_update(tracking);
diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c
index 17e4a3c73c3..882a6fabef1 100644
--- a/source/blender/blenkernel/intern/tracking_util.c
+++ b/source/blender/blenkernel/intern/tracking_util.c
@@ -172,8 +172,7 @@ void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
MovieTrackingTrack *new_track = BKE_tracking_track_duplicate(track);
/* Update old-new track mapping */
- BLI_ghash_remove(map->hash, track, NULL, NULL);
- BLI_ghash_insert(map->hash, track, new_track);
+ BLI_ghash_reinsert(map->hash, track, new_track, NULL, NULL);
BLI_addtail(&tracks, new_track);
}
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 8e3c92314e6..699e0d34161 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -38,8 +38,8 @@
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
-#include "BLI_listbase.h"
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
#include "BKE_animsys.h"
#include "BKE_global.h"
@@ -49,6 +49,8 @@
#include "BKE_node.h"
#include "BKE_world.h"
+#include "GPU_material.h"
+
void BKE_world_free_ex(World *wrld, bool do_id_user)
{
MTex *mtex;
@@ -69,6 +71,9 @@ void BKE_world_free_ex(World *wrld, bool do_id_user)
MEM_freeN(wrld->nodetree);
}
+ if (wrld->gpumaterial.first)
+ GPU_material_free(&wrld->gpumaterial);
+
BKE_icon_delete((struct ID *)wrld);
wrld->id.icon_id = 0;
}
@@ -134,6 +139,12 @@ World *BKE_world_copy(World *wrld)
if (wrld->preview)
wrldn->preview = BKE_previewimg_copy(wrld->preview);
+ BLI_listbase_clear(&wrldn->gpumaterial);
+
+ if (wrld->id.lib) {
+ BKE_id_lib_local_paths(G.main, wrld->id.lib, &wrldn->id);
+ }
+
return wrldn;
}
@@ -158,6 +169,8 @@ World *localize_world(World *wrld)
wrldn->preview = NULL;
+ BLI_listbase_clear(&wrldn->gpumaterial);
+
return wrldn;
}
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index aef44993912..8a6a0438b84 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -80,7 +80,9 @@ static void filepath_avi(char *string, RenderData *rd);
# include "BKE_writeffmpeg.h"
#endif
-#include "BKE_writeframeserver.h"
+#ifdef WITH_FRAMESERVER
+# include "BKE_writeframeserver.h"
+#endif
bMovieHandle *BKE_movie_handle_get(const char imtype)
{
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 1fe5d345621..9737ef429cb 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -57,7 +57,6 @@
#include "BKE_sound.h"
#include "BKE_writeffmpeg.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "ffmpeg_compat.h"
@@ -494,7 +493,7 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
*
* For as long we don't allow editing properties in the interface
* it's all good. bug if we allow editing them, we'll need to
- * repace it with some smarter code which would port settings
+ * replace it with some smarter code which would port settings
* from deprecated to new one.
*/
ffmpeg_set_expert_options(rd);
@@ -599,8 +598,12 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
/* Keep lossless encodes in the RGB domain. */
if (codec_id == AV_CODEC_ID_HUFFYUV) {
- /* HUFFYUV was PIX_FMT_YUV422P before */
- c->pix_fmt = PIX_FMT_RGB32;
+ if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
+ c->pix_fmt = PIX_FMT_BGRA;
+ }
+ else {
+ c->pix_fmt = PIX_FMT_RGB32;
+ }
}
if (codec_id == AV_CODEC_ID_FFV1) {
@@ -1629,6 +1632,12 @@ bool BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd)
if (codec == AV_CODEC_ID_PNG)
return true;
+ if (codec == AV_CODEC_ID_PNG)
+ return true;
+
+ if (codec == AV_CODEC_ID_HUFFYUV)
+ return true;
+
#ifdef FFMPEG_FFV1_ALPHA_SUPPORTED
if (codec == AV_CODEC_ID_FFV1)
return true;
diff --git a/source/blender/blenlib/BLI_astar.h b/source/blender/blenlib/BLI_astar.h
new file mode 100644
index 00000000000..b99a2534d33
--- /dev/null
+++ b/source/blender/blenlib/BLI_astar.h
@@ -0,0 +1,98 @@
+/*
+ * ***** 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): Bastien Montagne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_ASTAR_H__
+#define __BLI_ASTAR_H__
+
+/** \file BLI_astar.h
+ * \ingroup bli
+ * \brief An implementation of the A* (AStar) algorithm to solve shortest path problem.
+ */
+
+#include "BLI_utildefines.h"
+
+#include "BLI_bitmap.h"
+
+/* -------------------------------------------------------------------- */
+
+typedef struct BLI_AStarGNLink {
+ int nodes[2];
+ float cost;
+
+ void *custom_data;
+} BLI_AStarGNLink;
+
+typedef struct BLI_AStarGNode {
+ struct ListBase neighbor_links;
+
+ void *custom_data;
+} BLI_AStarGNode;
+
+typedef struct BLI_AStarSolution {
+ /* Final 'most useful' data. */
+ int steps; /* Number of steps (i.e. walked links) in path (nodes num, including start and end, is steps + 1). */
+ int *prev_nodes; /* Store the path, in reversed order (from destination to source node), as indices. */
+ BLI_AStarGNLink **prev_links; /* Indices are nodes' ones, as prev_nodes, but they map to relevant link. */
+
+ void *custom_data;
+
+ /* Mostly runtime data. */
+ BLI_bitmap *done_nodes;
+ float *g_costs;
+ int *g_steps;
+
+ struct MemArena *mem; /* Memory arena. */
+} BLI_AStarSolution;
+
+typedef struct BLI_AStarGraph {
+ int node_num;
+ BLI_AStarGNode *nodes;
+
+ void *custom_data;
+
+ struct MemArena *mem; /* Memory arena. */
+} BLI_AStarGraph;
+
+void BLI_astar_node_init(BLI_AStarGraph *as_graph, const int node_index, void *custom_data);
+void BLI_astar_node_link_add(
+ BLI_AStarGraph *as_graph, const int node1_index, const int node2_index, const float cost, void *custom_data);
+int BLI_astar_node_link_other_node(BLI_AStarGNLink *lnk, const int idx);
+
+void BLI_astar_solution_init(BLI_AStarGraph *as_graph, BLI_AStarSolution *as_solution, void *custom_data);
+void BLI_astar_solution_clear(BLI_AStarSolution *as_solution);
+void BLI_astar_solution_free(BLI_AStarSolution *as_solution);
+
+typedef float (*astar_f_cost)(BLI_AStarGraph *as_graph, BLI_AStarSolution *as_solution, BLI_AStarGNLink *link,
+ const int node_idx_curr, const int node_idx_next, const int node_idx_dst);
+
+void BLI_astar_graph_init(BLI_AStarGraph *as_graph, const int node_num, void *custom_data);
+void BLI_astar_graph_free(BLI_AStarGraph *as_graph);
+bool BLI_astar_graph_solve(
+ BLI_AStarGraph *as_graph, const int node_index_src, const int node_index_dst, astar_f_cost f_cost_cb,
+ BLI_AStarSolution *r_solution, const int max_steps);
+
+#endif /* __BLI_ASTAR_H__ */
diff --git a/source/blender/blenlib/BLI_bitmap.h b/source/blender/blenlib/BLI_bitmap.h
index 594bf89b667..60fc143a447 100644
--- a/source/blender/blenlib/BLI_bitmap.h
+++ b/source/blender/blenlib/BLI_bitmap.h
@@ -47,7 +47,7 @@ typedef unsigned int BLI_bitmap;
/* size (in bytes) used to hold '_tot' bits */
#define BLI_BITMAP_SIZE(_tot) \
- (_BITMAP_NUM_BLOCKS(_tot) * sizeof(BLI_bitmap))
+ ((size_t)(_BITMAP_NUM_BLOCKS(_tot)) * sizeof(BLI_bitmap))
/* allocate memory for a bitmap with '_tot' bits; free
* with MEM_freeN() */
@@ -59,25 +59,30 @@ typedef unsigned int BLI_bitmap;
#define BLI_BITMAP_NEW_ALLOCA(_tot) \
((BLI_bitmap *)memset(alloca(BLI_BITMAP_SIZE(_tot)), 0, BLI_BITMAP_SIZE(_tot)))
+/* Allocate using given MemArena */
+#define BLI_BITMAP_NEW_MEMARENA(_mem, _tot) \
+ (CHECK_TYPE_INLINE(_mem, MemArena *), \
+ ((BLI_bitmap *)BLI_memarena_calloc(_mem, BLI_BITMAP_SIZE(_tot))))
+
/* get the value of a single bit at '_index' */
#define BLI_BITMAP_TEST(_bitmap, _index) \
- (CHECK_TYPE_INLINE(_bitmap, BLI_bitmap *), \
+ (CHECK_TYPE_ANY(_bitmap, BLI_bitmap *, const BLI_bitmap *), \
((_bitmap)[(_index) >> _BITMAP_POWER] & \
(1u << ((_index) & _BITMAP_MASK))))
#define BLI_BITMAP_TEST_BOOL(_bitmap, _index) \
- (CHECK_TYPE_INLINE(_bitmap, BLI_bitmap *), \
+ (CHECK_TYPE_ANY(_bitmap, BLI_bitmap *, const BLI_bitmap *), \
(BLI_BITMAP_TEST(_bitmap, _index) != 0))
/* set the value of a single bit at '_index' */
#define BLI_BITMAP_ENABLE(_bitmap, _index) \
- (CHECK_TYPE_INLINE(_bitmap, BLI_bitmap *), \
+ (CHECK_TYPE_ANY(_bitmap, BLI_bitmap *, const BLI_bitmap *), \
((_bitmap)[(_index) >> _BITMAP_POWER] |= \
(1u << ((_index) & _BITMAP_MASK))))
/* clear the value of a single bit at '_index' */
#define BLI_BITMAP_DISABLE(_bitmap, _index) \
- (CHECK_TYPE_INLINE(_bitmap, BLI_bitmap *), \
+ (CHECK_TYPE_ANY(_bitmap, BLI_bitmap *, const BLI_bitmap *), \
((_bitmap)[(_index) >> _BITMAP_POWER] &= \
~(1u << ((_index) & _BITMAP_MASK))))
diff --git a/source/blender/blenlib/BLI_callbacks.h b/source/blender/blenlib/BLI_callbacks.h
index 2f963cfac51..7cf524749c2 100644
--- a/source/blender/blenlib/BLI_callbacks.h
+++ b/source/blender/blenlib/BLI_callbacks.h
@@ -41,6 +41,7 @@ typedef enum {
BLI_CB_EVT_FRAME_CHANGE_POST,
BLI_CB_EVT_RENDER_PRE,
BLI_CB_EVT_RENDER_POST,
+ BLI_CB_EVT_RENDER_WRITE,
BLI_CB_EVT_RENDER_STATS,
BLI_CB_EVT_RENDER_INIT,
BLI_CB_EVT_RENDER_COMPLETE,
diff --git a/source/blender/blenlib/BLI_compiler_typecheck.h b/source/blender/blenlib/BLI_compiler_typecheck.h
index 551569b066d..46c57772f64 100644
--- a/source/blender/blenlib/BLI_compiler_typecheck.h
+++ b/source/blender/blenlib/BLI_compiler_typecheck.h
@@ -51,9 +51,9 @@
}))
#else
-# define CHECK_TYPE(var, type)
-# define CHECK_TYPE_PAIR(var_a, var_b)
-# define CHECK_TYPE_PAIR_INLINE(var_a, var_b) (void)0
+# define CHECK_TYPE(var, type) { EXPR_NOP(var); }(void)0
+# define CHECK_TYPE_PAIR(var_a, var_b) { (EXPR_NOP(var_a), EXPR_NOP(var_b)); }(void)0
+# define CHECK_TYPE_PAIR_INLINE(var_a, var_b) (EXPR_NOP(var_a), EXPR_NOP(var_b))
#endif
/* can be used in simple macros */
@@ -66,10 +66,15 @@
((void)(((type)0) != (0 ? (val) : ((type)0))))
#endif
-#define CHECK_TYPE_NONCONST(var) { \
- void *non_const = 0 ? (var) : NULL; \
- (void)non_const; \
-} (void)0
+#if defined(__GNUC__) || defined(__clang__)
+# define CHECK_TYPE_NONCONST(var) __extension__ ({ \
+ void *non_const = 0 ? (var) : NULL; \
+ (void)non_const; \
+})
+#else
+# define CHECK_TYPE_NONCONST(var) EXPR_NOP(var)
+#endif
+
/**
* CHECK_TYPE_ANY: handy macro, eg:
diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h
index a0455489d24..ded4b163f71 100644
--- a/source/blender/blenlib/BLI_edgehash.h
+++ b/source/blender/blenlib/BLI_edgehash.h
@@ -26,7 +26,6 @@
/** \file BLI_edgehash.h
* \ingroup bli
* \author Daniel Dunbar
- * \brief A general unordered 2-int pair hash table ADT.
*/
#include "BLI_compiler_attrs.h"
@@ -55,6 +54,9 @@ bool BLI_edgehash_reinsert(EdgeHash *eh, unsigned int v0, unsigned in
void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
void *BLI_edgehash_lookup_default(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val_default) ATTR_WARN_UNUSED_RESULT;
void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
+bool BLI_edgehash_remove(EdgeHash *eh, unsigned int v0, unsigned int v1, EdgeHashFreeFP valfreefp);
+
+void *BLI_edgehash_popkey(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
int BLI_edgehash_size(EdgeHash *eh) ATTR_WARN_UNUSED_RESULT;
void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP valfreefp,
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index 4f451a6c741..86a8134376a 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -88,8 +88,13 @@ void BLI_dir_create_recursive(const char *dir);
double BLI_dir_free_space(const char *dir);
char *BLI_current_working_dir(char *dir, const size_t maxlen);
-unsigned int BLI_dir_contents(const char *dir, struct direntry **filelist);
-void BLI_free_filelist(struct direntry *filelist, unsigned int nrentries);
+/* Filelist */
+
+unsigned int BLI_filelist_dir_contents(const char *dir, struct direntry **filelist);
+void BLI_filelist_duplicate(
+ struct direntry **dest_filelist, struct direntry *src_filelist, unsigned int nrentries,
+ void *(*dup_poin)(void *));
+void BLI_filelist_free(struct direntry *filelist, unsigned int nrentries, void (*free_poin)(void *));
/* Files */
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index af2605894e3..bf2b4126453 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -30,7 +30,6 @@
/** \file BLI_ghash.h
* \ingroup bli
- * \brief A general (pointer -> pointer) hash table ADT
*/
#include "BLI_sys_types.h" /* for bool */
@@ -41,6 +40,7 @@ extern "C" {
#endif
typedef unsigned int (*GHashHashFP) (const void *key);
+/** returns false when equal */
typedef bool (*GHashCmpFP) (const void *a, const void *b);
typedef void (*GHashKeyFreeFP) (void *key);
typedef void (*GHashValFreeFP) (void *val);
@@ -124,17 +124,17 @@ bool BLI_ghashutil_ptrcmp(const void *a, const void *b);
unsigned int BLI_ghashutil_strhash_n(const char *key, size_t n);
#define BLI_ghashutil_strhash(key) ( \
- CHECK_TYPE_INLINE(key, char *), \
+ CHECK_TYPE_ANY(key, char *, const char *, const char * const), \
BLI_ghashutil_strhash_p(key))
unsigned int BLI_ghashutil_strhash_p(const void *key);
bool BLI_ghashutil_strcmp(const void *a, const void *b);
#define BLI_ghashutil_inthash(key) ( \
- CHECK_TYPE_INLINE(&(key), int *), \
+ CHECK_TYPE_ANY(&(key), int *, const int *), \
BLI_ghashutil_uinthash((unsigned int)key))
unsigned int BLI_ghashutil_uinthash(unsigned int key);
#define BLI_ghashutil_inthash_v4(key) ( \
- CHECK_TYPE_INLINE(key, int *), \
+ CHECK_TYPE_ANY(key, int *, const int *), \
BLI_ghashutil_uinthash_v4((const unsigned int *)key))
unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]);
#define BLI_ghashutil_inthash_v4_p \
diff --git a/source/blender/blenlib/BLI_heap.h b/source/blender/blenlib/BLI_heap.h
index ac9edfd46a2..ea361097b7b 100644
--- a/source/blender/blenlib/BLI_heap.h
+++ b/source/blender/blenlib/BLI_heap.h
@@ -37,6 +37,7 @@ typedef void (*HeapFreeFP)(void *ptr);
* are recycled, so memory usage will not shrink. */
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_clear(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1);
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,
diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h
index 17d40e068b3..9ac233a8fa4 100644
--- a/source/blender/blenlib/BLI_linklist_stack.h
+++ b/source/blender/blenlib/BLI_linklist_stack.h
@@ -51,46 +51,46 @@
#define BLI_LINKSTACK_DECLARE(var, type) \
LinkNode *var; \
- BLI_mempool *_##var##_pool; \
- type _##var##_type
+ BLI_mempool *var##_pool_; \
+ type var##_type_
#define BLI_LINKSTACK_INIT(var) { \
var = NULL; \
- _##var##_pool = BLI_mempool_create(sizeof(LinkNode), 0, 64, BLI_MEMPOOL_NOP); \
+ var##_pool_ = BLI_mempool_create(sizeof(LinkNode), 0, 64, BLI_MEMPOOL_NOP); \
} (void)0
#define BLI_LINKSTACK_SIZE(var) \
- BLI_mempool_count(_##var##_pool)
+ BLI_mempool_count(var##_pool_)
/* check for typeof() */
#ifdef __GNUC__
#define BLI_LINKSTACK_PUSH(var, ptr) ( \
- CHECK_TYPE_INLINE(ptr, typeof(_##var##_type)), \
- BLI_linklist_prepend_pool(&(var), ptr, _##var##_pool))
+ CHECK_TYPE_INLINE(ptr, typeof(var##_type_)), \
+ BLI_linklist_prepend_pool(&(var), ptr, var##_pool_))
#define BLI_LINKSTACK_POP(var) \
- (var ? (typeof(_##var##_type))BLI_linklist_pop_pool(&(var), _##var##_pool) : NULL)
+ (var ? (typeof(var##_type_))BLI_linklist_pop_pool(&(var), var##_pool_) : NULL)
#define BLI_LINKSTACK_POP_DEFAULT(var, r) \
- (var ? (typeof(_##var##_type))BLI_linklist_pop_pool(&(var), _##var##_pool) : r)
+ (var ? (typeof(var##_type_))BLI_linklist_pop_pool(&(var), var##_pool_) : r)
#else /* non gcc */
#define BLI_LINKSTACK_PUSH(var, ptr) ( \
- BLI_linklist_prepend_pool(&(var), ptr, _##var##_pool))
+ BLI_linklist_prepend_pool(&(var), ptr, var##_pool_))
#define BLI_LINKSTACK_POP(var) \
- (var ? BLI_linklist_pop_pool(&(var), _##var##_pool) : NULL)
+ (var ? BLI_linklist_pop_pool(&(var), var##_pool_) : NULL)
#define BLI_LINKSTACK_POP_DEFAULT(var, r) \
- (var ? BLI_linklist_pop_pool(&(var), _##var##_pool) : r)
+ (var ? BLI_linklist_pop_pool(&(var), var##_pool_) : r)
#endif /* gcc check */
#define BLI_LINKSTACK_SWAP(var_a, var_b) { \
- CHECK_TYPE_PAIR(_##var_a##_type, _##var_b##_type); \
+ CHECK_TYPE_PAIR(var_a##_type_, var_b##_type_); \
SWAP(LinkNode *, var_a, var_b); \
- SWAP(BLI_mempool *, _##var_a##_pool, _##var_b##_pool); \
+ SWAP(BLI_mempool *, var_a##_pool_, var_b##_pool_); \
} (void)0
#define BLI_LINKSTACK_FREE(var) { \
- BLI_mempool_destroy(_##var##_pool); \
- _##var##_pool = NULL; (void)_##var##_pool; \
+ BLI_mempool_destroy(var##_pool_); \
+ var##_pool_ = NULL; (void)var##_pool_; \
var = NULL; (void)var; \
- (void)&(_##var##_type); \
+ (void)&(var##_type_); \
} (void)0
#include "BLI_linklist.h"
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index 5711d09b530..2bc23c8a72d 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -48,13 +48,16 @@
#define M_PI_2 1.57079632679489661923
#endif
#ifndef M_SQRT2
-#define M_SQRT2 1.41421356237309504880
+#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
#endif
#ifndef M_SQRT1_2
-#define M_SQRT1_2 0.70710678118654752440
+#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
#endif
#ifndef M_SQRT3
-#define M_SQRT3 1.7320508075688772
+#define M_SQRT3 1.73205080756887729352 /* sqrt(3) */
+#endif
+#ifndef M_SQRT1_3
+#define M_SQRT1_3 0.57735026918962576450 /* 1/sqrt(3) */
#endif
#ifndef M_1_PI
#define M_1_PI 0.318309886183790671538
@@ -191,6 +194,8 @@ MINLINE int min_iiii(int a, int b, int c, int d);
MINLINE int max_iiii(int a, int b, int c, int d);
MINLINE float signf(float f);
+MINLINE int signum_i_ex(float a, float eps);
+MINLINE int signum_i(float a);
MINLINE float power_of_2(float f);
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index ba32b29becc..495aa6b2465 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -52,15 +52,23 @@ float normal_quad_v3(float r[3], const float a[3], const float b[3], const float
float normal_poly_v3(float r[3], const float verts[][3], unsigned int nr);
MINLINE float area_tri_v2(const float a[2], const float b[2], const float c[2]);
+MINLINE float area_squared_tri_v2(const float a[2], const float b[2], const float c[2]);
MINLINE float area_tri_signed_v2(const float v1[2], const float v2[2], const float v3[2]);
float area_tri_v3(const float a[3], const float b[3], const float c[3]);
+float area_squared_tri_v3(const float a[3], const float b[3], const float c[3]);
float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3]);
float area_quad_v3(const float a[3], const float b[3], const float c[3], const float d[3]);
+float area_squared_quad_v3(const float a[3], const float b[3], const float c[3], const float d[3]);
float area_poly_v3(const float verts[][3], unsigned int nr);
float area_poly_v2(const float verts[][2], unsigned int nr);
+float area_squared_poly_v3(const float verts[][3], unsigned int nr);
+float area_squared_poly_v2(const float verts[][2], unsigned int nr);
+float area_poly_signed_v2(const float verts[][2], unsigned int nr);
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3]);
+void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3]);
MINLINE float cross_tri_v2(const float v1[2], const float v2[2], const float v3[2]);
+void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr);
float cross_poly_v2(const float verts[][2], unsigned int nr);
/********************************* Planes **********************************/
@@ -77,6 +85,7 @@ float volume_tetrahedron_signed_v3(const float v1[3], const float v2[3], const f
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]);
bool is_poly_convex_v2(const float verts[][2], unsigned int nr);
+int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
/********************************* Distance **********************************/
@@ -263,6 +272,9 @@ void orthographic_m4(float mat[4][4], const float left, const float right,
void window_translate_m4(float winmat[4][4], float perspmat[4][4],
const float x, const float y);
+void planes_from_projmat(float mat[4][4], float left[4], float right[4], float top[4], float bottom[4],
+ float front[4], float back[4]);
+
int box_clip_bounds_m4(float boundbox[2][3],
const float bounds[4], float winmat[4][4]);
void box_minmax_bounds_m4(float min[3], float max[3],
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 6885a5aa351..4455e72cf45 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -148,6 +148,7 @@ MINLINE void negate_v3_short(short r[3]);
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_v3v3v3(const float p[3], const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT;
MINLINE float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 3d82480d050..bade390d056 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -40,40 +40,6 @@ extern "C" {
struct ListBase;
struct direntry;
-const char *BLI_getDefaultDocumentFolder(void);
-
-const char *BLI_get_folder(int folder_id, const char *subfolder);
-const char *BLI_get_folder_create(int folder_id, const char *subfolder);
-const char *BLI_get_user_folder_notest(int folder_id, const char *subfolder);
-const char *BLI_get_folder_version(const int id, const int ver, const bool do_check);
-
-/* folder_id */
-
-/* general, will find based on user/local/system priority */
-#define BLENDER_DATAFILES 2
-
-/* user-specific */
-#define BLENDER_USER_CONFIG 31
-#define BLENDER_USER_DATAFILES 32
-#define BLENDER_USER_SCRIPTS 33
-#define BLENDER_USER_AUTOSAVE 34
-
-/* system */
-#define BLENDER_SYSTEM_DATAFILES 52
-#define BLENDER_SYSTEM_SCRIPTS 53
-#define BLENDER_SYSTEM_PYTHON 54
-
-/* for BLI_get_folder_version only */
-#define BLENDER_RESOURCE_PATH_USER 0
-#define BLENDER_RESOURCE_PATH_LOCAL 1
-#define BLENDER_RESOURCE_PATH_SYSTEM 2
-
-#define BLENDER_STARTUP_FILE "startup.blend"
-#define BLENDER_USERPREF_FILE "userpref.blend"
-#define BLENDER_QUIT_FILE "quit.blend"
-#define BLENDER_BOOKMARK_FILE "bookmarks.txt"
-#define BLENDER_HISTORY_FILE "recent-files.txt"
-
#ifdef WIN32
#define SEP '\\'
#define ALTSEP '/'
@@ -185,19 +151,6 @@ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char
void BLI_char_switch(char *string, char from, char to) ATTR_NONNULL();
-/* Initialize path to program executable */
-void BLI_init_program_path(const char *argv0);
-/* Initialize path to temporary directory.
- * NOTE: On Window userdir will be set to the temporary directory! */
-void BLI_temp_dir_init(char *userdir);
-
-const char *BLI_program_path(void);
-const char *BLI_program_dir(void);
-const char *BLI_temp_dir_session(void);
-const char *BLI_temp_dir_base(void);
-void BLI_system_temporary_dir(char *dir);
-void BLI_temp_dir_session_purge(void);
-
#ifdef WITH_ICONV
void BLI_string_to_utf8(char *original, char *utf_8, const char *code);
#endif
diff --git a/source/blender/blenlib/BLI_polyfill2d.h b/source/blender/blenlib/BLI_polyfill2d.h
index 5c5cea8f67d..798055f9240 100644
--- a/source/blender/blenlib/BLI_polyfill2d.h
+++ b/source/blender/blenlib/BLI_polyfill2d.h
@@ -37,4 +37,7 @@ void BLI_polyfill_calc(
const int coords_sign,
unsigned int (*r_tris)[3]);
+/* default size of polyfill arena */
+#define BLI_POLYFILL_ARENA_SIZE MEM_SIZE_OPTIMAL(1 << 14)
+
#endif /* __BLI_POLYFILL2D_H__ */
diff --git a/source/blender/blenlib/BLI_polyfill2d_beautify.h b/source/blender/blenlib/BLI_polyfill2d_beautify.h
new file mode 100644
index 00000000000..20e53b080fe
--- /dev/null
+++ b/source/blender/blenlib/BLI_polyfill2d_beautify.h
@@ -0,0 +1,42 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_POLYFILL2D_BEAUTIFY_H__
+#define __BLI_POLYFILL2D_BEAUTIFY_H__
+
+struct EdgeHash;
+struct Heap;
+struct MemArena;
+
+void BLI_polyfill_beautify(
+ const float (*coords)[2],
+ const unsigned int coords_tot,
+ unsigned int (*tris)[3],
+
+ /* structs for reuse */
+ struct MemArena *arena, struct Heap *eheap, struct EdgeHash *eh);
+
+float BLI_polyfill_beautify_quad_rotate_calc(
+ const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
+
+/* avoid realloc's when creating new structures for polyfill ngons */
+#define BLI_POLYFILL_ALLOC_NGON_RESERVE 64
+
+#endif /* __BLI_POLYFILL2D_BEAUTIFY_H__ */
diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h
index 879af446469..7b84dddcb68 100644
--- a/source/blender/blenlib/BLI_rand.h
+++ b/source/blender/blenlib/BLI_rand.h
@@ -55,6 +55,9 @@ double BLI_rng_get_double(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NON
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_get_tri_sample_float_v2(
+ struct RNG *rng, const float v1[2], const float v2[2], const float v3[2],
+ float r_pt[2]) ATTR_NONNULL();
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! */
diff --git a/source/blender/blenlib/BLI_smallhash.h b/source/blender/blenlib/BLI_smallhash.h
index b80044bccff..e096354e5b1 100644
--- a/source/blender/blenlib/BLI_smallhash.h
+++ b/source/blender/blenlib/BLI_smallhash.h
@@ -52,7 +52,7 @@ typedef struct SmallHash {
} SmallHash;
typedef struct {
- SmallHash *sh;
+ const SmallHash *sh;
unsigned int i;
} SmallHashIter;
@@ -61,13 +61,16 @@ void BLI_smallhash_init_ex(SmallHash *sh,
void BLI_smallhash_init(SmallHash *sh) ATTR_NONNULL(1);
void BLI_smallhash_release(SmallHash *sh) ATTR_NONNULL(1);
void BLI_smallhash_insert(SmallHash *sh, uintptr_t key, void *item) ATTR_NONNULL(1);
+bool BLI_smallhash_reinsert(SmallHash *sh, uintptr_t key, void *item) ATTR_NONNULL(1);
bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
-void *BLI_smallhash_lookup(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
-void **BLI_smallhash_lookup_p(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
-bool BLI_smallhash_haskey(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
-int BLI_smallhash_count(SmallHash *sh) ATTR_NONNULL(1);
+void *BLI_smallhash_lookup(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+void **BLI_smallhash_lookup_p(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
+int BLI_smallhash_count(const SmallHash *sh) ATTR_NONNULL(1);
void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
-void *BLI_smallhash_iternew(SmallHash *sh, SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+void **BLI_smallhash_iternext_p(SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+void *BLI_smallhash_iternew(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
/* void BLI_smallhash_print(SmallHash *sh); */ /* UNUSED */
#ifdef DEBUG
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index b249bc720c6..c4853e37398 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -48,6 +48,8 @@ char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) AT
char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL();
+char *BLI_strncpy_ensure_pad(char *__restrict dst, const char *__restrict src, const char pad, size_t maxncpy) ATTR_NONNULL();
+
size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -71,6 +73,8 @@ char *BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT AT
int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BLI_strncasecmp(const char *s1, const char *s2, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BLI_natstrcmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BLI_strcmp_ignore_pad(const char *str1, const char *str2, const char pad) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
size_t BLI_strnlen(const char *str, const size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BLI_timestr(double _time, char *str, size_t maxlen) ATTR_NONNULL();
@@ -81,6 +85,9 @@ int BLI_str_rstrip_float_zero(char *str, const char pad) ATTR_NONNULL();
int BLI_str_index_in_array_n(const char *__restrict str, const char **__restrict str_array, const int str_array_len) ATTR_NONNULL();
int BLI_str_index_in_array(const char *__restrict str, const char **__restrict str_array) ATTR_NONNULL();
+bool BLI_str_endswith(const char *__restrict str, const char *__restrict end) ATTR_NONNULL();
+bool BLI_strn_endswith(const char *__restrict str, const char *__restrict end, size_t length) ATTR_NONNULL();
+
size_t BLI_str_partition(const char *str, const char delim[], char **sep, char **suf) ATTR_NONNULL();
size_t BLI_str_rpartition(const char *str, const char delim[], char **sep, char **suf) ATTR_NONNULL();
size_t BLI_str_partition_ex(const char *str, const char delim[], char **sep, char **suf, const bool from_right) ATTR_NONNULL();
diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h
index 89754be25ba..3e599865416 100644
--- a/source/blender/blenlib/BLI_string_utf8.h
+++ b/source/blender/blenlib/BLI_string_utf8.h
@@ -34,6 +34,7 @@ extern "C" {
#include "BLI_compiler_attrs.h"
char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL();
+size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL();
char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL();
int BLI_utf8_invalid_byte(const char *str, int length) ATTR_NONNULL();
int BLI_utf8_invalid_strip(char *str, int length) ATTR_NONNULL();
diff --git a/source/blender/blenlib/BLI_system.h b/source/blender/blenlib/BLI_system.h
index 8cdc9e4e6c5..cb8cb6f5a0d 100644
--- a/source/blender/blenlib/BLI_system.h
+++ b/source/blender/blenlib/BLI_system.h
@@ -27,6 +27,10 @@
int BLI_cpu_support_sse2(void);
+#if defined(NDEBUG) || !defined(__BLI_UTILDEFINES_H__)
+void BLI_system_backtrace(FILE *fp);
+#endif
+
/* getpid */
#ifdef WIN32
# define BLI_SYSTEM_PID_H <process.h>
@@ -35,4 +39,3 @@ int BLI_cpu_support_sse2(void);
#endif
#endif /* __BLI_SYSTEM_H__ */
-
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index 28da673ea97..2eaec024ce2 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -73,7 +73,7 @@ typedef enum TaskPriority {
} TaskPriority;
typedef struct TaskPool TaskPool;
-typedef void (*TaskRunFunction)(TaskPool *pool, void *taskdata, int threadid);
+typedef void (*TaskRunFunction)(TaskPool *__restrict pool, void *taskdata, int threadid);
TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata);
void BLI_task_pool_free(TaskPool *pool);
@@ -88,6 +88,9 @@ void BLI_task_pool_cancel(TaskPool *pool);
/* stop all worker threads */
void BLI_task_pool_stop(TaskPool *pool);
+/* set number of threads allowed to be used by this pool */
+void BLI_pool_set_num_threads(TaskPool *pool, int num_threads);
+
/* for worker threads, test if canceled */
bool BLI_task_pool_canceled(TaskPool *pool);
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index 16d3c2f8a42..b1b225096a7 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -32,6 +32,10 @@
* \ingroup bli
*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* avoid many includes for now */
#include "BLI_sys_types.h"
#include "BLI_compiler_compat.h"
@@ -51,7 +55,8 @@
_49_, _50_, _51_, _52_, _53_, _54_, _55_, _56_, _57_, _58_, _59_, _60_, _61_, _62_, _63_, _64_, \
count, ...) count
#define _VA_NARGS_EXPAND(args) _VA_NARGS_RETURN_COUNT args
-#define _VA_NARGS_COUNT_MAX64(...) _VA_NARGS_EXPAND((__VA_ARGS__, \
+/* 64 args max */
+#define _VA_NARGS_COUNT(...) _VA_NARGS_EXPAND((__VA_ARGS__, \
64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, \
48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, \
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, \
@@ -61,7 +66,7 @@
#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_MAX64(__VA_ARGS__)), (__VA_ARGS__))
+ _VA_NARGS_GLUE(_VA_NARGS_OVERLOAD_MACRO(name, _VA_NARGS_COUNT(__VA_ARGS__)), (__VA_ARGS__))
/* useful for finding bad use of min/max */
#if 0
@@ -215,6 +220,8 @@
/* reusable ELEM macro */
#define ELEM(...) VA_NARGS_CALL_OVERLOAD(_VA_ELEM, __VA_ARGS__)
+/* no-op for expressions we don't want to instansiate, but must remian valid */
+#define EXPR_NOP(expr) (void)(0 ? ((void)(expr), 1) : 0)
/* shift around elements */
#define SHIFT3(type, a, b, c) { \
@@ -429,13 +436,51 @@
/* assuming a static array */
#if defined(__GNUC__) && !defined(__cplusplus)
-# define ARRAY_SIZE(arr) \
- ((sizeof(struct {int isnt_array : ((void *)&(arr) == &(arr)[0]);}) * 0) + \
+# define ARRAY_SIZE(arr) \
+ ((sizeof(struct {int isnt_array : ((const void *)&(arr) == &(arr)[0]);}) * 0) + \
(sizeof(arr) / sizeof(*(arr))))
#else
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*(arr)))
#endif
+/* ELEM#(v, ...): is the first arg equal any others? */
+/* internal helpers*/
+#define _VA_ARRAY_SET_ITEMS2(v, a) \
+ ((v)[0] = (a))
+#define _VA_ARRAY_SET_ITEMS3(v, a, b) \
+ _VA_ARRAY_SET_ITEMS2(v, a); ((v)[1] = (b))
+#define _VA_ARRAY_SET_ITEMS4(v, a, b, c) \
+ _VA_ARRAY_SET_ITEMS3(v, a, b); ((v)[2] = (c))
+#define _VA_ARRAY_SET_ITEMS5(v, a, b, c, d) \
+ _VA_ARRAY_SET_ITEMS4(v, a, b, c); ((v)[3] = (d))
+#define _VA_ARRAY_SET_ITEMS6(v, a, b, c, d, e) \
+ _VA_ARRAY_SET_ITEMS5(v, a, b, c, d); ((v)[4] = (e))
+#define _VA_ARRAY_SET_ITEMS7(v, a, b, c, d, e, f) \
+ _VA_ARRAY_SET_ITEMS6(v, a, b, c, d, e); ((v)[5] = (f))
+#define _VA_ARRAY_SET_ITEMS8(v, a, b, c, d, e, f, g) \
+ _VA_ARRAY_SET_ITEMS7(v, a, b, c, d, e, f); ((v)[6] = (g))
+#define _VA_ARRAY_SET_ITEMS9(v, a, b, c, d, e, f, g, h) \
+ _VA_ARRAY_SET_ITEMS8(v, a, b, c, d, e, f, g); ((v)[7] = (h))
+#define _VA_ARRAY_SET_ITEMS10(v, a, b, c, d, e, f, g, h, i) \
+ _VA_ARRAY_SET_ITEMS9(v, a, b, c, d, e, f, g, h); ((v)[8] = (i))
+#define _VA_ARRAY_SET_ITEMS11(v, a, b, c, d, e, f, g, h, i, j) \
+ _VA_ARRAY_SET_ITEMS10(v, a, b, c, d, e, f, g, h, i); ((v)[9] = (j))
+#define _VA_ARRAY_SET_ITEMS12(v, a, b, c, d, e, f, g, h, i, j, k) \
+ _VA_ARRAY_SET_ITEMS11(v, a, b, c, d, e, f, g, h, i, j); ((v)[10] = (k))
+#define _VA_ARRAY_SET_ITEMS13(v, a, b, c, d, e, f, g, h, i, j, k, l) \
+ _VA_ARRAY_SET_ITEMS12(v, a, b, c, d, e, f, g, h, i, j, k); ((v)[11] = (l))
+#define _VA_ARRAY_SET_ITEMS14(v, a, b, c, d, e, f, g, h, i, j, k, l, m) \
+ _VA_ARRAY_SET_ITEMS13(v, a, b, c, d, e, f, g, h, i, j, k, l); ((v)[12] = (m))
+#define _VA_ARRAY_SET_ITEMS15(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n) \
+ _VA_ARRAY_SET_ITEMS14(v, a, b, c, d, e, f, g, h, i, j, k, l, m); ((v)[13] = (n))
+#define _VA_ARRAY_SET_ITEMS16(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
+ _VA_ARRAY_SET_ITEMS15(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n); ((v)[14] = (o))
+#define _VA_ARRAY_SET_ITEMS17(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
+ _VA_ARRAY_SET_ITEMS16(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); ((v)[15] = (p))
+
+/* reusable ELEM macro */
+#define ARRAY_SET_ITEMS(...) { VA_NARGS_CALL_OVERLOAD(_VA_ARRAY_SET_ITEMS, __VA_ARGS__); } (void)0
+
/* Like offsetof(typeof(), member), for non-gcc compilers */
#define OFFSETOF_STRUCT(_struct, _member) \
((((char *)&((_struct)->_member)) - ((char *)(_struct))) + sizeof((_struct)->_member))
@@ -493,6 +538,56 @@
# define UNUSED_FUNCTION(x) UNUSED_ ## x
#endif
+/**
+ * UNUSED_VARS#(a, ...): quiet unused warnings
+ *
+ * <pre>
+ * for i in range(16):
+ * args = [(chr(ord('a') + (c % 26)) + (chr(ord('0') + (c // 26)))) for c in range(i + 1)]
+ * print("#define _VA_UNUSED_VARS_%d(%s) \\" % (i + 1, ", ".join(args)))
+ * print("\t((void)(%s)%s)" %
+ * (args[0], ((", _VA_UNUSED_VARS_" + str(i) + "(%s)") if i else "%s") % ", ".join((args[1:]))))
+ * </pre>
+ *
+ */
+
+#define _VA_UNUSED_VARS_1(a0) \
+ ((void)(a0))
+#define _VA_UNUSED_VARS_2(a0, b0) \
+ ((void)(a0), _VA_UNUSED_VARS_1(b0))
+#define _VA_UNUSED_VARS_3(a0, b0, c0) \
+ ((void)(a0), _VA_UNUSED_VARS_2(b0, c0))
+#define _VA_UNUSED_VARS_4(a0, b0, c0, d0) \
+ ((void)(a0), _VA_UNUSED_VARS_3(b0, c0, d0))
+#define _VA_UNUSED_VARS_5(a0, b0, c0, d0, e0) \
+ ((void)(a0), _VA_UNUSED_VARS_4(b0, c0, d0, e0))
+#define _VA_UNUSED_VARS_6(a0, b0, c0, d0, e0, f0) \
+ ((void)(a0), _VA_UNUSED_VARS_5(b0, c0, d0, e0, f0))
+#define _VA_UNUSED_VARS_7(a0, b0, c0, d0, e0, f0, g0) \
+ ((void)(a0), _VA_UNUSED_VARS_6(b0, c0, d0, e0, f0, g0))
+#define _VA_UNUSED_VARS_8(a0, b0, c0, d0, e0, f0, g0, h0) \
+ ((void)(a0), _VA_UNUSED_VARS_7(b0, c0, d0, e0, f0, g0, h0))
+#define _VA_UNUSED_VARS_9(a0, b0, c0, d0, e0, f0, g0, h0, i0) \
+ ((void)(a0), _VA_UNUSED_VARS_8(b0, c0, d0, e0, f0, g0, h0, i0))
+#define _VA_UNUSED_VARS_10(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0) \
+ ((void)(a0), _VA_UNUSED_VARS_9(b0, c0, d0, e0, f0, g0, h0, i0, j0))
+#define _VA_UNUSED_VARS_11(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0) \
+ ((void)(a0), _VA_UNUSED_VARS_10(b0, c0, d0, e0, f0, g0, h0, i0, j0, k0))
+#define _VA_UNUSED_VARS_12(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0) \
+ ((void)(a0), _VA_UNUSED_VARS_11(b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0))
+#define _VA_UNUSED_VARS_13(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0) \
+ ((void)(a0), _VA_UNUSED_VARS_12(b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0))
+#define _VA_UNUSED_VARS_14(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0) \
+ ((void)(a0), _VA_UNUSED_VARS_13(b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0))
+#define _VA_UNUSED_VARS_15(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0) \
+ ((void)(a0), _VA_UNUSED_VARS_14(b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0))
+#define _VA_UNUSED_VARS_16(a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0) \
+ ((void)(a0), _VA_UNUSED_VARS_15(b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0))
+
+
+/* reusable ELEM macro */
+#define UNUSED_VARS(...) VA_NARGS_CALL_OVERLOAD(_VA_UNUSED_VARS_, __VA_ARGS__)
+
/*little macro so inline keyword works*/
#if defined(_MSC_VER)
# define BLI_INLINE static __forceinline
@@ -510,6 +605,7 @@
* for aborting need to define WITH_ASSERT_ABORT
*/
#ifndef NDEBUG
+extern void BLI_system_backtrace(FILE *fp);
# ifdef WITH_ASSERT_ABORT
# define _BLI_DUMMY_ABORT abort
# else
@@ -519,6 +615,7 @@
# define BLI_assert(a) \
(void)((!(a)) ? ( \
( \
+ BLI_system_backtrace(stderr), \
fprintf(stderr, \
"BLI_assert failed: %s:%d, %s(), at \'%s\'\n", \
__FILE__, __LINE__, __func__, STRINGIFY(a)), \
@@ -558,4 +655,8 @@
# define UNLIKELY(x) (x)
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __BLI_UTILDEFINES_H__ */
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index ba166b11960..fa08856517a 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -29,8 +29,8 @@ set(INC
.
# ../blenkernel # dont add this back!
../makesdna
- ../../../intern/ghost
../../../intern/guardedalloc
+ ../../../intern/atomic
../../../extern/wcwidth
)
@@ -52,6 +52,7 @@ set(SRC
intern/BLI_memarena.c
intern/BLI_mempool.c
intern/DLRB_tree.c
+ intern/astar.c
intern/boxpack2d.c
intern/buffer.c
intern/callbacks.c
@@ -85,6 +86,7 @@ set(SRC
intern/noise.c
intern/path_util.c
intern/polyfill2d.c
+ intern/polyfill2d_beautify.c
intern/quadric.c
intern/rand.c
intern/rct.c
@@ -112,6 +114,7 @@ set(SRC
BLI_alloca.h
BLI_args.h
BLI_array.h
+ BLI_astar.h
BLI_bitmap.h
BLI_blenlib.h
BLI_boxpack2d.h
@@ -161,6 +164,7 @@ set(SRC
BLI_noise.h
BLI_path_util.h
BLI_polyfill2d.h
+ BLI_polyfill2d_beautify.h
BLI_quadric.h
BLI_rand.h
BLI_rect.h
@@ -189,13 +193,6 @@ set(SRC
PIL_time_utildefines.h
)
-if(WITH_BINRELOC)
- list(APPEND INC_SYS
- ${BINRELOC_INCLUDE_DIRS}
- )
- add_definitions(-DWITH_BINRELOC)
-endif()
-
if(WITH_MEM_VALGRIND)
add_definitions(-DWITH_MEM_VALGRIND)
endif()
diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript
index b712d2032bf..8b4054e00b5 100644
--- a/source/blender/blenlib/SConscript
+++ b/source/blender/blenlib/SConscript
@@ -34,8 +34,8 @@ cflags=''
incs = [
'.',
'#/extern/wcwidth',
- '#/intern/ghost',
'#/intern/guardedalloc',
+ '#/intern/atomic',
'../makesdna',
env['BF_FREETYPE_INC'],
env['BF_ZLIB_INC'],
@@ -44,10 +44,6 @@ incs = ' '.join(incs)
defs = []
-if env['WITH_BF_BINRELOC']:
- incs += ' ../../../extern/binreloc/include'
- defs.append('WITH_BINRELOC')
-
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
incs += ' ../../../intern/utfconv'
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 6747e5c4e7e..c87b60f08db 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -28,7 +28,8 @@
/** \file blender/blenlib/intern/BLI_ghash.c
* \ingroup bli
*
- * A general (pointer -> pointer) hash table ADT
+ * A general (pointer -> pointer) chaining hash table
+ * for 'Abstract Data Types' (known as an ADT Hash Table).
*
* \note edgehash.c is based on this, make sure they stay in sync.
*/
diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c
index 55dee4e8677..66dfa87b7b9 100644
--- a/source/blender/blenlib/intern/BLI_heap.c
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -49,7 +49,6 @@ struct Heap {
unsigned int bufsize;
MemArena *arena;
HeapNode *freenodes;
- HeapNode *nodes;
HeapNode **tree;
};
@@ -139,9 +138,9 @@ Heap *BLI_heap_new(void)
void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp)
{
- unsigned int i;
-
if (ptrfreefp) {
+ unsigned int i;
+
for (i = 0; i < heap->size; i++) {
ptrfreefp(heap->tree[i]->ptr);
}
@@ -152,6 +151,21 @@ void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp)
MEM_freeN(heap);
}
+void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp)
+{
+ if (ptrfreefp) {
+ unsigned int i;
+
+ for (i = 0; i < heap->size; i++) {
+ ptrfreefp(heap->tree[i]->ptr);
+ }
+ }
+
+ heap->size = 0;
+ BLI_memarena_clear(heap->arena);
+ heap->freenodes = NULL;
+}
+
HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
{
HeapNode *node;
@@ -163,7 +177,7 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
if (heap->freenodes) {
node = heap->freenodes;
- heap->freenodes = (HeapNode *)(((HeapNode *)heap->freenodes)->ptr);
+ heap->freenodes = heap->freenodes->ptr;
}
else {
node = (HeapNode *)BLI_memarena_alloc(heap->arena, sizeof(*node));
@@ -206,13 +220,8 @@ void *BLI_heap_popmin(Heap *heap)
heap->tree[0]->ptr = heap->freenodes;
heap->freenodes = heap->tree[0];
- if (UNLIKELY(heap->size == 1)) {
- heap->size--;
- }
- else {
- heap_swap(heap, 0, heap->size - 1);
- heap->size--;
-
+ if (--heap->size) {
+ heap_swap(heap, 0, heap->size);
heap_down(heap, 0);
}
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index d28215ee8ed..b76b925e6cc 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -986,7 +986,7 @@ bool BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const
/* check if index exists */
if (index > tree->totleaf)
- return 0;
+ return false;
node = tree->nodearray + index;
@@ -1001,7 +1001,7 @@ bool BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const
node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */
}
- return 1;
+ return true;
}
/* call BLI_bvhtree_update_node() first for every node/point/triangle */
diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c
index a0b61e7945c..6b79cf97e86 100644
--- a/source/blender/blenlib/intern/BLI_linklist.c
+++ b/source/blender/blenlib/intern/BLI_linklist.c
@@ -32,6 +32,8 @@
#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
#include "BLI_mempool.h"
@@ -96,7 +98,7 @@ void BLI_linklist_prepend_nlink(LinkNode **listp, void *ptr, LinkNode *nlink)
void BLI_linklist_prepend(LinkNode **listp, void *ptr)
{
- LinkNode *nlink = MEM_mallocN(sizeof(*nlink), "nlink");
+ LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__);
BLI_linklist_prepend_nlink(listp, ptr, nlink);
}
@@ -135,7 +137,7 @@ void BLI_linklist_append_nlink(LinkNode **listp, void *ptr, LinkNode *nlink)
void BLI_linklist_append(LinkNode **listp, void *ptr)
{
- LinkNode *nlink = MEM_mallocN(sizeof(*nlink), "nlink");
+ LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__);
BLI_linklist_append_nlink(listp, ptr, nlink);
}
@@ -177,7 +179,7 @@ void *BLI_linklist_pop_pool(struct LinkNode **listp, struct BLI_mempool *mempool
void BLI_linklist_insert_after(LinkNode **listp, void *ptr)
{
- LinkNode *nlink = MEM_mallocN(sizeof(*nlink), "nlink");
+ LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__);
LinkNode *node = *listp;
nlink->link = ptr;
diff --git a/source/blender/blenlib/intern/astar.c b/source/blender/blenlib/intern/astar.c
new file mode 100644
index 00000000000..b7b41d2497e
--- /dev/null
+++ b/source/blender/blenlib/intern/astar.c
@@ -0,0 +1,294 @@
+/*
+ * ***** 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): Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/intern/astar.c
+ * \ingroup bli
+ * \brief An implementation of the A* (AStar) algorithm to solve shortest path problem.
+ *
+ * This library implements the simple A* (AStar) algorithm, an optimized version of
+ * classical dijkstra shortest path solver. The difference is that each future possible
+ * path is weighted from its 'shortest' (smallest) possible distance to destination,
+ * in addition to distance already walked. This heuristic allows more efficiency
+ * in finding optimal path.
+ *
+ * Implementation based on Wikipedia A* page [http://en.wikipedia.org/wiki/A*_search_algorithm].
+ *
+ * Note that most memory handling here is done through two different MemArena's. Those should also be used to allocate
+ * custom data needed to a specific use of A*.
+ * The first one, owned by BLI_AStarGraph, is for 'static' data that will live as long as the graph.
+ * The second one, owned by BLI_AStarSolution, is for data used during a single path solve. It will be cleared
+ * much more often than graph's one.
+ */
+
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_sys_types.h"
+#include "BLI_compiler_attrs.h"
+
+#include "BLI_alloca.h"
+#include "BLI_heap.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+
+#include "BLI_astar.h"
+
+/**
+ * Init a node in A* graph.
+ *
+ * \param custom_data an opaque pointer attached to this link, available e.g. to cost callback function.
+ */
+void BLI_astar_node_init(BLI_AStarGraph *as_graph, const int node_index, void *custom_data)
+{
+ as_graph->nodes[node_index].custom_data = custom_data;
+}
+
+/**
+ * Add a link between two nodes of our A* graph.
+ *
+ * \param cost the 'length' of the link (actual distance between two vertices or face centers e.g.).
+ * \param custom_data an opaque pointer attached to this link, available e.g. to cost callback function.
+ */
+void BLI_astar_node_link_add(
+ BLI_AStarGraph *as_graph, const int node1_index, const int node2_index, const float cost, void *custom_data)
+{
+ MemArena *mem = as_graph->mem;
+ BLI_AStarGNLink *link = BLI_memarena_alloc(mem, sizeof(*link));
+ LinkData *ld = BLI_memarena_alloc(mem, sizeof(*ld) * 2);
+
+ link->nodes[0] = node1_index;
+ link->nodes[1] = node2_index;
+ link->cost = cost;
+ link->custom_data = custom_data;
+
+ ld[0].data = ld[1].data = link;
+
+ BLI_addtail(&(as_graph->nodes[node1_index].neighbor_links), &ld[0]);
+ BLI_addtail(&(as_graph->nodes[node2_index].neighbor_links), &ld[1]);
+}
+
+/**
+ * \return The index of the other node of given link.
+ */
+int BLI_astar_node_link_other_node(BLI_AStarGNLink *lnk, const int idx)
+{
+ return (lnk->nodes[0] == idx) ? lnk->nodes[1] : lnk->nodes[0];
+}
+
+/**
+ * Initialize a solution data for given A* graph. Does not compute anything!
+ *
+ * \param custom_data an opaque pointer attached to this link, available e.g. to cost callback function.
+ *
+ * \note BLI_AStarSolution stores nearly all data needed during solution compute.
+ */
+void BLI_astar_solution_init(BLI_AStarGraph *as_graph, BLI_AStarSolution *as_solution, void *custom_data)
+{
+ MemArena *mem = as_solution->mem;
+ size_t node_num = (size_t)as_graph->node_num;
+
+ if (mem == NULL) {
+ mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ as_solution->mem = mem;
+ }
+ /* else memarena should be cleared */
+
+ as_solution->steps = 0;
+ as_solution->prev_nodes = BLI_memarena_alloc(mem, sizeof(*as_solution->prev_nodes) * node_num);
+ as_solution->prev_links = BLI_memarena_alloc(mem, sizeof(*as_solution->prev_links) * node_num);
+
+ as_solution->custom_data = custom_data;
+
+ as_solution->done_nodes = BLI_BITMAP_NEW_MEMARENA(mem, node_num);
+ as_solution->g_costs = BLI_memarena_alloc(mem, sizeof(*as_solution->g_costs) * node_num);
+ as_solution->g_steps = BLI_memarena_alloc(mem, sizeof(*as_solution->g_steps) * node_num);
+}
+
+/**
+ * Clear given solution's data, but does not release its memory. Avoids having to recreate/allocate
+ * a memarena in loops, e.g.
+ *
+ * \note This *has to be called* between each path solving.
+ */
+void BLI_astar_solution_clear(BLI_AStarSolution *as_solution)
+{
+ if (as_solution->mem) {
+ BLI_memarena_clear(as_solution->mem);
+ }
+
+ as_solution->steps = 0;
+ as_solution->prev_nodes = NULL;
+ as_solution->prev_links = NULL;
+
+ as_solution->custom_data = NULL;
+
+ as_solution->done_nodes = NULL;
+ as_solution->g_costs = NULL;
+ as_solution->g_steps = NULL;
+}
+
+/**
+ * Release the memory allocated for this solution.
+ */
+void BLI_astar_solution_free(BLI_AStarSolution *as_solution)
+{
+ if (as_solution->mem) {
+ BLI_memarena_free(as_solution->mem);
+ as_solution->mem = NULL;
+ }
+}
+
+/**
+ * Callback computing the current cost (distance) to next node, and the estimated overall cost to destination node
+ * (A* expects this estimation to always be less or equal than actual shortest path from next node to destination one).
+ *
+ * \param link the graph link between current node and next one.
+ * \param node_idx_curr current node index.
+ * \param node_idx_next next node index.
+ * \param node_idx_dst destination node index.
+ */
+typedef float (*astar_f_cost)(BLI_AStarGraph *as_graph, BLI_AStarSolution *as_solution, BLI_AStarGNLink *link,
+ const int node_idx_curr, const int node_idx_next, const int node_idx_dst);
+
+/**
+ * Init an A* graph. Total number of nodes must be known.
+ *
+ * Nodes might be e.g. vertices, faces, ...
+ *
+ * \param custom_data an opaque pointer attached to this link, available e.g. to cost callback function.
+ */
+void BLI_astar_graph_init(BLI_AStarGraph *as_graph, const int node_num, void *custom_data)
+{
+ MemArena *mem = as_graph->mem;
+
+ if (mem == NULL) {
+ mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ as_graph->mem = mem;
+ }
+ /* else memarena should be cleared */
+
+ as_graph->node_num = node_num;
+ as_graph->nodes = BLI_memarena_calloc(mem, sizeof(*as_graph->nodes) * (size_t)node_num);
+
+ as_graph->custom_data = custom_data;
+}
+
+void BLI_astar_graph_free(BLI_AStarGraph *as_graph)
+{
+ if (as_graph->mem) {
+ BLI_memarena_free(as_graph->mem);
+ as_graph->mem = NULL;
+ }
+}
+
+/**
+ * Solve a path in given graph, using given 'cost' callback function.
+ *
+ * \param max_steps maximum number of nodes the found path may have. Useful in performance-critical usages.
+ * If no path is found within given steps, returns false too.
+ * \return true if a path was found, false otherwise.
+ */
+bool BLI_astar_graph_solve(
+ BLI_AStarGraph *as_graph, const int node_index_src, const int node_index_dst, astar_f_cost f_cost_cb,
+ BLI_AStarSolution *r_solution, const int max_steps)
+{
+ Heap *todo_nodes;
+
+ BLI_bitmap *done_nodes = r_solution->done_nodes;
+ int *prev_nodes = r_solution->prev_nodes;
+ BLI_AStarGNLink **prev_links = r_solution->prev_links;
+ float *g_costs = r_solution->g_costs;
+ int *g_steps = r_solution->g_steps;
+
+ r_solution->steps = 0;
+ prev_nodes[node_index_src] = -1;
+ BLI_BITMAP_SET_ALL(done_nodes, false, as_graph->node_num);
+ fill_vn_fl(g_costs, as_graph->node_num, FLT_MAX);
+ g_costs[node_index_src] = 0.0f;
+ g_steps[node_index_src] = 0;
+
+ if (node_index_src == node_index_dst) {
+ return true;
+ }
+
+ todo_nodes = BLI_heap_new();
+ BLI_heap_insert(todo_nodes,
+ f_cost_cb(as_graph, r_solution, NULL, -1, node_index_src, node_index_dst),
+ SET_INT_IN_POINTER(node_index_src));
+
+ while (!BLI_heap_is_empty(todo_nodes)) {
+ const int node_curr_idx = GET_INT_FROM_POINTER(BLI_heap_popmin(todo_nodes));
+ BLI_AStarGNode *node_curr = &as_graph->nodes[node_curr_idx];
+ LinkData *ld;
+
+ if (BLI_BITMAP_TEST(done_nodes, node_curr_idx)) {
+ /* Might happen, because we always add nodes to heap when evaluating them, without ever removing them. */
+ continue;
+ }
+
+ /* If we are limited in amount of steps to find a path, skip if we reached limit. */
+ if (max_steps && g_steps[node_curr_idx] > max_steps) {
+ continue;
+ }
+
+ if (node_curr_idx == node_index_dst) {
+ /* Success! Path found... */
+ r_solution->steps = g_steps[node_curr_idx] + 1;
+
+ BLI_heap_free(todo_nodes, NULL);
+ return true;
+ }
+
+ BLI_BITMAP_ENABLE(done_nodes, node_curr_idx);
+
+ for (ld = node_curr->neighbor_links.first; ld; ld = ld->next) {
+ BLI_AStarGNLink *link = ld->data;
+ const int node_next_idx = BLI_astar_node_link_other_node(link, node_curr_idx);
+
+ if (!BLI_BITMAP_TEST(done_nodes, node_next_idx)) {
+ float g_cst = g_costs[node_curr_idx] + link->cost;
+
+ if (g_cst < g_costs[node_next_idx]) {
+ prev_nodes[node_next_idx] = node_curr_idx;
+ prev_links[node_next_idx] = link;
+ g_costs[node_next_idx] = g_cst;
+ g_steps[node_next_idx] = g_steps[node_curr_idx] + 1;
+ /* We might have this node already in heap, but since this 'instance' will be evaluated first,
+ * no problem. */
+ BLI_heap_insert(todo_nodes,
+ f_cost_cb(as_graph, r_solution, link, node_curr_idx, node_next_idx, node_index_dst),
+ SET_INT_IN_POINTER(node_next_idx));
+ }
+ }
+ }
+ }
+
+ BLI_heap_free(todo_nodes, NULL);
+ return false;
+}
diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c
index 91495ce3c9c..bae56444f37 100644
--- a/source/blender/blenlib/intern/boxpack2d.c
+++ b/source/blender/blenlib/intern/boxpack2d.c
@@ -236,8 +236,8 @@ static int vertex_sort(const void *p1, const void *p2)
BoxVert *v1, *v2;
float a1, a2;
- v1 = vertarray + ((int *)p1)[0];
- v2 = vertarray + ((int *)p2)[0];
+ v1 = vertarray + ((const int *)p1)[0];
+ v2 = vertarray + ((const int *)p2)[0];
#ifdef USE_FREE_STRIP
/* push free verts to the end so we can strip */
diff --git a/source/blender/blenlib/intern/convexhull2d.c b/source/blender/blenlib/intern/convexhull2d.c
index 361e4b4eadb..5f64088f433 100644
--- a/source/blender/blenlib/intern/convexhull2d.c
+++ b/source/blender/blenlib/intern/convexhull2d.c
@@ -187,8 +187,8 @@ static int pointref_cmp_yx(const void *a_, const void *b_)
* \param points An array of 2D points.
* \param n The number of points in points.
* \param r_points An array of the convex hull vertex indices (max is n).
- * _must_ be allocated as ``n * 2`` because of how its used internally,
- * even though the final result will be no more then \a n in size.
+ * _must_ be allocated as ``n * 2`` because of how its used internally,
+ * even though the final result will be no more than \a n in size.
* \returns the number of points in r_points.
*/
int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[])
diff --git a/source/blender/blenlib/intern/easing.c b/source/blender/blenlib/intern/easing.c
index 80f02d54eaa..90c8528338e 100644
--- a/source/blender/blenlib/intern/easing.c
+++ b/source/blender/blenlib/intern/easing.c
@@ -139,7 +139,7 @@ float BLI_easing_cubic_ease_in_out(float time, float begin, float change, float
#ifdef USE_ELASTIC_BLEND
/**
- * When the amplitude is less then the change, we need to blend
+ * When the amplitude is less than the change, we need to blend
* \a f when we're close to the crossing point (int time), else we get an ugly sharp falloff.
*/
static float elastic_blend(float time, float change, float duration, float amplitude, float s, float f)
diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c
index 4ed82f8a473..82d57dad753 100644
--- a/source/blender/blenlib/intern/edgehash.c
+++ b/source/blender/blenlib/intern/edgehash.c
@@ -23,12 +23,13 @@
/** \file blender/blenlib/intern/edgehash.c
* \ingroup bli
*
- * A general (pointer -> pointer) hash table ADT
+ * An (edge -> pointer) chaining hash table.
+ * Using unordered int-pairs as keys.
*
- * \note Based on 'BLI_ghash.c', make sure these stay in sync.
+ * \note Based on 'BLI_ghash.c', which is a more generalized hash-table
+ * make sure these stay in sync.
*/
-
#include <stdlib.h>
#include <string.h>
#include <limits.h>
@@ -146,7 +147,7 @@ BLI_INLINE void edgehash_buckets_reserve(EdgeHash *eh, const unsigned int nentri
/**
* Internal lookup function.
- * Takes a hash argument to avoid calling #ghash_keyhash multiple times.
+ * Takes a hash argument to avoid calling #edgehash_keyhash multiple times.
*/
BLI_INLINE EdgeEntry *edgehash_lookup_entry_ex(EdgeHash *eh, unsigned int v0, unsigned int v1,
const unsigned int hash)
@@ -256,6 +257,35 @@ BLI_INLINE void edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1,
}
/**
+ * Remove the entry and return it, caller must free from eh->epool.
+ */
+static EdgeEntry *edgehash_remove_ex(EdgeHash *eh, unsigned int v0, unsigned int v1, EdgeHashFreeFP valfreefp,
+ unsigned int hash)
+{
+ EdgeEntry *e;
+ EdgeEntry *e_prev = NULL;
+
+ BLI_assert(v0 < v1);
+
+ for (e = eh->buckets[hash]; e; e = e->next) {
+ if (UNLIKELY(v0 == e->v0 && v1 == e->v1)) {
+ EdgeEntry *e_next = e->next;
+
+ if (valfreefp) valfreefp(e->val);
+
+ if (e_prev) e_prev->next = e_next;
+ else eh->buckets[hash] = e_next;
+
+ eh->nentries--;
+ return e;
+ }
+ e_prev = e;
+ }
+
+ return NULL;
+}
+
+/**
* Run free callbacks for freeing entries.
*/
static void edgehash_free_cb(EdgeHash *eh, EdgeHashFreeFP valfreefp)
@@ -366,6 +396,57 @@ void *BLI_edgehash_lookup_default(EdgeHash *eh, unsigned int v0, unsigned int v1
}
/**
+ * Remove \a key from \a eh, or return false if the key wasn't found.
+ *
+ * \param key The key to remove.
+ * \param valfreefp Optional callback to free the value.
+ * \return true if \a key was removed from \a eh.
+ */
+bool BLI_edgehash_remove(EdgeHash *eh, unsigned int v0, unsigned int v1, EdgeHashFreeFP valfreefp)
+{
+ unsigned int hash;
+ EdgeEntry *e;
+
+ EDGE_ORD(v0, v1); /* ensure v0 is smaller */
+ hash = edgehash_keyhash(eh, v0, v1);
+ e = edgehash_remove_ex(eh, v0, v1, valfreefp, hash);
+ if (e) {
+ BLI_mempool_free(eh->epool, e);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/* same as above but return the value,
+ * no free value argument since it will be returned */
+/**
+ * Remove \a key from \a eh, returning the value or NULL if the key wasn't found.
+ *
+ * \param key The key to remove.
+ * \return the value of \a key int \a eh or NULL.
+ */
+void *BLI_edgehash_popkey(EdgeHash *eh, unsigned int v0, unsigned int v1)
+{
+ unsigned int hash;
+ EdgeEntry *e;
+
+ EDGE_ORD(v0, v1); /* ensure v0 is smaller */
+ hash = edgehash_keyhash(eh, v0, v1);
+ e = edgehash_remove_ex(eh, v0, v1, NULL, hash);
+ IS_EDGEHASH_ASSERT(eh);
+ if (e) {
+ void *val = e->val;
+ BLI_mempool_free(eh->epool, e);
+ return val;
+ }
+ else {
+ return NULL;
+ }
+}
+
+/**
* Return boolean true/false if edge (v0,v1) in hash.
*/
bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1)
@@ -404,6 +485,14 @@ void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP valfreefp,
BLI_mempool_clear_ex(eh->epool, nentries_reserve ? (int)nentries_reserve : -1);
}
+/**
+ * Wraps #BLI_edgehash_clear_ex with zero entries reserved.
+ */
+void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp)
+{
+ BLI_edgehash_clear_ex(eh, valfreefp, 0);
+}
+
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp)
{
BLI_assert((int)eh->nentries == BLI_mempool_count(eh->epool));
@@ -440,7 +529,7 @@ void BLI_edgehash_flag_clear(EdgeHash *eh, unsigned int flag)
/**
* Create a new EdgeHashIterator. The hash table must not be mutated
* while the iterator is in use, and the iterator will step exactly
- * BLI_edgehash_size(gh) times before becoming done.
+ * BLI_edgehash_size(eh) times before becoming done.
*/
EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh)
{
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index f6bbd3273f9..62e1b6e4cbf 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -311,7 +311,7 @@ static bool delete_recursive(const char *dir)
bool err = false;
unsigned int nbr, i;
- i = nbr = BLI_dir_contents(dir, &filelist);
+ i = nbr = BLI_filelist_dir_contents(dir, &filelist);
fl = filelist;
while (i--) {
char file[8];
@@ -336,7 +336,7 @@ static bool delete_recursive(const char *dir)
err = true;
}
- BLI_free_filelist(filelist, nbr);
+ BLI_filelist_free(filelist, nbr, NULL);
return err;
}
@@ -896,7 +896,7 @@ int BLI_move(const char *file, const char *to)
}
#endif
-static char *check_destination(const char *file, const char *to)
+static const char *check_destination(const char *file, const char *to)
{
struct stat st;
@@ -927,18 +927,18 @@ static char *check_destination(const char *file, const char *to)
}
}
- return (char *)to;
+ return to;
}
int BLI_copy(const char *file, const char *to)
{
- char *actual_to = check_destination(file, to);
+ const char *actual_to = check_destination(file, to);
int ret;
ret = recursive_operation(file, actual_to, copy_callback_pre, copy_single_file, NULL);
if (actual_to != to)
- MEM_freeN(actual_to);
+ MEM_freeN((void *)actual_to);
return ret;
}
diff --git a/source/blender/blenlib/intern/graph.c b/source/blender/blenlib/intern/graph.c
index d4d87dfdbf6..81cc9fde01f 100644
--- a/source/blender/blenlib/intern/graph.c
+++ b/source/blender/blenlib/intern/graph.c
@@ -170,11 +170,11 @@ bool BLI_hasAdjacencyList(BGraph *graph)
for (node = graph->nodes.first; node; node = node->next) {
if (node->arcs == NULL) {
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
void BLI_replaceNodeInArc(BGraph *graph, BArc *arc, BNode *node_src, BNode *node_replaced)
@@ -337,7 +337,7 @@ static bool detectCycle(BNode *node, BArc *src_arc)
}
}
else {
- value = 1;
+ value = true;
}
return value;
@@ -354,7 +354,7 @@ bool BLI_isGraphCyclic(BGraph *graph)
BLI_flagNodes(graph, 0);
/* detectCycles in subgraphs */
- for (node = graph->nodes.first; node && value == 0; node = node->next) {
+ for (node = graph->nodes.first; node && value == false; node = node->next) {
/* only for nodes in subgraphs that haven't been visited yet */
if (node->flag == 0) {
value = value || detectCycle(node, NULL);
diff --git a/source/blender/blenlib/intern/hash_md5.c b/source/blender/blenlib/intern/hash_md5.c
index bc7a495f213..4eec38278e9 100644
--- a/source/blender/blenlib/intern/hash_md5.c
+++ b/source/blender/blenlib/intern/hash_md5.c
@@ -22,7 +22,7 @@
* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>.
*/
-/** \file blender/blenlib/intern/md5.c
+/** \file blender/blenlib/intern/hash_md5.c
* \ingroup bli
*
* Functions to compute MD5 message digest of files or memory blocks
diff --git a/source/blender/blenlib/intern/hash_mm2a.c b/source/blender/blenlib/intern/hash_mm2a.c
index 8b4242fa5be..bae098ae96b 100644
--- a/source/blender/blenlib/intern/hash_mm2a.c
+++ b/source/blender/blenlib/intern/hash_mm2a.c
@@ -81,7 +81,7 @@ void BLI_hash_mm2a_add(BLI_HashMurmur2A *mm2, const unsigned char *data, size_t
mm2a_mix_tail(mm2, &data, &len);
for (; len >= 4; data += 4, len -= 4) {
- uint32_t k = *(uint32_t *)data;
+ uint32_t k = *(const uint32_t *)data;
MM2A_MIX(mm2->hash, k);
}
diff --git a/source/blender/blenlib/intern/lasso.c b/source/blender/blenlib/intern/lasso.c
index e89f7fd795b..23704538413 100644
--- a/source/blender/blenlib/intern/lasso.c
+++ b/source/blender/blenlib/intern/lasso.c
@@ -33,7 +33,6 @@
#include "DNA_vec_types.h"
#include "BLI_math.h"
-#include "BLI_rect.h"
#include "BLI_strict_flags.h"
#include "BLI_lasso.h" /* own include */
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index 39116d6f30f..f5713824296 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -276,5 +276,18 @@ MINLINE float signf(float f)
return (f < 0.f) ? -1.f : 1.f;
}
+MINLINE int signum_i_ex(float a, float eps)
+{
+ if (a > eps) return 1;
+ if (a < -eps) return -1;
+ else return 0;
+}
+
+MINLINE int signum_i(float a)
+{
+ if (a > 0.0f) return 1;
+ if (a < 0.0f) return -1;
+ else return 0;
+}
#endif /* __MATH_BASE_INLINE_C__ */
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 015313431cb..05a527c4f7a 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -50,6 +50,21 @@ void cent_quad_v3(float cent[3], const float v1[3], const float v2[3], const flo
cent[2] = 0.25f * (v1[2] + v2[2] + v3[2] + v4[2]);
}
+void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
+{
+ float n1[3], n2[3];
+
+ n1[0] = v1[0] - v2[0];
+ n2[0] = v2[0] - v3[0];
+ n1[1] = v1[1] - v2[1];
+ n2[1] = v2[1] - v3[1];
+ n1[2] = v1[2] - v2[2];
+ n2[2] = v2[2] - v3[2];
+ n[0] = n1[1] * n2[2] - n1[2] * n2[1];
+ n[1] = n1[2] * n2[0] - n1[0] * n2[2];
+ n[2] = n1[0] * n2[1] - n1[1] * n2[0];
+}
+
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
{
float n1[3], n2[3];
@@ -94,58 +109,44 @@ float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const flo
*/
float normal_poly_v3(float n[3], const float verts[][3], unsigned int nr)
{
- const float *v_prev = verts[nr - 1];
- const float *v_curr = verts[0];
- unsigned int i;
-
- zero_v3(n);
-
- /* Newell's Method */
- for (i = 0; i < nr; v_prev = v_curr, v_curr = verts[++i]) {
- add_newell_cross_v3_v3v3(n, v_prev, v_curr);
- }
-
+ cross_poly_v3(n, verts, nr);
return normalize_v3(n);
}
-/* only convex Quadrilaterals */
float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
- float len, vec1[3], vec2[3], n[3];
-
- sub_v3_v3v3(vec1, v2, v1);
- sub_v3_v3v3(vec2, v4, v1);
- cross_v3_v3v3(n, vec1, vec2);
- len = len_v3(n);
-
- sub_v3_v3v3(vec1, v4, v3);
- sub_v3_v3v3(vec2, v2, v3);
- cross_v3_v3v3(n, vec1, vec2);
- len += len_v3(n);
+ const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}};
+ return area_poly_v3(verts, 4);
+}
- return (len / 2.0f);
+float area_squared_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
+{
+ const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}};
+ return area_squared_poly_v3(verts, 4);
}
/* Triangles */
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
{
- float vec1[3], vec2[3], n[3];
-
- sub_v3_v3v3(vec1, v3, v2);
- sub_v3_v3v3(vec2, v1, v2);
- cross_v3_v3v3(n, vec1, vec2);
+ float n[3];
+ cross_tri_v3(n, v1, v2, v3);
+ return len_v3(n) * 0.5f;
+}
- return len_v3(n) / 2.0f;
+float area_squared_tri_v3(const float v1[3], const float v2[3], const float v3[3])
+{
+ float n[3];
+ cross_tri_v3(n, v1, v2, v3);
+ mul_v3_fl(n, 0.5f);
+ return len_squared_v3(n);
}
float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3])
{
- float area, vec1[3], vec2[3], n[3];
+ float area, n[3];
- sub_v3_v3v3(vec1, v3, v2);
- sub_v3_v3v3(vec2, v1, v2);
- cross_v3_v3v3(n, vec1, vec2);
- area = len_v3(n) / 2.0f;
+ cross_tri_v3(n, v1, v2, v3);
+ area = len_v3(n) * 0.5f;
/* negate area for flipped triangles */
if (dot_v3v3(n, normal) < 0.0f)
@@ -157,7 +158,17 @@ float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3]
float area_poly_v3(const float verts[][3], unsigned int nr)
{
float n[3];
- return normal_poly_v3(n, verts, nr) * 0.5f;
+ cross_poly_v3(n, verts, nr);
+ return len_v3(n) * 0.5f;
+}
+
+float area_squared_poly_v3(const float verts[][3], unsigned int nr)
+{
+ float n[3];
+
+ cross_poly_v3(n, verts, nr);
+ mul_v3_fl(n, 0.5f);
+ return len_squared_v3(n);
}
/**
@@ -185,11 +196,36 @@ float cross_poly_v2(const float verts[][2], unsigned int nr)
return cross;
}
+void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr)
+{
+ const float *v_prev = verts[nr - 1];
+ const float *v_curr = verts[0];
+ unsigned int i;
+
+ zero_v3(n);
+
+ /* Newell's Method */
+ for (i = 0; i < nr; v_prev = v_curr, v_curr = verts[++i]) {
+ add_newell_cross_v3_v3v3(n, v_prev, v_curr);
+ }
+}
+
float area_poly_v2(const float verts[][2], unsigned int nr)
{
return fabsf(0.5f * cross_poly_v2(verts, nr));
}
+float area_poly_signed_v2(const float verts[][2], unsigned int nr)
+{
+ return (0.5f * cross_poly_v2(verts, nr));
+}
+
+float area_squared_poly_v2(const float verts[][2], unsigned int nr)
+{
+ float area = area_poly_signed_v2(verts, nr);
+ return area * area;
+}
+
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3])
{
float a[3], b[3], c[3], c_len;
@@ -912,12 +948,12 @@ bool isect_point_tri_v2_cw(const float pt[2], const float v1[2], const float v2[
if (line_point_side_v2(v1, v2, pt) >= 0.0f) {
if (line_point_side_v2(v2, v3, pt) >= 0.0f) {
if (line_point_side_v2(v3, v1, pt) >= 0.0f) {
- return 1;
+ return true;
}
}
}
- return 0;
+ return false;
}
int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2])
@@ -983,28 +1019,28 @@ 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.0f) return 0;
+ if (a == 0.0f) return false;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
u = f * dot_v3v3(s, p);
- if ((u < 0.0f) || (u > 1.0f)) return 0;
+ if ((u < 0.0f) || (u > 1.0f)) return false;
cross_v3_v3v3(q, s, e1);
v = f * dot_v3v3(d, q);
- if ((v < 0.0f) || ((u + v) > 1.0f)) return 0;
+ if ((v < 0.0f) || ((u + v) > 1.0f)) return false;
*r_lambda = f * dot_v3v3(e2, q);
- if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return 0;
+ if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return false;
if (r_uv) {
r_uv[0] = u;
r_uv[1] = v;
}
- return 1;
+ return true;
}
/* like isect_line_tri_v3, but allows epsilon tolerance around triangle */
@@ -1022,28 +1058,28 @@ 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.0f) return 0;
+ if (a == 0.0f) return false;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
u = f * dot_v3v3(s, p);
- if ((u < -epsilon) || (u > 1.0f + epsilon)) return 0;
+ if ((u < -epsilon) || (u > 1.0f + epsilon)) return false;
cross_v3_v3v3(q, s, e1);
v = f * dot_v3v3(d, q);
- if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) return 0;
+ if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) return false;
*r_lambda = f * dot_v3v3(e2, q);
- if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return 0;
+ if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return false;
if (r_uv) {
r_uv[0] = u;
r_uv[1] = v;
}
- return 1;
+ return true;
}
/* moved from effect.c
@@ -1064,28 +1100,28 @@ bool isect_ray_tri_v3(const float p1[3], const float d[3],
a = dot_v3v3(e1, p);
/* note: these values were 0.000001 in 2.4x but for projection snapping on
* a human head (1BU == 1m), subsurf level 2, this gave many errors - campbell */
- if ((a > -0.00000001f) && (a < 0.00000001f)) return 0;
+ if ((a > -0.00000001f) && (a < 0.00000001f)) return false;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
u = f * dot_v3v3(s, p);
- if ((u < 0.0f) || (u > 1.0f)) return 0;
+ if ((u < 0.0f) || (u > 1.0f)) return false;
cross_v3_v3v3(q, s, e1);
v = f * dot_v3v3(d, q);
- if ((v < 0.0f) || ((u + v) > 1.0f)) return 0;
+ if ((v < 0.0f) || ((u + v) > 1.0f)) return false;
*r_lambda = f * dot_v3v3(e2, q);
- if ((*r_lambda < 0.0f)) return 0;
+ if ((*r_lambda < 0.0f)) return false;
if (r_uv) {
r_uv[0] = u;
r_uv[1] = v;
}
- return 1;
+ return true;
}
/**
@@ -1107,7 +1143,7 @@ bool isect_ray_plane_v3(const float p1[3], const float d[3],
a = dot_v3v3(e1, p);
/* note: these values were 0.000001 in 2.4x but for projection snapping on
* a human head (1BU == 1m), subsurf level 2, this gave many errors - campbell */
- if ((a > -0.00000001f) && (a < 0.00000001f)) return 0;
+ if ((a > -0.00000001f) && (a < 0.00000001f)) return false;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
@@ -1119,9 +1155,9 @@ bool isect_ray_plane_v3(const float p1[3], const float d[3],
/* v = f * dot_v3v3(d, q); */ /*UNUSED*/
*r_lambda = f * dot_v3v3(e2, q);
- if (clip && (*r_lambda < 0.0f)) return 0;
+ if (clip && (*r_lambda < 0.0f)) return false;
- return 1;
+ return true;
}
bool isect_ray_tri_epsilon_v3(const float p1[3], const float d[3],
@@ -1142,22 +1178,22 @@ bool isect_ray_tri_epsilon_v3(const float p1[3], const float d[3],
sub_v3_v3v3(s, p1, v0);
u = f * dot_v3v3(s, p);
- if ((u < -epsilon) || (u > 1.0f + epsilon)) return 0;
+ if ((u < -epsilon) || (u > 1.0f + epsilon)) return false;
cross_v3_v3v3(q, s, e1);
v = f * dot_v3v3(d, q);
- if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) return 0;
+ if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) return false;
*r_lambda = f * dot_v3v3(e2, q);
- if ((*r_lambda < 0.0f)) return 0;
+ if ((*r_lambda < 0.0f)) return false;
if (uv) {
uv[0] = u;
uv[1] = v;
}
- return 1;
+ return true;
}
bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
@@ -1173,14 +1209,14 @@ bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
cross_v3_v3v3(p, d, e2);
a = dot_v3v3(e1, p);
- if ((a > -0.000001f) && (a < 0.000001f)) return 0;
+ if ((a > -0.000001f) && (a < 0.000001f)) return false;
f = 1.0f / a;
sub_v3_v3v3(s, p1, v0);
cross_v3_v3v3(q, s, e1);
*r_lambda = f * dot_v3v3(e2, q);
- if ((*r_lambda < 0.0f)) return 0;
+ if ((*r_lambda < 0.0f)) return false;
u = f * dot_v3v3(s, p);
v = f * dot_v3v3(d, q);
@@ -1204,7 +1240,7 @@ bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
mul_v3_fl(e2, dv);
if (len_squared_v3(e1) + len_squared_v3(e2) > threshold * threshold) {
- return 0;
+ return false;
}
if (r_uv) {
@@ -1212,7 +1248,7 @@ bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
r_uv[1] = v;
}
- return 1;
+ return true;
}
/**
@@ -1363,7 +1399,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
if (t0 > t1)
SWAP(float, t0, t1);
- if (t0 > 1.0f || t1 < 0.0f) return 0;
+ if (t0 > 1.0f || t1 < 0.0f) return false;
/* clamp to [0, 1] */
CLAMP(t0, 0.0f, 1.0f);
@@ -1542,7 +1578,7 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
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;
+ if ((v < 0.0f) || (v > 1.0f)) return false;
f = e1[a1];
if ((f > -0.000001f) && (f < 0.000001f)) {
@@ -1553,7 +1589,7 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
else
u = (-p[a1] - v * e2[a1]) / f;
- if ((u < 0.0f) || ((u + v) > 1.0f)) return 0;
+ if ((u < 0.0f) || ((u + v) > 1.0f)) return false;
*r_lambda = (p[a0] + u * e1[a0] + v * e2[a0]) / (p2[a0] - p1[a0]);
@@ -1840,7 +1876,7 @@ 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'.
+/** Ensure the distance between these points is no greater than 'dist'.
* If it is, scale then both into the center.
*/
void limit_dist_v3(float v1[3], float v2[3], const float dist)
@@ -2350,15 +2386,15 @@ bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[
}
/**
- * \note: using #area_tri_signed_v2 means locations outside the triangle are correctly weighted
+ * \note: using #cross_tri_v2 means locations outside the triangle are correctly weighted
*/
void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
{
float wtot;
- w[0] = area_tri_signed_v2(v2, v3, co);
- w[1] = area_tri_signed_v2(v3, v1, co);
- w[2] = area_tri_signed_v2(v1, v2, co);
+ w[0] = cross_tri_v2(v2, v3, co);
+ w[1] = cross_tri_v2(v3, v1, co);
+ w[2] = cross_tri_v2(v1, v2, co);
wtot = w[0] + w[1] + w[2];
if (wtot != 0.0f) {
@@ -2377,9 +2413,9 @@ void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const fl
{
float wtot;
- w[0] = area_tri_signed_v2(v2, v3, co) / v1[3];
- w[1] = area_tri_signed_v2(v3, v1, co) / v2[3];
- w[2] = area_tri_signed_v2(v1, v2, co) / v3[3];
+ w[0] = cross_tri_v2(v2, v3, co) / v1[3];
+ w[1] = cross_tri_v2(v3, v1, co) / v2[3];
+ w[2] = cross_tri_v2(v1, v2, co) / v3[3];
wtot = w[0] + w[1] + w[2];
if (wtot != 0.0f) {
@@ -2602,38 +2638,55 @@ int interp_sparse_array(float *array, const int list_size, const float skipval)
return 1;
}
+/** \name interp_weights_poly_v2, v3
+ * \{ */
+
+#define IS_POINT_IX (1 << 0)
+#define IS_SEGMENT_IX (1 << 1)
+
+#define DIR_V3_SET(d_len, va, vb) { \
+ sub_v3_v3v3((d_len)->dir, va, vb); \
+ (d_len)->len = len_v3((d_len)->dir); \
+} (void)0
+
+#define DIR_V2_SET(d_len, va, vb) { \
+ sub_v2_v2v2((d_len)->dir, va, vb); \
+ (d_len)->len = len_v2((d_len)->dir); \
+} (void)0
+
+struct Float3_Len {
+ float dir[3], len;
+};
+
+struct Float2_Len {
+ float dir[2], len;
+};
+
/* Mean value weights - smooth interpolation weights for polygons with
* more than 3 vertices */
-static float mean_value_half_tan_v3(const float v1[3], const float v2[3], const float v3[3])
+static float mean_value_half_tan_v3(const struct Float3_Len *d_curr, const struct Float3_Len *d_next)
{
- float d2[3], d3[3], cross[3], area;
-
- sub_v3_v3v3(d2, v2, v1);
- sub_v3_v3v3(d3, v3, v1);
- cross_v3_v3v3(cross, d2, d3);
-
+ float cross[3], area;
+ cross_v3_v3v3(cross, d_curr->dir, d_next->dir);
area = len_v3(cross);
if (LIKELY(area != 0.0f)) {
- const float dot = dot_v3v3(d2, d3);
- const float len = len_v3(d2) * len_v3(d3);
+ const float dot = dot_v3v3(d_curr->dir, d_next->dir);
+ const float len = d_curr->len * d_next->len;
return (len - dot) / area;
}
else {
return 0.0f;
}
}
-static float mean_value_half_tan_v2(const float v1[2], const float v2[2], const float v3[2])
-{
- float d2[2], d3[2], area;
-
- sub_v2_v2v2(d2, v2, v1);
- sub_v2_v2v2(d3, v3, v1);
+static float mean_value_half_tan_v2(const struct Float2_Len *d_curr, const struct Float2_Len *d_next)
+{
+ float area;
/* different from the 3d version but still correct */
- area = cross_v2v2(d2, d3);
+ area = cross_v2v2(d_curr->dir, d_next->dir);
if (LIKELY(area != 0.0f)) {
- const float dot = dot_v2v2(d2, d3);
- const float len = len_v2(d2) * len_v2(d3);
+ const float dot = dot_v2v2(d_curr->dir, d_next->dir);
+ const float len = d_curr->len * d_next->len;
return (len - dot) / area;
}
else {
@@ -2649,30 +2702,34 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[
float ht_prev, ht; /* half tangents */
float totweight = 0.0f;
int i = 0;
- bool vert_interp = false;
- bool edge_interp = false;
+ char ix_flag = 0;
+ struct Float3_Len d_curr, d_next;
v_curr = v[0];
v_next = v[1];
- ht_prev = mean_value_half_tan_v3(co, v[n - 1], v_curr);
+ DIR_V3_SET(&d_curr, v[n - 1], co);
+ DIR_V3_SET(&d_next, v_curr, co);
+ ht_prev = mean_value_half_tan_v3(&d_curr, &d_next);
while (i < n) {
- const float len_sq = len_squared_v3v3(co, v_curr);
-
/* Mark Mayer et al algorithm that is used here does not operate well if vertex is close
* to borders of face. In that case, do simple linear interpolation between the two edge vertices */
- if (len_sq < eps_sq) {
- vert_interp = true;
+
+ /* 'd_next.len' is infact 'd_curr.len', just avoid copy to begin with */
+ if (UNLIKELY(d_next.len < eps)) {
+ ix_flag = IS_POINT_IX;
break;
}
- else if (dist_squared_to_line_segment_v3(co, v_curr, v_next) < eps_sq) {
- edge_interp = true;
+ else if (UNLIKELY(dist_squared_to_line_segment_v3(co, v_curr, v_next) < eps_sq)) {
+ ix_flag = IS_SEGMENT_IX;
break;
}
- ht = mean_value_half_tan_v3(co, v_curr, v_next);
- w[i] = (ht_prev + ht) / sqrtf(len_sq);
+ d_curr = d_next;
+ DIR_V3_SET(&d_next, v_next, co);
+ ht = mean_value_half_tan_v3(&d_curr, &d_next);
+ w[i] = (ht_prev + ht) / d_curr.len;
totweight += w[i];
/* step */
@@ -2683,22 +2740,21 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[
ht_prev = ht;
}
- if (vert_interp) {
+ if (ix_flag) {
const int i_curr = i;
- for (i = 0; i < n; i++)
- w[i] = 0.0;
- w[i_curr] = 1.0f;
- }
- else if (edge_interp) {
- const int i_curr = i;
- float len_curr = len_v3v3(co, v_curr);
- float len_next = len_v3v3(co, v_next);
- float edge_len = len_curr + len_next;
- for (i = 0; i < n; i++)
- w[i] = 0.0;
+ for (i = 0; i < n; i++) {
+ w[i] = 0.0f;
+ }
- w[i_curr] = len_next / edge_len;
- w[(i_curr + 1) % n] = len_curr / edge_len;
+ if (ix_flag & IS_POINT_IX) {
+ w[i_curr] = 1.0f;
+ }
+ else {
+ float fac = line_point_factor_v3(co, v_curr, v_next);
+ CLAMP(fac, 0.0f, 1.0f);
+ w[i_curr] = 1.0f - fac;
+ w[(i_curr + 1) % n] = fac;
+ }
}
else {
if (totweight != 0.0f) {
@@ -2718,30 +2774,34 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[
float ht_prev, ht; /* half tangents */
float totweight = 0.0f;
int i = 0;
- bool vert_interp = false;
- bool edge_interp = false;
+ char ix_flag = 0;
+ struct Float2_Len d_curr, d_next;
v_curr = v[0];
v_next = v[1];
- ht_prev = mean_value_half_tan_v2(co, v[n - 1], v_curr);
+ DIR_V2_SET(&d_curr, v[n - 1], co);
+ DIR_V2_SET(&d_next, v_curr, co);
+ ht_prev = mean_value_half_tan_v2(&d_curr, &d_next);
while (i < n) {
- const float len_sq = len_squared_v2v2(co, v_curr);
-
/* Mark Mayer et al algorithm that is used here does not operate well if vertex is close
* to borders of face. In that case, do simple linear interpolation between the two edge vertices */
- if (len_sq < eps_sq) {
- vert_interp = true;
+
+ /* 'd_next.len' is infact 'd_curr.len', just avoid copy to begin with */
+ if (UNLIKELY(d_next.len < eps)) {
+ ix_flag = IS_POINT_IX;
break;
}
- else if (dist_squared_to_line_segment_v2(co, v_curr, v_next) < eps_sq) {
- edge_interp = true;
+ else if (UNLIKELY(dist_squared_to_line_segment_v2(co, v_curr, v_next) < eps_sq)) {
+ ix_flag = IS_SEGMENT_IX;
break;
}
- ht = mean_value_half_tan_v2(co, v_curr, v_next);
- w[i] = (ht_prev + ht) / sqrtf(len_sq);
+ d_curr = d_next;
+ DIR_V2_SET(&d_next, v_next, co);
+ ht = mean_value_half_tan_v2(&d_curr, &d_next);
+ w[i] = (ht_prev + ht) / d_curr.len;
totweight += w[i];
/* step */
@@ -2752,22 +2812,21 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[
ht_prev = ht;
}
- if (vert_interp) {
- const int i_curr = i;
- for (i = 0; i < n; i++)
- w[i] = 0.0;
- w[i_curr] = 1.0f;
- }
- else if (edge_interp) {
+ if (ix_flag) {
const int i_curr = i;
- float len_curr = len_v2v2(co, v_curr);
- float len_next = len_v2v2(co, v_next);
- float edge_len = len_curr + len_next;
- for (i = 0; i < n; i++)
- w[i] = 0.0;
+ for (i = 0; i < n; i++) {
+ w[i] = 0.0f;
+ }
- w[i_curr] = len_next / edge_len;
- w[(i_curr + 1) % n] = len_curr / edge_len;
+ if (ix_flag & IS_POINT_IX) {
+ w[i_curr] = 1.0f;
+ }
+ else {
+ float fac = line_point_factor_v2(co, v_curr, v_next);
+ CLAMP(fac, 0.0f, 1.0f);
+ w[i_curr] = 1.0f - fac;
+ w[(i_curr + 1) % n] = fac;
+ }
}
else {
if (totweight != 0.0f) {
@@ -2778,6 +2837,15 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[
}
}
+#undef IS_POINT_IX
+#undef IS_SEGMENT_IX
+
+#undef DIR_V3_SET
+#undef DIR_V2_SET
+
+/** \} */
+
+
/* (x1, v1)(t1=0)------(x2, v2)(t2=1), 0<t<1 --> (x, v)(t) */
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)
{
@@ -3057,6 +3125,59 @@ void window_translate_m4(float winmat[4][4], float perspmat[4][4], const float x
}
}
+/**
+ * Frustum planes extraction from a projection matrix (homogeneous 4d vector representations of planes).
+ *
+ * plane parameters can be NULL if you do not need them.
+ */
+void planes_from_projmat(float mat[4][4], float left[4], float right[4], float top[4], float bottom[4],
+ float near[4], float far[4])
+{
+ /* References:
+ *
+ * https://fgiesen.wordpress.com/2012/08/31/frustum-planes-from-the-projection-matrix/
+ * http://www8.cs.umu.se/kurser/5DV051/HT12/lab/plane_extraction.pdf
+ */
+
+ int i;
+
+ if (left) {
+ for (i = 4; i--; ) {
+ left[i] = mat[i][3] + mat[i][0];
+ }
+ }
+
+ if (right) {
+ for (i = 4; i--; ) {
+ right[i] = mat[i][3] - mat[i][0];
+ }
+ }
+
+ if (bottom) {
+ for (i = 4; i--; ) {
+ bottom[i] = mat[i][3] + mat[i][1];
+ }
+ }
+
+ if (top) {
+ for (i = 4; i--; ) {
+ top[i] = mat[i][3] - mat[i][1];
+ }
+ }
+
+ if (near) {
+ for (i = 4; i--; ) {
+ near[i] = mat[i][3] + mat[i][2];
+ }
+ }
+
+ if (far) {
+ for (i = 4; i--; ) {
+ far[i] = mat[i][3] - mat[i][2];
+ }
+ }
+}
+
static void i_multmatrix(float icand[4][4], float Vm[4][4])
{
int row, col;
@@ -4016,3 +4137,31 @@ bool is_poly_convex_v2(const float verts[][2], unsigned int nr)
return true;
}
+
+/**
+ * Check if either of the diagonals along this quad create flipped triangles
+ * (normals pointing away from eachother).
+ * - (1 << 0): (v1-v3) is flipped.
+ * - (1 << 1): (v2-v4) is flipped.
+ */
+int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
+{
+ float d_12[3], d_23[3], d_34[3], d_41[3];
+ float cross_a[3], cross_b[3];
+ int ret = 0;
+
+ sub_v3_v3v3(d_12, v1, v2);
+ sub_v3_v3v3(d_23, v2, v3);
+ sub_v3_v3v3(d_34, v3, v4);
+ sub_v3_v3v3(d_41, v4, v1);
+
+ cross_v3_v3v3(cross_a, d_12, d_23);
+ cross_v3_v3v3(cross_b, d_34, d_41);
+ ret |= ((dot_v3v3(cross_a, cross_b) < 0.0f) << 0);
+
+ cross_v3_v3v3(cross_a, d_23, d_34);
+ cross_v3_v3v3(cross_b, d_41, d_12);
+ ret |= ((dot_v3v3(cross_a, cross_b) < 0.0f) << 1);
+
+ return ret;
+}
diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c
index 5a64ed63ecf..44b17681540 100644
--- a/source/blender/blenlib/intern/math_geom_inline.c
+++ b/source/blender/blenlib/intern/math_geom_inline.c
@@ -54,6 +54,12 @@ MINLINE float area_tri_v2(const float v1[2], const float v2[2], const float v3[2
return fabsf(area_tri_signed_v2(v1, v2, v3));
}
+MINLINE float area_squared_tri_v2(const float v1[2], const float v2[2], const float v3[2])
+{
+ float area = area_tri_signed_v2(v1, v2, v3);
+ return area * area;
+}
+
/****************************** Spherical Harmonics **************************/
MINLINE void zero_sh(float r[9])
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 0204c3bc86c..1b4bbafdb04 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -848,9 +848,10 @@ bool invert_m4_m4(float inverse[4][4], float mat[4][4])
}
}
- temp = tempmat[i][i];
- if (temp == 0)
- return 0; /* No non-zero pivot */
+ if (UNLIKELY(tempmat[i][i] == 0.0f)) {
+ return false; /* No non-zero pivot */
+ }
+ temp = (double)tempmat[i][i];
for (k = 0; k < 4; k++) {
tempmat[i][k] = (float)((double)tempmat[i][k] / temp);
inverse[i][k] = (float)((double)inverse[i][k] / temp);
@@ -865,7 +866,7 @@ bool invert_m4_m4(float inverse[4][4], float mat[4][4])
}
}
}
- return 1;
+ return true;
}
/****************************** Linear Algebra *******************************/
@@ -1149,11 +1150,11 @@ bool is_orthogonal_m3(float m[3][3])
for (i = 0; i < 3; i++) {
for (j = 0; j < i; j++) {
if (fabsf(dot_v3v3(m[i], m[j])) > 1.5f * FLT_EPSILON)
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
bool is_orthogonal_m4(float m[4][4])
@@ -1163,12 +1164,12 @@ bool is_orthogonal_m4(float m[4][4])
for (i = 0; i < 4; i++) {
for (j = 0; j < i; j++) {
if (fabsf(dot_v4v4(m[i], m[j])) > 1.5f * FLT_EPSILON)
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
bool is_orthonormal_m3(float m[3][3])
@@ -1178,12 +1179,12 @@ bool is_orthonormal_m3(float m[3][3])
for (i = 0; i < 3; i++)
if (fabsf(dot_v3v3(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON)
- return 0;
+ return false;
- return 1;
+ return true;
}
- return 0;
+ return false;
}
bool is_orthonormal_m4(float m[4][4])
@@ -1193,12 +1194,12 @@ bool is_orthonormal_m4(float m[4][4])
for (i = 0; i < 4; i++)
if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON)
- return 0;
+ return false;
- return 1;
+ return true;
}
- return 0;
+ return false;
}
bool is_uniform_scaled_m3(float m[3][3])
@@ -1448,7 +1449,7 @@ float mat3_to_scale(float mat[3][3])
{
/* unit length vector */
float unit_vec[3];
- copy_v3_fl(unit_vec, (float)(1.0 / M_SQRT3));
+ copy_v3_fl(unit_vec, (float)M_SQRT1_3);
mul_m3_v3(mat, unit_vec);
return len_v3(unit_vec);
}
@@ -1457,7 +1458,7 @@ float mat4_to_scale(float mat[4][4])
{
/* unit length vector */
float unit_vec[3];
- copy_v3_fl(unit_vec, (float)(1.0 / M_SQRT3));
+ copy_v3_fl(unit_vec, (float)M_SQRT1_3);
mul_mat3_m4_v3(mat, unit_vec);
return len_v3(unit_vec);
}
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 9a6515daf68..3ac031d7b90 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -1867,7 +1867,7 @@ float angle_wrap_deg(float angle)
/* returns an angle compatible with angle_compat */
float angle_compat_rad(float angle, float angle_compat)
{
- return angle + (floorf(((angle_compat - angle) / (float)M_PI) + 0.5f)) * (float)M_PI;
+ return angle_compat + angle_wrap_rad(angle - angle_compat);
}
/* axis conversion */
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index da9d5bd3f49..6b6a3113e0b 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -621,6 +621,18 @@ MINLINE float dot_v3v3(const float a[3], const float b[3])
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
+MINLINE float dot_v3v3v3(const float p[3], const float a[3], const float b[3])
+{
+ float vec1[3], vec2[3];
+
+ sub_v3_v3v3(vec1, a, p);
+ sub_v3_v3v3(vec2, b, p);
+ if (is_zero_v3(vec1) || is_zero_v3(vec2)) {
+ return 0.0f;
+ }
+ return dot_v3v3(vec1, vec2);
+}
+
MINLINE float dot_v4v4(const float a[4], const float b[4])
{
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index e3e13b0bcac..3fff22218e2 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -45,12 +45,6 @@
#include "BLI_string_utf8.h"
#include "BLI_fnmatch.h"
-#include "../blenkernel/BKE_blender.h" /* BLENDER_VERSION, bad level include (no function call) */
-
-#include "GHOST_Path-api.h"
-
-#include "MEM_guardedalloc.h"
-
#ifdef WIN32
# include "utf_winfunc.h"
# include "utfconv.h"
@@ -62,21 +56,12 @@
# include <windows.h>
# include <shlobj.h>
# include "BLI_winstuff.h"
-#else /* non windows */
-# ifdef WITH_BINRELOC
-# include "binreloc.h"
-# endif
-# include <unistd.h> /* mkdtemp on OSX (and probably all *BSD?), not worth making specific check for this OS. */
+# include "MEM_guardedalloc.h"
#endif /* WIN32 */
/* local */
#define UNIQUE_NAME_MAX 128
-static char bprogname[FILE_MAX]; /* full path to program executable */
-static char bprogdir[FILE_MAX]; /* full path to directory in which executable is located */
-static char btempdir_base[FILE_MAX]; /* persistent temporary directory */
-static char btempdir_session[FILE_MAX] = ""; /* volatile temporary directory */
-
/* implementation */
/**
@@ -243,7 +228,8 @@ bool BLI_uniquename_cb(bool (*unique_check)(void *arg, const char *name),
int number;
int len = BLI_split_name_num(left, &number, name, delim);
do {
- const int numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number);
+ /* add 1 to account for \0 */
+ const int numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number) + 1;
/* highly unlikely the string only has enough room for the number
* but support anyway */
@@ -253,9 +239,8 @@ bool BLI_uniquename_cb(bool (*unique_check)(void *arg, const char *name),
}
else {
char *tempname_buf;
- tempname[0] = '\0';
- tempname_buf = BLI_strncat_utf8(tempname, left, name_len - numlen);
- memcpy(tempname_buf, numstr, numlen + 1);
+ tempname_buf = tempname + BLI_strncpy_utf8_rlen(tempname, left, name_len - numlen);
+ memcpy(tempname_buf, numstr, numlen);
}
} while (unique_check(arg, tempname));
@@ -954,8 +939,6 @@ bool BLI_path_abs(char *path, const char *basepath)
BLI_strncpy(path, tmp, FILE_MAX);
}
- BLI_cleanup_path(NULL, path);
-
#ifdef WIN32
/* skip first two chars, which in case of
* absolute path will be drive:/blabla and
@@ -965,7 +948,10 @@ bool BLI_path_abs(char *path, const char *basepath)
*/
BLI_char_switch(path + 2, '/', '\\');
#endif
-
+
+ /* ensure this is after correcting for path switch */
+ BLI_cleanup_path(NULL, path);
+
return wasrelative;
}
@@ -1038,446 +1024,6 @@ void BLI_getlastdir(const char *dir, char *last, const size_t maxlen)
}
}
-/* This is now only used to really get the user's default document folder */
-/* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
- * as default location to save documents */
-const char *BLI_getDefaultDocumentFolder(void)
-{
-#ifndef WIN32
- const char * const xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR");
-
- if (xdg_documents_dir)
- return xdg_documents_dir;
-
- return getenv("HOME");
-#else /* Windows */
- static char documentfolder[MAXPATHLEN];
- HRESULT hResult;
-
- /* Check for %HOME% env var */
- if (uput_getenv("HOME", documentfolder, MAXPATHLEN)) {
- if (BLI_is_dir(documentfolder)) return documentfolder;
- }
-
- /* add user profile support for WIN 2K / NT.
- * This is %APPDATA%, which translates to either
- * %USERPROFILE%\Application Data or since Vista
- * to %USERPROFILE%\AppData\Roaming
- */
- hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
-
- if (hResult == S_OK) {
- if (BLI_is_dir(documentfolder)) return documentfolder;
- }
-
- return NULL;
-#endif /* WIN32 */
-}
-
-/* NEW stuff, to be cleaned up when fully migrated */
-/* ************************************************************* */
-/* ************************************************************* */
-
-// #define PATH_DEBUG
-
-/* returns a formatted representation of the specified version number. Non-reentrant! */
-static char *blender_version_decimal(const int ver)
-{
- static char version_str[5];
- sprintf(version_str, "%d.%02d", ver / 100, ver % 100);
- return version_str;
-}
-
-/**
- * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath,
- * returning true if result points to a directory.
- */
-static bool test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
-{
- char tmppath[FILE_MAX];
-
- if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
- else BLI_strncpy(tmppath, path_base, sizeof(tmppath));
-
- /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
- if (folder_name)
- BLI_make_file_string("/", targetpath, tmppath, folder_name);
- else
- BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
- /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile)
- * if folder_name is specified but not otherwise? */
-
- if (BLI_is_dir(targetpath)) {
-#ifdef PATH_DEBUG
- printf("\t%s found: %s\n", __func__, targetpath);
-#endif
- return true;
- }
- else {
-#ifdef PATH_DEBUG
- printf("\t%s missing: %s\n", __func__, targetpath);
-#endif
- //targetpath[0] = '\0';
- return false;
- }
-}
-
-/**
- * Puts the value of the specified environment variable into *path if it exists
- * and points at a directory. Returns true if this was done.
- */
-static bool test_env_path(char *path, const char *envvar)
-{
- const char *env = envvar ? getenv(envvar) : NULL;
- if (!env) return false;
-
- if (BLI_is_dir(env)) {
- BLI_strncpy(path, env, FILE_MAX);
-#ifdef PATH_DEBUG
- printf("\t%s env %s found: %s\n", __func__, envvar, env);
-#endif
- return true;
- }
- else {
- path[0] = '\0';
-#ifdef PATH_DEBUG
- printf("\t%s env %s missing: %s\n", __func__, envvar, env);
-#endif
- return false;
- }
-}
-
-/**
- * Constructs in \a targetpath the name of a directory relative to a version-specific
- * subdirectory in the parent directory of the Blender executable.
- *
- * \param targetpath String to return path
- * \param folder_name Optional folder name within version-specific directory
- * \param subfolder_name Optional subfolder name within folder_name
- * \param ver To construct name of version-specific directory within bprogdir
- * \return true if such a directory exists.
- */
-static bool get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
-{
- char relfolder[FILE_MAX];
-
-#ifdef PATH_DEBUG
- printf("%s...\n", __func__);
-#endif
-
- if (folder_name) {
- if (subfolder_name) {
- BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
- }
- else {
- BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
- }
- }
- else {
- relfolder[0] = '\0';
- }
-
- /* 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
-}
-
-/**
- * Is this an install with user files kept together with the Blender executable and its
- * installation files.
- */
-static bool is_portable_install(void)
-{
- /* detect portable install by the existence of config folder */
- const int ver = BLENDER_VERSION;
- char path[FILE_MAX];
-
- return get_path_local(path, "config", NULL, ver);
-}
-
-/**
- * Returns the path of a folder within the user-files area.
- *
- *
- * \param targetpath String to return path
- * \param folder_name default name of folder within user area
- * \param subfolder_name optional name of subfolder within folder
- * \param envvar name of environment variable which, if defined, overrides folder_name
- * \param ver Blender version, used to construct a subdirectory name
- * \return true if it was able to construct such a path.
- */
-static bool get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
-{
- char user_path[FILE_MAX];
- const char *user_base_path;
-
- /* for portable install, user path is always local */
- if (is_portable_install())
- return get_path_local(targetpath, folder_name, subfolder_name, ver);
-
- user_path[0] = '\0';
-
- if (test_env_path(user_path, envvar)) {
- if (subfolder_name) {
- return test_path(targetpath, user_path, NULL, subfolder_name);
- }
- else {
- BLI_strncpy(targetpath, user_path, FILE_MAX);
- return true;
- }
- }
-
- user_base_path = (const char *)GHOST_getUserDir(ver, blender_version_decimal(ver));
- if (user_base_path)
- BLI_strncpy(user_path, user_base_path, FILE_MAX);
-
- if (!user_path[0])
- return false;
-
-#ifdef PATH_DEBUG
- printf("%s: %s\n", __func__, user_path);
-#endif
-
- if (subfolder_name) {
- return test_path(targetpath, user_path, folder_name, subfolder_name);
- }
- else {
- return test_path(targetpath, user_path, NULL, folder_name);
- }
-}
-
-/**
- * Returns the path of a folder within the Blender installation directory.
- *
- * \param targetpath String to return path
- * \param folder_name default name of folder within installation area
- * \param subfolder_name optional name of subfolder within folder
- * \param envvar name of environment variable which, if defined, overrides folder_name
- * \param ver Blender version, used to construct a subdirectory name
- * \return true if it was able to construct such a path.
- */
-static bool get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
-{
- char system_path[FILE_MAX];
- const char *system_base_path;
- char cwd[FILE_MAX];
- char relfolder[FILE_MAX];
-
- if (folder_name) {
- if (subfolder_name) {
- BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
- }
- else {
- BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
- }
- }
- else {
- relfolder[0] = '\0';
- }
-
- /* first allow developer only overrides to the system path
- * these are only used when running blender from source */
-
- /* try CWD/release/folder_name */
- if (BLI_current_working_dir(cwd, sizeof(cwd))) {
- if (test_path(targetpath, cwd, "release", relfolder)) {
- return true;
- }
- }
-
- /* try EXECUTABLE_DIR/release/folder_name */
- if (test_path(targetpath, bprogdir, "release", relfolder))
- return true;
-
- /* end developer overrides */
-
-
-
- system_path[0] = '\0';
-
- if (test_env_path(system_path, envvar)) {
- if (subfolder_name) {
- return test_path(targetpath, system_path, NULL, subfolder_name);
- }
- else {
- BLI_strncpy(targetpath, system_path, FILE_MAX);
- return true;
- }
- }
-
- system_base_path = (const char *)GHOST_getSystemDir(ver, blender_version_decimal(ver));
- if (system_base_path)
- BLI_strncpy(system_path, system_base_path, FILE_MAX);
-
- if (!system_path[0])
- return false;
-
-#ifdef PATH_DEBUG
- printf("%s: %s\n", __func__, system_path);
-#endif
-
- if (subfolder_name) {
- /* try $BLENDERPATH/folder_name/subfolder_name */
- return test_path(targetpath, system_path, folder_name, subfolder_name);
- }
- else {
- /* try $BLENDERPATH/folder_name */
- return test_path(targetpath, system_path, NULL, folder_name);
- }
-}
-
-/* get a folder out of the 'folder_id' presets for paths */
-/* returns the path if found, NULL string if not */
-const char *BLI_get_folder(int folder_id, const char *subfolder)
-{
- const int ver = BLENDER_VERSION;
- static char path[FILE_MAX] = "";
-
- switch (folder_id) {
- case BLENDER_DATAFILES: /* general case */
- if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
- if (get_path_local(path, "datafiles", subfolder, ver)) break;
- if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
- return NULL;
-
- case BLENDER_USER_DATAFILES:
- if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
- return NULL;
-
- case BLENDER_SYSTEM_DATAFILES:
- if (get_path_local(path, "datafiles", subfolder, ver)) break;
- if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
- return NULL;
-
- case BLENDER_USER_AUTOSAVE:
- if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
- return NULL;
-
- case BLENDER_USER_CONFIG:
- if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
- return NULL;
-
- case BLENDER_USER_SCRIPTS:
- if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
- return NULL;
-
- case BLENDER_SYSTEM_SCRIPTS:
- if (get_path_local(path, "scripts", subfolder, ver)) break;
- if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
- return NULL;
-
- case BLENDER_SYSTEM_PYTHON:
- if (get_path_local(path, "python", subfolder, ver)) break;
- if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
- return NULL;
-
- default:
- BLI_assert(0);
- break;
- }
-
- return path;
-}
-
-/**
- * Returns the path to a folder in the user area without checking that it actually exists first.
- */
-const char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
-{
- const int ver = BLENDER_VERSION;
- static char path[FILE_MAX] = "";
-
- switch (folder_id) {
- case BLENDER_USER_DATAFILES:
- get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
- break;
- case BLENDER_USER_CONFIG:
- get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
- break;
- case BLENDER_USER_AUTOSAVE:
- get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
- break;
- case BLENDER_USER_SCRIPTS:
- get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- if ('\0' == path[0]) {
- return NULL;
- }
- return path;
-}
-
-/**
- * Returns the path to a folder in the user area, creating it if it doesn't exist.
- */
-const char *BLI_get_folder_create(int folder_id, const char *subfolder)
-{
- const char *path;
-
- /* only for user folders */
- 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);
-
- if (!path) {
- path = BLI_get_user_folder_notest(folder_id, subfolder);
- if (path) BLI_dir_create_recursive(path);
- }
-
- return path;
-}
-
-/**
- * Returns the path of the top-level version-specific local, user or system directory.
- * If do_check, then the result will be NULL if the directory doesn't exist.
- */
-const char *BLI_get_folder_version(const int id, const int ver, const bool do_check)
-{
- static char path[FILE_MAX] = "";
- bool ok;
- switch (id) {
- case BLENDER_RESOURCE_PATH_USER:
- ok = get_path_user(path, NULL, NULL, NULL, ver);
- break;
- case BLENDER_RESOURCE_PATH_LOCAL:
- ok = get_path_local(path, NULL, NULL, ver);
- break;
- case BLENDER_RESOURCE_PATH_SYSTEM:
- ok = get_path_system(path, NULL, NULL, NULL, ver);
- break;
- default:
- path[0] = '\0'; /* in case do_check is false */
- ok = false;
- BLI_assert(!"incorrect ID");
- break;
- }
-
- if (!ok && do_check) {
- return NULL;
- }
-
- return path;
-}
-
-/* End new stuff */
-/* ************************************************************* */
-/* ************************************************************* */
-
-
-
-#ifdef PATH_DEBUG
-# undef PATH_DEBUG
-#endif
/**
* Sets the specified environment variable to the specified value,
@@ -1541,18 +1087,22 @@ void BLI_char_switch(char *string, char from, char to)
}
/**
- * Strips off nonexistent subdirectories from the end of *dir, leaving the path of
- * the lowest-level directory that does exist.
+ * Strips off nonexistent (or non-accessible) subdirectories from the end of *dir, leaving the path of
+ * the lowest-level directory that does exist and we can read.
*/
void BLI_make_exist(char *dir)
{
int a;
+ char par_path[PATH_MAX + 3];
BLI_char_switch(dir, ALTSEP, SEP);
a = strlen(dir);
- while (!BLI_is_dir(dir)) {
+ for (BLI_join_dirfile(par_path, sizeof(par_path), dir, "..");
+ !(BLI_is_dir(dir) && BLI_exists(par_path));
+ BLI_join_dirfile(par_path, sizeof(par_path), dir, ".."))
+ {
a--;
while (dir[a] != SEP) {
a--;
@@ -1707,11 +1257,10 @@ bool BLI_testextensie_n(const char *str, ...)
while ((ext = (const char *) va_arg(args, void *))) {
if (testextensie_ex(str, str_len, ext, strlen(ext))) {
ret = true;
- goto finally;
+ break;
}
}
-finally:
va_end(args);
return ret;
@@ -2153,310 +1702,6 @@ void BLI_path_native_slash(char *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.
- */
-static int add_win32_extension(char *name)
-{
- int retval = 0;
- int type;
-
- type = BLI_exists(name);
- if ((type == 0) || S_ISDIR(type)) {
-#ifdef _WIN32
- char filename[FILE_MAX];
- char ext[FILE_MAX];
- const char *extensions = getenv("PATHEXT");
- if (extensions) {
- char *temp;
- do {
- strcpy(filename, name);
- temp = strstr(extensions, ";");
- if (temp) {
- strncpy(ext, extensions, temp - extensions);
- ext[temp - extensions] = 0;
- extensions = temp + 1;
- strcat(filename, ext);
- }
- else {
- strcat(filename, extensions);
- }
-
- type = BLI_exists(filename);
- if (type && (!S_ISDIR(type))) {
- retval = 1;
- strcpy(name, filename);
- break;
- }
- } while (temp);
- }
-#endif
- }
- else {
- retval = 1;
- }
-
- return (retval);
-}
-
-/**
- * Checks if name is a fully qualified filename to an executable.
- * If not it searches $PATH for the file. On Windows it also
- * adds the correct extension (.com .exe etc) from
- * $PATHEXT if necessary. Also on Windows it translates
- * the name to its 8.3 version to prevent problems with
- * spaces and stuff. Final result is returned in fullname.
- *
- * \param fullname The full path and full name of the executable
- * (must be FILE_MAX minimum)
- * \param name The name of the executable (usually argv[0]) to be checked
- */
-static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name)
-{
- char filename[FILE_MAX];
- const char *path = NULL, *temp;
-
-#ifdef _WIN32
- const char *separator = ";";
-#else
- const char *separator = ":";
-#endif
-
-
-#ifdef WITH_BINRELOC
- /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */
- path = br_find_exe(NULL);
- if (path) {
- BLI_strncpy(fullname, path, maxlen);
- free((void *)path);
- return;
- }
-#endif
-
-#ifdef _WIN32
- wchar_t *fullname_16 = MEM_mallocN(maxlen * sizeof(wchar_t), "ProgramPath");
- if (GetModuleFileNameW(0, fullname_16, maxlen)) {
- conv_utf_16_to_8(fullname_16, fullname, maxlen);
- if (!BLI_exists(fullname)) {
- printf("path can't be found: \"%.*s\"\n", (int)maxlen, fullname);
- MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
- }
- MEM_freeN(fullname_16);
- return;
- }
-
- MEM_freeN(fullname_16);
-#endif
-
- /* unix and non linux */
- if (name && name[0]) {
-
- BLI_strncpy(fullname, name, maxlen);
- if (name[0] == '.') {
- char wdir[FILE_MAX] = "";
- BLI_current_working_dir(wdir, sizeof(wdir)); /* backup cwd to restore after */
-
- // not needed but avoids annoying /./ in name
- if (name[1] == SEP)
- BLI_join_dirfile(fullname, maxlen, wdir, name + 2);
- else
- BLI_join_dirfile(fullname, maxlen, wdir, name);
-
- add_win32_extension(fullname); /* XXX, doesnt respect length */
- }
- else if (BLI_last_slash(name)) {
- // full path
- BLI_strncpy(fullname, name, maxlen);
- add_win32_extension(fullname);
- }
- else {
- // search for binary in $PATH
- path = getenv("PATH");
- if (path) {
- do {
- temp = strstr(path, separator);
- if (temp) {
- strncpy(filename, path, temp - path);
- filename[temp - path] = 0;
- path = temp + 1;
- }
- else {
- strncpy(filename, path, sizeof(filename));
- }
- BLI_path_append(fullname, maxlen, name);
- if (add_win32_extension(filename)) {
- BLI_strncpy(fullname, filename, maxlen);
- break;
- }
- } while (temp);
- }
- }
-#if defined(DEBUG)
- if (strcmp(name, fullname)) {
- printf("guessing '%s' == '%s'\n", name, fullname);
- }
-#endif
- }
-}
-
-void BLI_init_program_path(const char *argv0)
-{
- bli_where_am_i(bprogname, sizeof(bprogname), argv0);
- BLI_split_dir_part(bprogname, bprogdir, sizeof(bprogdir));
-}
-
-/**
- * Path to executable
- */
-const char *BLI_program_path(void)
-{
- return bprogname;
-}
-
-/**
- * Path to directory of executable
- */
-const char *BLI_program_dir(void)
-{
- return bprogdir;
-}
-
-/**
- * Gets the temp directory when blender first runs.
- * If the default path is not found, use try $TEMP
- *
- * Also make sure the temp dir has a trailing slash
- *
- * \param fullname The full path to the temporary temp directory
- * \param basename The full path to the persistent temp directory (may be NULL)
- * \param maxlen The size of the fullname buffer
- * \param userdir Directory specified in user preferences
- */
-static void BLI_where_is_temp(char *fullname, char *basename, const size_t maxlen, char *userdir)
-{
- /* Clear existing temp dir, if needed. */
- BLI_temp_dir_session_purge();
-
- fullname[0] = '\0';
- if (basename) {
- basename[0] = '\0';
- }
-
- if (userdir && BLI_is_dir(userdir)) {
- BLI_strncpy(fullname, userdir, maxlen);
- }
-
-
-#ifdef WIN32
- if (fullname[0] == '\0') {
- const char *tmp = getenv("TEMP"); /* Windows */
- if (tmp && BLI_is_dir(tmp)) {
- BLI_strncpy(fullname, tmp, maxlen);
- }
- }
-#else
- /* Other OS's - Try TMP and TMPDIR */
- if (fullname[0] == '\0') {
- const char *tmp = getenv("TMP");
- if (tmp && BLI_is_dir(tmp)) {
- BLI_strncpy(fullname, tmp, maxlen);
- }
- }
-
- if (fullname[0] == '\0') {
- const char *tmp = getenv("TMPDIR");
- if (tmp && BLI_is_dir(tmp)) {
- BLI_strncpy(fullname, tmp, maxlen);
- }
- }
-#endif
-
- if (fullname[0] == '\0') {
- BLI_strncpy(fullname, "/tmp/", maxlen);
- }
- else {
- /* add a trailing slash if needed */
- BLI_add_slash(fullname);
-#ifdef WIN32
- if (userdir && userdir != fullname) {
- BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
- }
-#endif
- }
-
- /* Now that we have a valid temp dir, add system-generated unique sub-dir. */
- if (basename) {
- /* 'XXXXXX' is kind of tag to be replaced by mktemp-familly by an uuid. */
- char *tmp_name = BLI_strdupcat(fullname, "blender_XXXXXX");
- const size_t ln = strlen(tmp_name) + 1;
- if (ln <= maxlen) {
-#ifdef WIN32
- if (_mktemp_s(tmp_name, ln) == 0) {
- BLI_dir_create_recursive(tmp_name);
- }
-#else
- mkdtemp(tmp_name);
-#endif
- }
- if (BLI_is_dir(tmp_name)) {
- BLI_strncpy(basename, fullname, maxlen);
- BLI_strncpy(fullname, tmp_name, maxlen);
- BLI_add_slash(fullname);
- }
- else {
- printf("Warning! Could not generate a temp file name for '%s', falling back to '%s'\n", tmp_name, fullname);
- }
-
- MEM_freeN(tmp_name);
- }
-}
-
-/**
- * Sets btempdir_base to userdir if specified and is a valid directory, otherwise
- * chooses a suitable OS-specific temporary directory.
- * Sets btempdir_session to a mkdtemp-generated sub-dir of btempdir_base.
- */
-void BLI_temp_dir_init(char *userdir)
-{
- BLI_where_is_temp(btempdir_session, btempdir_base, FILE_MAX, userdir);
-;
-}
-
-/**
- * Path to temporary directory (with trailing slash)
- */
-const char *BLI_temp_dir_session(void)
-{
- return btempdir_session[0] ? btempdir_session : BLI_temp_dir_base();
-}
-
-/**
- * Path to persistent temporary directory (with trailing slash)
- */
-const char *BLI_temp_dir_base(void)
-{
- return btempdir_base;
-}
-
-/**
- * Path to the system temporary directory (with trailing slash)
- */
-void BLI_system_temporary_dir(char *dir)
-{
- BLI_where_is_temp(dir, NULL, FILE_MAX, NULL);
-}
-
-/**
- * Delete content of this instance's temp dir.
- */
-void BLI_temp_dir_session_purge(void)
-{
- if (btempdir_session[0] && BLI_is_dir(btempdir_session)) {
- BLI_delete(btempdir_session, true, true);
- }
-}
#ifdef WITH_ICONV
diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c
index 16cf7ff960b..3aadbe5f1df 100644
--- a/source/blender/blenlib/intern/polyfill2d.c
+++ b/source/blender/blenlib/intern/polyfill2d.c
@@ -165,7 +165,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip);
static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip);
-BLI_INLINE eSign signum_i(float a)
+BLI_INLINE eSign signum_enum(float a)
{
if (UNLIKELY(a == 0.0f))
return 0;
@@ -191,7 +191,7 @@ BLI_INLINE float area_tri_signed_v2_alt_2x(const float v1[2], const float v2[2],
static eSign span_tri_v2_sign(const float v1[2], const float v2[2], const float v3[2])
{
- return signum_i(area_tri_signed_v2_alt_2x(v3, v2, v1));
+ return signum_enum(area_tri_signed_v2_alt_2x(v3, v2, v1));
}
diff --git a/source/blender/blenlib/intern/polyfill2d_beautify.c b/source/blender/blenlib/intern/polyfill2d_beautify.c
new file mode 100644
index 00000000000..7914b7cb39b
--- /dev/null
+++ b/source/blender/blenlib/intern/polyfill2d_beautify.c
@@ -0,0 +1,490 @@
+/*
+ * ***** 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/blenlib/intern/polyfill2d_beautify.c
+ * \ingroup bli
+ *
+ * This function is to improve the tessellation resulting from polyfill2d,
+ * creating optimal topology.
+ *
+ * The functionality here matches #BM_mesh_beautify_fill,
+ * but its far simpler to perform this operation in 2d,
+ * on a simple polygon representation where we _know_:
+ *
+ * - The polygon is primitive with no holes with a continuous boundary.
+ * - Tris have consistent winding.
+ * - 2d (saves some hassles projecting face pairs on an axis for every edge-rotation)
+ * also saves us having to store all previous edge-states (see #EdRotState in bmesh_beautify.c)
+ *
+ * \note
+ *
+ * No globals - keep threadsafe.
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "BLI_memarena.h"
+#include "BLI_edgehash.h"
+#include "BLI_heap.h"
+
+#include "BLI_polyfill2d_beautify.h" /* own include */
+
+#include "BLI_strict_flags.h"
+
+struct PolyEdge {
+ /** ordered vert indices (smaller first) */
+ unsigned int verts[2];
+ /** ordered face indices (depends on winding compared to the edge verts)
+ * - (verts[0], verts[1]) == faces[0]
+ * - (verts[1], verts[0]) == faces[1]
+ */
+ unsigned int faces[2];
+ /**
+ * The face-index which isn't used by either of the edges verts [0 - 2].
+ * could be calculated each time, but cleaner to store for reuse.
+ */
+ unsigned int faces_other_v[2];
+};
+
+
+#ifndef NDEBUG
+/**
+ * Only to check for error-cases.
+ */
+static void polyfill_validate_tri(unsigned int (*tris)[3], unsigned int tri_index, EdgeHash *ehash)
+{
+ const unsigned int *tri = tris[tri_index];
+ int j_curr;
+
+ BLI_assert(!ELEM(tri[0], tri[1], tri[2]) &&
+ !ELEM(tri[1], tri[0], tri[2]) &&
+ !ELEM(tri[2], tri[0], tri[1]));
+
+ for (j_curr = 0; j_curr < 3; j_curr++) {
+ struct PolyEdge *e;
+ unsigned int e_v1 = tri[(j_curr ) ];
+ unsigned int e_v2 = tri[(j_curr + 1) % 3];
+ e = BLI_edgehash_lookup(ehash, e_v1, e_v2);
+ if (e) {
+ if (e->faces[0] == tri_index) {
+ BLI_assert(e->verts[0] == e_v1);
+ BLI_assert(e->verts[1] == e_v2);
+ }
+ else if (e->faces[1] == tri_index) {
+ BLI_assert(e->verts[0] == e_v2);
+ BLI_assert(e->verts[1] == e_v1);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ BLI_assert(e->faces[0] != e->faces[1]);
+ BLI_assert(ELEM(e_v1, UNPACK3(tri)));
+ BLI_assert(ELEM(e_v2, UNPACK3(tri)));
+ BLI_assert(ELEM(e_v1, UNPACK2(e->verts)));
+ BLI_assert(ELEM(e_v2, UNPACK2(e->verts)));
+ BLI_assert(e_v1 != tris[e->faces[0]][e->faces_other_v[0]]);
+ BLI_assert(e_v1 != tris[e->faces[1]][e->faces_other_v[1]]);
+ BLI_assert(e_v2 != tris[e->faces[0]][e->faces_other_v[0]]);
+ BLI_assert(e_v2 != tris[e->faces[1]][e->faces_other_v[1]]);
+
+ BLI_assert(ELEM(tri_index, UNPACK2(e->faces)));
+ }
+ }
+}
+#endif
+
+BLI_INLINE bool is_boundary_edge(unsigned int i_a, unsigned int i_b, const unsigned int coord_last)
+{
+ BLI_assert(i_a < i_b);
+ return ((i_a + 1 == i_b) || UNLIKELY((i_a == 0) && (i_b == coord_last)));
+}
+/**
+ * Assuming we have 2 triangles sharing an edge (2 - 4),
+ * check if the edge running from (1 - 3) gives better results.
+ *
+ * \return (negative number means the edge can be rotated, lager == better).
+ */
+float BLI_polyfill_beautify_quad_rotate_calc(
+ const float v1[2], const float v2[2], const float v3[2], const float v4[2])
+{
+ /* not a loop (only to be able to break out) */
+ do {
+ bool is_zero_a, is_zero_b;
+
+ const float area_2x_234 = cross_tri_v2(v2, v3, v4);
+ const float area_2x_241 = cross_tri_v2(v2, v4, v1);
+
+ const float area_2x_123 = cross_tri_v2(v1, v2, v3);
+ const float area_2x_134 = cross_tri_v2(v1, v3, v4);
+
+ {
+ 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 = (fabsf(area_2x_234) <= FLT_EPSILON);
+ is_zero_b = (fabsf(area_2x_241) <= FLT_EPSILON);
+
+ if (is_zero_a && is_zero_b) {
+ break;
+ }
+ }
+
+ /* one of the tri's was degenerate, check we're not rotating
+ * into a different degenerate shape or flipping the face */
+ if ((fabsf(area_2x_123) <= FLT_EPSILON) || (fabsf(area_2x_134) <= FLT_EPSILON)) {
+ /* one of the new rotations is degenerate */
+ break;
+ }
+
+ if ((area_2x_123 >= 0.0f) != (area_2x_134 >= 0.0f)) {
+ /* rotation would cause flipping */
+ break;
+ }
+
+ {
+ /* testing rule: the area divided by the perimeter,
+ * check if (1-3) beats the existing (2-4) edge rotation */
+ float area_a, area_b;
+ float prim_a, prim_b;
+ float fac_24, fac_13;
+
+ float len_12, len_23, len_34, len_41, len_24, len_13;
+
+ /* edges around the quad */
+ len_12 = len_v2v2(v1, v2);
+ len_23 = len_v2v2(v2, v3);
+ len_34 = len_v2v2(v3, v4);
+ len_41 = len_v2v2(v4, v1);
+ /* edges crossing the quad interior */
+ len_13 = len_v2v2(v1, v3);
+ len_24 = len_v2v2(v2, v4);
+
+ /* note, area is in fact (area * 2),
+ * but in this case its OK, since we're comparing ratios */
+
+ /* edge (2-4), current state */
+ area_a = fabsf(area_2x_234);
+ area_b = fabsf(area_2x_241);
+ prim_a = len_23 + len_34 + len_24;
+ prim_b = len_41 + len_12 + len_24;
+ fac_24 = (area_a / prim_a) + (area_b / prim_b);
+
+ /* edge (1-3), new state */
+ area_a = fabsf(area_2x_123);
+ area_b = fabsf(area_2x_134);
+ prim_a = len_12 + len_23 + len_13;
+ prim_b = len_34 + len_41 + len_13;
+ fac_13 = (area_a / prim_a) + (area_b / prim_b);
+
+ /* negative number if (1-3) is an improved state */
+ return fac_24 - fac_13;
+ }
+ } while (false);
+
+ return FLT_MAX;
+}
+
+static float polyedge_rotate_beauty_calc(
+ const float (*coords)[2],
+ const unsigned int (*tris)[3],
+ const struct PolyEdge *e)
+{
+ const float *v1, *v2, *v3, *v4;
+
+ v1 = coords[tris[e->faces[0]][e->faces_other_v[0]]];
+ v3 = coords[tris[e->faces[1]][e->faces_other_v[1]]];
+ v2 = coords[e->verts[0]];
+ v4 = coords[e->verts[1]];
+
+ return BLI_polyfill_beautify_quad_rotate_calc(v1, v2, v3, v4);
+}
+
+static void polyedge_beauty_cost_update_single(
+ const float (*coords)[2],
+ const unsigned int (*tris)[3],
+ const struct PolyEdge *edges,
+ struct PolyEdge *e,
+ Heap *eheap, HeapNode **eheap_table)
+{
+ const unsigned int i = (unsigned int)(e - edges);
+
+ if (eheap_table[i]) {
+ BLI_heap_remove(eheap, eheap_table[i]);
+ eheap_table[i] = NULL;
+ }
+
+ {
+ /* recalculate edge */
+ const float cost = polyedge_rotate_beauty_calc(coords, tris, e);
+ if (cost < 0.0f) {
+ eheap_table[i] = BLI_heap_insert(eheap, cost, e);
+ }
+ else {
+ eheap_table[i] = NULL;
+ }
+ }
+}
+
+static void polyedge_beauty_cost_update(
+ const float (*coords)[2],
+ const unsigned int (*tris)[3],
+ const struct PolyEdge *edges,
+ struct PolyEdge *e,
+ Heap *eheap, HeapNode **eheap_table,
+ EdgeHash *ehash)
+{
+ const unsigned int *tri_0 = tris[e->faces[0]];
+ const unsigned int *tri_1 = tris[e->faces[1]];
+ unsigned int i;
+
+ struct PolyEdge *e_arr[4] = {
+ BLI_edgehash_lookup(ehash,
+ tri_0[(e->faces_other_v[0] ) % 3],
+ tri_0[(e->faces_other_v[0] + 1) % 3]),
+ BLI_edgehash_lookup(ehash,
+ tri_0[(e->faces_other_v[0] + 2) % 3],
+ tri_0[(e->faces_other_v[0] ) % 3]),
+ BLI_edgehash_lookup(ehash,
+ tri_1[(e->faces_other_v[1] ) % 3],
+ tri_1[(e->faces_other_v[1] + 1) % 3]),
+ BLI_edgehash_lookup(ehash,
+ tri_1[(e->faces_other_v[1] + 2) % 3],
+ tri_1[(e->faces_other_v[1] ) % 3]),
+ };
+
+
+ for (i = 0; i < 4; i++) {
+ if (e_arr[i]) {
+ BLI_assert(!(ELEM(e_arr[i]->faces[0], UNPACK2(e->faces)) &&
+ ELEM(e_arr[i]->faces[1], UNPACK2(e->faces))));
+
+ polyedge_beauty_cost_update_single(
+ coords, tris, edges,
+ e_arr[i],
+ eheap, eheap_table);
+ }
+ }
+}
+
+static void polyedge_rotate(
+ unsigned int (*tris)[3],
+ struct PolyEdge *e,
+ EdgeHash *ehash)
+{
+ unsigned int e_v1_new = tris[e->faces[0]][e->faces_other_v[0]];
+ unsigned int e_v2_new = tris[e->faces[1]][e->faces_other_v[1]];
+
+#ifndef NDEBUG
+ polyfill_validate_tri(tris, e->faces[0], ehash);
+ polyfill_validate_tri(tris, e->faces[1], ehash);
+#endif
+
+ BLI_assert(e_v1_new != e_v2_new);
+ BLI_assert(!ELEM(e_v2_new, UNPACK3(tris[e->faces[0]])));
+ BLI_assert(!ELEM(e_v1_new, UNPACK3(tris[e->faces[1]])));
+
+ tris[e->faces[0]][(e->faces_other_v[0] + 1) % 3] = e_v2_new;
+ tris[e->faces[1]][(e->faces_other_v[1] + 1) % 3] = e_v1_new;
+
+ e->faces_other_v[0] = (e->faces_other_v[0] + 2) % 3;
+ e->faces_other_v[1] = (e->faces_other_v[1] + 2) % 3;
+
+ BLI_assert((tris[e->faces[0]][e->faces_other_v[0]] != e_v1_new) &&
+ (tris[e->faces[0]][e->faces_other_v[0]] != e_v2_new));
+ BLI_assert((tris[e->faces[1]][e->faces_other_v[1]] != e_v1_new) &&
+ (tris[e->faces[1]][e->faces_other_v[1]] != e_v2_new));
+
+ BLI_edgehash_remove(ehash, e->verts[0], e->verts[1], NULL);
+ BLI_edgehash_insert(ehash, e_v1_new, e_v2_new, e);
+
+ if (e_v1_new < e_v2_new) {
+ e->verts[0] = e_v1_new;
+ e->verts[1] = e_v2_new;
+ }
+ else {
+ /* maintain winding info */
+ e->verts[0] = e_v2_new;
+ e->verts[1] = e_v1_new;
+
+ SWAP(unsigned int, e->faces[0], e->faces[1]);
+ SWAP(unsigned int, e->faces_other_v[0], e->faces_other_v[1]);
+ }
+
+ /* update adjacent data */
+ {
+ unsigned int e_side = 0;
+
+ for (e_side = 0; e_side < 2; e_side++) {
+ /* 't_other' which we need to swap out is always the same edge-order */
+ const unsigned int t_other = (((e->faces_other_v[e_side]) + 2)) % 3;
+ unsigned int t_index = e->faces[e_side];
+ unsigned int t_index_other = e->faces[!e_side];
+ unsigned int *tri = tris[t_index];
+
+ struct PolyEdge *e_other;
+ unsigned int e_v1 = tri[(t_other ) ];
+ unsigned int e_v2 = tri[(t_other + 1) % 3];
+
+ e_other = BLI_edgehash_lookup(ehash, e_v1, e_v2);
+ if (e_other) {
+ BLI_assert(t_index != e_other->faces[0] && t_index != e_other->faces[1]);
+ if (t_index_other == e_other->faces[0]) {
+ e_other->faces[0] = t_index;
+ e_other->faces_other_v[0] = (t_other + 2) % 3;
+ BLI_assert(!ELEM(tri[e_other->faces_other_v[0]], e_v1, e_v2));
+ }
+ else if (t_index_other == e_other->faces[1]) {
+ e_other->faces[1] = t_index;
+ e_other->faces_other_v[1] = (t_other + 2) % 3;
+ BLI_assert(!ELEM(tri[e_other->faces_other_v[1]], e_v1, e_v2));
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ }
+ }
+
+#ifndef NDEBUG
+ polyfill_validate_tri(tris, e->faces[0], ehash);
+ polyfill_validate_tri(tris, e->faces[1], ehash);
+#endif
+
+ BLI_assert(!ELEM(tris[e->faces[0]][e->faces_other_v[0]], UNPACK2(e->verts)));
+ BLI_assert(!ELEM(tris[e->faces[1]][e->faces_other_v[1]], UNPACK2(e->verts)));
+}
+
+/**
+ * The intention is that this calculates the output of #BLI_polyfill_calc
+ *
+ *
+ * \note assumes the \a coords form a boundary,
+ * so any edges running along contiguous (wrapped) indices,
+ * are ignored since the edges wont share 2 faces.
+ */
+void BLI_polyfill_beautify(
+ const float (*coords)[2],
+ const unsigned int coords_tot,
+ unsigned int (*tris)[3],
+
+ /* structs for reuse */
+ MemArena *arena, Heap *eheap, EdgeHash *ehash)
+{
+ const unsigned int coord_last = coords_tot - 1;
+ const unsigned int tris_tot = coords_tot - 2;
+ /* internal edges only (between 2 tris) */
+ const unsigned int edges_tot = tris_tot - 1;
+ unsigned int edges_tot_used = 0;
+ unsigned int i;
+
+ HeapNode **eheap_table;
+
+ struct PolyEdge *edges = BLI_memarena_alloc(arena, edges_tot * sizeof(*edges));
+
+ BLI_assert(BLI_heap_size(eheap) == 0);
+ BLI_assert(BLI_edgehash_size(ehash) == 0);
+
+ /* first build edges */
+ for (i = 0; i < tris_tot; i++) {
+ unsigned int j_prev, j_curr, j_next;
+ j_prev = 2;
+ j_next = 1;
+ for (j_curr = 0; j_curr < 3; j_next = j_prev, j_prev = j_curr++) {
+ int e_index;
+
+ unsigned int e_pair[2] = {
+ tris[i][j_prev],
+ tris[i][j_curr],
+ };
+
+ if (e_pair[0] > e_pair[1]) {
+ SWAP(unsigned int, e_pair[0], e_pair[1]);
+ e_index = 1;
+ }
+ else {
+ e_index = 0;
+ }
+
+ if (!is_boundary_edge(e_pair[0], e_pair[1], coord_last)) {
+ struct PolyEdge *e = BLI_edgehash_lookup(ehash, e_pair[0], e_pair[1]);
+ if (e == NULL) {
+ e = &edges[edges_tot_used++];
+ BLI_edgehash_insert(ehash, e_pair[0], e_pair[1], e);
+ memcpy(e->verts, e_pair, sizeof(e->verts));
+#ifndef NDEBUG
+ e->faces[!e_index] = (unsigned int)-1;
+#endif
+ }
+ else {
+
+ /* ensure each edge only ever has 2x users */
+#ifndef NDEBUG
+ BLI_assert(e->faces[e_index] == (unsigned int)-1);
+ BLI_assert((e->verts[0] == e_pair[0]) &&
+ (e->verts[1] == e_pair[1]));
+#endif
+ }
+
+ e->faces[e_index] = i;
+ e->faces_other_v[e_index] = j_next;
+ }
+ }
+ }
+
+ /* now perform iterative rotations */
+ eheap_table = BLI_memarena_alloc(arena, sizeof(HeapNode *) * (size_t)edges_tot);
+
+ // for (i = 0; i < tris_tot; i++) { polyfill_validate_tri(tris, i, eh); }
+
+ /* build heap */
+ for (i = 0; i < edges_tot; i++) {
+ struct PolyEdge *e = &edges[i];
+ const float cost = polyedge_rotate_beauty_calc(coords, (const unsigned int (*)[3])tris, e);
+ if (cost < 0.0f) {
+ eheap_table[i] = BLI_heap_insert(eheap, cost, e);
+ }
+ else {
+ eheap_table[i] = NULL;
+ }
+ }
+
+ while (BLI_heap_is_empty(eheap) == false) {
+ struct PolyEdge *e = BLI_heap_popmin(eheap);
+ i = (unsigned int)(e - edges);
+ eheap_table[i] = NULL;
+
+ polyedge_rotate(tris, e, ehash);
+
+ /* recalculate faces connected on the heap */
+ polyedge_beauty_cost_update(
+ coords, (const unsigned int (*)[3])tris, edges,
+ e,
+ eheap, eheap_table, ehash);
+ }
+
+ BLI_heap_clear(eheap, NULL);
+ BLI_edgehash_clear_ex(ehash, NULL, BLI_POLYFILL_ALLOC_NGON_RESERVE);
+
+ /* MEM_freeN(eheap_table); */ /* arena */
+}
diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c
index 59ccf381f29..7657cec8cfd 100644
--- a/source/blender/blenlib/intern/rand.c
+++ b/source/blender/blenlib/intern/rand.c
@@ -144,6 +144,31 @@ void BLI_rng_get_float_unit_v3(RNG *rng, float v[3])
}
}
+/**
+ * Generate a random point inside given tri.
+ */
+void BLI_rng_get_tri_sample_float_v2(
+ RNG *rng, const float v1[2], const float v2[2], const float v3[2],
+ float r_pt[2])
+{
+ float u = BLI_rng_get_float(rng);
+ float v = BLI_rng_get_float(rng);
+
+ float side_u[2], side_v[2];
+
+ if ((u + v) > 1.0f) {
+ u = 1.0f - u;
+ v = 1.0f - v;
+ }
+
+ sub_v2_v2v2(side_u, v2, v1);
+ sub_v2_v2v2(side_v, v3, v1);
+
+ copy_v2_v2(r_pt, v1);
+ madd_v2_v2fl(r_pt, side_u, u);
+ madd_v2_v2fl(r_pt, side_v, v);
+}
+
void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_tot)
{
const size_t elem_size = (unsigned int)elem_size_i;
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index 1653ba5ae6e..8a96daeeb91 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -173,13 +173,13 @@ static bool boundisect(PolyFill *pf2, PolyFill *pf1)
/* has pf2 been touched (intersected) by pf1 ? with bounding box */
/* test first if polys exist */
- if (pf1->edges == 0 || pf2->edges == 0) return 0;
+ if (pf1->edges == 0 || pf2->edges == 0) return false;
- if (pf2->max_xy[0] < pf1->min_xy[0]) return 0;
- if (pf2->max_xy[1] < pf1->min_xy[1]) return 0;
+ if (pf2->max_xy[0] < pf1->min_xy[0]) return false;
+ if (pf2->max_xy[1] < pf1->min_xy[1]) return false;
- if (pf2->min_xy[0] > pf1->max_xy[0]) return 0;
- if (pf2->min_xy[1] > pf1->max_xy[1]) return 0;
+ if (pf2->min_xy[0] > pf1->max_xy[0]) return false;
+ if (pf2->min_xy[1] > pf1->max_xy[1]) return false;
/* join */
if (pf2->max_xy[0] < pf1->max_xy[0]) pf2->max_xy[0] = pf1->max_xy[0];
@@ -188,7 +188,7 @@ static bool boundisect(PolyFill *pf2, PolyFill *pf1)
if (pf2->min_xy[0] > pf1->min_xy[0]) pf2->min_xy[0] = pf1->min_xy[0];
if (pf2->min_xy[1] > pf1->min_xy[1]) pf2->min_xy[1] = pf1->min_xy[1];
- return 1;
+ return true;
}
@@ -225,13 +225,13 @@ static bool testedgeside(const float v1[2], const float v2[2], const float v3[2]
(v1[1] - v2[1]) * (v1[0] - v3[0]);
if (inp < 0.0f) {
- return 0;
+ return false;
}
else if (inp == 0.0f) {
- if (v1[0] == v3[0] && v1[1] == v3[1]) return 0;
- if (v2[0] == v3[0] && v2[1] == v3[1]) return 0;
+ if (v1[0] == v3[0] && v1[1] == v3[1]) return false;
+ if (v2[0] == v3[0] && v2[1] == v3[1]) return false;
}
- return 1;
+ return true;
}
static bool addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed)
@@ -261,7 +261,7 @@ static bool addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed)
for (ed = sc->edge_first; ed; ed = ed->next) {
if (ed->v2 == eed->v2) {
- return 0;
+ return false;
}
fac = ed->v2->xy[1] - y;
@@ -279,7 +279,7 @@ static bool addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed)
if (ed) BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed, eed);
else BLI_addtail((ListBase *)&(sc->edge_first), eed);
- return 1;
+ return true;
}
@@ -341,10 +341,10 @@ static bool boundinsideEV(ScanFillEdge *eed, ScanFillVert *eve)
maxy = eed->v1->xy[1];
}
if (eve->xy[1] >= miny && eve->xy[1] <= maxy) {
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
diff --git a/source/blender/blenlib/intern/scanfill_utils.c b/source/blender/blenlib/intern/scanfill_utils.c
index 029e98bad5e..a606ac41aa1 100644
--- a/source/blender/blenlib/intern/scanfill_utils.c
+++ b/source/blender/blenlib/intern/scanfill_utils.c
@@ -76,7 +76,7 @@ typedef struct ScanFillIsect {
#if 0
-void BKE_scanfill_obj_dump(ScanFillContext *sf_ctx)
+void BLI_scanfill_obj_dump(ScanFillContext *sf_ctx)
{
FILE *f = fopen("test.obj", "w");
unsigned int i = 1;
@@ -96,7 +96,7 @@ void BKE_scanfill_obj_dump(ScanFillContext *sf_ctx)
#endif
#if 0
-void BKE_scanfill_view3d_dump(ScanFillContext *sf_ctx)
+void BLI_scanfill_view3d_dump(ScanFillContext *sf_ctx)
{
ScanFillEdge *eed;
@@ -136,8 +136,8 @@ static int edge_isect_ls_sort_cb(void *thunk, const void *def_a_ptr, const void
{
const float *co = thunk;
- const ScanFillIsect *i_a = ((LinkData *)def_a_ptr)->data;
- const ScanFillIsect *i_b = ((LinkData *)def_b_ptr)->data;
+ const ScanFillIsect *i_a = ((const LinkData *)def_a_ptr)->data;
+ const ScanFillIsect *i_b = ((const LinkData *)def_b_ptr)->data;
const float a = len_squared_v2v2(co, i_a->co);
const float b = len_squared_v2v2(co, i_b->co);
@@ -508,8 +508,8 @@ bool BLI_scanfill_calc_self_isect(
sf_ctx->poly_nr = SF_POLY_UNSET;
#if 0
- BKE_scanfill_view3d_dump(sf_ctx);
- BKE_scanfill_obj_dump(sf_ctx);
+ BLI_scanfill_view3d_dump(sf_ctx);
+ BLI_scanfill_obj_dump(sf_ctx);
#endif
return changed;
diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c
index 0cf9f69b9ae..ba336ab6c4b 100644
--- a/source/blender/blenlib/intern/smallhash.c
+++ b/source/blender/blenlib/intern/smallhash.c
@@ -118,7 +118,7 @@ BLI_INLINE void smallhash_buckets_reserve(SmallHash *sh, const unsigned int nent
}
}
-BLI_INLINE SmallHashEntry *smallhash_lookup(SmallHash *sh, const uintptr_t key)
+BLI_INLINE SmallHashEntry *smallhash_lookup(const SmallHash *sh, const uintptr_t key)
{
SmallHashEntry *e;
unsigned int h = smallhash_key(key);
@@ -246,6 +246,26 @@ void BLI_smallhash_insert(SmallHash *sh, uintptr_t key, void *val)
e->val = val;
}
+/**
+ * Inserts a new value to a key that may already be in ghash.
+ *
+ * Avoids #BLI_smallhash_remove, #BLI_smallhash_insert calls (double lookups)
+ *
+ * \returns true if a new key has been added.
+ */
+bool BLI_smallhash_reinsert(SmallHash *sh, uintptr_t key, void *item)
+{
+ SmallHashEntry *e = smallhash_lookup(sh, key);
+ if (e) {
+ e->val = item;
+ return false;
+ }
+ else {
+ BLI_smallhash_insert(sh, key, item);
+ return true;
+ }
+}
+
#ifdef USE_REMOVE
bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key)
{
@@ -264,33 +284,33 @@ bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key)
}
#endif
-void *BLI_smallhash_lookup(SmallHash *sh, uintptr_t key)
+void *BLI_smallhash_lookup(const SmallHash *sh, uintptr_t key)
{
SmallHashEntry *e = smallhash_lookup(sh, key);
return e ? e->val : NULL;
}
-void **BLI_smallhash_lookup_p(SmallHash *sh, uintptr_t key)
+void **BLI_smallhash_lookup_p(const SmallHash *sh, uintptr_t key)
{
SmallHashEntry *e = smallhash_lookup(sh, key);
return e ? &e->val : NULL;
}
-bool BLI_smallhash_haskey(SmallHash *sh, uintptr_t key)
+bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key)
{
SmallHashEntry *e = smallhash_lookup(sh, key);
return (e != NULL);
}
-int BLI_smallhash_count(SmallHash *sh)
+int BLI_smallhash_count(const SmallHash *sh)
{
return (int)sh->nentries;
}
-void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
+BLI_INLINE SmallHashEntry *smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
{
while (iter->i < iter->sh->nbuckets) {
if (smallhash_val_is_used(iter->sh->buckets[iter->i].val)) {
@@ -298,7 +318,7 @@ void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
*key = iter->sh->buckets[iter->i].key;
}
- return iter->sh->buckets[iter->i++].val;
+ return &iter->sh->buckets[iter->i++];
}
iter->i++;
@@ -307,7 +327,21 @@ void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
return NULL;
}
-void *BLI_smallhash_iternew(SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
+void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
+{
+ SmallHashEntry *e = smallhash_iternext(iter, key);
+
+ return e ? e->val : NULL;
+}
+
+void **BLI_smallhash_iternext_p(SmallHashIter *iter, uintptr_t *key)
+{
+ SmallHashEntry *e = smallhash_iternext(iter, key);
+
+ return e ? &e->val : NULL;
+}
+
+void *BLI_smallhash_iternew(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
{
iter->sh = sh;
iter->i = 0;
@@ -315,6 +349,15 @@ void *BLI_smallhash_iternew(SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
return BLI_smallhash_iternext(iter, key);
}
+void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
+{
+ iter->sh = sh;
+ iter->i = 0;
+
+ return BLI_smallhash_iternext_p(iter, key);
+}
+
+
/** \name Debugging & Introspection
* \{ */
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index c062d62bca5..4c5268562ad 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -385,9 +385,11 @@ static void bli_adddirstrings(struct BuildDirCtx *dir_ctx)
/**
* Scans the contents of the directory named *dirname, and allocates and fills in an
- * array of entries describing them in *filelist. The length of the array is the function result.
+ * array of entries describing them in *filelist.
+ *
+ * \return The length of filelist array.
*/
-unsigned int BLI_dir_contents(const char *dirname, struct direntry **filelist)
+unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **filelist)
{
struct BuildDirCtx dir_ctx;
@@ -409,12 +411,45 @@ unsigned int BLI_dir_contents(const char *dirname, struct direntry **filelist)
return dir_ctx.nrfiles;
}
-/* frees storage for an array of direntries, including the array itself. */
-void BLI_free_filelist(struct direntry *filelist, unsigned int nrentries)
+/**
+ * Deep-duplicate of an array of direntries, including the array itself.
+ *
+ * \param dup_poin If given, called for each non-NULL direntry->poin. Otherwise, pointer is always simply copied over.
+ */
+void BLI_filelist_duplicate(
+ struct direntry **dest_filelist, struct direntry *src_filelist, unsigned int nrentries,
+ void *(*dup_poin)(void *))
+{
+ unsigned int i;
+
+ *dest_filelist = malloc(sizeof(**dest_filelist) * (size_t)(nrentries));
+ for (i = 0; i < nrentries; ++i) {
+ struct direntry * const src = &src_filelist[i];
+ struct direntry *dest = &(*dest_filelist)[i];
+ *dest = *src;
+ if (dest->image) {
+ dest->image = IMB_dupImBuf(src->image);
+ }
+ if (dest->relname) {
+ dest->relname = MEM_dupallocN(src->relname);
+ }
+ if (dest->path) {
+ dest->path = MEM_dupallocN(src->path);
+ }
+ if (dest->poin && dup_poin) {
+ dest->poin = dup_poin(src->poin);
+ }
+ }
+}
+
+/**
+ * frees storage for an array of direntries, including the array itself.
+ */
+void BLI_filelist_free(struct direntry *filelist, unsigned int nrentries, void (*free_poin)(void *))
{
unsigned int i;
for (i = 0; i < nrentries; ++i) {
- struct direntry * const entry = filelist + i;
+ struct direntry *entry = filelist + i;
if (entry->image) {
IMB_freeImBuf(entry->image);
}
@@ -422,7 +457,8 @@ void BLI_free_filelist(struct direntry *filelist, unsigned int nrentries)
MEM_freeN(entry->relname);
if (entry->path)
MEM_freeN(entry->path);
- /* entry->poin assumed not to point to anything needing freeing here */
+ if (entry->poin && free_poin)
+ free_poin(entry->poin);
}
free(filelist);
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index eeafc1a9e8f..cc5a90dbc39 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -126,6 +126,54 @@ char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t
}
/**
+ * Like BLI_strncpy but ensures dst is always padded by given char, on both sides (unless src is empty).
+ *
+ * \param dst Destination for copy
+ * \param src Source string to copy
+ * \param pad the char to use for padding
+ * \param maxncpy Maximum number of characters to copy (generally the size of dst)
+ * \retval Returns dst
+ */
+char *BLI_strncpy_ensure_pad(char *__restrict dst, const char *__restrict src, const char pad, size_t maxncpy)
+{
+ BLI_assert(maxncpy != 0);
+
+#ifdef DEBUG_STRSIZE
+ memset(dst, 0xff, sizeof(*dst) * maxncpy);
+#endif
+
+ if (src[0] == '\0') {
+ dst[0] = '\0';
+ }
+ else {
+ /* Add heading/trailing wildcards if needed. */
+ size_t idx = 0;
+ size_t srclen;
+
+ if (src[idx] != pad) {
+ dst[idx++] = pad;
+ maxncpy--;
+ }
+ maxncpy--; /* trailing '\0' */
+
+ srclen = BLI_strnlen(src, maxncpy);
+ if ((src[srclen - 1] != pad) && (srclen == maxncpy)) {
+ srclen--;
+ }
+
+ memcpy(&dst[idx], src, srclen);
+ idx += srclen;
+
+ if (dst[idx - 1] != pad) {
+ dst[idx++] = pad;
+ }
+ dst[idx] = '\0';
+ }
+
+ return dst;
+}
+
+/**
* Like strncpy but ensures dst is always
* '\0' terminated.
*
@@ -566,6 +614,50 @@ int BLI_natstrcmp(const char *s1, const char *s2)
return strcmp(s1, s2);
}
+/**
+ * Like strcmp, but will ignore any heading/trailing pad char for comparison.
+ * So e.g. if pad is '*', '*world' and 'world*' will compare equal.
+ */
+int BLI_strcmp_ignore_pad(const char *str1, const char *str2, const char pad)
+{
+ size_t str1_len, str2_len;
+
+ while (*str1 == pad) {
+ str1++;
+ }
+ while (*str2 == pad) {
+ str2++;
+ }
+
+ str1_len = strlen(str1);
+ str2_len = strlen(str2);
+
+ while (str1_len && (str1[str1_len - 1] == pad)) {
+ str1_len--;
+ }
+ while (str2_len && (str2[str2_len - 1] == pad)) {
+ str2_len--;
+ }
+
+ if (str1_len == str2_len) {
+ return strncmp(str1, str2, str2_len);
+ }
+ else if (str1_len > str2_len) {
+ int ret = strncmp(str1, str2, str2_len);
+ if (ret == 0) {
+ ret = 1;
+ }
+ return ret;
+ }
+ else {
+ int ret = strncmp(str1, str2, str1_len);
+ if (ret == 0) {
+ ret = -1;
+ }
+ return ret;
+ }
+}
+
void BLI_timestr(double _time, char *str, size_t maxlen)
{
/* format 00:00:00.00 (hr:min:sec) string has to be 12 long */
@@ -681,6 +773,35 @@ int BLI_str_index_in_array(const char *__restrict str, const char **__restrict s
return -1;
}
+bool BLI_strn_endswith(const char *__restrict str, const char *__restrict end, size_t slength)
+{
+ size_t elength = strlen(end);
+
+ if (elength < slength) {
+ const char *iter = &str[slength - elength];
+ while (*iter) {
+ if (*iter++ != *end++) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Find if a string ends with another string.
+ *
+ * \param str The string to search within.
+ * \param end The string we look for at the end.
+ * \return If str ends with end.
+ */
+bool BLI_str_endswith(const char *__restrict str, const char *end)
+{
+ const size_t slength = strlen(str);
+ return BLI_strn_endswith(str, end, slength);
+}
+
/**
* Find the first char matching one of the chars in \a delim, from left.
*
diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c
index 9697fcf09e9..f2930044204 100644
--- a/source/blender/blenlib/intern/string_utf8.c
+++ b/source/blender/blenlib/intern/string_utf8.c
@@ -69,11 +69,11 @@ static const char trailingBytesForUTF8[256] = {
int BLI_utf8_invalid_byte(const char *str, int length)
{
- const unsigned char *p, *pend = (unsigned char *)str + length;
+ const unsigned char *p, *pend = (const unsigned char *)str + length;
unsigned char c;
int ab;
- for (p = (unsigned char *)str; p < pend; p++) {
+ for (p = (const unsigned char *)str; p < pend; p++) {
c = *p;
if (c < 128)
continue;
@@ -130,7 +130,7 @@ int BLI_utf8_invalid_byte(const char *str, int length)
utf8_error:
- return (int)((char *)p - (char *)str) - 1;
+ return (int)((const char *)p - (const char *)str) - 1;
}
int BLI_utf8_invalid_strip(char *str, int length)
@@ -209,6 +209,22 @@ char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t
return r_dst;
}
+size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy)
+{
+ char *r_dst = dst;
+
+ BLI_assert(maxncpy != 0);
+
+#ifdef DEBUG_STRSIZE
+ memset(dst, 0xff, sizeof(*dst) * maxncpy);
+#endif
+
+ /* note: currently we don't attempt to deal with invalid utf8 chars */
+ BLI_STR_UTF8_CPY(dst, src, maxncpy);
+
+ return (size_t)(dst - r_dst);
+}
+
char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy)
{
while (*dst && maxncpy > 0) {
diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c
index e6389bc68f3..51b8efbb79f 100644
--- a/source/blender/blenlib/intern/system.c
+++ b/source/blender/blenlib/intern/system.c
@@ -22,9 +22,18 @@
* \ingroup bli
*/
+#include <stdio.h>
+#include <stdlib.h>
#include "BLI_system.h"
+/* for backtrace */
+#if defined(__linux__) || defined(__APPLE__)
+# include <execinfo.h>
+#elif defined(_MSV_VER)
+# include <DbgHelp.h>
+#endif
+
int BLI_cpu_support_sse2(void)
{
#if defined(__x86_64__) || defined(_M_X64)
@@ -57,3 +66,69 @@ int BLI_cpu_support_sse2(void)
#endif
}
+/**
+ * Write a backtrace into a file for systems which support it.
+ */
+void BLI_system_backtrace(FILE *fp)
+{
+ /* ------------- */
+ /* Linux / Apple */
+#if defined(__linux__) || defined(__APPLE__)
+
+#define SIZE 100
+ void *buffer[SIZE];
+ int nptrs;
+ char **strings;
+ int i;
+
+ /* include a backtrace for good measure */
+ nptrs = backtrace(buffer, SIZE);
+ strings = backtrace_symbols(buffer, nptrs);
+ for (i = 0; i < nptrs; i++) {
+ fputs(strings[i], fp);
+ fputc('\n', fp);
+ }
+
+ free(strings);
+#undef SIZE
+
+ /* -------- */
+ /* Windows */
+#elif defined(_MSC_VER)
+
+ (void)fp;
+#if 0
+#define MAXSYMBOL 256
+ unsigned short i;
+ void *stack[SIZE];
+ unsigned short nframes;
+ SYMBOL_INFO *symbolinfo;
+ HANDLE process;
+
+ process = GetCurrentProcess();
+
+ SymInitialize(process, NULL, true);
+
+ nframes = CaptureStackBackTrace(0, SIZE, stack, NULL);
+ symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof(char), "crash Symbol table");
+ symbolinfo->MaxNameLen = MAXSYMBOL - 1;
+ symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO);
+
+ for (i = 0; i < nframes; i++) {
+ SymFromAddr(process, ( DWORD64 )( stack[ i ] ), 0, symbolinfo);
+
+ fprintf(fp, "%u: %s - 0x%0X\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address);
+ }
+
+ MEM_freeN(symbolinfo);
+#undef MAXSYMBOL
+#endif
+
+ /* ------------------ */
+ /* non msvc/osx/linux */
+#else
+ (void)fp;
+#endif
+
+}
+/* end BLI_system_backtrace */
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index 219ccb18d98..d187a8d1968 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -33,6 +33,8 @@
#include "BLI_task.h"
#include "BLI_threads.h"
+#include "atomic_ops.h"
+
/* Types */
typedef struct Task {
@@ -49,6 +51,8 @@ struct TaskPool {
volatile size_t num;
volatile size_t done;
+ size_t num_threads;
+ size_t currently_running_tasks;
ThreadMutex num_mutex;
ThreadCondition num_cond;
@@ -84,6 +88,7 @@ static void task_pool_num_decrease(TaskPool *pool, size_t done)
BLI_assert(pool->num >= done);
pool->num -= done;
+ atomic_sub_z(&pool->currently_running_tasks, done);
pool->done += done;
if (pool->num == 0)
@@ -104,19 +109,37 @@ static void task_pool_num_increase(TaskPool *pool)
static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task)
{
+ bool found_task = false;
BLI_mutex_lock(&scheduler->queue_mutex);
while (!scheduler->queue.first && !scheduler->do_exit)
BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex);
- if (!scheduler->queue.first) {
- BLI_mutex_unlock(&scheduler->queue_mutex);
- BLI_assert(scheduler->do_exit);
- return false;
- }
-
- *task = scheduler->queue.first;
- BLI_remlink(&scheduler->queue, *task);
+ do {
+ Task *current_task;
+ if (!scheduler->queue.first) {
+ BLI_mutex_unlock(&scheduler->queue_mutex);
+ BLI_assert(scheduler->do_exit);
+ return false;
+ }
+ for (current_task = scheduler->queue.first;
+ current_task != NULL;
+ current_task = current_task->next)
+ {
+ TaskPool *pool = current_task->pool;
+ if (pool->num_threads == 0 ||
+ pool->currently_running_tasks < pool->num_threads)
+ {
+ *task = current_task;
+ found_task = true;
+ atomic_add_z(&pool->currently_running_tasks, 1);
+ BLI_remlink(&scheduler->queue, *task);
+ break;
+ }
+ }
+ if (!found_task)
+ BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex);
+ } while (!found_task);
BLI_mutex_unlock(&scheduler->queue_mutex);
@@ -288,6 +311,8 @@ TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata)
pool->scheduler = scheduler;
pool->num = 0;
+ pool->num_threads = 0;
+ pool->currently_running_tasks = 0;
pool->do_cancel = false;
BLI_mutex_init(&pool->num_mutex);
@@ -351,12 +376,16 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
/* find task from this pool. if we get a task from another pool,
* we can get into deadlock */
- for (task = scheduler->queue.first; task; task = task->next) {
- if (task->pool == pool) {
- work_task = task;
- found_task = true;
- BLI_remlink(&scheduler->queue, task);
- break;
+ if (pool->num_threads == 0 ||
+ pool->currently_running_tasks < pool->num_threads)
+ {
+ for (task = scheduler->queue.first; task; task = task->next) {
+ if (task->pool == pool) {
+ work_task = task;
+ found_task = true;
+ BLI_remlink(&scheduler->queue, task);
+ break;
+ }
}
}
@@ -365,6 +394,7 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
/* if found task, do it, otherwise wait until other tasks are done */
if (found_task) {
/* run task */
+ atomic_add_z(&pool->currently_running_tasks, 1);
work_task->run(pool, work_task->taskdata, 0);
/* delete task */
@@ -387,6 +417,12 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
BLI_mutex_unlock(&pool->num_mutex);
}
+void BLI_pool_set_num_threads(TaskPool *pool, int num_threads)
+{
+ /* NOTE: Don't try to modify threads while tasks are running! */
+ pool->num_threads = num_threads;
+}
+
void BLI_task_pool_cancel(TaskPool *pool)
{
pool->do_cancel = true;
diff --git a/source/blender/blenlib/intern/winstuff_dir.c b/source/blender/blenlib/intern/winstuff_dir.c
index 3d669a869f9..b20da9ce959 100644
--- a/source/blender/blenlib/intern/winstuff_dir.c
+++ b/source/blender/blenlib/intern/winstuff_dir.c
@@ -45,11 +45,11 @@
#include "utfconv.h"
/* Note: MinGW (FREE_WINDOWS) has opendir() and _wopendir(), and only the
-* latter accepts a path name of wchar_t type. Rather than messing up with
-* extra #ifdef's here and there, Blender's own implementations of opendir()
-* and related functions are used to properly support paths with non-ASCII
-* characters. (kjym3)
-*/
+ * latter accepts a path name of wchar_t type. Rather than messing up with
+ * extra #ifdef's here and there, Blender's own implementations of opendir()
+ * and related functions are used to properly support paths with non-ASCII
+ * characters. (kjym3)
+ */
DIR *opendir(const char *path)
{
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index d9bcfc2e8f9..95440158277 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -308,6 +308,9 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
/* makes lookup of existing video clips in old main */
blo_make_movieclip_pointer_map(fd, oldmain);
+
+ /* make lookups of existing sound data in old main */
+ blo_make_sound_pointer_map(fd, oldmain);
/* removed packed data from this trick - it's internal data that needs saves */
@@ -318,7 +321,10 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
/* ensures relinked movie clips are not freed */
blo_end_movieclip_pointer_map(fd, oldmain);
-
+
+ /* ensures relinked sounds are not freed */
+ blo_end_sound_pointer_map(fd, oldmain);
+
/* move libraries from old main to new main */
if (bfd && mainlist.first != mainlist.last) {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 4aa4cde4687..d31167976ed 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -143,13 +143,9 @@
#include "BKE_treehash.h"
#include "BKE_sound.h"
-#include "IMB_imbuf.h" // for proxy / timecode versioning stuff
#include "NOD_common.h"
#include "NOD_socket.h"
-#include "NOD_composite.h"
-#include "NOD_shader.h"
-#include "NOD_texture.h"
#include "BLO_readfile.h"
#include "BLO_undofile.h"
@@ -159,7 +155,6 @@
#include "readfile.h"
-#include "PIL_time.h"
#include <errno.h>
@@ -1130,6 +1125,8 @@ void blo_freefiledata(FileData *fd)
oldnewmap_free(fd->imamap);
if (fd->movieclipmap)
oldnewmap_free(fd->movieclipmap);
+ if (fd->soundmap)
+ oldnewmap_free(fd->soundmap);
if (fd->packedmap)
oldnewmap_free(fd->packedmap);
if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP))
@@ -1223,6 +1220,13 @@ static void *newmclipadr(FileData *fd, void *adr) /* used to restore movie
return NULL;
}
+static void *newsoundadr(FileData *fd, void *adr) /* used to restore sound data after undo */
+{
+ if (fd->soundmap && adr)
+ return oldnewmap_lookup_and_inc(fd->soundmap, adr, true);
+ return NULL;
+}
+
static void *newpackedadr(FileData *fd, void *adr) /* used to restore packed data after undo */
{
if (fd->packedmap && adr)
@@ -1439,6 +1443,37 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain)
}
}
+void blo_make_sound_pointer_map(FileData *fd, Main *oldmain)
+{
+ bSound *sound = oldmain->sound.first;
+
+ fd->soundmap = oldnewmap_new();
+
+ for (; sound; sound = sound->id.next) {
+ if (sound->waveform)
+ oldnewmap_insert(fd->soundmap, sound->waveform, sound->waveform, 0);
+ }
+}
+
+/* set old main sound caches to zero if it has been restored */
+/* this works because freeing old main only happens after this call */
+void blo_end_sound_pointer_map(FileData *fd, Main *oldmain)
+{
+ OldNew *entry = fd->soundmap->entries;
+ bSound *sound = oldmain->sound.first;
+ int i;
+
+ /* used entries were restored, so we put them to zero */
+ for (i = 0; i < fd->soundmap->nentries; i++, entry++) {
+ if (entry->nr > 0)
+ entry->newp = NULL;
+ }
+
+ for (; sound; sound = sound->id.next) {
+ sound->waveform = newsoundadr(fd, sound->waveform);
+ }
+}
+
/* XXX disabled this feature - packed files also belong in temp saves and quit.blend, to make restore work */
static void insert_packedmap(FileData *fd, PackedFile *pf)
@@ -3090,14 +3125,14 @@ static void lib_link_key(FileData *fd, Main *main)
static void switch_endian_keyblock(Key *key, KeyBlock *kb)
{
int elemsize, a, b;
- const char *data, *poin, *cp;
+ char *data;
elemsize = key->elemsize;
data = kb->data;
for (a = 0; a < kb->totelem; a++) {
- cp = key->elemstr;
- poin = data;
+ const char *cp = key->elemstr;
+ char *poin = data;
while (cp[0]) { /* cp[0] == amount */
switch (cp[1]) { /* cp[1] = type */
@@ -3222,6 +3257,7 @@ static void direct_link_world(FileData *fd, World *wrld)
}
wrld->preview = direct_link_preview_image(fd, wrld->preview);
+ BLI_listbase_clear(&wrld->gpumaterial);
}
@@ -4822,9 +4858,14 @@ static void direct_link_object(FileData *fd, Object *ob)
/* loading saved files with editmode enabled works, but for undo we like
* to stay in object mode during undo presses so keep editmode disabled.
*
- * Also when linking in a file don't allow editmode: [#34776] */
+ * Also when linking in a file don't allow edit and pose modes.
+ * See [#34776, #42780] for more information.
+ */
if (fd->memfile || (ob->id.flag & (LIB_EXTERN | LIB_INDIRECT))) {
ob->mode &= ~(OB_MODE_EDIT | OB_MODE_PARTICLE_EDIT);
+ if (!fd->memfile) {
+ ob->mode &= ~OB_MODE_POSE;
+ }
}
ob->adt = newdataadr(fd, ob->adt);
@@ -5406,7 +5447,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
}
if (sce->ed) {
- ListBase *old_seqbasep = &((Editing *)sce->ed)->seqbase;
+ ListBase *old_seqbasep = &sce->ed->seqbase;
ed = sce->ed = newdataadr(fd, sce->ed);
@@ -5420,6 +5461,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
seq->seq1= newdataadr(fd, seq->seq1);
seq->seq2= newdataadr(fd, seq->seq2);
seq->seq3= newdataadr(fd, seq->seq3);
+
/* a patch: after introduction of effects with 3 input strips */
if (seq->seq3 == NULL) seq->seq3 = seq->seq2;
@@ -5590,6 +5632,9 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
win->eventstate = NULL;
win->curswin = NULL;
win->tweak = NULL;
+#ifdef WIN32
+ win->ime_data = NULL;
+#endif
BLI_listbase_clear(&win->queue);
BLI_listbase_clear(&win->handlers);
@@ -5645,6 +5690,21 @@ static void lib_link_windowmanager(FileData *fd, Main *main)
/* ****************** READ GREASE PENCIL ***************** */
+/* relink's grease pencil data's refs */
+static void lib_link_gpencil(FileData *fd, Main *main)
+{
+ bGPdata *gpd;
+
+ for (gpd = main->gpencil.first; gpd; gpd = gpd->id.next) {
+ if (gpd->id.flag & LIB_NEED_LINK) {
+ gpd->id.flag -= LIB_NEED_LINK;
+
+ if (gpd->adt)
+ lib_link_animdata(fd, &gpd->id, gpd->adt);
+ }
+ }
+}
+
/* relinks grease-pencil data - used for direct_link and old file linkage */
static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
{
@@ -5656,6 +5716,10 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
if (gpd == NULL)
return;
+ /* relink animdata */
+ gpd->adt = newdataadr(fd, gpd->adt);
+ direct_link_animdata(fd, gpd->adt);
+
/* relink layers */
link_list(fd, &gpd->layers);
@@ -6726,14 +6790,26 @@ static void direct_link_sound(FileData *fd, bSound *sound)
{
sound->handle = NULL;
sound->playback_handle = NULL;
- sound->waveform = NULL;
- // versioning stuff, if there was a cache, then we enable caching:
+ /* versioning stuff, if there was a cache, then we enable caching: */
if (sound->cache) {
sound->flags |= SOUND_FLAGS_CACHING;
sound->cache = NULL;
}
+ if (fd->soundmap) {
+ sound->waveform = newsoundadr(fd, sound->waveform);
+ }
+ else {
+ sound->waveform = NULL;
+ }
+
+ if (sound->mutex)
+ sound->mutex = BLI_mutex_alloc();
+
+ /* clear waveform loading flag */
+ sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+
sound->packedfile = direct_link_packedfile(fd, sound->packedfile);
sound->newpackedfile = direct_link_packedfile(fd, sound->newpackedfile);
}
@@ -7615,6 +7691,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_movieclip(fd, main);
lib_link_mask(fd, main);
lib_link_linestyle(fd, main);
+ lib_link_gpencil(fd, main);
lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
@@ -8720,6 +8797,12 @@ static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *li
}
}
+static void expand_gpencil(FileData *fd, Main *mainvar, bGPdata *gpd)
+{
+ if (gpd->adt)
+ expand_animdata(fd, mainvar, gpd->adt);
+}
+
void BLO_main_expander(void (*expand_doit_func)(void *, Main *, void *))
{
expand_doit = expand_doit_func;
@@ -8814,6 +8897,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
case ID_LS:
expand_linestyle(fd, mainvar, (FreestyleLineStyle *)id);
break;
+ case ID_GD:
+ expand_gpencil(fd, mainvar, (bGPdata *)id);
+ break;
}
do_it = true;
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index d56f58d1b37..2b40accbf21 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -88,6 +88,7 @@ typedef struct FileData {
struct OldNewMap *libmap;
struct OldNewMap *imamap;
struct OldNewMap *movieclipmap;
+ struct OldNewMap *soundmap;
struct OldNewMap *packedmap;
struct BHeadSort *bheadmap;
@@ -133,6 +134,8 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain);
void blo_end_image_pointer_map(FileData *fd, Main *oldmain);
void blo_make_movieclip_pointer_map(FileData *fd, Main *oldmain);
void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain);
+void blo_make_sound_pointer_map(FileData *fd, Main *oldmain);
+void blo_end_sound_pointer_map(FileData *fd, Main *oldmain);
void blo_make_packed_pointer_map(FileData *fd, Main *oldmain);
void blo_end_packed_pointer_map(FileData *fd, Main *oldmain);
void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd);
diff --git a/source/blender/blenloader/intern/runtime.c b/source/blender/blenloader/intern/runtime.c
index d6fd2f92443..ec496e1c866 100644
--- a/source/blender/blenloader/intern/runtime.c
+++ b/source/blender/blenloader/intern/runtime.c
@@ -51,7 +51,6 @@
#include "BLO_readfile.h"
#include "BLO_runtime.h"
-#include "BKE_blender.h"
#include "BKE_report.h"
/* Runtime reading */
diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c
index 12f4a295a34..f70d889828f 100644
--- a/source/blender/blenloader/intern/undofile.c
+++ b/source/blender/blenloader/intern/undofile.c
@@ -40,7 +40,6 @@
#include "DNA_listBase.h"
#include "BLI_blenlib.h"
-#include "BLI_linklist.h"
#include "BLO_undofile.h"
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 14b165e2341..8eb54c30cb1 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -25,11 +25,10 @@
* \ingroup blenloader
*/
-#include "zlib.h"
-
#ifndef WIN32
# include <unistd.h> /* for read close */
#else
+# include <zlib.h> /* odd include order-issue */
# include <io.h> // for open close read
# include "winsock2.h"
# include "BLI_winstuff.h"
@@ -92,14 +91,9 @@
#include "NOD_socket.h"
#include "BLO_readfile.h"
-#include "BLO_undofile.h"
-
-#include "RE_engine.h"
#include "readfile.h"
-#include "PIL_time.h"
-
#include <errno.h>
/* 2.50 patch */
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 7c6b6ec7249..7e5127aa407 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -25,8 +25,6 @@
* \ingroup blenloader
*/
-#include "zlib.h"
-
#include "BLI_utildefines.h"
/* allow readfile to use deprecated functionality */
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index 37ad2167332..0ff953e7420 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -54,14 +54,12 @@
#include "DNA_genfile.h"
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_pointcache.h"
#include "BLI_math.h"
+#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLO_readfile.h"
@@ -512,4 +510,27 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
do_versions_pointcache(&sce->id, rbw->pointcache);
}
}
+
+ if (!MAIN_VERSION_ATLEAST(main, 273, 1)) {
+#define BRUSH_RAKE (1 << 7)
+#define BRUSH_RANDOM_ROTATION (1 << 25)
+
+ Brush *br;
+
+ for (br = main->brush.first; br; br = br->id.next) {
+ if (br->flag & BRUSH_RAKE) {
+ br->mtex.brush_angle_mode |= MTEX_ANGLE_RAKE;
+ br->mask_mtex.brush_angle_mode |= MTEX_ANGLE_RAKE;
+ }
+ else if (br->flag & BRUSH_RANDOM_ROTATION) {
+ br->mtex.brush_angle_mode |= MTEX_ANGLE_RANDOM;
+ br->mask_mtex.brush_angle_mode |= MTEX_ANGLE_RANDOM;
+ }
+ br->mtex.random_angle = 2.0f * M_PI;
+ br->mask_mtex.random_angle = 2.0f * M_PI;
+ }
+
+#undef BRUSH_RAKE
+#undef BRUSH_RANDOM_ROTATION
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 4732f8578ed..4c7b011097b 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -138,9 +138,13 @@ void BLO_update_defaults_startup_blend(Main *bmain)
{
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, "Fill");
+ if (!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) {
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 1d0babcad3e..27e49522be4 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -30,13 +30,12 @@
*/
-#include "zlib.h"
-
#include <limits.h>
#ifndef WIN32
# include <unistd.h> // for read close
#else
+# include <zlib.h> /* odd include order-issue */
# include <io.h> // for open close read
# include "winsock2.h"
# include "BLI_winstuff.h"
@@ -96,14 +95,9 @@
#include "BKE_scene.h"
#include "BKE_sequencer.h"
-#include "IMB_imbuf.h" // for proxy / timecode versioning stuff
-
#include "NOD_socket.h"
#include "BLO_readfile.h"
-#include "BLO_undofile.h"
-
-#include "RE_engine.h"
#include "readfile.h"
@@ -523,6 +517,40 @@ static void do_version_free_effects_245(ListBase *lb)
}
}
+static void do_version_constraints_245(ListBase *lb)
+{
+ bConstraint *con;
+ bConstraintTarget *ct;
+
+ for (con = lb->first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_PYTHON) {
+ bPythonConstraint *data = (bPythonConstraint *)con->data;
+ if (data->tar) {
+ /* version patching needs to be done */
+ ct = MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
+
+ ct->tar = data->tar;
+ BLI_strncpy(ct->subtarget, data->subtarget, sizeof(ct->subtarget));
+ ct->space = con->tarspace;
+
+ BLI_addtail(&data->targets, ct);
+ data->tarnum++;
+
+ /* clear old targets to avoid problems */
+ data->tar = NULL;
+ data->subtarget[0] = '\0';
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_LOCLIKE) {
+ bLocateLikeConstraint *data = (bLocateLikeConstraint *)con->data;
+
+ /* new headtail functionality makes Bone-Tip function obsolete */
+ if (data->flag & LOCLIKE_TIP)
+ con->headtail = 1.0f;
+ }
+ }
+}
+
PartEff *blo_do_version_give_parteff_245(Object *ob)
{
PartEff *paf;
@@ -2953,69 +2981,14 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 7)) {
Object *ob;
bPoseChannel *pchan;
- bConstraint *con;
- bConstraintTarget *ct;
for (ob = main->object.first; ob; ob = ob->id.next) {
if (ob->pose) {
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_PYTHON) {
- bPythonConstraint *data = (bPythonConstraint *)con->data;
- if (data->tar) {
- /* version patching needs to be done */
- ct = MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
-
- ct->tar = data->tar;
- BLI_strncpy(ct->subtarget, data->subtarget, sizeof(ct->subtarget));
- ct->space = con->tarspace;
-
- BLI_addtail(&data->targets, ct);
- data->tarnum++;
-
- /* clear old targets to avoid problems */
- data->tar = NULL;
- data->subtarget[0] = '\0';
- }
- }
- else if (con->type == CONSTRAINT_TYPE_LOCLIKE) {
- bLocateLikeConstraint *data = (bLocateLikeConstraint *)con->data;
-
- /* new headtail functionality makes Bone-Tip function obsolete */
- if (data->flag & LOCLIKE_TIP)
- con->headtail = 1.0f;
- }
- }
- }
- }
-
- for (con = ob->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_PYTHON) {
- bPythonConstraint *data = (bPythonConstraint *)con->data;
- if (data->tar) {
- /* version patching needs to be done */
- ct = MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
-
- ct->tar = data->tar;
- BLI_strncpy(ct->subtarget, data->subtarget, sizeof(ct->subtarget));
- ct->space = con->tarspace;
-
- BLI_addtail(&data->targets, ct);
- data->tarnum++;
-
- /* clear old targets to avoid problems */
- data->tar = NULL;
- data->subtarget[0] = '\0';
- }
- }
- else if (con->type == CONSTRAINT_TYPE_LOCLIKE) {
- bLocateLikeConstraint *data = (bLocateLikeConstraint *)con->data;
-
- /* new headtail functionality makes Bone-Tip function obsolete */
- if (data->flag & LOCLIKE_TIP)
- con->headtail = 1.0f;
+ do_version_constraints_245(&pchan->constraints);
}
}
+ do_version_constraints_245(&ob->constraints);
if (ob->soft && ob->soft->keys) {
SoftBody *sb = ob->soft;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index fa7f2d6ae95..f4c08149e05 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -79,9 +79,8 @@
#include <string.h>
#include <stdlib.h>
-#include "zlib.h"
-
#ifdef WIN32
+# include <zlib.h> /* odd include order-issue */
# include "winsock2.h"
# include <io.h>
# include "BLI_winstuff.h"
@@ -163,11 +162,9 @@
#include "BKE_mesh.h"
#ifdef USE_NODE_COMPAT_CUSTOMNODES
-#include "NOD_common.h"
#include "NOD_socket.h" /* for sock->default_value data */
#endif
-#include "RNA_access.h"
#include "BLO_writefile.h"
#include "BLO_readfile.h"
@@ -1405,7 +1402,7 @@ static void write_pose(WriteData *wd, bPose *pose)
/* write IK param */
if (pose->ikparam) {
- const char *structname = (char *)BKE_pose_ikparam_get_name(pose);
+ const char *structname = BKE_pose_ikparam_get_name(pose);
if (structname)
writestruct(wd, DATA, structname, 1, pose->ikparam);
}
@@ -2019,7 +2016,8 @@ static void write_lattices(WriteData *wd, ListBase *idbase)
static void write_previews(WriteData *wd, PreviewImage *prv)
{
- if (prv) {
+ /* Never write previews in undo steps! */
+ if (prv && !wd->current) {
short w = prv->w[1];
short h = prv->h[1];
unsigned int *rect = prv->rect[1];
@@ -2427,6 +2425,8 @@ static void write_gpencils(WriteData *wd, ListBase *lb)
/* write gpd data block to file */
writestruct(wd, ID_GD, "bGPdata", 1, gpd);
+ if (gpd->adt) write_animdata(wd, gpd->adt);
+
/* write grease-pencil layers to file */
writelist(wd, DATA, "bGPDlayer", &gpd->layers);
for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 39359b97a4e..120ff4997dc 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -256,6 +256,12 @@ enum {
#define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)
#define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE)
+#define BM_CHECK_TYPE_ELEM(ele) \
+ CHECK_TYPE_ANY(ele, void *, BMFace *, BMEdge *, BMVert *, BMLoop *, BMElem *, BMElemF *, BMHeader *)
+
+#define BM_CHECK_TYPE_ELEM_ASSIGN(ele) \
+ (BM_CHECK_TYPE_ELEM(ele), CHECK_TYPE_NONCONST(ele)), ele
+
/* BMHeader->hflag (char) */
enum {
BM_ELEM_SELECT = (1 << 0),
diff --git a/source/blender/bmesh/intern/bmesh_callback_generic.c b/source/blender/bmesh/intern/bmesh_callback_generic.c
index 84fcc67f3c4..913255bfb33 100644
--- a/source/blender/bmesh/intern/bmesh_callback_generic.c
+++ b/source/blender/bmesh/intern/bmesh_callback_generic.c
@@ -53,3 +53,8 @@ bool BM_elem_cb_check_hflag_disabled(BMElem *ele, void *user_data)
return (BM_elem_flag_test(ele, hflag) == 0);
}
+
+bool BM_elem_cb_check_elem_not_equal(BMElem *ele, void *user_data)
+{
+ return (ele != user_data);
+}
diff --git a/source/blender/bmesh/intern/bmesh_callback_generic.h b/source/blender/bmesh/intern/bmesh_callback_generic.h
index 8c46128f3b0..3cae01d417f 100644
--- a/source/blender/bmesh/intern/bmesh_callback_generic.h
+++ b/source/blender/bmesh/intern/bmesh_callback_generic.h
@@ -28,6 +28,7 @@
bool BM_elem_cb_check_hflag_enabled(BMElem *, void *user_data);
bool BM_elem_cb_check_hflag_disabled(BMElem *, void *user_data);
bool BM_elem_cb_check_hflag_ex(BMElem *, void *user_data);
+bool BM_elem_cb_check_elem_not_equal(BMElem *ele, void *user_data);
#define BM_elem_cb_check_hflag_ex_simple(type, hflag_p, hflag_n) \
(bool (*)(type, void *))BM_elem_cb_check_hflag_ex, \
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c
index e83a1d5b00a..aa1f511e8d7 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.c
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.c
@@ -662,7 +662,7 @@ void BM_edgeloop_flip(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
void BM_edgeloop_expand(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store, int el_store_len)
{
- /* first double until we are more then half as big */
+ /* first double until we are more than half as big */
while ((el_store->len * 2) < el_store_len) {
LinkData *node_curr = el_store->verts.first;
while (node_curr) {
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index 792a9cdfe0d..49e511bdcb5 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -84,30 +84,40 @@ typedef enum BMIterType {
extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX];
#define BM_ITER_MESH(ele, iter, bm, itype) \
- for (ele = BM_iter_new(iter, bm, itype, NULL); ele; ele = BM_iter_step(iter))
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar) \
- for (ele = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; ele; ele = BM_iter_step(iter), (indexvar)++)
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++)
/* a version of BM_ITER_MESH which keeps the next item in storage
* so we can delete the current item, see bug [#36923] */
#ifdef DEBUG
# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \
- for (ele = BM_iter_new(iter, bm, itype, NULL); \
- ele ? ((void)((iter)->count = BM_iter_mesh_count(itype, bm)), \
- (void)(ele_next = BM_iter_step(iter)), 1) : 0; \
- ele = ele_next)
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \
+ ele ? ((void)((iter)->count = BM_iter_mesh_count(itype, bm)), \
+ (void)(ele_next = BM_iter_step(iter)), 1) : 0; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = ele_next)
#else
# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \
- for (ele = BM_iter_new(iter, bm, itype, NULL); ele ? ((ele_next = BM_iter_step(iter)), 1) : 0; ele = ele_next)
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \
+ ele ? ((BM_CHECK_TYPE_ELEM_ASSIGN(ele_next) = BM_iter_step(iter)), 1) : 0; \
+ ele = ele_next)
#endif
#define BM_ITER_ELEM(ele, iter, data, itype) \
- for (ele = BM_iter_new(iter, NULL, itype, data); ele; ele = BM_iter_step(iter))
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data); \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
#define BM_ITER_ELEM_INDEX(ele, iter, data, itype, indexvar) \
- for (ele = BM_iter_new(iter, NULL, itype, data), indexvar = 0; ele; ele = BM_iter_step(iter), (indexvar)++)
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data), indexvar = 0; \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++)
/* iterator type structs */
struct BMIter__elem_of_mesh {
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 825bbb136b1..d966d882c67 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -479,7 +479,9 @@ int BMO_iter_map_value_int(BMOIter *iter);
bool BMO_iter_map_value_bool(BMOIter *iter);
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \
- for (ele = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); ele; ele = BMO_iter_step(iter))
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter))
/******************* Inlined Functions********************/
typedef void (*opexec)(BMesh *bm, BMOperator *op);
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index 8557bcd91b7..f39fe29b596 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -82,6 +82,7 @@ enum {
SIMFACE_PERIMETER,
SIMFACE_NORMAL,
SIMFACE_COPLANAR,
+ SIMFACE_SMOOTH,
#ifdef WITH_FREESTYLE
SIMFACE_FREESTYLE
#endif
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index a5a7bc5189e..e4aa4bb0c0e 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -37,6 +37,7 @@
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_polyfill2d.h"
+#include "BLI_polyfill2d_beautify.h"
#include "bmesh.h"
#include "bmesh_tools.h"
@@ -213,9 +214,6 @@ float BM_face_calc_area(BMFace *f)
if (f->len == 3) {
area = area_tri_v3(verts[0], verts[1], verts[2]);
}
- else if (f->len == 4) {
- area = area_quad_v3(verts[0], verts[1], verts[2], verts[3]);
- }
else {
area = area_poly_v3((const float (*)[3])verts, f->len);
}
@@ -742,20 +740,21 @@ bool BM_face_point_inside_test(BMFace *f, const float co[3])
*
* \note use_tag tags new flags and edges.
*/
-void BM_face_triangulate(BMesh *bm, BMFace *f,
- BMFace **r_faces_new,
- int *r_faces_new_tot,
- MemArena *sf_arena,
- const int quad_method,
- const int ngon_method,
- const bool use_tag)
+void BM_face_triangulate(
+ BMesh *bm, BMFace *f,
+ BMFace **r_faces_new,
+ int *r_faces_new_tot,
+ const int quad_method,
+ const int ngon_method,
+ const bool use_tag,
+ MemArena *pf_arena,
+
+ /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
+ struct Heap *pf_heap, struct EdgeHash *pf_ehash)
{
BMLoop *l_iter, *l_first, *l_new;
BMFace *f_new;
- int orig_f_len = f->len;
int nf_i = 0;
- BMEdge **edge_array;
- int edge_array_len;
bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY);
BLI_assert(BM_face_is_normal_valid(f));
@@ -781,38 +780,39 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
break;
}
case MOD_TRIANGULATE_QUAD_SHORTEDGE:
- {
- BMLoop *l_v3, *l_v4;
- float d1, d2;
-
- l_v1 = l_first;
- l_v2 = l_first->next->next;
- l_v3 = l_first->next;
- l_v4 = l_first->prev;
-
- d1 = len_squared_v3v3(l_v1->v->co, l_v2->v->co);
- d2 = len_squared_v3v3(l_v3->v->co, l_v4->v->co);
-
- if (d2 < d1) {
- l_v1 = l_v3;
- l_v2 = l_v4;
- }
- break;
- }
case MOD_TRIANGULATE_QUAD_BEAUTY:
default:
{
BMLoop *l_v3, *l_v4;
- float cost;
+ bool split_24;
l_v1 = l_first->next;
l_v2 = l_first->next->next;
l_v3 = l_first->prev;
l_v4 = l_first;
- cost = BM_verts_calc_rotate_beauty(l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0);
+ if (quad_method == MOD_TRIANGULATE_QUAD_SHORTEDGE) {
+ float d1, d2;
+ d1 = len_squared_v3v3(l_v4->v->co, l_v2->v->co);
+ d2 = len_squared_v3v3(l_v1->v->co, l_v3->v->co);
+ split_24 = ((d2 - d1) > 0.0f);
+ }
+ else {
+ /* first check if the quad is concave on either diagonal */
+ const int flip_flag = is_quad_flip_v3(l_v1->v->co, l_v2->v->co, l_v3->v->co, l_v4->v->co);
+ if (UNLIKELY(flip_flag & (1 << 0))) {
+ split_24 = true;
+ }
+ else if (UNLIKELY(flip_flag & (1 << 1))) {
+ split_24 = false;
+ }
+ else {
+ split_24 = (BM_verts_calc_rotate_beauty(l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) > 0.0f);
+ }
+ }
- if (cost < 0.0f) {
+ /* named confusingly, l_v1 is in fact the second vertex */
+ if (split_24) {
l_v1 = l_v4;
//l_v2 = l_v2;
}
@@ -854,11 +854,12 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
}
BLI_polyfill_calc_arena((const float (*)[2])projverts, f->len, -1, tris,
- sf_arena);
+ pf_arena);
if (use_beauty) {
- edge_array = BLI_array_alloca(edge_array, orig_f_len - 3);
- edge_array_len = 0;
+ BLI_polyfill_beautify(
+ (const float (*)[2])projverts, f->len, tris,
+ pf_arena, pf_heap, pf_ehash);
}
/* loop over calculated triangles and create new geometry */
@@ -895,7 +896,7 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
}
/* we know any edge that we create and _isnt_ */
- if (use_beauty || use_tag) {
+ if (use_tag) {
/* new faces loops */
l_iter = l_first = l_new;
do {
@@ -905,92 +906,19 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
bool is_new_edge = (l_iter == l_iter->radial_next);
if (is_new_edge) {
- if (use_beauty) {
- edge_array[edge_array_len] = e;
- edge_array_len++;
- }
-
- if (use_tag) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
-
- }
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
}
/* note, never disable tag's */
} while ((l_iter = l_iter->next) != l_first);
}
}
- if ((!use_beauty) || (!r_faces_new)) {
+ {
/* we can't delete the real face, because some of the callers expect it to remain valid.
* so swap data and delete the last created tri */
bmesh_face_swap_data(f, f_new);
BM_face_kill(bm, f_new);
}
-
- if (use_beauty) {
- BLI_assert(edge_array_len <= orig_f_len - 3);
-
- BM_mesh_beautify_fill(bm, edge_array, edge_array_len, 0, 0, 0, 0);
-
- if (r_faces_new) {
- /* beautify deletes and creates new faces
- * we need to re-populate the r_faces_new array
- * with the new faces
- */
- int i;
-
-
-#define FACE_USED_TEST(f) (BM_elem_index_get(f) == -2)
-#define FACE_USED_SET(f) BM_elem_index_set(f, -2)
-
- nf_i = 0;
- for (i = 0; i < edge_array_len; i++) {
- BMFace *f_a, *f_b;
- BMEdge *e = edge_array[i];
-#ifndef NDEBUG
- const bool ok = BM_edge_face_pair(e, &f_a, &f_b);
- BLI_assert(ok);
-#else
- BM_edge_face_pair(e, &f_a, &f_b);
-#endif
-
- if (FACE_USED_TEST(f_a) == false) {
- FACE_USED_SET(f_a); /* set_dirty */
-
- if (nf_i < edge_array_len) {
- r_faces_new[nf_i++] = f_a;
- }
- else {
- f_new = f_a;
- break;
- }
- }
-
- if (FACE_USED_TEST(f_b) == false) {
- FACE_USED_SET(f_b); /* set_dirty */
-
- if (nf_i < edge_array_len) {
- r_faces_new[nf_i++] = f_b;
- }
- else {
- f_new = f_b;
- break;
- }
- }
- }
-
-#undef FACE_USED_TEST
-#undef FACE_USED_SET
-
- /* nf_i doesn't include the last face */
- BLI_assert(nf_i <= orig_f_len - 3);
-
- /* we can't delete the real face, because some of the callers expect it to remain valid.
- * so swap data and delete the last created tri */
- bmesh_face_swap_data(f, f_new);
- BM_face_kill(bm, f_new);
- }
- }
}
bm->elem_index_dirty |= BM_FACE;
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index d62c81c4052..b25a7dbaa55 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -27,6 +27,9 @@
* \ingroup bmesh
*/
+struct EdgeHash;
+struct Heap;
+
#include "BLI_compiler_attrs.h"
void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot);
@@ -56,12 +59,15 @@ void BM_vert_normal_update_all(BMVert *v) ATTR_NONNULL();
void BM_face_normal_flip(BMesh *bm, BMFace *f) ATTR_NONNULL();
bool BM_face_point_inside_test(BMFace *f, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BM_face_triangulate(BMesh *bm, BMFace *f,
- BMFace **r_faces_new,
- int *r_faces_new_tot,
- struct MemArena *sf_arena,
- const int quad_method, const int ngon_method,
- const bool use_tag) ATTR_NONNULL(1, 2);
+void BM_face_triangulate(
+ BMesh *bm, BMFace *f,
+ BMFace **r_faces_new,
+ int *r_faces_new_tot,
+ const int quad_method, const int ngon_method,
+ const bool use_tag,
+ struct MemArena *pf_arena,
+ struct Heap *pf_heap, struct EdgeHash *pf_ehash
+ ) ATTR_NONNULL(1, 2);
void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL();
void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL();
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 0792e956e5b..f56cf76c41d 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -193,7 +193,7 @@ bool BM_vert_pair_share_face_check(
BMFace *f;
BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) {
- if (BM_vert_in_face(f, v_b)) {
+ if (BM_vert_in_face(v_b, f)) {
return true;
}
}
@@ -212,7 +212,7 @@ bool BM_vert_pair_share_face_check_cb(
BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) {
if (test_fn(f, user_data)) {
- if (BM_vert_in_face(f, v_b)) {
+ if (BM_vert_in_face(v_b, f)) {
return true;
}
}
@@ -270,6 +270,36 @@ static float bm_face_calc_split_dot(BMLoop *l_a, BMLoop *l_b)
}
/**
+ * Check if a point is inside the corner defined by a loop
+ * (within the 2 planes defined by the loops corner & face normal).
+ *
+ * \return less than 0.0 when inside.
+ */
+float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3])
+{
+ const float *axis = l->f->no;
+ return (angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, co, axis) -
+ angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, l->next->v->co, axis));
+}
+
+/**
+ * Check if a point is inside the edge defined by a loop
+ * (within the plane defined by the loops edge & face normal).
+ *
+ * \return less than 0.0 when inside.
+ */
+float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3])
+{
+ const float *axis = l->f->no;
+ float dir[3];
+ float plane[3];
+ sub_v3_v3v3(dir, l->v->co, l->next->v->co);
+ cross_v3_v3v3(plane, axis, dir);
+ return (dot_v3v3(plane, co) -
+ dot_v3v3(plane, l->v->co));
+}
+
+/**
* Given 2 verts, find a face they share that has the lowest angle across these verts and give back both loops.
*
* This can be better then #BM_vert_pair_share_face_by_len because concave splits are ranked lowest.
@@ -345,7 +375,7 @@ BMLoop *BM_vert_find_first_loop(BMVert *v)
/**
* Returns true if the vertex is used in a given face.
*/
-bool BM_vert_in_face(BMFace *f, BMVert *v)
+bool BM_vert_in_face(BMVert *v, BMFace *f)
{
BMLoop *l_iter, *l_first;
@@ -373,7 +403,7 @@ bool BM_vert_in_face(BMFace *f, BMVert *v)
* Compares the number of vertices in an array
* that appear in a given face
*/
-int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len)
+int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f)
{
BMLoop *l_iter, *l_first;
@@ -417,7 +447,7 @@ int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len)
/**
* Return true if all verts are in the face.
*/
-bool BM_verts_in_face(BMFace *f, BMVert **varr, int len)
+bool BM_verts_in_face(BMVert **varr, int len, BMFace *f)
{
BMLoop *l_iter, *l_first;
@@ -714,17 +744,17 @@ bool BM_vert_is_edge_pair(BMVert *v)
/**
* Returns the number of edges around this vertex.
*/
-int BM_vert_edge_count(BMVert *v)
+int BM_vert_edge_count(const BMVert *v)
{
return bmesh_disk_count(v);
}
-int BM_vert_edge_count_nonwire(BMVert *v)
+int BM_vert_edge_count_nonwire(const BMVert *v)
{
int count = 0;
BMIter eiter;
BMEdge *edge;
- BM_ITER_ELEM (edge, &eiter, v, BM_EDGES_OF_VERT) {
+ BM_ITER_ELEM (edge, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) {
if (edge->l) {
count++;
}
@@ -734,7 +764,7 @@ int BM_vert_edge_count_nonwire(BMVert *v)
/**
* Returns the number of faces around this edge
*/
-int BM_edge_face_count(BMEdge *e)
+int BM_edge_face_count(const BMEdge *e)
{
int count = 0;
@@ -756,7 +786,7 @@ int BM_edge_face_count(BMEdge *e)
* Returns the number of faces around this vert
* length matches #BM_LOOPS_OF_VERT iterator
*/
-int BM_vert_face_count(BMVert *v)
+int BM_vert_face_count(const BMVert *v)
{
return bmesh_disk_facevert_count(v);
}
@@ -1572,7 +1602,7 @@ bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface)
#if 0
BM_ITER_ELEM (f, &viter, v_search, BM_FACES_OF_VERT) {
if (f->len == len) {
- if (BM_verts_in_face(f, varr, len)) {
+ if (BM_verts_in_face(varr, len, f)) {
if (r_existface) {
*r_existface = f;
}
@@ -1797,7 +1827,7 @@ bool BM_face_exists_multi_edge(BMEdge **earr, int len)
*
* \note The face may contain other verts \b not in \a varr.
*
- * \note Its possible there are more then one overlapping faces,
+ * \note Its possible there are more than one overlapping faces,
* in this case the first one found will be assigned to \a r_f_overlap.
*
* \param varr Array of unordered verts.
@@ -1830,7 +1860,7 @@ bool BM_face_exists_overlap(BMVert **varr, const int len, BMFace **r_f_overlap)
for (i = 0; i < len; i++) {
BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
if (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0) {
- if (len <= BM_verts_in_face_count(f, varr, len)) {
+ if (len <= BM_verts_in_face_count(varr, len, f)) {
if (r_f_overlap)
*r_f_overlap = f;
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index b5b423ed58f..5e6d4b5154b 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -27,9 +27,9 @@
* \ingroup bmesh
*/
-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_vert_in_face(BMVert *v, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) 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();
@@ -64,10 +64,10 @@ 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) 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();
+int BM_vert_edge_count_nonwire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_vert_edge_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_edge_face_count(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_vert_face_count(const 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) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -83,6 +83,8 @@ bool BM_edge_is_convex(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(
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_point_side_of_loop_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
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();
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
index c6829b8d5f1..b7bf80b0e3f 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_impl.c
+++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c
@@ -33,7 +33,6 @@
#include "BKE_customdata.h"
#include "bmesh.h"
-#include "intern/bmesh_private.h"
#include "intern/bmesh_walkers_private.h"
/* pop into stack memory (common operation) */
diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c
index e4417477e76..6002dcf2c0d 100644
--- a/source/blender/bmesh/operators/bmo_bridge.c
+++ b/source/blender/bmesh/operators/bmo_bridge.c
@@ -180,20 +180,42 @@ static void bridge_loop_pair(BMesh *bm,
/* normalizing isn't strictly needed but without we may get very large values */
float no[3];
+ float dir_a_orig[3], dir_b_orig[3];
float dir_a[3], dir_b[3];
+ const float *test_a, *test_b;
- sub_v3_v3v3(dir_a,
+ sub_v3_v3v3(dir_a_orig,
((BMVert *)(((LinkData *)lb_a->first)->data))->co,
((BMVert *)(((LinkData *)lb_a->last)->data))->co);
- sub_v3_v3v3(dir_b,
+ sub_v3_v3v3(dir_b_orig,
((BMVert *)(((LinkData *)lb_b->first)->data))->co,
((BMVert *)(((LinkData *)lb_b->last)->data))->co);
/* make the directions point out from the normals, 'no' is used as a temp var */
- cross_v3_v3v3(no, dir_a, el_dir); cross_v3_v3v3(dir_a, no, el_dir);
- cross_v3_v3v3(no, dir_b, el_dir); cross_v3_v3v3(dir_b, no, el_dir);
+ cross_v3_v3v3(no, dir_a_orig, el_dir); cross_v3_v3v3(dir_a, no, el_dir);
+ cross_v3_v3v3(no, dir_b_orig, el_dir); cross_v3_v3v3(dir_b, no, el_dir);
- if (dot_v3v3(dir_a, dir_b) < 0.0f) {
+ if (LIKELY(!is_zero_v3(dir_a) && !is_zero_v3(dir_b))) {
+ test_a = dir_a;
+ test_b = dir_b;
+ }
+ else {
+ /**
+ * This is a corner case:
+ *
+ * <pre>
+ * (loop a) (loop b)
+ * +--------+ +--------+
+ * </pre>
+ *
+ * When loops are aligned to the direction between the loops values of 'dir_a/b' is degenerate,
+ * in this case compare the original directions (before they were corrected by 'el_dir'), see: T43013
+ */
+ test_a = dir_a_orig;
+ test_b = dir_b_orig;
+ }
+
+ if (dot_v3v3(test_a, test_b) < 0.0f) {
BM_edgeloop_flip(bm, el_store_b);
}
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index 418e75b7ac3..9db87ddfb77 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -141,7 +141,7 @@ static void state_calc_co_pair(const PathContext *pc,
/**
* Ideally we wouldn't need this and for most cases we don't.
- * But when a face has vertices that are on the boundary more then once this becomes tricky.
+ * But when a face has vertices that are on the boundary more than once this becomes tricky.
*/
static bool state_link_find(PathLinkState *state, BMElem *ele)
{
@@ -464,19 +464,23 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
negate_v3(basis_nor_b);
}
add_v3_v3v3(basis_nor, basis_nor_a, basis_nor_b);
-
- if (UNLIKELY(fabsf(dot_v3v3(basis_nor, basis_dir)) < FLT_EPSILON)) {
- ortho_v3_v3(basis_nor, basis_dir);
- }
}
#endif
/* get third axis */
+ normalize_v3(basis_dir);
+ normalize_v3(basis_nor);
cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
+ if (UNLIKELY(normalize_v3(basis_tmp) < FLT_EPSILON)) {
+ ortho_v3_v3(basis_nor, basis_dir);
+ normalize_v3(basis_nor);
+ cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
+ normalize_v3(basis_tmp);
+ }
- normalize_v3_v3(pc.matrix[0], basis_tmp);
- normalize_v3_v3(pc.matrix[1], basis_dir);
- normalize_v3_v3(pc.matrix[2], basis_nor);
+ copy_v3_v3(pc.matrix[0], basis_tmp);
+ copy_v3_v3(pc.matrix[1], basis_dir);
+ copy_v3_v3(pc.matrix[2], basis_nor);
invert_m3(pc.matrix);
pc.axis_sep = dot_m3_v3_row_x(pc.matrix, pc.v_a->co);
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index cd5592f08c9..a5a6480c187 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -109,7 +109,7 @@ static BMEdge *bmo_edge_copy(BMOperator *op,
/* add to new/old edge map if necassary */
if (rlen < 2) {
- /* not sure what non-manifold cases of greater then three
+ /* not sure what non-manifold cases of greater than three
* radial should do. */
BMO_slot_map_elem_insert(op, slot_boundarymap_out, e_src, e_dst);
}
diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c
index 26a4dbe1e1d..fb99c9777d0 100644
--- a/source/blender/bmesh/operators/bmo_hull.c
+++ b/source/blender/bmesh/operators/bmo_hull.c
@@ -285,8 +285,8 @@ static void hull_remove_overlapping(BMesh *bm, GSet *hull_triangles,
/* Note: can't change ghash while iterating, so mark
* with 'skip' flag rather than deleting triangles */
- if (BM_vert_in_face(f, t->v[1]) &&
- BM_vert_in_face(f, t->v[2]) && f_on_hull)
+ if (BM_vert_in_face(t->v[1], f) &&
+ BM_vert_in_face(t->v[2], f) && f_on_hull)
{
t->skip = true;
BMO_elem_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE);
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index e69dcca6342..2108a2c0589 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -662,78 +662,46 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
{
- BMVert *v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8;
- float vec[3], mat[4][4], off = BMO_slot_float_get(op->slots_in, "size") / 2.0f;
+ BMVert *verts[8];
+ float mat[4][4];
+ float off = BMO_slot_float_get(op->slots_in, "size") / 2.0f;
+ int i, x, y, z;
+ const char faces[6][4] = {
+ {1, 3, 2, 0},
+ {3, 7, 6, 2},
+ {7, 5, 4, 6},
+ {5, 1, 0, 4},
+ {0, 2, 6, 4},
+ {5, 7, 3, 1},
+ };
BMO_slot_mat4_get(op->slots_in, "matrix", mat);
if (!off) off = 0.5f;
+ i = 0;
- vec[0] = -off;
- vec[1] = -off;
- vec[2] = -off;
- mul_m4_v3(mat, vec);
- v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v1, VERT_MARK);
-
- vec[0] = -off;
- vec[1] = off;
- vec[2] = -off;
- mul_m4_v3(mat, vec);
- v2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v2, VERT_MARK);
-
- vec[0] = off;
- vec[1] = off;
- vec[2] = -off;
- mul_m4_v3(mat, vec);
- v3 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v3, VERT_MARK);
-
- vec[0] = off;
- vec[1] = -off;
- vec[2] = -off;
- mul_m4_v3(mat, vec);
- v4 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v4, VERT_MARK);
-
- vec[0] = -off;
- vec[1] = -off;
- vec[2] = off;
- mul_m4_v3(mat, vec);
- v5 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v5, VERT_MARK);
-
- vec[0] = -off;
- vec[1] = off;
- vec[2] = off;
- mul_m4_v3(mat, vec);
- v6 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v6, VERT_MARK);
-
- vec[0] = off;
- vec[1] = off;
- vec[2] = off;
- mul_m4_v3(mat, vec);
- v7 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v7, VERT_MARK);
-
- vec[0] = off;
- vec[1] = -off;
- vec[2] = off;
- mul_m4_v3(mat, vec);
- v8 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, v8, VERT_MARK);
-
- /* the four sides */
- 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, BM_CREATE_NOP);
- BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, BM_CREATE_NOP);
+ for (x = -1; x < 2; x += 2) {
+ for (y = -1; y < 2; y += 2) {
+ for (z = -1; z < 2; z += 2) {
+ float vec[3] = {(float)x * off, (float)y * off, (float)z * off};
+ mul_m4_v3(mat, vec);
+ verts[i] = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
+ BMO_elem_flag_enable(bm, verts[i], VERT_MARK);
+ i++;
+ }
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(faces); i++) {
+ BMVert *quad[4] = {
+ verts[faces[i][0]],
+ verts[faces[i][1]],
+ verts[faces[i][2]],
+ verts[faces[i][3]],
+ };
+
+ BM_face_create_verts(bm, quad, 4, NULL, BM_CREATE_NOP, true);
+ }
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 75f9feef413..9c8b9ca160d 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -238,7 +238,7 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
static int vergaverco(const void *e1, const void *e2)
{
- const BMVert *v1 = *(void **)e1, *v2 = *(void **)e2;
+ const BMVert *v1 = *(const void **)e1, *v2 = *(const void **)e2;
float x1 = v1->co[0] + v1->co[1] + v1->co[2];
float x2 = v2->co[0] + v2->co[1] + v2->co[2];
diff --git a/source/blender/bmesh/operators/bmo_similar.c b/source/blender/bmesh/operators/bmo_similar.c
index 4b5eebb2a73..02462e380b4 100644
--- a/source/blender/bmesh/operators/bmo_similar.c
+++ b/source/blender/bmesh/operators/bmo_similar.c
@@ -245,6 +245,13 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
cont = false;
}
break;
+
+ case SIMFACE_SMOOTH:
+ if (BM_elem_flag_test(fm, BM_ELEM_SMOOTH) == BM_elem_flag_test(fs, BM_ELEM_SMOOTH)) {
+ BMO_elem_flag_enable(bm, fm, FACE_MARK);
+ cont = false;
+ }
+ break;
#ifdef WITH_FREESTYLE
case SIMFACE_FREESTYLE:
if (CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE)) {
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index 7b125186110..87311199f52 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -1082,7 +1082,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BMIter other_fiter;
BM_ITER_ELEM (other_loop, &other_fiter, loops[a]->v, BM_LOOPS_OF_VERT) {
if (other_loop->f != face) {
- if (BM_vert_in_face(other_loop->f, loops[b]->v)) {
+ if (BM_vert_in_face(loops[b]->v, other_loop->f)) {
/* we assume that these verts are not making an edge in the face */
BLI_assert(other_loop->prev->v != loops[a]->v);
BLI_assert(other_loop->next->v != loops[a]->v);
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index e7b65a10790..da1991a187d 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -236,6 +236,20 @@ static void bmo_region_extend_expand(
bmo_face_flag_set_flush(bm, f, SEL_FLAG, true);
}
}
+
+ /* handle wire edges (when stepping over faces) */
+ {
+ BMIter eiter;
+ BMEdge *e;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_wire(e)) {
+ if (!BMO_elem_flag_test(bm, e, SEL_FLAG)) {
+ BMO_elem_flag_enable(bm, e, SEL_FLAG);
+ BMO_elem_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG);
+ }
+ }
+ }
+ }
}
}
}
@@ -306,6 +320,21 @@ static void bmo_region_extend_contract(
break;
}
}
+
+ /* handle wire edges (when stepping over faces) */
+ if (!found) {
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_wire(e)) {
+ if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
}
if (found) {
diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c
index 62409fc3987..ac81dde93c0 100644
--- a/source/blender/bmesh/operators/bmo_wireframe.c
+++ b/source/blender/bmesh/operators/bmo_wireframe.c
@@ -26,8 +26,6 @@
* Creates a solid wireframe from connected faces.
*/
-#include "MEM_guardedalloc.h"
-
#include "DNA_material_types.h"
#include "BLI_sys_types.h"
diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c
index 6639e767e77..990a2108bd7 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.c
+++ b/source/blender/bmesh/tools/bmesh_beautify.c
@@ -37,6 +37,7 @@
#include "BLI_math.h"
#include "BLI_heap.h"
+#include "BLI_polyfill2d_beautify.h"
#include "MEM_guardedalloc.h"
@@ -96,7 +97,7 @@ static GSet *erot_gset_new(void)
static void erot_state_ex(const BMEdge *e, int v_index[2], int f_index[2])
{
- BLI_assert(BM_edge_is_manifold((BMEdge *)e));
+ BLI_assert(BM_edge_is_manifold(e));
BLI_assert(BM_vert_in_edge(e, e->l->prev->v) == false);
BLI_assert(BM_vert_in_edge(e, e->l->radial_next->prev->v) == false);
@@ -125,22 +126,22 @@ static void erot_state_alternate(const BMEdge *e, EdRotState *e_state)
/* -------------------------------------------------------------------- */
/* Calculate the improvement of rotating the edge */
-/**
- * \return a negative value means the edge can be rotated.
- */
static float bm_edge_calc_rotate_beauty__area(
const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
/* not a loop (only to be able to break out) */
do {
float v1_xy[2], v2_xy[2], v3_xy[2], v4_xy[2];
- bool is_zero_a, is_zero_b;
/* first get the 2d values */
{
+ const float eps = 1e-5;
float no_a[3], no_b[3];
float no[3];
float axis_mat[3][3];
+ float no_scale;
+ cross_tri_v3(no_a, v2, v3, v4);
+ cross_tri_v3(no_b, v2, v4, v1);
// printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
BLI_assert((ELEM(v1, v2, v3, v4) == false) &&
@@ -148,97 +149,40 @@ static float bm_edge_calc_rotate_beauty__area(
(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);
-
- if (LIKELY(is_zero_a == false && is_zero_b == false)) {
- add_v3_v3v3(no, no_a, no_b);
- if (UNLIKELY(normalize_v3(no) <= FLT_EPSILON)) {
- break;
- }
- }
- else if (is_zero_a == false) {
- copy_v3_v3(no, no_a);
- }
- else if (is_zero_b == false) {
- copy_v3_v3(no, no_b);
- }
- else {
- /* both zero area, no useful normal can be calculated */
+ add_v3_v3v3(no, no_a, no_b);
+ if (UNLIKELY((no_scale = normalize_v3(no)) <= FLT_EPSILON)) {
break;
}
- // { float a = angle_normalized_v3v3(no_a, no_b); printf("~ %.7f\n", a); fflush(stdout);}
-
axis_dominant_v3_to_m3(axis_mat, no);
mul_v2_m3v3(v1_xy, axis_mat, v1);
mul_v2_m3v3(v2_xy, axis_mat, v2);
mul_v2_m3v3(v3_xy, axis_mat, v3);
mul_v2_m3v3(v4_xy, axis_mat, v4);
- }
-
- // printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
-
- if (is_zero_a == false && is_zero_b == false) {
- /* both tri's are valid, check we make a concave quad */
- if (!is_quad_convex_v2(v1_xy, v2_xy, v3_xy, v4_xy)) {
- break;
- }
- }
- else {
- /* one of the tri's was degenerate, chech we're not rotating
- * into a different degenerate shape or flipping the face */
- float area_a, area_b;
-
- area_a = area_tri_signed_v2(v1_xy, v2_xy, v3_xy);
- area_b = area_tri_signed_v2(v1_xy, v3_xy, v4_xy);
-
- if ((fabsf(area_a) <= FLT_EPSILON) || (fabsf(area_b) <= FLT_EPSILON)) {
- /* one of the new rotations is degenerate */
- break;
- }
- if ((area_a >= 0.0f) != (area_b >= 0.0f)) {
- /* rotation would cause flipping */
+ /**
+ * Check if input faces are already flipped.
+ * Logic for 'signum_i' addition is:
+ *
+ * Accept:
+ * - (1, 1) or (-1, -1): same side (common case).
+ * - (-1/1, 0): one degenerate, OK since we may rotate into a valid state.
+ *
+ * Ignore:
+ * - (-1, 1): opposite winding, ignore.
+ * - ( 0, 0): both degenerate, ignore.
+ *
+ * \note The cross product is divided by 'no_scale'
+ * so the rotation calculation is scale independent.
+ */
+ if (!(signum_i_ex(cross_tri_v2(v2_xy, v3_xy, v4_xy) / no_scale, eps) +
+ signum_i_ex(cross_tri_v2(v2_xy, v4_xy, v1_xy) / no_scale, eps)))
+ {
break;
}
}
- {
- /* testing rule: the area divided by the perimeter,
- * check if (1-3) beats the existing (2-4) edge rotation */
- float area_a, area_b;
- float prim_a, prim_b;
- float fac_24, fac_13;
-
- float len_12, len_23, len_34, len_41, len_24, len_13;
-
- /* edges around the quad */
- len_12 = len_v2v2(v1_xy, v2_xy);
- len_23 = len_v2v2(v2_xy, v3_xy);
- len_34 = len_v2v2(v3_xy, v4_xy);
- len_41 = len_v2v2(v4_xy, v1_xy);
- /* edges crossing the quad interior */
- len_13 = len_v2v2(v1_xy, v3_xy);
- len_24 = len_v2v2(v2_xy, v4_xy);
-
- /* edge (2-4), current state */
- area_a = area_tri_v2(v2_xy, v3_xy, v4_xy);
- area_b = area_tri_v2(v2_xy, v4_xy, v1_xy);
- prim_a = len_23 + len_34 + len_24;
- prim_b = len_24 + len_41 + len_12;
- fac_24 = (area_a / prim_a) + (area_b / prim_b);
-
- /* edge (1-3), new state */
- area_a = area_tri_v2(v1_xy, v2_xy, v3_xy);
- area_b = area_tri_v2(v1_xy, v3_xy, v4_xy);
- prim_a = len_12 + len_23 + len_13;
- prim_b = len_34 + len_41 + len_13;
- fac_13 = (area_a / prim_a) + (area_b / prim_b);
-
- /* negative number if (1-3) is an improved state */
- return fac_24 - fac_13;
- }
+ return BLI_polyfill_beautify_quad_rotate_calc(v1_xy, v2_xy, v3_xy, v4_xy);
} while (false);
return FLT_MAX;
@@ -272,6 +216,12 @@ static float bm_edge_calc_rotate_beauty__angle(
return FLT_MAX;
}
+/**
+ * Assuming we have 2 triangles sharing an edge (2 - 4),
+ * check if the edge running from (1 - 3) gives better results.
+ *
+ * \return (negative number means the edge can be rotated, lager == better).
+ */
float BM_verts_calc_rotate_beauty(
const BMVert *v1, const BMVert *v2, const BMVert *v3, const BMVert *v4,
const short flag, const short method)
@@ -400,9 +350,10 @@ static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_
/**
* \note This function sets the edge indices to invalid values.
*/
-void BM_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge_array_len,
- const short flag, const short method,
- const short oflag_edge, const short oflag_face)
+void BM_mesh_beautify_fill(
+ BMesh *bm, BMEdge **edge_array, const int edge_array_len,
+ const short flag, const short method,
+ const short oflag_edge, const short oflag_face)
{
Heap *eheap; /* edge heap */
HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */
diff --git a/source/blender/bmesh/tools/bmesh_beautify.h b/source/blender/bmesh/tools/bmesh_beautify.h
index 7cc17008b50..0d6aa23b81d 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.h
+++ b/source/blender/bmesh/tools/bmesh_beautify.h
@@ -31,12 +31,14 @@ enum {
VERT_RESTRICT_TAG = (1 << 0),
};
-void BM_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge_array_len,
- const short flag, const short method,
- const short oflag_edge, const short oflag_face);
+void BM_mesh_beautify_fill(
+ BMesh *bm, BMEdge **edge_array, const int edge_array_len,
+ const short flag, const short method,
+ const short oflag_edge, const short oflag_face);
-float BM_verts_calc_rotate_beauty(const BMVert *v1, const BMVert *v2,
- const BMVert *v3, const BMVert *v4,
- const short flag, const short method);
+float BM_verts_calc_rotate_beauty(
+ const BMVert *v1, const BMVert *v2,
+ const BMVert *v3, const BMVert *v4,
+ const short flag, const short method);
#endif /* __BMESH_BEAUTIFY_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 99ff6996b71..b25572ed8e2 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -1474,7 +1474,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
return;
}
- lastd = bp->vertex_only ? bv->offset : e->offset_l;
+ lastd = e->offset_l;
do {
if (e->is_bev) {
/* handle only left side of beveled edge e here: next iteration should do right side */
@@ -1557,9 +1557,10 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
/* None of e->prev, e, e->next are beveled.
* could either leave alone or add slide points to make
* one polygon around bv->v. For now, we choose latter.
+ * For vertex bevel, we use e->offset_l as slide distance.
* Could slide to make an even bevel plane but for now will
* just use last distance a meet point moved from bv->v. */
- slide_dist(e, bv->v, lastd, co);
+ slide_dist(e, bv->v, bp->vertex_only ? e->offset_l : lastd, co);
if (construct) {
v = add_new_bound_vert(mem_arena, vm, co);
v->efirst = v->elast = e;
@@ -2229,7 +2230,6 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
BoundVert *bndv;
int i, j, k, ns2;
float co[3], coc[3];
- float w;
if (r == PRO_SQUARE_R)
return make_cube_corner_straight(mem_arena, nseg);
@@ -2262,10 +2262,8 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
bndv = bndv->next;
}
/* center vertex */
- w = (float)(1.0 / M_SQRT3);
- co[0] = w;
- co[1] = w;
- co[2] = w;
+ copy_v3_fl(co, M_SQRT1_3);
+
if (nseg > 2) {
if (r > 1.5f)
mul_v3_fl(co, 1.4f);
@@ -3081,6 +3079,18 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
e->offset_r_spec *= weight;
}
}
+ else if (bp->vertex_only) {
+ /* Weight has already been applied to bv->offset, if present.
+ * Transfer to e->offset_[lr]_spec and treat percent as special case */
+ if (bp->offset_type == BEVEL_AMT_PERCENT) {
+ v2 = BM_edge_other_vert(e->e, bv->v);
+ e->offset_l_spec = BM_edge_calc_length(e->e) * bv->offset / 100.0f;
+ }
+ else {
+ e->offset_l_spec = bv->offset;
+ }
+ e->offset_r_spec = e->offset_l_spec;
+ }
else {
e->offset_l_spec = e->offset_r_spec = 0.0f;
}
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c
index 463304f27f7..e6e33c905da 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.c
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c
@@ -112,7 +112,7 @@ static int bm_vert_sortval_cb(const void *v_a_v, const void *v_b_v)
static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center)
{
- /* unlikely more then 2 verts are needed */
+ /* unlikely more than 2 verts are needed */
const unsigned int f_len_orig = (unsigned int)f->len;
BMVert **vert_split_arr = BLI_array_alloca(vert_split_arr, f_len_orig);
STACK_DECLARE(vert_split_arr);
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 4d87c3e3551..8a1569630fa 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -857,7 +857,7 @@ bool BM_mesh_intersect(
{UNPACK3(looptris[i][2]->v->co)},
};
- BLI_bvhtree_insert(tree_a, i, (float *)t_cos, 3);
+ BLI_bvhtree_insert(tree_a, i, (const float *)t_cos, 3);
}
}
BLI_bvhtree_balance(tree_a);
@@ -874,7 +874,7 @@ bool BM_mesh_intersect(
{UNPACK3(looptris[i][2]->v->co)},
};
- BLI_bvhtree_insert(tree_b, i, (float *)t_cos, 3);
+ BLI_bvhtree_insert(tree_b, i, (const float *)t_cos, 3);
}
}
BLI_bvhtree_balance(tree_b);
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c
index 446c03a543f..b76054f270f 100644
--- a/source/blender/bmesh/tools/bmesh_triangulate.c
+++ b/source/blender/bmesh/tools/bmesh_triangulate.c
@@ -27,13 +27,20 @@
*
*/
+#include "DNA_modifier_types.h" /* for MOD_TRIANGULATE_NGON_BEAUTY only */
+
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
#include "BLI_memarena.h"
#include "BLI_listbase.h"
-#include "BLI_scanfill.h"
+#include "BLI_heap.h"
+#include "BLI_edgehash.h"
+
+/* only for defines */
+#include "BLI_polyfill2d.h"
+#include "BLI_polyfill2d_beautify.h"
#include "bmesh.h"
@@ -42,16 +49,25 @@
/**
* a version of #BM_face_triangulate that maps to #BMOpSlot
*/
-static void bm_face_triangulate_mapping(BMesh *bm, BMFace *face, MemArena *sf_arena,
- const int quad_method, const int ngon_method,
- const bool use_tag,
- BMOperator *op, BMOpSlot *slot_facemap_out)
+static void bm_face_triangulate_mapping(
+ BMesh *bm, BMFace *face,
+ const int quad_method, const int ngon_method,
+ const bool use_tag,
+ BMOperator *op, BMOpSlot *slot_facemap_out,
+
+ MemArena *pf_arena,
+ /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
+ struct Heap *pf_heap, struct EdgeHash *pf_ehash)
{
int faces_array_tot = face->len - 3;
BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
BLI_assert(face->len > 3);
- BM_face_triangulate(bm, face, faces_array, &faces_array_tot, sf_arena, quad_method, ngon_method, use_tag);
+ BM_face_triangulate(
+ bm, face, faces_array, &faces_array_tot,
+ quad_method, ngon_method, use_tag,
+ pf_arena,
+ pf_heap, pf_ehash);
if (faces_array_tot) {
int i;
@@ -63,22 +79,39 @@ static void bm_face_triangulate_mapping(BMesh *bm, BMFace *face, MemArena *sf_ar
}
-void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method, const bool tag_only,
- BMOperator *op, BMOpSlot *slot_facemap_out)
+void BM_mesh_triangulate(
+ BMesh *bm, const int quad_method, const int ngon_method, const bool tag_only,
+ BMOperator *op, BMOpSlot *slot_facemap_out)
{
BMIter iter;
BMFace *face;
- MemArena *sf_arena;
+ MemArena *pf_arena;
+ Heap *pf_heap;
+ EdgeHash *pf_ehash;
- sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
+ pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
+
+ if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) {
+ pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ pf_ehash = BLI_edgehash_new_ex(__func__, BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ }
+ else {
+ pf_heap = NULL;
+ pf_ehash = NULL;
+ }
if (slot_facemap_out) {
/* same as below but call: bm_face_triangulate_mapping() */
BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
if (face->len > 3) {
if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) {
- bm_face_triangulate_mapping(bm, face, sf_arena, quad_method, ngon_method, tag_only,
- op, slot_facemap_out);
+ bm_face_triangulate_mapping(
+ bm, face, quad_method,
+ ngon_method, tag_only,
+ op, slot_facemap_out,
+
+ pf_arena,
+ pf_heap, pf_ehash);
}
}
}
@@ -87,11 +120,20 @@ void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method
BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
if (face->len > 3) {
if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) {
- BM_face_triangulate(bm, face, NULL, NULL, sf_arena, quad_method, ngon_method, tag_only);
+ BM_face_triangulate(
+ bm, face, NULL, NULL,
+ quad_method, ngon_method, tag_only,
+ pf_arena,
+ pf_heap, pf_ehash);
}
}
}
}
- BLI_memarena_free(sf_arena);
+ BLI_memarena_free(pf_arena);
+
+ if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) {
+ BLI_heap_free(pf_heap, NULL);
+ BLI_edgehash_free(pf_ehash, NULL);
+ }
}
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index 033145b33d1..7ffd300c6de 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -37,6 +37,7 @@
#include "BKE_object.h"
#include "BKE_armature.h"
#include "BLI_string.h"
+#include "BLI_listbase.h"
#include "ED_armature.h"
#include "ArmatureImporter.h"
@@ -49,7 +50,22 @@ static const char *bc_get_joint_name(T *node)
return id.size() ? id.c_str() : node->getOriginalId().c_str();
}
-ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce) :
+static EditBone *get_edit_bone(bArmature * armature, char *name) {
+ EditBone *eBone;
+
+ for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) {
+ if (!strcmp(name, eBone->name))
+ return eBone;
+ }
+
+ return NULL;
+
+}
+
+
+
+ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, const ImportSettings *import_settings) :
+ import_settings(import_settings),
unit_converter(conv),
TransformReader(conv),
scene(sce),
@@ -57,6 +73,15 @@ ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh,
mesh_importer(mesh) {
}
+void ArmatureImporter::clear_extended_boneset()
+{
+ for (std::map<std::string, BoneExtended *>::iterator it = extended_bones.begin(); it != extended_bones.end(); ++it) {
+ if (it->second != NULL)
+ delete it->second;
+ }
+ extended_bones.clear();
+}
+
ArmatureImporter::~ArmatureImporter()
{
// free skin controller data if we forget to do this earlier
@@ -64,6 +89,7 @@ ArmatureImporter::~ArmatureImporter()
for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) {
it->second.free();
}
+ clear_extended_boneset();
}
#if 0
@@ -83,16 +109,17 @@ JointData *ArmatureImporter::get_joint_data(COLLADAFW::Node *node);
}
#endif
-void ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
+int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
float parent_mat[4][4], bArmature *arm)
{
float mat[4][4];
float joint_inv_bind_mat[4][4];
+ int chain_length = 0;
//Checking if bone is already made.
std::vector<COLLADAFW::Node *>::iterator it;
it = std::find(finished_joints.begin(), finished_joints.end(), node);
- if (it != finished_joints.end()) return;
+ if (it != finished_joints.end()) return chain_length;
// JointData* jd = get_joint_data(node);
@@ -143,96 +170,156 @@ void ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBo
// set tail, don't set it to head because 0-length bones are not allowed
add_v3_v3v3(bone->tail, bone->head, vec);
- // set parent tail
+ /* find smallest bone length in armature (used later for leaf bone length) */
if (parent) {
- // XXX increase this to prevent "very" small bones?
- const float epsilon = 0.000001f;
-
- // derive leaf bone length
+ /* guess reasonable leaf bone length */
float length = len_v3v3(parent->head, bone->head);
- if ((length < leaf_bone_length || totbone == 0) && length > epsilon) {
+ if ((length < leaf_bone_length || totbone == 0) && length > MINIMUM_BONE_LENGTH) {
leaf_bone_length = length;
}
-
- if (totchild == 1) {
- copy_v3_v3(parent->tail, bone->head);
-
- // not setting BONE_CONNECTED because this would lock child bone location with respect to parent
- bone->flag |= BONE_CONNECTED;
-
-
- // treat zero-sized bone like a leaf bone
- if (length <= epsilon) {
- add_leaf_bone(parent_mat, parent, node);
- }
- }
-
}
COLLADAFW::NodePointerArray& children = node->getChildNodes();
+
+ BoneExtended &be = add_bone_extended(bone, node);
+ be.set_leaf_bone(true);
+
for (unsigned int i = 0; i < children.getCount(); i++) {
- create_bone(skin, children[i], bone, children.getCount(), mat, arm);
+ int cl = create_bone(skin, children[i], bone, children.getCount(), mat, arm);
+ if (cl > chain_length)
+ chain_length = cl;
}
- // in second case it's not a leaf bone, but we handle it the same way
- if (!children.getCount() || children.getCount() > 1) {
- add_leaf_bone(mat, bone, node);
- }
bone->length = len_v3v3(bone->head, bone->tail);
joint_by_uid[node->getUniqueId()] = node;
finished_joints.push_back(node);
+
+ be.set_chain_length(chain_length + 1);
+
+ return chain_length + 1;
}
-void ArmatureImporter::add_leaf_bone(float mat[4][4], EditBone *bone, COLLADAFW::Node *node)
+/**
+ * Collada only knows Joints, hence bones at the end of a bone chain
+ * don't have a defined length. This function guesses reasonable
+ * tail locations for the affected bones (nodes which don't have any connected child)
+ * Hint: The extended_bones set gets populated in ArmatureImporter::create_bone
+**/
+void ArmatureImporter::fix_leaf_bones(bArmature *armature, Bone *bone)
{
- LeafBone leaf;
+ /* armature has no bones */
+ if (bone == NULL)
+ return;
- leaf.bone = bone;
- copy_m4_m4(leaf.mat, mat);
- BLI_strncpy(leaf.name, bone->name, sizeof(leaf.name));
-
- TagsMap::iterator etit;
- ExtraTags *et = 0;
- etit = uid_tags_map.find(node->getUniqueId().toAscii());
- if (etit != uid_tags_map.end()) {
- et = etit->second;
- //else return;
+ BoneExtended *be = extended_bones[bone->name];
+ if (be != NULL && be->is_leaf_bone() ) {
+ /* Collada only knows Joints, Here we guess a reasonable leaf bone length */
+ float leaf_length = (leaf_bone_length == FLT_MAX) ? 1.0 : leaf_bone_length;
+
+ EditBone *ebone = get_edit_bone(armature, bone->name);
+ float vec[3];
+
+ if (this->import_settings->fix_orientation) {
+ if (ebone->parent != NULL) {
+ EditBone *parent = ebone->parent;
+ sub_v3_v3v3(vec, ebone->head, parent->tail);
+ if (len_squared_v3(vec) < MINIMUM_BONE_LENGTH)
+ {
+ sub_v3_v3v3(vec, parent->tail, parent->head);
+ }
+ }
+ else {
+ vec[2] = 0.1f;
+ sub_v3_v3v3(vec, ebone->tail, ebone->head);
+ }
+ }
+ else {
+ sub_v3_v3v3(vec, ebone->tail, ebone->head);
+ }
- float x, y, z;
- et->setData("tip_x", &x);
- et->setData("tip_y", &y);
- et->setData("tip_z", &z);
- float vec[3] = {x, y, z};
- copy_v3_v3(leaf.bone->tail, leaf.bone->head);
- add_v3_v3v3(leaf.bone->tail, leaf.bone->head, vec);
- }
- else {
- leaf_bones.push_back(leaf);
+ normalize_v3_v3(vec, vec);
+ mul_v3_fl(vec, leaf_length);
+ add_v3_v3v3(ebone->tail, ebone->head, vec);
}
-}
-void ArmatureImporter::fix_leaf_bones( )
-{
- // Collada only knows Joints, Here we guess a reasonable
- // leaf bone length
- float leaf_length = (leaf_bone_length == FLT_MAX) ? 1.0:leaf_bone_length;
+ for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+ fix_leaf_bones(armature, child);
+ }
- // just setting tail for leaf bones here
- std::vector<LeafBone>::iterator it;
- for (it = leaf_bones.begin(); it != leaf_bones.end(); it++) {
+}
- LeafBone& leaf = *it;
- // pointing up
- float vec[3] = {0.0f, 0.0f, 0.1f};
-
- sub_v3_v3v3(vec, leaf.bone->tail , leaf.bone->head);
- mul_v3_fl(vec, leaf_length);
- add_v3_v3v3(leaf.bone->tail, leaf.bone->head , vec);
+void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone, int clip)
+{
+ BoneExtended *dominant_child = NULL;
+ int maxlen = 0;
+ Bone *child = (Bone *)parentbone->childbase.first;
+ if (child && (import_settings->find_chains || child->next==NULL) )
+ {
+ for (; child; child = child->next) {
+ BoneExtended *be = extended_bones[child->name];
+ if (be != NULL) {
+ if (be->get_chain_length() <= clip) {
+ if (be->get_chain_length() > maxlen) {
+ dominant_child = be;
+ maxlen = be->get_chain_length();
+ }
+ else if (be->get_chain_length() == maxlen) {
+ dominant_child = NULL;
+ }
+ }
+ }
+ }
+ }
+ BoneExtended *pbe = extended_bones[parentbone->name];
+ if (dominant_child != NULL) {
+ /* Found a valid chain. Now connect current bone with that chain.*/
+ EditBone *pebone = get_edit_bone(armature, parentbone->name);
+ EditBone *cebone = get_edit_bone(armature, dominant_child->get_name());
+ if (pebone && !(cebone->flag & BONE_CONNECTED)) {
+
+ float vec[3];
+ sub_v3_v3v3(vec, cebone->head, pebone->head);
+
+ /*
+ * It is possible that the child's head is located on the parents head.
+ * When this happens, then moving the parent's tail to the child's head
+ * would result in a zero sized bone and Blender would silently remove the bone.
+ * So we move the tail only when the resulting bone has a minimum length:
+ */
+
+ if (len_squared_v3(vec) > MINIMUM_BONE_LENGTH)
+ {
+ pebone->tail[0] = cebone->head[0];
+ pebone->tail[1] = cebone->head[1];
+ pebone->tail[2] = cebone->head[2];
+
+ if (pbe && pbe->get_chain_length() >= this->import_settings->min_chain_length) {
+ cebone->flag |= BONE_CONNECTED;
+ printf("Connecting chain: parent %s --> %s (child)\n", pebone->name, cebone->name);
+ pbe->set_leaf_bone(false);
+ }
+ }
+ }
+ for (Bone *child = (Bone *)parentbone->childbase.first; child; child = child->next) {
+ ArmatureImporter::connect_bone_chains(armature, child, UNLIMITED_CHAIN_MAX);
+ }
+ }
+ else if (maxlen>1 && maxlen > this->import_settings->min_chain_length) {
+ /* Try again with smaller chain length */
+ ArmatureImporter::connect_bone_chains(armature, parentbone, maxlen - 1);
}
+ else {
+ /* can't connect this Bone. Proceed with children ... */
+ if (pbe) pbe->set_leaf_bone(true);
+ for (Bone *child = (Bone *)parentbone->childbase.first; child; child = child->next) {
+ ArmatureImporter::connect_bone_chains(armature, child, UNLIMITED_CHAIN_MAX);
+ }
+ }
+
}
#if 0
@@ -351,21 +438,26 @@ void ArmatureImporter::create_armature_bones( )
continue;
}
+ clear_extended_boneset();
+
ED_armature_to_edit(armature);
create_bone(NULL, *ri , NULL, (*ri)->getChildNodes().getCount(), NULL, armature);
- //leaf bone tails are derived from the matrix, so no need of this.
- fix_leaf_bones();
+ /* exit armature edit mode to populate the Armature object */
+ ED_armature_from_edit(armature);
+ ED_armature_edit_free(armature);
+
+ /* and step back to edit mode to fix the leaf nodes */
+ ED_armature_to_edit(armature);
+
+ connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX);
+ fix_leaf_bones(armature, (Bone *)armature->bonebase.first);
// exit armature edit mode
unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm;
ED_armature_from_edit(armature);
-
- //This serves no purpose, as pose is automatically reset later, in BKE_where_is_bone()
- //set_pose(ob_arm, *ri, NULL, NULL);
-
ED_armature_edit_free(armature);
DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
}
@@ -459,9 +551,11 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
}
// enter armature edit mode
- ED_armature_to_edit((bArmature *)ob_arm->data);
+ bArmature * armature = (bArmature *)ob_arm->data;
+ ED_armature_to_edit(armature);
+
+ clear_extended_boneset();
- leaf_bones.clear();
totbone = 0;
// bone_direction_row = 1; // TODO: don't default to Y but use asset and based on it decide on default row
leaf_bone_length = FLT_MAX;
@@ -480,20 +574,27 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
// since root_joints may contain joints for multiple controllers, we need to filter
if (skin.uses_joint_or_descendant(*ri)) {
- create_bone(&skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, (bArmature *)ob_arm->data);
+ create_bone(&skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, armature);
if (joint_parent_map.find((*ri)->getUniqueId()) != joint_parent_map.end() && !skin.get_parent())
skin.set_parent(joint_parent_map[(*ri)->getUniqueId()]);
}
}
- fix_leaf_bones();
+ /* exit armature edit mode to populate the Armature object */
+ ED_armature_from_edit(armature);
+ ED_armature_edit_free(armature);
+
+ /* and step back to edit mode to fix the leaf nodes */
+ ED_armature_to_edit(armature);
+
+ connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX);
+ fix_leaf_bones(armature, (Bone *)armature->bonebase.first);
// exit armature edit mode
- ED_armature_from_edit((bArmature *)ob_arm->data);
- ED_armature_edit_free((bArmature *)ob_arm->data);
+ ED_armature_from_edit(armature);
+ ED_armature_edit_free(armature);
DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
-
}
void ArmatureImporter::set_pose(Object *ob_arm, COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4])
@@ -538,10 +639,11 @@ void ArmatureImporter::set_pose(Object *ob_arm, COLLADAFW::Node *root_node, con
}
-
-// root - if this joint is the top joint in hierarchy, if a joint
-// is a child of a node (not joint), root should be true since
-// this is where we build armature bones from
+/**
+ * root - if this joint is the top joint in hierarchy, if a joint
+ * is a child of a node (not joint), root should be true since
+ * this is where we build armature bones from
+ **/
void ArmatureImporter::add_root_joint(COLLADAFW::Node *node, Object *parent)
{
root_joints.push_back(node);
@@ -785,3 +887,71 @@ bool ArmatureImporter::get_joint_bind_mat(float m[4][4], COLLADAFW::Node *joint)
return found;
}
+
+
+/**
+ * BoneExtended is a helper class needed for the Bone chain finder
+ * See ArmatureImporter::fix_leaf_bones()
+ * and ArmatureImporter::connect_bone_chains()
+ **/
+
+BoneExtended::BoneExtended(EditBone *aBone)
+{
+ this->set_name(aBone->name);
+ this->chain_length = 0;
+ this->is_leaf = false;
+}
+
+char *BoneExtended::get_name()
+{
+ return name;
+}
+
+void BoneExtended::set_name(char *aName)
+{
+ BLI_strncpy(name, aName, MAXBONENAME);
+}
+
+int BoneExtended::get_chain_length()
+{
+ return chain_length;
+}
+
+void BoneExtended::set_chain_length(const int aLength)
+{
+ chain_length = aLength;
+}
+
+
+void BoneExtended::set_leaf_bone(bool state)
+{
+ is_leaf = state;
+}
+
+bool BoneExtended::is_leaf_bone()
+{
+ return is_leaf;
+}
+
+BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Node *node)
+{
+
+ TagsMap::iterator etit;
+ ExtraTags *et = 0;
+ etit = uid_tags_map.find(node->getUniqueId().toAscii());
+ if (etit != uid_tags_map.end()) {
+ float x, y, z;
+
+ et = etit->second;
+ et->setData("tip_x", &x);
+ et->setData("tip_y", &y);
+ et->setData("tip_z", &z);
+ float vec[3] = { x, y, z };
+ copy_v3_v3(bone->tail, bone->head);
+ add_v3_v3v3(bone->tail, bone->head, vec);
+ }
+
+ BoneExtended *be = new BoneExtended(bone);
+ extended_bones[bone->name] = be;
+ return *be;
+}
diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h
index beeac85cc4d..732fda80ff1 100644
--- a/source/blender/collada/ArmatureImporter.h
+++ b/source/blender/collada/ArmatureImporter.h
@@ -54,23 +54,41 @@ extern "C" {
#include "collada_internal.h"
#include "collada_utils.h"
+#include "ImportSettings.h"
+
+#define UNLIMITED_CHAIN_MAX INT_MAX
+#define MINIMUM_BONE_LENGTH 0.000001f
+
+class BoneExtended {
+
+private:
+ char name[MAXBONENAME];
+ int chain_length;
+ bool is_leaf;
+
+public:
+
+ BoneExtended(EditBone *aBone);
+ char *get_name();
+ int get_chain_length();
+
+ void set_name(char *aName);
+ void set_chain_length(const int aLength);
+ void set_leaf_bone(bool state);
+ bool is_leaf_bone();
+};
class ArmatureImporter : private TransformReader
{
private:
Scene *scene;
UnitConverter *unit_converter;
+ const ImportSettings *import_settings;
// std::map<int, JointData> joint_index_to_joint_info_map;
// std::map<COLLADAFW::UniqueId, int> joint_id_to_joint_index_map;
- struct LeafBone {
- // COLLADAFW::Node *node;
- EditBone *bone;
- char name[32];
- float mat[4][4]; // bone matrix, derived from inv_bind_mat
- };
- std::vector<LeafBone> leaf_bones;
+ std::map<std::string, BoneExtended *> extended_bones;
// int bone_direction_row; // XXX not used
float leaf_bone_length;
int totbone;
@@ -106,13 +124,15 @@ private:
JointData *get_joint_data(COLLADAFW::Node *node);
#endif
- void create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
+ int create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
float parent_mat[4][4], bArmature *arm);
- void add_leaf_bone(float mat[4][4], EditBone *bone, COLLADAFW::Node * node);
+ BoneExtended &add_bone_extended(EditBone *bone, COLLADAFW::Node * node);
+ void clear_extended_boneset();
+
+ void fix_leaf_bones(bArmature *armature, Bone *bone);
+ void connect_bone_chains(bArmature *armature, Bone *bone, const int max_chain_length);
- void fix_leaf_bones();
-
void set_pose( Object *ob_arm, COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4]);
@@ -137,7 +157,7 @@ private:
TagsMap uid_tags_map;
public:
- ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce);
+ ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, const ImportSettings *import_settings);
~ArmatureImporter();
void add_root_joint(COLLADAFW::Node *node, Object *parent);
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 8101e579098..20ef45b6b71 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -104,7 +104,7 @@ DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_set
import_settings(import_settings),
mImportStage(General),
mContext(C),
- armature_importer(&unit_converter, &mesh_importer, CTX_data_scene(C)),
+ armature_importer(&unit_converter, &mesh_importer, CTX_data_scene(C), import_settings),
mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)),
anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C))
{
diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp
index 7ac138ac807..854e8abd76d 100644
--- a/source/blender/collada/ErrorHandler.cpp
+++ b/source/blender/collada/ErrorHandler.cpp
@@ -47,7 +47,7 @@ ErrorHandler::~ErrorHandler()
//--------------------------------------------------------------------
bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
{
- mError = true;
+ bool isError = true;
if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXPARSER) {
COLLADASaxFWL::SaxParserError *saxParserError = (COLLADASaxFWL::SaxParserError *) error;
@@ -56,14 +56,14 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
// Workaround to avoid wrong error
if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_VALIDATION_MIN_OCCURS_UNMATCHED) {
if (strcmp(parserError.getElement(), "effect") == 0) {
- mError = false;
+ isError = false;
}
}
if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_VALIDATION_SEQUENCE_PREVIOUS_SIBLING_NOT_PRESENT) {
if (!((strcmp(parserError.getElement(), "extra") == 0) &&
(strcmp(parserError.getAdditionalText().c_str(), "sibling: fx_profile_abstract") == 0)))
{
- mError = false;
+ isError = false;
}
}
@@ -75,11 +75,21 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
}
else if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXFWL) {
COLLADASaxFWL::SaxFWLError *saxFWLError = (COLLADASaxFWL::SaxFWLError *) error;
+ /*
+ * Accept non critical errors as warnings (i.e. texture not found)
+ * This makes the importer more gracefull, so it now imports what makes sense.
+ */
+ if (saxFWLError->getSeverity() == COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL) {
+ isError = false;
+ }
+
std::cout << "Sax FWL Error: " << saxFWLError->getErrorMessage() << std::endl;
}
else {
std::cout << "opencollada error: " << error->getFullErrorMessage() << std::endl;
}
- return false;
+ mError |= isError;
+
+ return false; // let OpenCollada decide when to abort
}
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index 55fe2034869..5fd5fab3492 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -67,7 +67,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
return;
}
- bool is_dirty = imbuf->userflags & IB_BITMAPDIRTY;
+ bool is_dirty = (imbuf->userflags & IB_BITMAPDIRTY) != 0;
ImageFormatData imageFormat;
BKE_imbuf_to_image_format(&imageFormat, imbuf);
diff --git a/source/blender/collada/ImportSettings.h b/source/blender/collada/ImportSettings.h
index 3f3a9fb354e..51a13da7724 100644
--- a/source/blender/collada/ImportSettings.h
+++ b/source/blender/collada/ImportSettings.h
@@ -32,7 +32,9 @@
struct ImportSettings {
public:
bool import_units;
-
+ bool find_chains;
+ bool fix_orientation;
+ int min_chain_length;
char *filepath;
};
diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp
index 75928f9d189..71875d6274a 100644
--- a/source/blender/collada/SkinInfo.cpp
+++ b/source/blender/collada/SkinInfo.cpp
@@ -38,13 +38,16 @@
#include "BLI_math.h"
#include "BLI_compiler_attrs.h"
-#include "BKE_object.h"
#include "DNA_armature_types.h"
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
+
+#include "BKE_action.h"
+#include "BKE_object.h"
+#include "BKE_object_deform.h"
+
#include "ED_mesh.h"
#include "ED_object.h"
-#include "BKE_action.h"
#include "SkinInfo.h"
#include "collada_utils.h"
@@ -263,7 +266,7 @@ void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::Unique
name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]);
}
- ED_vgroup_add_name(ob, (char *)name);
+ BKE_object_defgroup_add_name(ob, name);
}
// <vcount> - number of joints per vertex - joints_per_vertex
diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp
index 595787b44ac..e205608a365 100644
--- a/source/blender/collada/TransformWriter.cpp
+++ b/source/blender/collada/TransformWriter.cpp
@@ -102,7 +102,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, B
double d_obmat[4][4];
float f_obmat[4][4];
- /* Export the local Matrix (relative to the object parent) */
+ /* Export the local Matrix (relative to the object parent, be it an object, bone or vertex(-tices)) */
BKE_object_matrix_local_get(ob, f_obmat);
converter.mat4_to_dae_double(d_obmat, f_obmat);
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index ffbbb8623ac..f1d5f1a208a 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -44,13 +44,18 @@ extern "C"
int collada_import(bContext *C,
const char *filepath,
- int import_units)
+ int import_units,
+ int find_chains,
+ int fix_orientation,
+ int min_chain_length)
{
ImportSettings import_settings;
- import_settings.filepath = (char *)filepath;
-
- import_settings.import_units = import_units != 0;
+ import_settings.filepath = (char *)filepath;
+ import_settings.import_units = import_units != 0;
+ import_settings.find_chains = find_chains != 0;
+ import_settings.fix_orientation = fix_orientation != 0;
+ import_settings.min_chain_length = min_chain_length;
DocumentImporter imp(C, &import_settings);
if (imp.import()) return 1;
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index 524c704cdee..6819a62fdf0 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -55,7 +55,10 @@ struct Scene;
*/
int collada_import(struct bContext *C,
const char *filepath,
- int import_units);
+ int import_units,
+ int find_chains,
+ int fix_orientation,
+ int min_chain_length);
int collada_export(struct Scene *sce,
const char *filepath,
diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h
index a398ae937a3..3fbafa0a029 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.h
+++ b/source/blender/compositor/intern/COM_CompositorContext.h
@@ -185,7 +185,7 @@ public:
void setFastCalculation(bool fastCalculation) {this->m_fastCalculation = fastCalculation;}
bool isFastCalculation() const { return this->m_fastCalculation; }
- bool isGroupnodeBufferEnabled() const { return this->getbNodeTree()->flag & NTREE_COM_GROUPNODE_BUFFER; }
+ bool isGroupnodeBufferEnabled() const { return (this->getbNodeTree()->flag & NTREE_COM_GROUPNODE_BUFFER) != 0; }
};
diff --git a/source/blender/compositor/intern/COM_Debug.cpp b/source/blender/compositor/intern/COM_Debug.cpp
index 470f8fd2ef7..af693ea9149 100644
--- a/source/blender/compositor/intern/COM_Debug.cpp
+++ b/source/blender/compositor/intern/COM_Debug.cpp
@@ -398,7 +398,7 @@ void DebugInfo::graphviz(const ExecutionSystem *system)
char filename[FILE_MAX];
BLI_snprintf(basename, sizeof(basename), "compositor_%d.dot", m_file_index);
- BLI_join_dirfile(filename, sizeof(filename), BLI_temp_dir_session(), basename);
+ BLI_join_dirfile(filename, sizeof(filename), BKE_tempdir_session(), basename);
++m_file_index;
FILE *fp = BLI_fopen(filename, "wb");
diff --git a/source/blender/compositor/intern/COM_NodeGraph.cpp b/source/blender/compositor/intern/COM_NodeGraph.cpp
index 2dcf419d81b..c5096a6b352 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.cpp
+++ b/source/blender/compositor/intern/COM_NodeGraph.cpp
@@ -179,6 +179,8 @@ void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink
/// @note: ignore invalid links
if (!(b_nodelink->flag & NODE_LINK_VALID))
return;
+ if ((b_nodelink->fromsock->flag & SOCK_UNAVAIL) || (b_nodelink->tosock->flag & SOCK_UNAVAIL))
+ return;
/* Note: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies)
* The output then gets linked to each one of them.
diff --git a/source/blender/compositor/nodes/COM_CompositorNode.cpp b/source/blender/compositor/nodes/COM_CompositorNode.cpp
index 3d79eb693ea..933b8d0282b 100644
--- a/source/blender/compositor/nodes/COM_CompositorNode.cpp
+++ b/source/blender/compositor/nodes/COM_CompositorNode.cpp
@@ -34,7 +34,7 @@ void CompositorNode::convertToOperations(NodeConverter &converter, const Composi
bNode *editorNode = this->getbNode();
bool is_active = (editorNode->flag & NODE_DO_OUTPUT_RECALC) ||
context.isRendering();
- bool ignore_alpha = editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA;
+ bool ignore_alpha = (editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA) != 0;
NodeInput *imageSocket = this->getInputSocket(0);
NodeInput *alphaSocket = this->getInputSocket(1);
diff --git a/source/blender/compositor/nodes/COM_MixNode.cpp b/source/blender/compositor/nodes/COM_MixNode.cpp
index b12dfc02ed7..89010d0e861 100644
--- a/source/blender/compositor/nodes/COM_MixNode.cpp
+++ b/source/blender/compositor/nodes/COM_MixNode.cpp
@@ -41,8 +41,8 @@ void MixNode::convertToOperations(NodeConverter &converter, const CompositorCont
NodeInput *color2Socket = this->getInputSocket(2);
NodeOutput *outputSocket = this->getOutputSocket(0);
bNode *editorNode = this->getbNode();
- bool useAlphaPremultiply = this->getbNode()->custom2 & 1;
- bool useClamp = this->getbNode()->custom2 & 2;
+ bool useAlphaPremultiply = (this->getbNode()->custom2 & 1) != 0;
+ bool useClamp = (this->getbNode()->custom2 & 2) != 0;
MixBaseOperation *convertProg;
switch (editorNode->custom1) {
diff --git a/source/blender/compositor/nodes/COM_ViewerNode.cpp b/source/blender/compositor/nodes/COM_ViewerNode.cpp
index 07aa960c4d9..ff0b8fb1706 100644
--- a/source/blender/compositor/nodes/COM_ViewerNode.cpp
+++ b/source/blender/compositor/nodes/COM_ViewerNode.cpp
@@ -35,7 +35,7 @@ void ViewerNode::convertToOperations(NodeConverter &converter, const CompositorC
{
bNode *editorNode = this->getbNode();
bool do_output = (editorNode->flag & NODE_DO_OUTPUT_RECALC || context.isRendering()) && (editorNode->flag & NODE_DO_OUTPUT);
- bool ignore_alpha = editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA;
+ bool ignore_alpha = (editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA) != 0;
NodeInput *imageSocket = this->getInputSocket(0);
NodeInput *alphaSocket = this->getInputSocket(1);
diff --git a/source/blender/compositor/operations/COM_OpenCLKernels.cl b/source/blender/compositor/operations/COM_OpenCLKernels.cl
index 1b965eb8659..cbd05cbec17 100644
--- a/source/blender/compositor/operations/COM_OpenCLKernels.cl
+++ b/source/blender/compositor/operations/COM_OpenCLKernels.cl
@@ -80,10 +80,10 @@ __kernel void bokehBlurKernel(__read_only image2d_t boundingBox, __read_only ima
}
//KERNEL --- DEFOCUS /VARIABLESIZEBOKEHBLUR ---
-__kernel void defocusKernel(__read_only image2d_t inputImage, __read_only image2d_t bokehImage,
- __read_only image2d_t inputSize,
- __write_only image2d_t output, int2 offsetInput, int2 offsetOutput,
- int step, int maxBlurScalar, float threshold, float scalar, int2 dimension, int2 offset)
+__kernel void defocusKernel(__read_only image2d_t inputImage, __read_only image2d_t bokehImage,
+ __read_only image2d_t inputSize,
+ __write_only image2d_t output, int2 offsetInput, int2 offsetOutput,
+ int step, int maxBlurScalar, float threshold, float scalar, int2 dimension, int2 offset)
{
float4 color = {1.0f, 0.0f, 0.0f, 1.0f};
int2 coords = {get_global_id(0), get_global_id(1)};
@@ -212,8 +212,8 @@ __kernel void erodeKernel(__read_only image2d_t inputImage, __write_only image2
// KERNEL --- DIRECTIONAL BLUR ---
__kernel void directionalBlurKernel(__read_only image2d_t inputImage, __write_only image2d_t output,
- int2 offsetOutput, int iterations, float scale, float rotation, float2 translate,
- float2 center, int2 offset)
+ int2 offsetOutput, int iterations, float scale, float rotation, float2 translate,
+ float2 center, int2 offset)
{
int2 coords = {get_global_id(0), get_global_id(1)};
coords += offset;
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
index bcef652a8b5..12b04c386f2 100644
--- a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
@@ -50,34 +50,52 @@ void SunBeamsOperation::initExecution()
* 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 parameters:
+ * fxu : buffer increment in x for sector u+1
+ * fxv : buffer increment in x for sector v+1
+ * fyu : buffer increment in y for sector u+1
+ * fyv : buffer increment in y for sector v+1
*/
-template <int fxx, int fxy, int fyx, int fyy>
+template <int fxu, int fxv, int fyu, int fyv>
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)
+
+ static inline void buffer_to_sector(const float source[2], int x, int y, int &u, int &v)
{
- u = x * fxx + y * fyx;
- v = x * fxy + y * fyy;
+ int x0 = (int)source[0];
+ int y0 = (int)source[1];
+ x -= x0;
+ y -= y0;
+ u = x * fxu + y * fyu;
+ v = x * fxv + y * fyv;
}
- static inline void buffer_to_sector(float x, float y, float &u, float &v)
+ static inline void buffer_to_sector(const float source[2], float x, float y, float &u, float &v)
{
- u = x * fxx + y * fyx;
- v = x * fxy + y * fyy;
+ int x0 = (int)source[0];
+ int y0 = (int)source[1];
+ x -= (float)x0;
+ y -= (float)y0;
+ u = x * fxu + y * fyu;
+ v = x * fxv + y * fyv;
}
- static inline void sector_to_buffer(int u, int v, int &x, int &y)
+ static inline void sector_to_buffer(const float source[2], int u, int v, int &x, int &y)
{
- x = u * fxx + v * fxy;
- y = u * fyx + v * fyy;
+ int x0 = (int)source[0];
+ int y0 = (int)source[1];
+ x = x0 + u * fxu + v * fxv;
+ y = y0 + u * fyu + v * fyv;
}
- static inline void sector_to_buffer(float u, float v, float &x, float &y)
+ static inline void sector_to_buffer(const float source[2], float u, float v, float &x, float &y)
{
- x = u * fxx + v * fxy;
- y = u * fyx + v * fyy;
+ int x0 = (int)source[0];
+ int y0 = (int)source[1];
+ x = (float)x0 + u * fxu + v * fxv;
+ y = (float)y0 + u * fyu + v * fyv;
}
/**
@@ -91,12 +109,12 @@ struct BufferLineAccumulator {
* \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],
+ static float *init_buffer_iterator(MemoryBuffer *input, const float source[2], const float co[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);
+ buffer_to_sector(source, co[0], co[1], pu, pv);
/* line angle */
float tan_phi = pv / pu;
@@ -113,9 +131,7 @@ struct BufferLineAccumulator {
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];
+ sector_to_buffer(source, end, (int)ceilf(v), x, y);
falloff_factor = dist_max > dist_min ? dr / (float)(dist_max - dist_min) : 0.0f;
@@ -130,7 +146,7 @@ struct BufferLineAccumulator {
* 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],
+ static void eval(MemoryBuffer *input, float output[4], const float co[2], const float source[2],
float dist_min, float dist_max)
{
rcti rect = *input->getRect();
@@ -139,14 +155,16 @@ struct BufferLineAccumulator {
float v, dv;
float falloff_factor;
float border[4];
-
- if ((int)pt_ofs[0] == 0 && (int)pt_ofs[1] == 0) {
+
+ zero_v4(output);
+
+ if ((int)(co[0] - source[0]) == 0 && (int)(co[1] - source[1]) == 0) {
copy_v4_v4(output, input->getBuffer() + COM_NUMBER_OF_CHANNELS * ((int)source[0] + input->getWidth() * (int)source[1]));
return;
}
/* initialise the iteration variables */
- float *buffer = init_buffer_iterator(input, source, pt_ofs, dist_min, dist_max, x, y, num, v, dv, falloff_factor);
+ float *buffer = init_buffer_iterator(input, source, co, dist_min, dist_max, x, y, num, v, dv, falloff_factor);
zero_v3(border);
border[3] = 1.0f;
@@ -178,18 +196,18 @@ struct BufferLineAccumulator {
*/
/* decrement u */
- x -= fxx;
- y -= fyx;
- buffer -= (fxx + fyx * buffer_width) * COM_NUMBER_OF_CHANNELS;
+ x -= fxu;
+ y -= fyu;
+ buffer -= (fxu + fyu * 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;
+ x -= fxv;
+ y -= fyv;
+ buffer -= (fxv + fyv * buffer_width) * COM_NUMBER_OF_CHANNELS;
}
}
@@ -233,21 +251,21 @@ static void accumulate_line(MemoryBuffer *input, float output[4], const float co
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);
+ BufferLineAccumulator<0, 1, 1, 0>::eval(input, output, co, source, dist_min, dist_max);
}
else {
/* 7 */
- BufferLineAccumulator<0, 1, -1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ BufferLineAccumulator<0, 1, -1, 0>::eval(input, output, co, 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);
+ BufferLineAccumulator<0, -1, 1, 0>::eval(input, output, co, source, dist_min, dist_max);
}
else {
/* 6 */
- BufferLineAccumulator<0, -1, -1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ BufferLineAccumulator<0, -1, -1, 0>::eval(input, output, co, source, dist_min, dist_max);
}
}
}
@@ -255,21 +273,21 @@ static void accumulate_line(MemoryBuffer *input, float output[4], const float co
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);
+ BufferLineAccumulator< 1, 0, 0, 1>::eval(input, output, co, source, dist_min, dist_max);
}
else {
/* 8 */
- BufferLineAccumulator< 1, 0, 0, -1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ BufferLineAccumulator< 1, 0, 0, -1>::eval(input, output, co, 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);
+ BufferLineAccumulator<-1, 0, 0, 1>::eval(input, output, co, source, dist_min, dist_max);
}
else {
/* 5 */
- BufferLineAccumulator<-1, 0, 0, -1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ BufferLineAccumulator<-1, 0, 0, -1>::eval(input, output, co, source, dist_min, dist_max);
}
}
}
diff --git a/source/blender/datatoc/datatoc_icon.c b/source/blender/datatoc/datatoc_icon.c
index 7df9269a4a8..92048f32a28 100644
--- a/source/blender/datatoc/datatoc_icon.c
+++ b/source/blender/datatoc/datatoc_icon.c
@@ -166,7 +166,8 @@ static bool write_png(const char *name, const unsigned int *pixels,
/* set the individual row-pointers to point at the correct offsets */
for (i = 0; i < height; i++) {
row_pointers[height - 1 - i] = (png_bytep)
- (((unsigned char *)pixels) + (i * width) * bytesperpixel * sizeof(unsigned char));
+ (((const unsigned char *)pixels) +
+ (i * width) * bytesperpixel * sizeof(unsigned char));
}
/* write out the entire image data in one call */
diff --git a/source/blender/datatoc/datatoc_icon.py b/source/blender/datatoc/datatoc_icon.py
index 930d588f859..16092431195 100755
--- a/source/blender/datatoc/datatoc_icon.py
+++ b/source/blender/datatoc/datatoc_icon.py
@@ -113,6 +113,17 @@ def icondir_to_png(path_src, file_dst):
files = [os.path.join(path_src, f) for f in os.listdir(path_src) if f.endswith(".dat")]
+ # First check if we need to bother.
+ if os.path.exists(file_dst):
+ dst_time = os.path.getmtime(file_dst)
+ has_newer = False
+ for f in files:
+ if os.path.getmtime(f) > dst_time:
+ has_newer = True
+ break
+ if not has_newer:
+ return
+
with open(files[0], 'rb') as f_src:
(icon_w, icon_h,
orig_x, orig_y,
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index f384b2f372c..d76eba93640 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -2365,6 +2365,83 @@ static bAnimChannelType ACF_DSSPK =
acf_dsspk_setting_ptr /* pointer for setting */
};
+/* GPencil Expander ------------------------------------------- */
+
+// TODO: just get this from RNA?
+static int acf_dsgpencil_icon(bAnimListElem *UNUSED(ale))
+{
+ return ICON_GREASEPENCIL;
+}
+
+/* get the appropriate flag(s) for the setting when it is valid */
+static int acf_dsgpencil_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+{
+ /* clear extra return data first */
+ *neg = false;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GP_DATA_EXPAND;
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ return ADT_NLA_EVAL_OFF;
+
+ case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
+
+ default: /* unsupported */
+ return 0;
+ }
+}
+
+/* get pointer to the setting */
+static void *acf_dsgpencil_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+{
+ bGPdata *gpd = (bGPdata *)ale->data;
+
+ /* clear extra return data first */
+ *type = 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(gpd->flag, type);
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (gpd->adt)
+ return GET_ACF_FLAG_PTR(gpd->adt->flag, type);
+ return NULL;
+
+ default: /* unsupported */
+ return NULL;
+ }
+}
+
+/* grease pencil expander type define */
+static bAnimChannelType ACF_DSGPENCIL =
+{
+ "GPencil DS Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop, /* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_basic_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_dsgpencil_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dsgpencil_setting_flag, /* flag for setting */
+ acf_dsgpencil_setting_ptr /* pointer for setting */
+};
+
/* ShapeKey Entry ------------------------------------------- */
/* name for ShapeKey */
@@ -3162,6 +3239,7 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_DSLAT; /* Lattice Channel */
animchannelTypeInfo[type++] = &ACF_DSLINESTYLE; /* LineStyle Channel */
animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */
+ animchannelTypeInfo[type++] = &ACF_DSGPENCIL; /* GreasePencil Channel */
animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */
@@ -3407,6 +3485,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* step 4) draw special toggles .................................
* - in Graph Editor, checkboxes for visibility in curves area
* - in NLA Editor, glowing dots for solo/not solo...
+ * - in Grease Pencil mode, color swatches for layer color
*/
if (ac->sl) {
if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
@@ -3431,6 +3510,10 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* just skip - drawn as widget now */
offset += ICON_WIDTH;
}
+ else if (ale->type == ANIMTYPE_GPLAYER) {
+ /* just skip - drawn as a widget */
+ offset += ICON_WIDTH;
+ }
}
/* step 5) draw name ............................................... */
@@ -3601,18 +3684,6 @@ static void achannel_nlatrack_solo_widget_cb(bContext *C, void *adt_poin, void *
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL);
}
-/* callback for rename widgets - clear rename-in-progress */
-static void achannel_setting_rename_done_cb(bContext *C, void *ads_poin, void *UNUSED(arg2))
-{
- bDopeSheet *ads = (bDopeSheet *)ads_poin;
-
- /* reset rename index so that edit box disappears now that editing is done */
- ads->renameIndex = 0;
-
- /* send notifiers */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL);
-}
-
/* callback for widget sliders - insert keyframes */
static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poin)
{
@@ -3838,7 +3909,7 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann
}
/* Draw UI widgets the given channel */
-void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale, uiBlock *block, float yminc, float ymaxc, size_t channel_index)
+void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListElem *ale, uiBlock *block, float yminc, float ymaxc, size_t channel_index)
{
bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
View2D *v2d = &ac->ar->v2d;
@@ -3878,6 +3949,7 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
/* step 3) draw special toggles .................................
* - in Graph Editor, checkboxes for visibility in curves area
* - in NLA Editor, glowing dots for solo/not solo...
+ * - in Grease Pencil mode, color swatches for layer color
*/
if (ac->sl) {
if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
@@ -3890,6 +3962,31 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO);
offset += ICON_WIDTH;
}
+ else if (ale->type == ANIMTYPE_GPLAYER) {
+ /* color swatch for layer color */
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ PointerRNA ptr;
+ float w = ICON_WIDTH / 2.0f;
+
+ RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, &ptr);
+
+ UI_block_align_begin(block);
+
+ UI_block_emboss_set(block, RNA_boolean_get(&ptr, "is_stroke_visible") ? UI_EMBOSS : UI_EMBOSS_NONE);
+ uiDefButR(block, UI_BTYPE_COLOR, 1, "", offset, yminc, w, ICON_WIDTH,
+ &ptr, "color", -1,
+ 0, 0, 0, 0, gpl->info);
+
+ UI_block_emboss_set(block, RNA_boolean_get(&ptr, "is_fill_visible") ? UI_EMBOSS : UI_EMBOSS_NONE);
+ uiDefButR(block, UI_BTYPE_COLOR, 1, "", offset + w, yminc, w, ICON_WIDTH,
+ &ptr, "fill_color", -1,
+ 0, 0, 0, 0, gpl->info);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ UI_block_align_end(block);
+
+ offset += ICON_WIDTH;
+ }
}
/* step 4) draw text - check if renaming widget is in use... */
@@ -3912,8 +4009,14 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
but = uiDefButR(block, UI_BTYPE_TEXT, 1, "", offset + 3, yminc, RENAME_TEXT_WIDTH, channel_height,
&ptr, RNA_property_identifier(prop), -1, 0, 0, -1, -1, NULL);
- UI_but_func_set(but, achannel_setting_rename_done_cb, ac->ads, NULL);
- UI_but_active_only(C, ac->ar, block, but);
+
+ /* copy what outliner does here, see outliner_buttons */
+ if (UI_but_active_only(C, ac->ar, block, but) == false) {
+ ac->ads->renameIndex = 0;
+
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL);
+ }
UI_block_emboss_set(block, UI_EMBOSS_NONE);
}
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index b6ab0407711..d8ad6506186 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -129,6 +129,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
case ANIMTYPE_DSLAT:
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
{
/* need to verify that this data is valid for now */
if (ale->adt) {
@@ -136,6 +137,13 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
}
break;
}
+ case ANIMTYPE_GPLAYER:
+ {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+
+ ACHANNEL_SET_FLAG(gpl, ACHANNEL_SETFLAG_CLEAR, GP_LAYER_ACTIVE);
+ break;
+ }
}
}
@@ -176,6 +184,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
case ANIMTYPE_DSSPK:
case ANIMTYPE_DSNTREE:
case ANIMTYPE_DSTEX:
+ case ANIMTYPE_DSGPENCIL:
{
/* need to verify that this data is valid for now */
if (ale && ale->adt) {
@@ -184,8 +193,14 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
break;
}
- /* unhandled currently, but may be interesting */
case ANIMTYPE_GPLAYER:
+ {
+ bGPDlayer *gpl = (bGPDlayer *)channel_data;
+ gpl->flag |= GP_LAYER_ACTIVE;
+ break;
+ }
+
+ /* unhandled currently, but may be interesting */
case ANIMTYPE_MASKLAYER:
case ANIMTYPE_SHAPEKEY:
case ANIMTYPE_NLAACTION:
@@ -268,6 +283,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
case ANIMTYPE_DSLAT:
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
{
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
sel = ACHANNEL_SETFLAG_CLEAR;
@@ -361,6 +377,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
case ANIMTYPE_DSLAT:
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
{
/* need to verify that this data is valid for now */
if (ale->adt) {
@@ -843,6 +860,13 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr
is_sel = SEL_NLT(nlt);
break;
}
+ case ANIMTYPE_GPLAYER:
+ {
+ bGPDlayer *gpl = (bGPDlayer *)channel;
+
+ is_sel = SEL_GPL(gpl);
+ break;
+ }
default:
printf("rearrange_animchannel_add_to_islands(): don't know how to handle channels of type %d\n", type);
return;
@@ -1167,6 +1191,47 @@ static void rearrange_action_channels(bAnimContext *ac, bAction *act, eRearrange
/* ------------------- */
+static void rearrange_gpencil_channels(bAnimContext *ac, eRearrangeAnimChan_Mode mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get rearranging function */
+ AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
+
+ if (rearrange_func == NULL)
+ return;
+
+ /* get Grease Pencil datablocks */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ ListBase anim_data_visible = {NULL, NULL};
+ bGPdata *gpd = ale->data;
+
+ /* only consider layers if this datablock is open */
+ BLI_assert(ale->type == ANIMTYPE_GPDATABLOCK);
+ if ((gpd->flag & GP_DATA_EXPAND) == 0)
+ continue;
+
+ /* Filter visible data. */
+ rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GPLAYER);
+
+ /* rearrange datablock's layers */
+ rearrange_animchannel_islands(&gpd->layers, rearrange_func, mode, ANIMTYPE_GPLAYER, &anim_data_visible);
+
+ /* free visible layers data */
+ BLI_freelistN(&anim_data_visible);
+ }
+
+ /* free GPD channel data */
+ ANIM_animdata_freelist(&anim_data);
+}
+
+/* ------------------- */
+
static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
@@ -1182,7 +1247,7 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
/* method to move channels depends on the editor */
if (ac.datatype == ANIMCONT_GPENCIL) {
/* Grease Pencil channels */
- printf("Grease Pencil not supported for moving yet\n");
+ rearrange_gpencil_channels(&ac, mode);
}
else if (ac.datatype == ANIMCONT_MASK) {
/* Grease Pencil channels */
@@ -1585,175 +1650,6 @@ static void ANIM_OT_channels_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************** Set Channel Visibility Operator *********************** */
-/* NOTE: this operator is only valid in the Graph Editor channels region */
-
-static int animchannels_visibility_set_exec(bContext *C, wmOperator *UNUSED(op))
-{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- ListBase all_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get list of all channels that selection may need to be flushed to
- * - hierarchy mustn't affect what we have access to here...
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
-
- /* hide all channels not selected
- * - hierarchy matters if we're doing this from the channels region
- * since we only want to apply this to channels we can "see",
- * and have these affect their relatives
- * - but for Graph Editor, this gets used also from main region
- * where hierarchy doesn't apply, as for [#21276]
- */
- if ((ac.spacetype == SPACE_IPO) && (ac.regiontype != RGN_TYPE_CHANNELS)) {
- /* graph editor (case 2) */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_UNSEL | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- }
- else {
- /* standard case */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_UNSEL | ANIMFILTER_NODUPLIS);
- }
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* clear setting first */
- ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
-
- /* now also flush selection status as appropriate
- * NOTE: in some cases, this may result in repeat flushing being performed
- */
- ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, 0);
- }
-
- ANIM_animdata_freelist(&anim_data);
-
- /* make all the selected channels visible */
- filter = (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
- /* TODO: find out why this is the case, and fix that */
- if (ale->type == ANIMTYPE_OBJECT)
- continue;
-
- /* enable the setting */
- ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
-
- /* now, also flush selection status up/down as appropriate */
- ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, 1);
- }
-
- ANIM_animdata_freelist(&anim_data);
- BLI_freelistN(&all_data);
-
-
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-static void ANIM_OT_channels_visibility_set(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Set Visibility";
- ot->idname = "ANIM_OT_channels_visibility_set";
- ot->description = "Make only the selected animation channels visible in the Graph Editor";
-
- /* api callbacks */
- ot->exec = animchannels_visibility_set_exec;
- ot->poll = ED_operator_graphedit_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-
-/* ******************** Toggle Channel Visibility Operator *********************** */
-/* NOTE: this operator is only valid in the Graph Editor channels region */
-
-static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *UNUSED(op))
-{
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- ListBase all_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- short vis = ACHANNEL_SETFLAG_ADD;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get list of all channels that selection may need to be flushed to
- * - hierarchy mustn't affect what we have access to here...
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
-
- /* filter data
- * - restrict this to only applying on settings we can get to in the list
- */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* See if we should be making showing all selected or hiding */
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* set the setting in the appropriate way (if available) */
- if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE)) {
- vis = ACHANNEL_SETFLAG_CLEAR;
- break;
- }
- }
-
- /* Now set the flags */
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
- /* TODO: find out why this is the case, and fix that */
- if (ale->type == ANIMTYPE_OBJECT)
- continue;
-
- /* change the setting */
- ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, vis);
-
- /* now, also flush selection status up/down as appropriate */
- ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, (vis == ACHANNEL_SETFLAG_ADD));
- }
-
- /* cleanup */
- ANIM_animdata_freelist(&anim_data);
- BLI_freelistN(&all_data);
-
- /* send notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-static void ANIM_OT_channels_visibility_toggle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Toggle Visibility";
- ot->idname = "ANIM_OT_channels_visibility_toggle";
- ot->description = "Toggle visibility in Graph Editor of all selected animation channels";
-
- /* api callbacks */
- ot->exec = animchannels_visibility_toggle_exec;
- ot->poll = ED_operator_graphedit_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
/* ********************** Set Flags Operator *********************** */
/* defines for setting animation-channel flags */
@@ -2334,7 +2230,7 @@ static int animchannels_deselectall_exec(bContext *C, wmOperator *op)
/* 'standard' behavior - check if selected, then apply relevant selection */
if (RNA_boolean_get(op->ptr, "invert"))
- ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_TOGGLE);
+ ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_INVERT);
else
ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_ADD);
@@ -2736,6 +2632,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
case ANIMTYPE_DSLAT:
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
{
/* sanity checking... */
if (ale->adt) {
@@ -2897,7 +2794,13 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
gpl->flag |= GP_LAYER_SELECT;
}
- notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+ /* change active layer, if this is selected (since we must always have an active layer) */
+ if (gpl->flag & GP_LAYER_SELECT) {
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, gpl, ANIMTYPE_GPLAYER);
+ }
+
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); /* Grease Pencil updates */
+ notifierFlags |= (ND_ANIMCHAN | NA_EDITED); /* Animation Ediotrs updates */
break;
}
case ANIMTYPE_MASKDATABLOCK:
@@ -3042,9 +2945,6 @@ void ED_operatortypes_animchannels(void)
WM_operatortype_append(ANIM_OT_channels_expand);
WM_operatortype_append(ANIM_OT_channels_collapse);
- WM_operatortype_append(ANIM_OT_channels_visibility_toggle);
- WM_operatortype_append(ANIM_OT_channels_visibility_set);
-
WM_operatortype_append(ANIM_OT_channels_fcurves_enable);
WM_operatortype_append(ANIM_OT_channels_clean_empty);
@@ -3110,10 +3010,6 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
/* grouping */
WM_keymap_add_item(keymap, "ANIM_OT_channels_group", GKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ANIM_OT_channels_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
-
- /* Graph Editor only */
- WM_keymap_add_item(keymap, "ANIM_OT_channels_visibility_set", VKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "ANIM_OT_channels_visibility_toggle", VKEY, KM_PRESS, KM_SHIFT, 0);
}
/* ************************************************************************** */
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index f3b47b168e9..eb57907c9ec 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -92,7 +92,7 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale)
RNA_property_update_main(G.main, scene, &ptr, prop);
}
else {
- /* in other case we do standard depsgaph update, ideally
+ /* in other case we do standard depsgraph update, ideally
* we'd be calling property update functions here too ... */
DAG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive?
}
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 807e1322595..2d7656642d3 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -41,7 +41,6 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_nla.h"
-#include "BKE_object.h"
#include "ED_anim_api.h"
#include "ED_keyframes_edit.h"
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index cedaea716e3..d6daa64a9f2 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -771,6 +771,21 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
ale->adt = BKE_animdata_from_id(data);
break;
}
+ case ANIMTYPE_DSGPENCIL:
+ {
+ bGPdata *gpd = (bGPdata *)data;
+ AnimData *adt = gpd->adt;
+
+ /* NOTE: we just reuse the same expand filter for this case */
+ ale->flag = EXPANDED_GPD(gpd);
+
+ // XXX: currently, this is only used for access to its animation data
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
case ANIMTYPE_GROUP:
{
bActionGroup *agrp = (bActionGroup *)data;
@@ -1413,27 +1428,77 @@ static size_t animdata_filter_gpencil(ListBase *anim_data, void *UNUSED(data), i
/* only show if gpd is used by something... */
if (ID_REAL_USERS(gpd) < 1)
continue;
+
+ /* When asked from "AnimData" blocks (i.e. the top-level containers for normal animation),
+ * for convenience, this will return GP Datablocks instead. This may cause issues down
+ * the track, but for now, this will do...
+ */
+ if (filter_mode & ANIMFILTER_ANIMDATA) {
+ /* just add GPD as a channel - this will add everything needed */
+ ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, NULL);
+ }
+ else {
+ /* add gpencil animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_GPD(gpd))
+ {
+ tmp_items += animdata_filter_gpencil_data(&tmp_data, gpd, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
- /* add gpencil animation channels */
- BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_GPD(gpd))
- {
- tmp_items += animdata_filter_gpencil_data(&tmp_data, gpd, filter_mode);
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* add gpd as channel too (if for drawing, and it has layers) */
+ ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, NULL);
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
}
- END_ANIMFILTER_SUBCHANNELS;
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
+/* Helper for Grease Pencil data integrated with main DopeSheet */
+static size_t animdata_filter_ds_gpencil(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bGPdata *gpd, int filter_mode)
+{
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add relevant animation channels for Grease Pencil */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_GPD(gpd))
+ {
+ /* add animation channels */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, &gpd->id, filter_mode);
- /* did we find anything? */
- if (tmp_items) {
- /* include data-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* add gpd as channel too (if for drawing, and it has layers) */
- ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, NULL);
+ /* add Grease Pencil layers */
+ // TODO: do these need a separate expander?
+ // XXX: what order should these go in?
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ // XXX: active check here needs checking
+ if (ANIMCHANNEL_ACTIVEOK(gpd)) {
+ ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_DSGPENCIL, gpd);
}
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
}
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
}
/* return the number of items added to the list */
@@ -1699,6 +1764,12 @@ static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data,
mtex = (MTex **)(&wo->mtex);
break;
}
+ case ID_PA:
+ {
+ ParticleSettings *part = (ParticleSettings *)owner_id;
+ mtex = (MTex **)(&part->mtex);
+ break;
+ }
default:
{
/* invalid/unsupported option */
@@ -1910,8 +1981,12 @@ static size_t animdata_filter_ds_particles(bAnimContext *ac, ListBase *anim_data
/* add particle-system's animation data to temp collection */
BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_PART_OBJD(psys->part))
{
- /* material's animation data */
+ /* particle system's animation data */
tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
+
+ /* textures */
+ if (!(ads->filterflag & ADS_FILTER_NOTEX))
+ tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
}
END_ANIMFILTER_SUBCHANNELS;
@@ -2215,6 +2290,11 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
if ((ob->particlesystem.first) && !(ads->filterflag & ADS_FILTER_NOPART)) {
tmp_items += animdata_filter_ds_particles(ac, &tmp_data, ads, ob, filter_mode);
}
+
+ /* grease pencil */
+ if ((ob->gpd) && !(ads->filterflag & ADS_FILTER_NOGPENCIL)) {
+ tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, ob->gpd, filter_mode);
+ }
}
END_ANIMFILTER_SUBCHANNELS;
@@ -2257,7 +2337,7 @@ static size_t animdata_filter_ds_world(bAnimContext *ac, ListBase *anim_data, bD
/* textures for world */
if (!(ads->filterflag & ADS_FILTER_NOTEX))
- items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)wo, filter_mode);
+ tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)wo, filter_mode);
/* nodes */
if ((wo->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE))
@@ -2349,6 +2429,7 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_d
BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_SCEC(sce))
{
bNodeTree *ntree = sce->nodetree;
+ bGPdata *gpd = sce->gpd;
World *wo = sce->world;
/* Action, Drivers, or NLA for Scene */
@@ -2371,6 +2452,11 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_d
tmp_items += animdata_filter_ds_linestyle(ac, &tmp_data, ads, sce, filter_mode);
}
+ /* grease pencil */
+ if ((gpd) && !(ads->filterflag & ADS_FILTER_NOGPENCIL)) {
+ tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, gpd, filter_mode);
+ }
+
/* TODO: one day, when sequencer becomes its own datatype, perhaps it should be included here */
}
END_ANIMFILTER_SUBCHANNELS;
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 0f202003dd8..cbcbc8743f1 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -41,6 +41,7 @@
#include "DNA_scene_types.h"
#include "BKE_context.h"
+#include "BKE_sequencer.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_sound.h"
@@ -55,6 +56,7 @@
#include "ED_anim_api.h"
#include "ED_screen.h"
+#include "ED_sequencer.h"
#include "anim_intern.h"
@@ -92,9 +94,15 @@ static void change_frame_apply(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
-
+ int frame = RNA_int_get(op->ptr, "frame");
+ bool do_snap = RNA_boolean_get(op->ptr, "snap");
+
+ if (do_snap && CTX_wm_space_seq(C)) {
+ frame = BKE_sequencer_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false);
+ }
+
/* set the new frame number */
- CFRA = RNA_int_get(op->ptr, "frame");
+ CFRA = frame;
FRAMENUMBER_MIN_CLAMP(CFRA);
SUBFRA = 0.0f;
@@ -136,6 +144,25 @@ static int frame_from_event(bContext *C, const wmEvent *event)
return frame;
}
+static void change_frame_seq_preview_begin(bContext *C, const wmEvent *event)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && sa->spacetype == SPACE_SEQ) {
+ SpaceSeq *sseq = sa->spacedata.first;
+ if (ED_space_sequencer_check_show_strip(sseq)) {
+ ED_sequencer_special_preview_set(C, event->mval);
+ }
+ }
+}
+static void change_frame_seq_preview_end(bContext *C)
+{
+ if (ED_sequencer_special_preview_get() != NULL) {
+ Scene *scene = CTX_data_scene(C);
+ ED_sequencer_special_preview_clear();
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ }
+}
+
/* Modal Operator init */
static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
@@ -144,7 +171,9 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
* click-dragging over a range (modal scrubbing).
*/
RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
-
+
+ change_frame_seq_preview_begin(C, event);
+
change_frame_apply(C, op);
/* add temp handler */
@@ -153,14 +182,21 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
return OPERATOR_RUNNING_MODAL;
}
+static void change_frame_cancel(bContext *C, wmOperator *UNUSED(op))
+{
+ change_frame_seq_preview_end(C);
+}
+
/* Modal event handling of frame changing */
static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
+ int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
switch (event->type) {
case ESCKEY:
- return OPERATOR_FINISHED;
-
+ ret = OPERATOR_FINISHED;
+ break;
+
case MOUSEMOVE:
RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
change_frame_apply(C, op);
@@ -173,15 +209,31 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
* the modal op) doesn't work for some reason
*/
if (event->val == KM_RELEASE)
- return OPERATOR_FINISHED;
+ ret = OPERATOR_FINISHED;
+ break;
+
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ if (event->val == KM_RELEASE) {
+ RNA_boolean_set(op->ptr, "snap", false);
+ }
+ else if (event->val == KM_PRESS) {
+ RNA_boolean_set(op->ptr, "snap", true);
+ }
break;
}
- return OPERATOR_RUNNING_MODAL;
+ if (ret != OPERATOR_RUNNING_MODAL) {
+ change_frame_seq_preview_end(C);
+ }
+
+ return ret;
}
static void ANIM_OT_change_frame(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Change Frame";
ot->idname = "ANIM_OT_change_frame";
@@ -190,6 +242,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
/* api callbacks */
ot->exec = change_frame_exec;
ot->invoke = change_frame_invoke;
+ ot->cancel = change_frame_cancel;
ot->modal = change_frame_modal;
ot->poll = change_frame_poll;
@@ -198,6 +251,8 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
/* rna */
ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
+ prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ****************** set preview range operator ****************************/
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 7bdc49da54e..5799101a7db 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -39,18 +39,12 @@
#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
-#include "DNA_object_types.h"
-#include "DNA_material_types.h"
#include "DNA_texture_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
#include "BKE_animsys.h"
#include "BKE_fcurve.h"
#include "BKE_context.h"
#include "BKE_report.h"
-#include "BKE_material.h"
-#include "BKE_texture.h"
#include "ED_keyframing.h"
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index c5e54cc1c7c..d2dbe961b42 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -39,7 +39,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_dlrbTree.h"
#include "BLI_utildefines.h"
@@ -155,6 +154,7 @@ static DLRBT_Node *nalloc_ak_gpframe(void *data)
/* store settings based on state of BezTriple */
ak->cfra = gpf->framenum;
ak->sel = (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0;
+ ak->key_type = gpf->key_type;
/* set 'modified', since this is used to identify long keyframes */
ak->modified = 1;
@@ -171,6 +171,10 @@ static void nupdate_ak_gpframe(void *node, void *data)
/* set selection status and 'touched' status */
if (gpf->flag & GP_FRAME_SELECT) ak->sel = SELECT;
ak->modified += 1;
+
+ /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
+ if (gpf->key_type == BEZT_KEYTYPE_KEYFRAME)
+ ak->key_type = BEZT_KEYTYPE_KEYFRAME;
}
/* ......... */
@@ -732,6 +736,21 @@ void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
BLI_dlrbTree_free(&blocks);
}
+void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos)
+{
+ DLRBT_Tree keys;
+
+ BLI_dlrbTree_init(&keys);
+
+ gpencil_to_keylist(ads, gpd, &keys);
+
+ BLI_dlrbTree_linkedlist_sync(&keys);
+
+ draw_keylist(v2d, &keys, NULL, ypos, 0);
+
+ BLI_dlrbTree_free(&keys);
+}
+
void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
{
DLRBT_Tree keys;
@@ -924,6 +943,20 @@ void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, DLRBT_Tree
}
+void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys)
+{
+ bGPDlayer *gpl;
+
+ if (gpd && keys) {
+ /* for now, just aggregate out all the frames, but only for visible layers */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if ((gpl->flag & GP_LAYER_HIDE) == 0) {
+ gpl_to_keylist(ads, gpl, keys);
+ }
+ }
+ }
+}
+
void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys)
{
bGPDframe *gpf;
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 7f612de14b7..439b3b94974 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -41,9 +41,7 @@
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
-#include "DNA_node_types.h"
#include "DNA_scene_types.h"
-#include "DNA_space_types.h"
#include "BKE_fcurve.h"
@@ -548,6 +546,44 @@ static short ok_bezier_region_lasso(KeyframeEditData *ked, BezTriple *bezt)
return 0;
}
+/**
+ * only called from #ok_bezier_region_circle
+ */
+static bool bezier_region_circle_test(
+ const struct KeyframeEdit_CircleData *data_circle,
+ const float xy[2])
+{
+ if (BLI_rctf_isect_pt_v(data_circle->rectf_scaled, xy)) {
+ float xy_view[2];
+
+ BLI_rctf_transform_pt_v(data_circle->rectf_view, data_circle->rectf_scaled, xy_view, xy);
+
+ xy_view[0] = xy_view[0] - data_circle->mval[0];
+ xy_view[1] = xy_view[1] - data_circle->mval[1];
+ return len_squared_v2(xy_view) < data_circle->radius_squared;
+ }
+
+ return false;
+}
+
+
+static short ok_bezier_region_circle(KeyframeEditData *ked, BezTriple *bezt)
+{
+ /* rect is stored in data property (it's of type rectf, but may not be set) */
+ if (ked->data) {
+ short ok = 0;
+
+#define KEY_CHECK_OK(_index) bezier_region_circle_test(ked->data, bezt->vec[_index])
+ KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
+#undef KEY_CHECK_OK
+
+ /* return ok flags */
+ return ok;
+ }
+ else
+ return 0;
+}
+
KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
{
@@ -567,6 +603,8 @@ KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
return ok_bezier_region;
case BEZT_OK_REGION_LASSO: /* only if the point falls within KeyframeEdit_LassoData defined data */
return ok_bezier_region_lasso;
+ case BEZT_OK_REGION_CIRCLE: /* only if the point falls within KeyframeEdit_LassoData defined data */
+ return ok_bezier_region_circle;
default: /* nothing was ok */
return NULL;
}
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index 6e59bb9f463..7ac11c1cd06 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -43,13 +43,14 @@
#include "DNA_scene_types.h"
+#include "BKE_action.h"
#include "BKE_fcurve.h"
#include "BKE_report.h"
#include "BKE_library.h"
#include "BKE_global.h"
+#include "BKE_deform.h"
#include "RNA_access.h"
-#include "RNA_enum_types.h"
#include "ED_anim_api.h"
#include "ED_keyframing.h"
@@ -478,6 +479,7 @@ typedef struct tAnimCopybufItem {
BezTriple *bezt; /* keyframes in buffer */
short id_type; /* Result of GS(id->name)*/
+ bool is_bone; /* special flag for armature bones */
} tAnimCopybufItem;
@@ -541,6 +543,31 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
aci->grp = fcu->grp;
aci->rna_path = MEM_dupallocN(fcu->rna_path);
aci->array_index = fcu->array_index;
+
+ /* detect if this is a bone. We do that here rather than during pasting because ID pointers will get invalidated if we undo.
+ * storing the relevant information here helps avoiding crashes if we undo-repaste */
+ if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) {
+ Object *ob = (Object *)aci->id;
+ char *str_start;
+
+ if ((str_start = strstr(aci->rna_path, "pose.bones["))) {
+ bPoseChannel *pchan;
+ int length = 0;
+ char *str_end;
+
+ str_start += 12;
+ str_end = strchr(str_start, '\"');
+ length = str_end - str_start;
+ str_start[length] = 0;
+ pchan = BKE_pose_channel_find_name(ob->pose, str_start);
+ str_start[length] = '\"';
+
+ if (pchan) {
+ aci->is_bone = true;
+ }
+ }
+ }
+
BLI_addtail(&animcopybuf, aci);
/* add selected keyframes to buffer */
@@ -588,19 +615,65 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data)
return 0;
}
+static void flip_names(tAnimCopybufItem *aci, char **name)
+{
+ if (aci->is_bone) {
+ char *str_start;
+ if ((str_start = strstr(aci->rna_path, "pose.bones["))) {
+ /* ninja coding, try to change the name */
+ char bname_new[MAX_VGROUP_NAME];
+ char *str_iter, *str_end;
+ int length, prefix_l, postfix_l;
+
+ str_start += 12;
+ prefix_l = str_start - aci->rna_path;
+
+ str_end = strchr(str_start, '\"');
+
+ length = str_end - str_start;
+ postfix_l = strlen(str_end);
+
+ /* more ninja stuff, temporary substitute with NULL terminator */
+ str_start[length] = 0;
+ BKE_deform_flip_side_name(bname_new, str_start, false);
+ str_start[length] = '\"';
+
+ str_iter = *name = MEM_mallocN(sizeof(char) * (prefix_l + postfix_l + length + 1), "flipped_path");
+
+ BLI_strncpy(str_iter, aci->rna_path, prefix_l + 1);
+ str_iter += prefix_l ;
+ BLI_strncpy(str_iter, bname_new, length + 1);
+ str_iter += length;
+ BLI_strncpy(str_iter, str_end, postfix_l + 1);
+ str_iter[postfix_l] = '\0';
+ }
+ }
+}
+
/* ------------------- */
/* most strict method: exact matches only */
-static tAnimCopybufItem *pastebuf_match_path_full(FCurve *fcu, const short from_single, const short to_simple)
+static tAnimCopybufItem *pastebuf_match_path_full(FCurve *fcu, const short from_single, const short to_simple, bool flip)
{
tAnimCopybufItem *aci;
for (aci = animcopybuf.first; aci; aci = aci->next) {
- /* check that paths exist */
if (to_simple || (aci->rna_path && fcu->rna_path)) {
- if (to_simple || (strcmp(aci->rna_path, fcu->rna_path) == 0)) {
- if ((from_single) || (aci->array_index == fcu->array_index))
+ if (!to_simple && flip && aci->is_bone && fcu->rna_path) {
+ if ((from_single) || (aci->array_index == fcu->array_index)) {
+ char *name = NULL;
+ flip_names(aci, &name);
+ if (strcmp(name, fcu->rna_path) == 0) {
+ MEM_freeN(name);
+ break;
+ }
+ MEM_freeN(name);
+ }
+ }
+ else if (to_simple || (strcmp(aci->rna_path, fcu->rna_path) == 0)) {
+ if ((from_single) || (aci->array_index == fcu->array_index)) {
break;
+ }
}
}
}
@@ -671,8 +744,30 @@ static tAnimCopybufItem *pastebuf_match_index_only(FCurve *fcu, const short from
/* ................ */
+static void do_curve_mirror_flippping(tAnimCopybufItem *aci, BezTriple *bezt)
+{
+ if (aci->is_bone) {
+ const size_t slength = strlen(aci->rna_path);
+ bool flip = false;
+ if (BLI_strn_endswith(aci->rna_path, "location", slength) && aci->array_index == 0)
+ flip = true;
+ else if (BLI_strn_endswith(aci->rna_path, "rotation_quaternion", slength) && ELEM(aci->array_index, 2, 3))
+ flip = true;
+ else if (BLI_strn_endswith(aci->rna_path, "rotation_euler", slength) && ELEM(aci->array_index, 1, 2))
+ flip = true;
+ else if (BLI_strn_endswith(aci->rna_path, "rotation_axis_angle", slength) && ELEM(aci->array_index, 2, 3))
+ flip = true;
+
+ if (flip) {
+ bezt->vec[0][1] = -bezt->vec[0][1];
+ bezt->vec[1][1] = -bezt->vec[1][1];
+ bezt->vec[2][1] = -bezt->vec[2][1];
+ }
+ }
+}
+
/* helper for paste_animedit_keys() - performs the actual pasting */
-static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float offset, const eKeyMergeMode merge_mode)
+static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float offset, const eKeyMergeMode merge_mode, bool flip)
{
BezTriple *bezt;
int i;
@@ -727,6 +822,9 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float
/* just start pasting, with the first keyframe on the current frame, and so on */
for (i = 0, bezt = aci->bezt; i < aci->totvert; i++, bezt++) {
/* temporarily apply offset to src beztriple while copying */
+ if (flip)
+ do_curve_mirror_flippping(aci, bezt);
+
bezt->vec[0][0] += offset;
bezt->vec[1][0] += offset;
bezt->vec[2][0] += offset;
@@ -734,12 +832,16 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float
/* insert the keyframe
* NOTE: we do not want to inherit handles from existing keyframes in this case!
*/
- insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL);
+ insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL);
+
/* un-apply offset from src beztriple after copying */
bezt->vec[0][0] -= offset;
bezt->vec[1][0] -= offset;
bezt->vec[2][0] -= offset;
+
+ if (flip)
+ do_curve_mirror_flippping(aci, bezt);
}
/* recalculate F-Curve's handles? */
@@ -769,7 +871,7 @@ EnumPropertyItem keyframe_paste_merge_items[] = {
* \return Status code is whether the method FAILED to do anything
*/
short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
- const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode)
+ const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
{
bAnimListElem *ale;
@@ -817,7 +919,7 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
fcu = (FCurve *)ale->data; /* destination F-Curve */
aci = animcopybuf.first;
- paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode);
+ paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, false);
}
else {
/* from selected channels
@@ -840,7 +942,7 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
switch (pass) {
case 0:
/* most strict, must be exact path match data_path & index */
- aci = pastebuf_match_path_full(fcu, from_single, to_simple);
+ aci = pastebuf_match_path_full(fcu, from_single, to_simple, flip);
break;
case 1:
@@ -857,7 +959,7 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
/* copy the relevant data from the matching buffer curve */
if (aci) {
totmatch++;
- paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode);
+ paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
}
ale->update |= ANIM_UPDATE_DEFAULT;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 2c66d92ab58..7e2ce4cd3f1 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -658,7 +658,7 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
/* validate data */
if (ELEM(NULL, ptr, ptr->data, prop))
- return 0;
+ return false;
/* get first constraint and determine type of keyframe constraints to check for
* - constraints can be on either Objects or PoseChannels, so we only check if the
@@ -880,7 +880,7 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
/* no F-Curve to add keyframe to? */
if (fcu == NULL) {
BKE_report(reports, RPT_ERROR, "No F-Curve to add keyframes to");
- return 0;
+ return false;
}
/* F-Curve not editable? */
if (fcurve_is_keyframable(fcu) == 0) {
@@ -888,13 +888,13 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
"F-Curve with path '%s[%d]' cannot be keyframed, ensure that it is not locked or sampled, "
"and try removing F-Modifiers",
fcu->rna_path, fcu->array_index);
- return 0;
+ return false;
}
/* if no property given yet, try to validate from F-Curve info */
if ((ptr.id.data == NULL) && (ptr.data == NULL)) {
BKE_report(reports, RPT_ERROR, "No RNA pointer available to retrieve values for keyframing from");
- return 0;
+ return false;
}
if (prop == NULL) {
PointerRNA tmp_ptr;
@@ -907,7 +907,7 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
BKE_reportf(reports, RPT_ERROR,
"Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
idname, fcu->rna_path);
- return 0;
+ return false;
}
else {
/* property found, so overwrite 'ptr' to make later code easier */
@@ -956,18 +956,18 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
/* only return success if keyframe added */
if (insert_mode)
- return 1;
+ return true;
}
else {
/* just insert keyframe */
insert_vert_fcurve(fcu, cfra, curval, flag);
/* return success */
- return 1;
+ return true;
}
/* failed */
- return 0;
+ return false;
}
/* Main Keyframing API call:
@@ -1284,10 +1284,10 @@ static int modify_key_op_poll(bContext *C)
/* if no area or active scene */
if (ELEM(NULL, sa, scene))
- return 0;
+ return false;
/* should be fine */
- return 1;
+ return true;
}
/* Insert Key Operator ------------------------ */
@@ -1922,17 +1922,17 @@ void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
/* ******************************************* */
/* AUTO KEYFRAME */
-int autokeyframe_cfra_can_key(Scene *scene, ID *id)
+bool autokeyframe_cfra_can_key(Scene *scene, ID *id)
{
float cfra = (float)CFRA; // XXX for now, this will do
/* only filter if auto-key mode requires this */
if (IS_AUTOKEY_ON(scene) == 0)
- return 0;
+ return false;
if (IS_AUTOKEY_MODE(scene, NORMAL)) {
/* can insert anytime we like... */
- return 1;
+ return true;
}
else { /* REPLACE */
/* for whole block - only key if there's a keyframe on that frame already
@@ -1952,7 +1952,7 @@ bool fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter)
{
/* quick sanity check */
if (ELEM(NULL, fcu, fcu->bezt))
- return 0;
+ return false;
/* we either include all regardless of muting, or only non-muted */
if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED) == 0) {
@@ -1965,11 +1965,11 @@ bool fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter)
if (replace) {
/* sanity check: 'i' may in rare cases exceed arraylen */
if ((i >= 0) && (i < fcu->totvert))
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
/* Checks whether an Action has a keyframe for a given frame
@@ -1981,11 +1981,11 @@ static bool action_frame_has_keyframe(bAction *act, float frame, short filter)
/* can only find if there is data */
if (act == NULL)
- return 0;
+ return false;
/* if only check non-muted, check if muted */
if ((filter & ANIMFILTER_KEYS_MUTED) || (act->flag & ACT_MUTED))
- return 0;
+ return false;
/* loop over F-Curves, using binary-search to try to find matches
* - this assumes that keyframes are only beztriples
@@ -1994,12 +1994,12 @@ static bool action_frame_has_keyframe(bAction *act, float frame, short filter)
/* only check if there are keyframes (currently only of type BezTriple) */
if (fcu->bezt && fcu->totvert) {
if (fcurve_frame_has_keyframe(fcu, frame, filter))
- return 1;
+ return true;
}
}
/* nothing found */
- return 0;
+ return false;
}
/* Checks whether an Object has a keyframe for a given frame */
@@ -2007,7 +2007,7 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
{
/* error checking */
if (ob == NULL)
- return 0;
+ return false;
/* check own animation data - specifically, the action it contains */
if ((ob->adt) && (ob->adt->action)) {
@@ -2018,7 +2018,7 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
float ob_frame = BKE_nla_tweakedit_remap(ob->adt, frame, NLATIME_CONVERT_UNMAP);
if (action_frame_has_keyframe(ob->adt->action, ob_frame, filter))
- return 1;
+ return true;
}
/* try shapekey keyframes (if available, and allowed by filter) */
@@ -2031,7 +2031,7 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
/* 1. test for relative (with keyframes) */
if (id_frame_has_keyframe((ID *)key, frame, filter))
- return 1;
+ return true;
/* 2. test for time */
/* TODO... yet to be implemented (this feature may evolve before then anyway) */
@@ -2045,7 +2045,7 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
/* we only retrieve the active material... */
if (id_frame_has_keyframe((ID *)ma, frame, filter))
- return 1;
+ return true;
}
else {
int a;
@@ -2055,13 +2055,13 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
Material *ma = give_current_material(ob, a + 1);
if (id_frame_has_keyframe((ID *)ma, frame, filter))
- return 1;
+ return true;
}
}
}
/* nothing found */
- return 0;
+ return false;
}
/* --------------- API ------------------- */
@@ -2071,7 +2071,7 @@ bool id_frame_has_keyframe(ID *id, float frame, short filter)
{
/* sanity checks */
if (id == NULL)
- return 0;
+ return false;
/* perform special checks for 'macro' types */
switch (GS(id->name)) {
@@ -2095,7 +2095,7 @@ bool id_frame_has_keyframe(ID *id, float frame, short filter)
/* no keyframe found */
- return 0;
+ return false;
}
/* ************************************************** */
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index b7e38546ca2..574258de4f6 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -28,8 +28,6 @@
* \ingroup edarmature
*/
-#include "BLI_math.h"
-
#include "RNA_access.h"
#include "WM_api.h"
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index 15f75ada060..3126cca7457 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -43,6 +43,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_deform.h"
+#include "BKE_object_deform.h"
#include "BKE_report.h"
#include "BKE_subsurf.h"
#include "BKE_modifier.h"
@@ -52,7 +53,10 @@
#include "armature_intern.h"
-#include "meshlaplacian.h"
+
+#ifdef WITH_OPENNL
+# include "meshlaplacian.h"
+#endif
#if 0
#include "reeb.h"
@@ -117,7 +121,7 @@ static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
*/
if (!(bone->flag & BONE_NO_DEFORM)) {
if (!defgroup_find_name(ob, bone->name)) {
- ED_vgroup_add_name(ob, bone->name);
+ BKE_object_defgroup_add_name(ob, bone->name);
return 1;
}
}
@@ -164,7 +168,7 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
if (!wpmode || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED)))
if (!(defgroup = defgroup_find_name(ob, bone->name)))
- defgroup = ED_vgroup_add_name(ob, bone->name);
+ defgroup = BKE_object_defgroup_add_name(ob, bone->name);
if (data->list != NULL) {
hgroup = (bDeformGroup ***) &data->list;
@@ -276,7 +280,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
if (numbones == 0)
return;
- if (ED_vgroup_data_create(ob->data) == false)
+ if (BKE_object_defgroup_data_create(ob->data) == NULL)
return;
/* create an array of pointer to bones that are skinnable
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index 912fbc36d5d..3dbf7b4b65a 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -31,8 +31,6 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLF_translation.h"
-
#include "BKE_context.h"
#include "BKE_sketch.h"
diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c
index 9c27fe5218a..413a74d24b5 100644
--- a/source/blender/editors/armature/pose_group.c
+++ b/source/blender/editors/armature/pose_group.c
@@ -365,8 +365,8 @@ typedef struct tSortActionGroup {
/* compare bone groups by name */
static int compare_agroup(const void *sgrp_a_ptr, const void *sgrp_b_ptr)
{
- tSortActionGroup *sgrp_a = (tSortActionGroup *)sgrp_a_ptr;
- tSortActionGroup *sgrp_b = (tSortActionGroup *)sgrp_b_ptr;
+ const tSortActionGroup *sgrp_a = sgrp_a_ptr;
+ const tSortActionGroup *sgrp_b = sgrp_b_ptr;
return strcmp(sgrp_a->agrp->name, sgrp_b->agrp->name);
}
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 15e70980425..2e6eace88aa 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -916,7 +916,7 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData
KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
ListBase dsources = {NULL, NULL};
- short autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id);
+ bool autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id);
/* start tagging/keying */
for (agrp = act->groups.first; agrp; agrp = agrp->next) {
diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c
index 380a3fffc6d..1297755b7d0 100644
--- a/source/blender/editors/armature/pose_utils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -49,8 +49,6 @@
#include "WM_api.h"
#include "WM_types.h"
-
-
#include "ED_armature.h"
#include "ED_keyframing.h"
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
index f1b34182439..0f42dc923a4 100644
--- a/source/blender/editors/curve/curve_ops.c
+++ b/source/blender/editors/curve/curve_ops.c
@@ -36,10 +36,6 @@
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-
-
#include "RNA_access.h"
#include "WM_api.h"
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index d1208b8ba1c..99c64be5797 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -85,6 +85,7 @@ typedef struct {
GHash *undoIndex;
ListBase fcurves, drivers;
int actnu;
+ int flag;
} UndoCurve;
/* Definitions needed for shape keys */
@@ -6880,6 +6881,7 @@ static void undoCurve_to_editCurve(void *ucu, void *UNUSED(edata), void *cu_v)
cu->actvert = undoCurve->actvert;
cu->actnu = undoCurve->actnu;
+ cu->flag = undoCurve->flag;
ED_curve_updateAnimPaths(cu);
}
@@ -6919,6 +6921,7 @@ static void *editCurve_to_undoCurve(void *UNUSED(edata), void *cu_v)
undoCurve->actvert = cu->actvert;
undoCurve->actnu = cu->actnu;
+ undoCurve->flag = cu->flag;
return undoCurve;
}
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 108166109b8..8393acc6919 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -500,7 +500,7 @@ void FONT_OT_text_paste_from_file(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
}
@@ -558,7 +558,7 @@ void FONT_OT_text_paste_from_clipboard(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
}
@@ -1835,7 +1835,7 @@ void FONT_OT_open(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | FTFONTFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_FTFONT, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
}
@@ -1884,8 +1884,8 @@ static void undoFont_to_editFont(void *strv, void *ecu, void *UNUSED(obdata))
EditFont *ef = cu->editfont;
const char *str = strv;
- ef->pos = *((short *)str);
- ef->len = *((short *)(str + 2));
+ ef->pos = *((const short *)str);
+ ef->len = *((const short *)(str + 2));
memcpy(ef->textbuf, str + 4, (ef->len + 1) * sizeof(wchar_t));
memcpy(ef->textbufinfo, str + 4 + (ef->len + 1) * sizeof(wchar_t), ef->len * sizeof(CharInfo));
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index 5dc9679777f..58192f59219 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -39,11 +39,12 @@ set(INC_SYS
set(SRC
drawgpencil.c
editaction_gpencil.c
- gpencil_buttons.c
gpencil_edit.c
gpencil_ops.c
gpencil_paint.c
+ gpencil_select.c
gpencil_undo.c
+ gpencil_utils.c
gpencil_intern.h
)
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 5a838d7bc39..895fc6608e2 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -27,6 +27,7 @@
* \ingroup edgpencil
*/
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -58,6 +59,8 @@
#include "ED_gpencil.h"
#include "ED_view3d.h"
+#include "UI_resources.h"
+
#include "gpencil_intern.h"
/* ************************************************** */
@@ -73,6 +76,9 @@ typedef enum eDrawStrokeFlags {
GP_DRAWDATA_ONLYI2D = (1 << 3), /* only draw 'image' strokes */
GP_DRAWDATA_IEDITHACK = (1 << 4), /* special hack for drawing strokes in Image Editor (weird coordinates) */
GP_DRAWDATA_NO_XRAY = (1 << 5), /* don't draw xray in 3D view (which is default) */
+ GP_DRAWDATA_NO_ONIONS = (1 << 6), /* no onionskins should be drawn (for animation playback) */
+ GP_DRAWDATA_VOLUMETRIC = (1 << 7), /* draw strokes as "volumetric" circular billboards */
+ GP_DRAWDATA_FILL = (1 << 8), /* fill insides/bounded-regions of strokes */
} eDrawStrokeFlags;
@@ -111,10 +117,10 @@ static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickn
/* draw stroke curve */
if (G.debug & G_DEBUG) setlinestyle(2);
-
+
glLineWidth(oldpressure * thickness);
glBegin(GL_LINE_STRIP);
-
+
for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
/* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
* and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
@@ -126,7 +132,7 @@ static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickn
/* need to roll-back one point to ensure that there are no gaps in the stroke */
if (i != 0) glVertex2iv(&(pt - 1)->x);
-
+
/* now the point we want... */
glVertex2iv(&pt->x);
@@ -136,14 +142,221 @@ static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickn
glVertex2iv(&pt->x);
}
glEnd();
-
+
/* reset for predictable OpenGL context */
glLineWidth(1.0f);
-
+
if (G.debug & G_DEBUG) setlinestyle(0);
}
}
+/* --------- 2D Stroke Drawing Helpers --------- */
+
+/* helper function to calculate x-y drawing coordinates for 2D points */
+static void gp_calc_2d_stroke_xy(bGPDspoint *pt, short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
+{
+ if (sflag & GP_STROKE_2DSPACE) {
+ r_co[0] = pt->x;
+ r_co[1] = pt->y;
+ }
+ else if (sflag & GP_STROKE_2DIMAGE) {
+ const float x = (float)((pt->x * winx) + offsx);
+ const float y = (float)((pt->y * winy) + offsy);
+
+ r_co[0] = x;
+ r_co[1] = y;
+ }
+ else {
+ const float x = (float)(pt->x / 100 * winx) + offsx;
+ const float y = (float)(pt->y / 100 * winy) + offsy;
+
+ r_co[0] = x;
+ r_co[1] = y;
+ }
+}
+
+/* ----------- Volumetric Strokes --------------- */
+
+/* draw a 2D buffer stroke in "volumetric" style
+ * NOTE: the stroke buffer doesn't have any coordinate offsets/transforms
+ */
+static void gp_draw_stroke_volumetric_buffer(tGPspoint *points, int totpoints, short thickness,
+ short dflag, short UNUSED(sflag))
+{
+ GLUquadricObj *qobj = gluNewQuadric();
+ float modelview[4][4];
+
+ tGPspoint *pt;
+ int i;
+
+ /* error checking */
+ if ((points == NULL) || (totpoints <= 0))
+ return;
+
+ /* check if buffer can be drawn */
+ if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
+ return;
+
+ /* get basic matrix - should be camera space (i.e "identity") */
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview);
+
+ /* draw points */
+ glPushMatrix();
+
+ for (i = 0, pt = points; i < totpoints; i++, pt++) {
+ /* set the transformed position */
+ // TODO: scale should change based on zoom level, which requires proper translation mult too!
+ modelview[3][0] = pt->x;
+ modelview[3][1] = pt->y;
+
+ glLoadMatrixf((float *)modelview);
+
+ /* draw the disk using the current state... */
+ gluDisk(qobj, 0.0, pt->pressure * thickness, 32, 1);
+
+
+ modelview[3][0] = modelview[3][1] = 0.0f;
+ }
+
+ glPopMatrix();
+ gluDeleteQuadric(qobj);
+}
+
+/* draw a 2D strokes in "volumetric" style */
+static void gp_draw_stroke_volumetric_2d(bGPDspoint *points, int totpoints, short thickness,
+ short dflag, short sflag,
+ int offsx, int offsy, int winx, int winy)
+{
+ GLUquadricObj *qobj = gluNewQuadric();
+ float modelview[4][4];
+ float baseloc[3];
+ float scalefac = 1.0f;
+
+ bGPDspoint *pt;
+ int i;
+
+
+ /* HACK: We need a scale factor for the drawing in the image editor,
+ * which seems to use 1 unit as it's maximum size, whereas everything
+ * else assumes 1 unit = 1 pixel. Otherwise, we only get a massive blob.
+ */
+ if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
+ scalefac = 0.001f;
+ }
+
+ /* get basic matrix */
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview);
+ copy_v3_v3(baseloc, modelview[3]);
+
+ /* draw points */
+ glPushMatrix();
+
+ for (i = 0, pt = points; i < totpoints; i++, pt++) {
+ /* set the transformed position */
+ float co[2];
+
+ gp_calc_2d_stroke_xy(pt, sflag, offsx, offsy, winx, winy, co);
+ translate_m4(modelview, co[0], co[1], 0.0f);
+
+ glLoadMatrixf((float *)modelview);
+
+ /* draw the disk using the current state... */
+ gluDisk(qobj, 0.0, pt->pressure * thickness * scalefac, 32, 1);
+
+ /* restore matrix */
+ copy_v3_v3(modelview[3], baseloc);
+ }
+
+ glPopMatrix();
+ gluDeleteQuadric(qobj);
+}
+
+/* draw a 3D stroke in "volumetric" style */
+static void gp_draw_stroke_volumetric_3d(bGPDspoint *points, int totpoints, short thickness,
+ short UNUSED(dflag), short UNUSED(sflag))
+{
+ GLUquadricObj *qobj = gluNewQuadric();
+
+ float base_modelview[4][4], modelview[4][4];
+ float base_loc[3];
+
+ bGPDspoint *pt;
+ int i;
+
+
+ /* Get the basic modelview matrix we use for performing calculations */
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)base_modelview);
+ copy_v3_v3(base_loc, base_modelview[3]);
+
+ /* Create the basic view-aligned billboard matrix we're going to actually draw qobj with:
+ * - We need to knock out the rotation so that we are
+ * simply left with a camera-facing billboard
+ * - The scale factors here are chosen so that the thickness
+ * is relatively reasonable. Otherwise, it gets far too
+ * large!
+ */
+ scale_m4_fl(modelview, 0.1f);
+
+ /* draw each point as a disk... */
+ glPushMatrix();
+
+ for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
+ /* apply translation to base_modelview, so that the translated point is put in the right place */
+ translate_m4(base_modelview, pt->x, pt->y, pt->z);
+
+ /* copy the translation component to the billboard matrix we're going to use,
+ * then reset the base matrix to the original values so that we can do the same
+ * for the next point without accumulation/pollution effects
+ */
+ copy_v3_v3(modelview[3], base_modelview[3]); /* copy offset value */
+ copy_v3_v3(base_modelview[3], base_loc); /* restore */
+
+ /* apply our billboard matrix for drawing... */
+ glLoadMatrixf((float *)modelview);
+
+ /* draw the disk using the current state... */
+ gluDisk(qobj, 0.0, pt->pressure * thickness, 32, 1);
+ }
+
+ glPopMatrix();
+ gluDeleteQuadric(qobj);
+}
+
+
+/* --------------- Stroke Fills ----------------- */
+
+/* draw fills for shapes */
+static void gp_draw_stroke_fill(bGPDspoint *points, int totpoints, short UNUSED(thickness),
+ short UNUSED(dflag), short sflag,
+ int offsx, int offsy, int winx, int winy)
+{
+ bGPDspoint *pt;
+ int i;
+
+ BLI_assert(totpoints >= 3);
+
+ /* As an initial implementation, we use the OpenGL filled polygon drawing
+ * here since it's the easiest option to implement for this case. It does
+ * come with limitations (notably for concave shapes), though it shouldn't
+ * be much of an issue in most cases.
+ */
+ glBegin(GL_POLYGON);
+
+ for (i = 0, pt = points; i < totpoints; i++, pt++) {
+ if (sflag & GP_STROKE_3DSPACE) {
+ glVertex3fv(&pt->x);
+ }
+ else {
+ float co[2];
+
+ gp_calc_2d_stroke_xy(pt, sflag, offsx, offsy, winx, winy, co);
+ glVertex2fv(co);
+ }
+ }
+
+ glEnd();
+}
+
/* ----- Existing Strokes Drawing (3D and Point) ------ */
/* draw a given stroke - just a single dot (only one point) */
@@ -160,18 +373,7 @@ static void gp_draw_stroke_point(bGPDspoint *points, short thickness, short dfla
float co[2];
/* get coordinates of point */
- if (sflag & GP_STROKE_2DSPACE) {
- co[0] = points->x;
- co[1] = points->y;
- }
- else if (sflag & GP_STROKE_2DIMAGE) {
- co[0] = (points->x * winx) + offsx;
- co[1] = (points->y * winy) + offsy;
- }
- else {
- co[0] = (points->x / 100 * winx) + offsx;
- co[1] = (points->y / 100 * winy) + offsy;
- }
+ gp_calc_2d_stroke_xy(points, sflag, offsx, offsy, winx, winy, co);
/* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple dot looks ok
* - also mandatory in if Image Editor 'image-based' dot
@@ -185,13 +387,13 @@ static void gp_draw_stroke_point(bGPDspoint *points, short thickness, short dfla
}
else {
/* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */
- GLUquadricObj *qobj = gluNewQuadric();
+ GLUquadricObj *qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_FILL);
+ gluQuadricDrawStyle(qobj, GLU_FILL);
/* need to translate drawing position, but must reset after too! */
glTranslatef(co[0], co[1], 0.0);
- gluDisk(qobj, 0.0, thickness, 32, 1);
+ gluDisk(qobj, 0.0, thickness, 32, 1);
glTranslatef(-co[0], -co[1], 0.0);
gluDeleteQuadric(qobj);
@@ -200,7 +402,7 @@ static void gp_draw_stroke_point(bGPDspoint *points, short thickness, short dfla
}
/* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
-static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness, short debug)
+static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness, bool debug, short UNUSED(sflag))
{
bGPDspoint *pt;
float curpressure = points[0].pressure;
@@ -231,8 +433,9 @@ static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness
}
}
glEnd();
-
+
/* draw debug points of curve on top? */
+ /* XXX: for now, we represent "selected" strokes in the same way as debug, which isn't used anymore */
if (debug) {
glBegin(GL_POINTS);
for (i = 0, pt = points; i < totpoints && pt; i++, pt++)
@@ -244,46 +447,22 @@ static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness
/* ----- Fancy 2D-Stroke Drawing ------ */
/* draw a given stroke in 2d */
-static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
- short debug, int offsx, int offsy, int winx, int winy)
+static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
+ bool debug, int offsx, int offsy, int winx, int winy)
{
/* otherwise thickness is twice that of the 3D view */
float thickness = (float)thickness_s * 0.5f;
-
- /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better
- * - 'smooth' opengl lines are also required if Image Editor 'image-based' stroke
- */
- if ((thickness < GP_DRAWTHICKNESS_SPECIAL) ||
- ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)))
- {
- bGPDspoint *pt;
- int i;
-
- glBegin(GL_LINE_STRIP);
- for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
- if (sflag & GP_STROKE_2DSPACE) {
- glVertex2f(pt->x, pt->y);
- }
- else if (sflag & GP_STROKE_2DIMAGE) {
- const float x = (pt->x * winx) + offsx;
- const float y = (pt->y * winy) + offsy;
-
- glVertex2f(x, y);
- }
- else {
- const float x = (pt->x / 100 * winx) + offsx;
- const float y = (pt->y / 100 * winy) + offsy;
-
- glVertex2f(x, y);
- }
- }
- glEnd();
+
+ /* strokes in Image Editor need a scale factor, since units there are not pixels! */
+ float scalefac = 1.0f;
+ if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
+ scalefac = 0.001f;
}
/* tessellation code - draw stroke as series of connected quads with connection
* edges rotated to minimize shrinking artifacts, and rounded endcaps
*/
- else {
+ {
bGPDspoint *pt1, *pt2;
float pm[2];
int i;
@@ -299,22 +478,8 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s,
float pthick; /* thickness at segment point */
/* get x and y coordinates from points */
- if (sflag & GP_STROKE_2DSPACE) {
- s0[0] = pt1->x; s0[1] = pt1->y;
- s1[0] = pt2->x; s1[1] = pt2->y;
- }
- else if (sflag & GP_STROKE_2DIMAGE) {
- s0[0] = (pt1->x * winx) + offsx;
- s0[1] = (pt1->y * winy) + offsy;
- s1[0] = (pt2->x * winx) + offsx;
- s1[1] = (pt2->y * winy) + offsy;
- }
- else {
- s0[0] = (pt1->x / 100 * winx) + offsx;
- s0[1] = (pt1->y / 100 * winy) + offsy;
- s1[0] = (pt2->x / 100 * winx) + offsx;
- s1[1] = (pt2->y / 100 * winy) + offsy;
- }
+ gp_calc_2d_stroke_xy(pt1, sflag, offsx, offsy, winx, winy, s0);
+ gp_calc_2d_stroke_xy(pt2, sflag, offsx, offsy, winx, winy, s1);
/* calculate gradient and normal - 'angle'=(ny/nx) */
m1[1] = s1[1] - s0[1];
@@ -324,12 +489,12 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s,
m2[0] = m1[1];
/* always use pressure from first point here */
- pthick = (pt1->pressure * thickness);
+ pthick = (pt1->pressure * thickness * scalefac);
/* if the first segment, start of segment is segment's normal */
if (i == 0) {
- /* draw start cap first
- * - make points slightly closer to center (about halfway across)
+ /* draw start cap first
+ * - make points slightly closer to center (about halfway across)
*/
mt[0] = m2[0] * pthick * 0.5f;
mt[1] = m2[1] * pthick * 0.5f;
@@ -369,7 +534,7 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s,
mb[1] = (pm[1] + m2[1]) / 2;
normalize_v2(mb);
- /* calculate gradient to apply
+ /* calculate gradient to apply
* - as basis, use just pthick * bisector gradient
* - if cross-section not as thick as it should be, add extra padding to fix it
*/
@@ -399,7 +564,7 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s,
/* if last segment, also draw end of segment (defined as segment's normal) */
if (i == totpoints - 2) {
/* for once, we use second point's pressure (otherwise it won't be drawn) */
- pthick = (pt2->pressure * thickness);
+ pthick = (pt2->pressure * thickness * scalefac);
/* calculate points for end of segment */
mt[0] = m2[0] * pthick;
@@ -417,8 +582,8 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s,
glVertex2fv(t1);
- /* draw end cap as last step
- * - make points slightly closer to center (about halfway across)
+ /* draw end cap as last step
+ * - make points slightly closer to center (about halfway across)
*/
mt[0] = m2[0] * pthick * 0.5f;
mt[1] = m2[1] * pthick * 0.5f;
@@ -448,52 +613,57 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s,
glBegin(GL_POINTS);
for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
- if (sflag & GP_STROKE_2DSPACE) {
- glVertex2fv(&pt->x);
- }
- else if (sflag & GP_STROKE_2DIMAGE) {
- const float x = (float)((pt->x * winx) + offsx);
- const float y = (float)((pt->y * winy) + offsy);
-
- glVertex2f(x, y);
- }
- else {
- const float x = (float)(pt->x / 100 * winx) + offsx;
- const float y = (float)(pt->y / 100 * winy) + offsy;
-
- glVertex2f(x, y);
- }
+ float co[2];
+
+ gp_calc_2d_stroke_xy(pt, sflag, offsx, offsy, winx, winy, co);
+ glVertex2fv(co);
}
glEnd();
}
}
-/* ----- General Drawing ------ */
+/* ----- Strokes Drawing ------ */
+
+/* Helper for doing all the checks on whether a stroke can be drawn */
+static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag)
+{
+ /* skip stroke if it isn't in the right display space for this drawing context */
+ /* 1) 3D Strokes */
+ if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
+ return false;
+
+ /* 2) Screen Space 2D Strokes */
+ if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
+ return false;
+
+ /* 3) Image Space (2D) */
+ if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
+ return false;
+
+
+ /* skip stroke if it doesn't have any valid data */
+ if ((gps->points == NULL) || (gps->totpoints < 1))
+ return false;
+
+ /* stroke can be drawn */
+ return true;
+}
/* draw a set of strokes */
static void gp_draw_strokes(bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag,
- short debug, short lthick, const float color[4])
+ bool debug, short lthick, const float color[4], const float fill_color[4])
{
bGPDstroke *gps;
- /* set color first (may need to reset it again later too) */
- glColor4fv(color);
-
for (gps = gpf->strokes.first; gps; gps = gps->next) {
- /* check if stroke can be drawn - checks here generally fall into pairs */
- if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE))
- continue;
- if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
- continue;
- if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
- continue;
- if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
- continue;
- if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
- continue;
- if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
- continue;
- if ((gps->points == NULL) || (gps->totpoints < 1))
+ /* check if stroke can be drawn */
+ if (gp_can_draw_stroke(gps, dflag) == false)
continue;
/* check which stroke-drawer to use */
@@ -515,11 +685,27 @@ static void gp_draw_strokes(bGPDframe *gpf, int offsx, int offsy, int winx, int
#endif
}
- if (gps->totpoints == 1) {
- gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
+ /* 3D Fill */
+ if ((dflag & GP_DRAWDATA_FILL) && (gps->totpoints >= 3)) {
+ glColor4fv(fill_color);
+ gp_draw_stroke_fill(gps->points, gps->totpoints, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
+ }
+
+ /* 3D Stroke */
+ glColor4fv(color);
+
+ if (dflag & GP_DRAWDATA_VOLUMETRIC) {
+ /* volumetric stroke drawing */
+ gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, lthick, dflag, gps->flag);
}
else {
- gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, debug);
+ /* 3D Lines - OpenGL primitives-based */
+ if (gps->totpoints == 1) {
+ gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
+ }
+ else {
+ gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, debug, gps->flag);
+ }
}
if (no_xray) {
@@ -534,116 +720,302 @@ static void gp_draw_strokes(bGPDframe *gpf, int offsx, int offsy, int winx, int
}
}
else {
- if (gps->totpoints == 1) {
- gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
+ /* 2D - Fill */
+ if ((dflag & GP_DRAWDATA_FILL) && (gps->totpoints >= 3)) {
+ glColor4fv(fill_color);
+ gp_draw_stroke_fill(gps->points, gps->totpoints, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
+ }
+
+ /* 2D Strokes... */
+ glColor4fv(color);
+
+ if (dflag & GP_DRAWDATA_VOLUMETRIC) {
+ /* blob/disk-based "volumetric" drawing */
+ gp_draw_stroke_volumetric_2d(gps->points, gps->totpoints, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
}
else {
- gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, offsx, offsy, winx, winy);
+ /* normal 2D strokes */
+ if (gps->totpoints == 1) {
+ gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
+ }
+ else {
+ gp_draw_stroke_2d(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, offsx, offsy, winx, winy);
+ }
}
}
}
}
-/* draw grease-pencil datablock */
-static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
+/* Draw selected verts for strokes being edited */
+static void gp_draw_strokes_edit(bGPDframe *gpf, int offsx, int offsy, int winx, int winy, short dflag, const float tcolor[3])
{
- bGPDlayer *gpl;
+ bGPDstroke *gps;
- /* reset line drawing style (in case previous user didn't reset) */
- setlinestyle(0);
+ const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY);
+ int mask_orig = 0;
- /* turn on smooth lines (i.e. anti-aliasing) */
- glEnable(GL_LINE_SMOOTH);
+ /* set up depth masks... */
+ if (dflag & GP_DRAWDATA_ONLY3D) {
+ if (no_xray) {
+ glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
+ glDepthMask(0);
+ glEnable(GL_DEPTH_TEST);
+
+ /* first arg is normally rv3d->dist, but this isn't
+ * available here and seems to work quite well without */
+ bglPolygonOffset(1.0f, 1.0f);
+#if 0
+ glEnable(GL_POLYGON_OFFSET_LINE);
+ glPolygonOffset(-1.0f, -1.0f);
+#endif
+ }
+ }
- /* turn on alpha-blending */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+
+ /* draw stroke verts */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt;
+ float vsize, bsize;
+ int i;
+
+ /* check if stroke can be drawn */
+ if (gp_can_draw_stroke(gps, dflag) == false)
+ continue;
- /* loop over layers, drawing them */
+ /* Optimisation: only draw points for selected strokes
+ * We assume that selected points can only occur in
+ * strokes that are selected too.
+ */
+ if ((gps->flag & GP_STROKE_SELECT) == 0)
+ continue;
+
+ /* Get size of verts:
+ * - The selected state needs to be larger than the unselected state so that
+ * they stand out more.
+ * - We use the theme setting for size of the unselected verts
+ */
+ bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
+ if ((int)bsize > 8) {
+ vsize = 10.0f;
+ bsize = 8.0f;
+ }
+ else {
+ vsize = bsize + 2;
+ }
+
+ /* First Pass: Draw all the verts (i.e. these become the unselected state) */
+ if (tcolor != NULL) {
+ /* for now, we assume that the base color of the points is not too close to the real color */
+ glColor3fv(tcolor);
+ }
+ else {
+ /* this doesn't work well with the default theme and black strokes... */
+ UI_ThemeColor(TH_GP_VERTEX);
+ }
+ glPointSize(bsize);
+
+ glBegin(GL_POINTS);
+ for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ glVertex3fv(&pt->x);
+ }
+ else {
+ float co[2];
+
+ gp_calc_2d_stroke_xy(pt, gps->flag, offsx, offsy, winx, winy, co);
+ glVertex2fv(co);
+ }
+ }
+ glEnd();
+
+
+ /* Second Pass: Draw only verts which are selected */
+ UI_ThemeColor(TH_GP_VERTEX_SELECT);
+ glPointSize(vsize);
+
+ glBegin(GL_POINTS);
+ for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ glVertex3fv(&pt->x);
+ }
+ else {
+ float co[2];
+
+ gp_calc_2d_stroke_xy(pt, gps->flag, offsx, offsy, winx, winy, co);
+ glVertex2fv(co);
+ }
+ }
+ }
+ glEnd();
+ }
+
+
+ /* clear depth mask */
+ if (dflag & GP_DRAWDATA_ONLY3D) {
+ if (no_xray) {
+ glDepthMask(mask_orig);
+ glDisable(GL_DEPTH_TEST);
+
+ bglPolygonOffset(0.0, 0.0);
+#if 0
+ glDisable(GL_POLYGON_OFFSET_LINE);
+ glPolygonOffset(0, 0);
+#endif
+ }
+ }
+}
+
+/* ----- General Drawing ------ */
+
+/* draw onion-skinning for a layer */
+static void gp_draw_onionskins(bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy,
+ int UNUSED(cfra), int dflag, short debug, short lthick)
+{
+ const float alpha = gpl->color[3];
+ float color[4];
+
+ /* 1) Draw Previous Frames First */
+ if (gpl->flag & GP_LAYER_GHOST_PREVCOL) {
+ copy_v3_v3(color, gpl->gcolor_prev);
+ }
+ else {
+ copy_v3_v3(color, gpl->color);
+ }
+
+ if (gpl->gstep) {
+ bGPDframe *gf;
+ float fac;
+
+ /* draw previous frames first */
+ for (gf = gpf->prev; gf; gf = gf->prev) {
+ /* check if frame is drawable */
+ if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
+ /* alpha decreases with distance from curframe index */
+ fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
+ color[3] = alpha * fac * 0.66f;
+ gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, color, color);
+ }
+ else
+ break;
+ }
+ }
+ else {
+ /* draw the strokes for the ghost frames (at half of the alpha set by user) */
+ if (gpf->prev) {
+ color[3] = (alpha / 7);
+ gp_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, debug, lthick, color, color);
+ }
+ }
+
+
+ /* 2) Now draw next frames */
+ if (gpl->flag & GP_LAYER_GHOST_NEXTCOL) {
+ copy_v3_v3(color, gpl->gcolor_next);
+ }
+ else {
+ copy_v3_v3(color, gpl->color);
+ }
+
+ if (gpl->gstep_next) {
+ bGPDframe *gf;
+ float fac;
+
+ /* now draw next frames */
+ for (gf = gpf->next; gf; gf = gf->next) {
+ /* check if frame is drawable */
+ if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) {
+ /* alpha decreases with distance from curframe index */
+ fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
+ color[3] = alpha * fac * 0.66f;
+ gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, color, color);
+ }
+ else
+ break;
+ }
+ }
+ else {
+ /* draw the strokes for the ghost frames (at half of the alpha set by user) */
+ if (gpf->next) {
+ color[3] = (alpha / 4);
+ gp_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, debug, lthick, color, color);
+ }
+ }
+
+ /* 3) restore alpha */
+ glColor4fv(gpl->color);
+}
+
+/* loop over gpencil data layers, drawing them */
+static void gp_draw_data_layers(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
+{
+ bGPDlayer *gpl;
+
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
bGPDframe *gpf;
- short debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? 1 : 0;
+ bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? true : false;
short lthick = gpl->thickness;
- float color[4], tcolor[4];
/* don't draw layer if hidden */
- if (gpl->flag & GP_LAYER_HIDE)
+ if (gpl->flag & GP_LAYER_HIDE)
continue;
/* get frame to draw */
gpf = gpencil_layer_getframe(gpl, cfra, 0);
- if (gpf == NULL)
+ if (gpf == NULL)
continue;
/* set color, stroke thickness, and point size */
glLineWidth(lthick);
- copy_v4_v4(color, gpl->color); // just for copying 4 array elements
- copy_v4_v4(tcolor, gpl->color); // additional copy of color (for ghosting)
- glColor4fv(color);
glPointSize((float)(gpl->thickness + 2));
- /* apply xray layer setting */
- if (gpl->flag & GP_LAYER_NO_XRAY) dflag |= GP_DRAWDATA_NO_XRAY;
- else dflag &= ~GP_DRAWDATA_NO_XRAY;
+ /* Add layer drawing settings to the set of "draw flags"
+ * NOTE: If the setting doesn't apply, it *must* be cleared,
+ * as dflag's carry over from the previous layer
+ */
+#define GP_DRAWFLAG_APPLY(condition, draw_flag_value) { \
+ if (condition) dflag |= (draw_flag_value); \
+ else dflag &= ~(draw_flag_value); \
+ } (void)0
+
+ /* xray... */
+ GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_NO_XRAY), GP_DRAWDATA_NO_XRAY);
+
+ /* volumetric strokes... */
+ GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_VOLUMETRIC), GP_DRAWDATA_VOLUMETRIC);
+
+ /* fill strokes... */
+ // XXX: this is not a very good limit
+ GP_DRAWFLAG_APPLY((gpl->fill[3] > 0.001f), GP_DRAWDATA_FILL);
+#undef GP_DRAWFLAG_APPLY
/* draw 'onionskins' (frame left + right) */
- if (gpl->flag & GP_LAYER_ONIONSKIN) {
- /* drawing method - only immediately surrounding (gstep = 0),
- * or within a frame range on either side (gstep > 0)*/
- if (gpl->gstep) {
- bGPDframe *gf;
- float fac;
-
- /* draw previous frames first */
- for (gf = gpf->prev; gf; gf = gf->prev) {
- /* check if frame is drawable */
- if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
- /* alpha decreases with distance from curframe index */
- fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
- tcolor[3] = color[3] * fac * 0.66f;
- gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
- }
- else
- break;
- }
-
- /* now draw next frames */
- for (gf = gpf->next; gf; gf = gf->next) {
- /* check if frame is drawable */
- if ((gf->framenum - gpf->framenum) <= gpl->gstep) {
- /* alpha decreases with distance from curframe index */
- fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep + 1));
- tcolor[3] = color[3] * fac * 0.66f;
- gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
- }
- else
- break;
- }
-
- /* restore alpha */
- glColor4fv(color);
- }
- else {
- /* draw the strokes for the ghost frames (at half of the alpha set by user) */
- if (gpf->prev) {
- tcolor[3] = (color[3] / 7);
- gp_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
- }
-
- if (gpf->next) {
- tcolor[3] = (color[3] / 4);
- gp_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
- }
-
- /* restore alpha */
- glColor4fv(color);
- }
+ if ((gpl->flag & GP_LAYER_ONIONSKIN) && !(dflag & GP_DRAWDATA_NO_ONIONS)) {
+ /* Drawing method - only immediately surrounding (gstep = 0),
+ * or within a frame range on either side (gstep > 0)
+ */
+ gp_draw_onionskins(gpl, gpf, offsx, offsy, winx, winy, cfra, dflag, debug, lthick);
}
/* draw the strokes already in active frame */
- tcolor[3] = color[3];
- gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
+ gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, gpl->color, gpl->fill);
+
+ /* Draw verts of selected strokes
+ * - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering
+ * - locked layers can't be edited, so there's no point showing these verts
+ * as they will have no bearings on what gets edited
+ * - only show when in editmode, since operators shouldn't work otherwise
+ * (NOTE: doing it this way means that the toggling editmode shows visible change immediately)
+ */
+ /* XXX: perhaps we don't want to show these when users are drawing... */
+ if ((G.f & G_RENDER_OGL) == 0 &&
+ (gpl->flag & GP_LAYER_LOCKED) == 0 &&
+ (gpd->flag & GP_DATA_STROKE_EDITMODE))
+ {
+ gp_draw_strokes_edit(gpf, offsx, offsy, winx, winy, dflag,
+ (gpl->color[3] < 0.95f) ? gpl->color : NULL);
+ }
/* Check if may need to draw the active stroke cache, only if this layer is the active layer
* that is being edited. (Stroke buffer is currently stored in gp-data)
@@ -651,22 +1023,83 @@ static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy,
if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
(gpf->flag & GP_FRAME_PAINT))
{
+ /* Set color for drawing buffer stroke - since this may not be set yet */
+ glColor4fv(gpl->color);
+
/* Buffer stroke needs to be drawn with a different linestyle
- * to help differentiate them from normal strokes. */
- gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag);
+ * to help differentiate them from normal strokes.
+ *
+ * It should also be noted that sbuffer contains temporary point types
+ * i.e. tGPspoints NOT bGPDspoints
+ */
+ if (gpl->flag & GP_LAYER_VOLUMETRIC) {
+ gp_draw_stroke_volumetric_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag);
+ }
+ else {
+ gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag);
+ }
}
}
+}
+
+/* draw grease-pencil datablock */
+static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
+{
+ /* reset line drawing style (in case previous user didn't reset) */
+ setlinestyle(0);
+
+ /* turn on smooth lines (i.e. anti-aliasing) */
+ glEnable(GL_LINE_SMOOTH);
+
+ glEnable(GL_POLYGON_SMOOTH);
+ glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
+
+ /* turn on alpha-blending */
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ /* draw! */
+ gp_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag);
/* turn off alpha blending, then smooth lines */
glDisable(GL_BLEND); // alpha blending
glDisable(GL_LINE_SMOOTH); // smooth lines
-
+ glDisable(GL_POLYGON_SMOOTH); // smooth poly lines
+
/* restore initial gl conditions */
glLineWidth(1.0);
glPointSize(1.0);
glColor4f(0, 0, 0, 1);
}
+/* if we have strokes for scenes (3d view)/clips (movie clip editor)
+ * and objects/tracks, multiple data blocks have to be drawn */
+static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, int winx, int winy,
+ int cfra, int dflag, const char spacetype)
+{
+ bGPdata *gpd_source = NULL;
+
+ if (scene) {
+ if (spacetype == SPACE_VIEW3D) {
+ gpd_source = (scene->gpd ? scene->gpd : NULL);
+ }
+ else if (spacetype == SPACE_CLIP && scene->clip) {
+ /* currently drawing only gpencil data from either clip or track, but not both - XXX fix logic behind */
+ gpd_source = (scene->clip->gpd ? scene->clip->gpd : NULL);
+ }
+
+ if (gpd_source) {
+ gp_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag);
+ }
+ }
+
+ /* scene/clip data has already been drawn, only object/track data is drawn here
+ * if gpd_source == gpd, we don't have any object/track data and we can skip */
+ if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) {
+ gp_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag);
+ }
+}
+
/* ----- Grease Pencil Sketches Drawing API ------ */
/* ............................
@@ -693,7 +1126,7 @@ void ED_gpencil_draw_2dimage(const bContext *C)
case SPACE_IMAGE: /* image */
case SPACE_CLIP: /* clip */
{
-
+
/* just draw using standard scaling (settings here are currently ignored anyways) */
/* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */
offsx = 0;
@@ -714,8 +1147,8 @@ void ED_gpencil_draw_2dimage(const bContext *C)
sizex = ar->winx;
sizey = ar->winy;
- /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
- * and everything moved to standard View2d
+ /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
+ * and everything moved to standard View2d
*/
dflag |= GP_DRAWDATA_ONLYV2D;
break;
@@ -732,10 +1165,10 @@ void ED_gpencil_draw_2dimage(const bContext *C)
/* draw it! */
- gp_draw_data(gpd, offsx, offsy, sizex, sizey, CFRA, dflag);
+ gp_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, sa->spacetype);
}
-/* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly
+/* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly
* Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes,
* second time with onlyv2d=0 for screen-aligned strokes */
void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d)
@@ -758,10 +1191,10 @@ void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d)
/* draw it! */
if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS);
- gp_draw_data(gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag);
+ gp_draw_data_all(scene, gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag, sa->spacetype);
}
-/* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly
+/* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly
* Note: this gets called twice - first time with only3d=1 to draw 3d-strokes,
* second time with only3d=0 for screen-aligned strokes */
void ED_gpencil_draw_view3d(Scene *scene, View3D *v3d, ARegion *ar, bool only3d)
@@ -770,17 +1203,17 @@ void ED_gpencil_draw_view3d(Scene *scene, View3D *v3d, ARegion *ar, bool only3d)
int dflag = 0;
RegionView3D *rv3d = ar->regiondata;
int offsx, offsy, winx, winy;
-
+
/* check that we have grease-pencil stuff to draw */
gpd = ED_gpencil_data_get_active_v3d(scene, v3d);
if (gpd == NULL) return;
-
+
/* when rendering to the offscreen buffer we don't want to
* deal with the camera border, otherwise map the coords to the camera border. */
if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) {
rctf rectf;
ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &rectf, true); /* no shift */
-
+
offsx = iroundf(rectf.xmin);
offsy = iroundf(rectf.ymin);
winx = iroundf(rectf.xmax - rectf.xmin);
@@ -795,15 +1228,15 @@ void ED_gpencil_draw_view3d(Scene *scene, View3D *v3d, ARegion *ar, bool only3d)
/* draw it! */
if (only3d) dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
-
- gp_draw_data(gpd, offsx, offsy, winx, winy, CFRA, dflag);
+
+ gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
}
-void ED_gpencil_draw_ex(bGPdata *gpd, int winx, int winy, const int cfra)
+void ED_gpencil_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
{
int dflag = GP_DRAWDATA_NOSTATUS | GP_DRAWDATA_ONLYV2D;
-
- gp_draw_data(gpd, 0, 0, winx, winy, cfra, dflag);
+
+ gp_draw_data_all(scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype);
}
/* ************************************************** */
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index dba80164e93..97adaea41a8 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -27,7 +27,7 @@
* \ingroup edgpencil
*/
-
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -49,8 +49,6 @@
#include "ED_keyframes_edit.h"
#include "ED_markers.h"
-#include "gpencil_intern.h"
-
/* ***************************************** */
/* NOTE ABOUT THIS FILE:
* This file contains code for editing Grease Pencil data in the Action Editor
@@ -75,7 +73,7 @@ bool ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPD
if (gpf_cb(gpf, scene))
return true;
}
-
+
/* nothing to return */
return false;
}
@@ -115,7 +113,7 @@ bool ED_gplayer_frame_select_check(bGPDlayer *gpl)
bGPDframe *gpf;
/* error checking */
- if (gpl == NULL)
+ if (gpl == NULL)
return false;
/* stop at the first one found */
@@ -153,9 +151,9 @@ void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode)
bGPDframe *gpf;
/* error checking */
- if (gpl == NULL)
+ if (gpl == NULL)
return;
-
+
/* handle according to mode */
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
gpframe_select(gpf, select_mode);
@@ -166,7 +164,7 @@ void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode)
void ED_gplayer_frame_select_set(bGPDlayer *gpl, short mode)
{
/* error checking */
- if (gpl == NULL)
+ if (gpl == NULL)
return;
/* now call the standard function */
@@ -178,11 +176,11 @@ void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode)
{
bGPDframe *gpf;
- if (gpl == NULL)
+ if (gpl == NULL)
return;
-
+
gpf = BKE_gpencil_layer_find_frame(gpl, selx);
-
+
if (gpf) {
gpframe_select(gpf, select_mode);
}
@@ -215,7 +213,7 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl)
/* error checking */
if (gpl == NULL)
return false;
-
+
/* check for frames to delete */
for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
gpfn = gpf->next;
@@ -223,7 +221,7 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl)
if (gpf->flag & GP_FRAME_SELECT)
changed |= gpencil_layer_delframe(gpl, gpf);
}
-
+
return changed;
}
@@ -242,7 +240,7 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
/* duplicate this frame */
if (gpf->flag & GP_FRAME_SELECT) {
- bGPDframe *gpfd;
+ bGPDframe *gpfd;
/* duplicate frame, and deselect self */
gpfd = gpencil_frame_duplicate(gpf);
@@ -253,6 +251,23 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
}
}
+/* Set keyframe type for selected frames from given gp-layer
+ * \param type The type of keyframe (eBezTriple_KeyframeType) to set selected frames to
+ */
+void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type)
+{
+ bGPDframe *gpf;
+
+ if (gpl == NULL)
+ return;
+
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if (gpf->flag & GP_FRAME_SELECT) {
+ gpf->key_type = type;
+ }
+ }
+}
+
#if 0 // XXX disabled until grease pencil code stabilises again
/* -------------------------------------- */
/* Copy and Paste Tools */
@@ -263,7 +278,7 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
* the current frame and the 'first keyframe' (i.e. the earliest one in all channels).
* - The earliest frame is calculated per copy operation.
*/
-
+
/* globals for copy/paste data (like for other copy/paste buffers) */
ListBase gpcopybuf = {NULL, NULL};
static int gpcopy_firstframe = 999999999;
@@ -271,7 +286,7 @@ static int gpcopy_firstframe = 999999999;
/* This function frees any MEM_calloc'ed copy/paste buffer data */
void free_gpcopybuf()
{
- free_gpencil_layers(&gpcopybuf);
+ free_gpencil_layers(&gpcopybuf);
BLI_listbase_clear(&gpcopybuf);
gpcopy_firstframe = 999999999;
@@ -398,8 +413,8 @@ void paste_gpdata(Scene *scene)
//sa = gpencil_data_findowner((bGPdata *)ale->owner);
sa = NULL;
- /* this should be the right frame... as it may be a pre-existing frame,
- * must make sure that only compatible stroke types get copied over
+ /* this should be the right frame... as it may be a pre-existing frame,
+ * must make sure that only compatible stroke types get copied over
* - we cannot just add a duplicate frame, as that would cause errors
* - need to check for compatible types to minimize memory usage (copying 'junk' over)
*/
@@ -418,14 +433,14 @@ void paste_gpdata(Scene *scene)
if ((gps->flag == 0) || (gps->flag & GP_STROKE_3DSPACE))
stroke_ok = 1;
break;
-
+
case SPACE_NODE: /* Nodes Editor: either screen-aligned or view-aligned */
case SPACE_IMAGE: /* Image Editor: either screen-aligned or view\image-aligned */
case SPACE_CLIP: /* Image Editor: either screen-aligned or view\image-aligned */
if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DSPACE))
stroke_ok = 1;
break;
-
+
case SPACE_SEQ: /* Sequence Editor: either screen-aligned or view-aligned */
if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DIMAGE))
stroke_ok = 1;
@@ -567,9 +582,9 @@ static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene)
/* In order for this mirror function to work without
* any extra arguments being added, we use the case
- * of bezt==NULL to denote that we should find the
+ * of bezt==NULL to denote that we should find the
* marker to mirror over. The static pointer is safe
- * to use this way, as it will be set to null after
+ * to use this way, as it will be set to null after
* each cycle in which this is called.
*/
diff --git a/source/blender/editors/gpencil/gpencil_buttons.c b/source/blender/editors/gpencil/gpencil_buttons.c
deleted file mode 100644
index a7635c12d56..00000000000
--- a/source/blender/editors/gpencil/gpencil_buttons.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2008, Blender Foundation, Joshua Leung
- * This is a new part of Blender
- *
- * Contributor(s): Joshua Leung
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/gpencil/gpencil_buttons.c
- * \ingroup edgpencil
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-
-#include "BLI_blenlib.h"
-
-#include "BLF_translation.h"
-
-#include "DNA_gpencil_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-
-#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_gpencil.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "RNA_access.h"
-
-#include "ED_gpencil.h"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
-
-#include "gpencil_intern.h"
-
-/* ************************************************** */
-/* GREASE PENCIL PANEL-UI DRAWING */
-
-/* Every space which implements Grease-Pencil functionality should have a panel
- * for the settings. All of the space-dependent parts should be coded in the panel
- * code for that space, but the rest is all handled by generic panel here.
- */
-
-/* ------- Callbacks ----------- */
-/* These are just 'dummy wrappers' around gpencil api calls */
-
-/* make layer active one after being clicked on */
-static void gp_ui_activelayer_cb(bContext *C, void *gpd, void *gpl)
-{
- /* make sure the layer we want to remove is the active one */
- gpencil_layer_setactive(gpd, gpl);
-
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-}
-
-/* delete 'active' layer */
-static void gp_ui_dellayer_cb(bContext *C, void *gpd, void *gpl)
-{
- gpencil_layer_delete((bGPdata *)gpd, (bGPDlayer *)gpl);
-
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-}
-
-/* move layer up */
-static void gp_ui_layer_up_cb(bContext *C, void *gpd_v, void *gpl_v)
-{
- bGPdata *gpd = gpd_v;
- bGPDlayer *gpl = gpl_v;
-
- BLI_remlink(&gpd->layers, gpl);
- BLI_insertlinkbefore(&gpd->layers, gpl->prev, gpl);
-
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-}
-
-/* move layer down */
-static void gp_ui_layer_down_cb(bContext *C, void *gpd_v, void *gpl_v)
-{
- bGPdata *gpd = gpd_v;
- bGPDlayer *gpl = gpl_v;
-
- BLI_remlink(&gpd->layers, gpl);
- BLI_insertlinkafter(&gpd->layers, gpl->next, gpl);
-
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-}
-
-/* ------- Drawing Code ------- */
-
-/* draw the controls for a given layer */
-static void gp_drawui_layer(uiLayout *layout, bGPdata *gpd, bGPDlayer *gpl, const bool is_v3d)
-{
- uiLayout *box = NULL, *split = NULL;
- uiLayout *col = NULL;
- uiLayout *row = NULL, *sub = NULL;
- uiBlock *block;
- uiBut *but;
- PointerRNA ptr;
- int icon;
-
- /* make pointer to layer data */
- RNA_pointer_create((ID *)gpd, &RNA_GPencilLayer, gpl, &ptr);
-
- /* unless button has own callback, it adds this callback to button */
- block = uiLayoutGetBlock(layout);
- UI_block_func_set(block, gp_ui_activelayer_cb, gpd, gpl);
-
- /* draw header ---------------------------------- */
- /* get layout-row + UI-block for header */
- box = uiLayoutBox(layout);
-
- row = uiLayoutRow(box, false);
- uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
- block = uiLayoutGetBlock(row); /* err... */
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- /* left-align ............................... */
- sub = uiLayoutRow(row, false);
-
- /* active */
- block = uiLayoutGetBlock(sub);
- icon = (gpl->flag & GP_LAYER_ACTIVE) ? ICON_RADIOBUT_ON : ICON_RADIOBUT_OFF;
- but = uiDefIconButBitI(block, UI_BTYPE_TOGGLE, GP_LAYER_ACTIVE, 0, icon, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- &gpl->flag, 0.0, 0.0, 0.0, 0.0, TIP_("Set active layer"));
- UI_but_func_set(but, gp_ui_activelayer_cb, gpd, gpl);
-
- /* locked */
- icon = (gpl->flag & GP_LAYER_LOCKED) ? ICON_LOCKED : ICON_UNLOCKED;
- uiItemR(sub, &ptr, "lock", 0, "", icon);
-
- /* when layer is locked or hidden, only draw header */
- if (gpl->flag & (GP_LAYER_LOCKED | GP_LAYER_HIDE)) {
- char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */
-
- /* visibility button (only if hidden but not locked!) */
- if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED))
- uiItemR(sub, &ptr, "hide", 0, "", ICON_RESTRICT_VIEW_ON);
-
- /* name */
- if (gpl->flag & GP_LAYER_HIDE)
- BLI_snprintf(name, sizeof(name), IFACE_("%s (Hidden)"), gpl->info);
- else
- BLI_snprintf(name, sizeof(name), IFACE_("%s (Locked)"), gpl->info);
- uiItemL(sub, name, ICON_NONE);
-
- /* delete button (only if hidden but not locked!) */
- if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED)) {
- /* right-align ............................... */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
- block = uiLayoutGetBlock(sub); /* XXX... err... */
-
- but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete layer"));
- UI_but_func_set(but, gp_ui_dellayer_cb, gpd, gpl);
- }
- UI_block_emboss_set(block, UI_EMBOSS);
- }
- else {
- /* draw rest of header -------------------------------- */
- /* visibility button */
- uiItemR(sub, &ptr, "hide", 0, "", ICON_RESTRICT_VIEW_OFF);
-
- /* frame locking */
- /* TODO: this needs its own icons... */
- icon = (gpl->flag & GP_LAYER_FRAMELOCK) ? ICON_RENDER_STILL : ICON_RENDER_ANIMATION;
- uiItemR(sub, &ptr, "lock_frame", 0, "", icon);
-
- UI_block_emboss_set(block, UI_EMBOSS);
-
- /* name */
- uiItemR(sub, &ptr, "info", 0, "", ICON_NONE);
-
- /* move up/down */
- UI_block_align_begin(block);
-
- if (gpl->prev) {
- but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_TRIA_UP, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Move layer up"));
- UI_but_func_set(but, gp_ui_layer_up_cb, gpd, gpl);
- }
- if (gpl->next) {
- but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_TRIA_DOWN, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Move layer down"));
- UI_but_func_set(but, gp_ui_layer_down_cb, gpd, gpl);
- }
-
- UI_block_align_end(block);
-
- /* delete 'button' */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- /* right-align ............................... */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
- block = uiLayoutGetBlock(sub); /* XXX... err... */
-
- but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete layer"));
- UI_but_func_set(but, gp_ui_dellayer_cb, gpd, gpl);
- UI_block_emboss_set(block, UI_EMBOSS);
-
- /* new backdrop ----------------------------------- */
- box = uiLayoutBox(layout);
- split = uiLayoutSplit(box, 0.5f, false);
-
- /* draw settings ---------------------------------- */
- /* left column ..................... */
- col = uiLayoutColumn(split, false);
-
- /* color */
- sub = uiLayoutColumn(col, true);
- uiItemR(sub, &ptr, "color", 0, "", ICON_NONE);
- uiItemR(sub, &ptr, "alpha", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
-
- /* stroke thickness */
- uiItemR(col, &ptr, "line_width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
-
- /* debugging options */
- if (G.debug & G_DEBUG) {
- uiItemR(col, &ptr, "show_points", 0, NULL, ICON_NONE);
- }
-
- /* right column ................... */
- col = uiLayoutColumn(split, false);
-
- /* onion-skinning */
- sub = uiLayoutColumn(col, true);
- uiItemR(sub, &ptr, "use_onion_skinning", 0, NULL, ICON_NONE);
- uiItemR(sub, &ptr, "ghost_range_max", 0, IFACE_("Frames"), ICON_NONE);
-
- /* 3d-view specific drawing options */
- if (is_v3d) {
- uiItemR(col, &ptr, "show_x_ray", 0, NULL, ICON_NONE);
- }
- }
-}
-
-/* stroke drawing options available */
-typedef enum eGP_Stroke_Ops {
- STROKE_OPTS_NORMAL = 0,
- STROKE_OPTS_V3D_OFF,
- STROKE_OPTS_V3D_ON,
-} eGP_Stroke_Ops;
-
-static void draw_gpencil_space_specials(const bContext *C, uiLayout *layout)
-{
- uiLayout *col, *row;
- SpaceClip *sc = CTX_wm_space_clip(C);
-
- col = uiLayoutColumn(layout, false);
-
- if (sc) {
- bScreen *screen = CTX_wm_screen(C);
- PointerRNA sc_ptr;
-
- RNA_pointer_create(&screen->id, &RNA_SpaceClipEditor, sc, &sc_ptr);
- row = uiLayoutRow(col, true);
- uiItemR(row, &sc_ptr, "grease_pencil_source", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- }
-}
-
-/* Draw the contents for a grease-pencil panel*/
-static void draw_gpencil_panel(bContext *C, uiLayout *layout, bGPdata *gpd, PointerRNA *ctx_ptr)
-{
- PointerRNA gpd_ptr;
- bGPDlayer *gpl;
- uiLayout *col, *row;
- SpaceClip *sc = CTX_wm_space_clip(C);
- short v3d_stroke_opts = STROKE_OPTS_NORMAL;
- const bool is_v3d = CTX_wm_view3d(C) != NULL;
-
- /* make new PointerRNA for Grease Pencil block */
- RNA_id_pointer_create((ID *)gpd, &gpd_ptr);
-
- /* draw gpd settings first ------------------------------------- */
- col = uiLayoutColumn(layout, false);
-
- /* current Grease Pencil block */
- /* TODO: show some info about who owns this? */
- uiTemplateID(col, C, ctx_ptr, "grease_pencil", "GPENCIL_OT_data_add", NULL, "GPENCIL_OT_data_unlink");
-
- /* add new layer button - can be used even when no data, since it can add a new block too */
- uiItemO(col, IFACE_("New Layer"), ICON_NONE, "GPENCIL_OT_layer_add");
- row = uiLayoutRow(col, true);
- uiItemO(row, IFACE_("Delete Frame"), ICON_NONE, "GPENCIL_OT_active_frame_delete");
- uiItemO(row, IFACE_("Convert"), ICON_NONE, "GPENCIL_OT_convert");
-
- /* sanity checks... */
- if (gpd == NULL)
- return;
-
- /* draw each layer --------------------------------------------- */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- col = uiLayoutColumn(layout, true);
- gp_drawui_layer(col, gpd, gpl, is_v3d);
- }
-
- /* draw gpd drawing settings first ------------------------------------- */
- col = uiLayoutColumn(layout, true);
- /* label */
- uiItemL(col, IFACE_("Drawing Settings:"), ICON_NONE);
-
- /* check whether advanced 3D-View drawing space options can be used */
- if (is_v3d) {
- if (gpd->flag & (GP_DATA_DEPTH_STROKE | GP_DATA_DEPTH_VIEW))
- v3d_stroke_opts = STROKE_OPTS_V3D_ON;
- else
- v3d_stroke_opts = STROKE_OPTS_V3D_OFF;
- }
-
- /* drawing space options */
- row = uiLayoutRow(col, true);
- uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "VIEW", NULL, ICON_NONE);
- uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "CURSOR", NULL, ICON_NONE);
-
- if (sc == NULL) {
- row = uiLayoutRow(col, true);
- uiLayoutSetActive(row, v3d_stroke_opts);
- uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "SURFACE", NULL, ICON_NONE);
- uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "STROKE", NULL, ICON_NONE);
-
- row = uiLayoutRow(col, false);
- uiLayoutSetActive(row, v3d_stroke_opts == STROKE_OPTS_V3D_ON);
- uiItemR(row, &gpd_ptr, "use_stroke_endpoints", 0, NULL, ICON_NONE);
- }
-}
-
-void ED_gpencil_panel_standard_header(const bContext *C, Panel *pa)
-{
- PointerRNA ptr;
- RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, CTX_wm_space_data(C), &ptr);
-
- uiItemR(pa->layout, &ptr, "show_grease_pencil", 0, "", ICON_NONE);
-}
-
-/* Standard panel to be included wherever Grease Pencil is used... */
-void ED_gpencil_panel_standard(const bContext *C, Panel *pa)
-{
- bGPdata **gpd_ptr = NULL;
- PointerRNA ptr;
-
- /* if (v3d->flag2 & V3D_DISPGP)... etc. */
-
- draw_gpencil_space_specials(C, pa->layout);
-
- /* get pointer to Grease Pencil Data */
- gpd_ptr = ED_gpencil_data_get_pointers((bContext *)C, &ptr);
-
- if (gpd_ptr)
- draw_gpencil_panel((bContext *)C, pa->layout, *gpd_ptr, &ptr);
-}
-
-/* ************************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 13334448941..3dae25263e8 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -27,6 +27,7 @@
* \ingroup edgpencil
*/
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -86,50 +87,59 @@
/* ************************************************ */
/* Context Wrangling... */
-/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it */
-bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr)
+/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it,
+ * when context info is not available.
+ */
+bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrArea *sa, Object *ob, PointerRNA *ptr)
{
- ID *screen_id = (ID *)CTX_wm_screen(C);
- Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
-
/* if there's an active area, check if the particular editor may
* have defined any special Grease Pencil context for editing...
*/
if (sa) {
+ SpaceLink *sl = sa->spacedata.first;
+
switch (sa->spacetype) {
case SPACE_VIEW3D: /* 3D-View */
+ case SPACE_TIME: /* Timeline - XXX: this is a hack to get it to show GP keyframes for 3D view */
{
- Object *ob = CTX_data_active_object(C);
-
- /* TODO: we can include other data-types such as bones later if need be... */
-
- /* just in case no active/selected object */
- if (ob && (ob->flag & SELECT)) {
- /* for now, as long as there's an object, default to using that in 3D-View */
- if (ptr) RNA_id_pointer_create(&ob->id, ptr);
- return &ob->gpd;
+ BLI_assert(scene && ELEM(scene->toolsettings->gpencil_src,
+ GP_TOOL_SOURCE_SCENE, GP_TOOL_SOURCE_OBJECT));
+
+ if (scene->toolsettings->gpencil_src == GP_TOOL_SOURCE_OBJECT) {
+ /* legacy behaviour for usage with old addons requiring object-linked to objects */
+
+ /* just in case no active/selected object... */
+ if (ob && (ob->flag & SELECT)) {
+ /* for now, as long as there's an object, default to using that in 3D-View */
+ if (ptr) RNA_id_pointer_create(&ob->id, ptr);
+ return &ob->gpd;
+ }
+ /* else: defaults to scene... */
+ }
+ else {
+ if (ptr) RNA_id_pointer_create(&scene->id, ptr);
+ return &scene->gpd;
}
break;
}
case SPACE_NODE: /* Nodes Editor */
{
- SpaceNode *snode = (SpaceNode *)CTX_wm_space_data(C);
-
+ SpaceNode *snode = (SpaceNode *)sl;
+
/* return the GP data for the active node block/node */
if (snode && snode->nodetree) {
/* for now, as long as there's an active node tree, default to using that in the Nodes Editor */
if (ptr) RNA_id_pointer_create(&snode->nodetree->id, ptr);
return &snode->nodetree->gpd;
}
-
+
/* even when there is no node-tree, don't allow this to flow to scene */
return NULL;
}
case SPACE_SEQ: /* Sequencer */
{
- SpaceSeq *sseq = (SpaceSeq *)CTX_wm_space_data(C);
-
+ SpaceSeq *sseq = (SpaceSeq *)sl;
+
/* for now, Grease Pencil data is associated with the space (actually preview region only) */
/* XXX our convention for everything else is to link to data though... */
if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, ptr);
@@ -137,8 +147,8 @@ bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr)
}
case SPACE_IMAGE: /* Image/UV Editor */
{
- SpaceImage *sima = (SpaceImage *)CTX_wm_space_data(C);
-
+ SpaceImage *sima = (SpaceImage *)sl;
+
/* for now, Grease Pencil data is associated with the space... */
/* XXX our convention for everything else is to link to data though... */
if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, ptr);
@@ -146,25 +156,25 @@ bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr)
}
case SPACE_CLIP: /* Nodes Editor */
{
- SpaceClip *sc = (SpaceClip *)CTX_wm_space_data(C);
+ SpaceClip *sc = (SpaceClip *)sl;
MovieClip *clip = ED_space_clip_get_clip(sc);
-
+
if (clip) {
if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
-
+
if (!track)
return NULL;
-
+
if (ptr)
RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr);
-
+
return &track->gpd;
}
else {
if (ptr)
RNA_id_pointer_create(&clip->id, ptr);
-
+
return &clip->gpd;
}
}
@@ -174,12 +184,32 @@ bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr)
return NULL;
}
}
-
+
/* just fall back on the scene's GP data */
if (ptr) RNA_id_pointer_create((ID *)scene, ptr);
return (scene) ? &scene->gpd : NULL;
}
+/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it */
+bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr)
+{
+ ID *screen_id = (ID *)CTX_wm_screen(C);
+ Scene *scene = CTX_data_scene(C);
+ ScrArea *sa = CTX_wm_area(C);
+ Object *ob = CTX_data_active_object(C);
+
+ return ED_gpencil_data_get_pointers_direct(screen_id, scene, sa, ob, ptr);
+}
+
+/* -------------------------------------------------------- */
+
+/* Get the active Grease Pencil datablock, when context is not available */
+bGPdata *ED_gpencil_data_get_active_direct(ID *screen_id, Scene *scene, ScrArea *sa, Object *ob)
+{
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(screen_id, scene, sa, ob, NULL);
+ return (gpd_ptr) ? *(gpd_ptr) : NULL;
+}
+
/* Get the active Grease Pencil datablock */
bGPdata *ED_gpencil_data_get_active(const bContext *C)
{
@@ -187,6 +217,9 @@ bGPdata *ED_gpencil_data_get_active(const bContext *C)
return (gpd_ptr) ? *(gpd_ptr) : NULL;
}
+/* -------------------------------------------------------- */
+
+// XXX: this should be removed... We really shouldn't duplicate logic like this!
bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d)
{
Base *base = scene->basact;
@@ -194,7 +227,7 @@ bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d)
/* 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 && TESTBASE(v3d, base)) {
gpd = base->object->gpd;
}
@@ -211,13 +244,22 @@ static int gp_add_poll(bContext *C)
return ED_gpencil_data_get_pointers(C, NULL) != NULL;
}
+/* poll callback for checking if there is an active layer */
+static int gp_active_layer_poll(bContext *C)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ return (gpl != NULL);
+}
+
/* ******************* Add New Data ************************ */
/* add new datablock - wrapper around API */
static int gp_data_add_exec(bContext *C, wmOperator *op)
{
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
-
+
if (gpd_ptr == NULL) {
BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
return OPERATOR_CANCELLED;
@@ -225,14 +267,14 @@ static int gp_data_add_exec(bContext *C, wmOperator *op)
else {
/* decrement user count and add new datablock */
bGPdata *gpd = (*gpd_ptr);
-
+
id_us_min(&gpd->id);
*gpd_ptr = gpencil_data_addnew(DATA_("GPencil"));
}
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -243,7 +285,7 @@ void GPENCIL_OT_data_add(wmOperatorType *ot)
ot->idname = "GPENCIL_OT_data_add";
ot->description = "Add new Grease Pencil datablock";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* callbacks */
ot->exec = gp_data_add_exec;
ot->poll = gp_add_poll;
@@ -255,7 +297,7 @@ void GPENCIL_OT_data_add(wmOperatorType *ot)
static int gp_data_unlink_poll(bContext *C)
{
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
-
+
/* if we have access to some active data, make sure there's a datablock before enabling this */
return (gpd_ptr && *gpd_ptr);
}
@@ -265,7 +307,7 @@ static int gp_data_unlink_poll(bContext *C)
static int gp_data_unlink_exec(bContext *C, wmOperator *op)
{
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
-
+
if (gpd_ptr == NULL) {
BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
return OPERATOR_CANCELLED;
@@ -277,10 +319,10 @@ static int gp_data_unlink_exec(bContext *C, wmOperator *op)
id_us_min(&gpd->id);
*gpd_ptr = NULL;
}
-
+
/* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
return OPERATOR_FINISHED;
}
@@ -291,7 +333,7 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot)
ot->idname = "GPENCIL_OT_data_unlink";
ot->description = "Unlink active Grease Pencil datablock";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* callbacks */
ot->exec = gp_data_unlink_exec;
ot->poll = gp_data_unlink_poll;
@@ -303,7 +345,7 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot)
static int gp_layer_add_exec(bContext *C, wmOperator *op)
{
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
-
+
/* if there's no existing Grease-Pencil data there, add some */
if (gpd_ptr == NULL) {
BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
@@ -311,13 +353,13 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op)
}
if (*gpd_ptr == NULL)
*gpd_ptr = gpencil_data_addnew(DATA_("GPencil"));
-
+
/* add new layer now */
gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), 1);
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -327,20 +369,497 @@ void GPENCIL_OT_layer_add(wmOperatorType *ot)
ot->name = "Add New Layer";
ot->idname = "GPENCIL_OT_layer_add";
ot->description = "Add new Grease Pencil layer for the active Grease Pencil datablock";
+
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* callbacks */
ot->exec = gp_layer_add_exec;
ot->poll = gp_add_poll;
}
+/* ******************* Remove Active Layer ************************* */
+
+static int gp_layer_remove_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl))
+ return OPERATOR_CANCELLED;
+
+ if (gpl->flag & GP_LAYER_LOCKED) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* make the layer before this the new active layer
+ * - use the one after if this is the first
+ * - if this is the only layer, this naturally becomes NULL
+ */
+ if (gpl->prev)
+ gpencil_layer_setactive(gpd, gpl->prev);
+ else
+ gpencil_layer_setactive(gpd, gpl->next);
+
+ /* delete the layer now... */
+ gpencil_layer_delete(gpd, gpl);
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Layer";
+ ot->idname = "GPENCIL_OT_layer_remove";
+ ot->description = "Remove active Grease Pencil layer";
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* callbacks */
+ ot->exec = gp_layer_remove_exec;
+ ot->poll = gp_active_layer_poll;
+}
+
+/* ******************* Move Layer Up/Down ************************** */
+
+enum {
+ GP_LAYER_MOVE_UP = -1,
+ GP_LAYER_MOVE_DOWN = 1
+};
+
+static int gp_layer_move_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ int direction = RNA_enum_get(op->ptr, "type");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl))
+ return OPERATOR_CANCELLED;
+
+ /* up or down? */
+ if (direction == GP_LAYER_MOVE_UP) {
+ /* up */
+ BLI_remlink(&gpd->layers, gpl);
+ BLI_insertlinkbefore(&gpd->layers, gpl->prev, gpl);
+ }
+ else {
+ /* down */
+ BLI_remlink(&gpd->layers, gpl);
+ BLI_insertlinkafter(&gpd->layers, gpl->next, gpl);
+ }
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem slot_move[] = {
+ {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""},
+ {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Move Grease Pencil Layer";
+ ot->idname = "GPENCIL_OT_layer_move";
+ ot->description = "Move the active Grease Pencil layer up/down in the list";
+
+ /* api callbacks */
+ ot->exec = gp_layer_move_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
+}
+
+/* ********************* Duplicate Layer ************************** */
+
+static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+ bGPDlayer *new_layer;
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl))
+ return OPERATOR_CANCELLED;
+
+ /* make copy of layer, and add it immediately after the existing layer */
+ new_layer = gpencil_layer_duplicate(gpl);
+ BLI_insertlinkafter(&gpd->layers, gpl, new_layer);
+
+ /* ensure new layer has a unique name, and is now the active layer */
+ BLI_uniquename(&gpd->layers, new_layer, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(new_layer->info));
+ gpencil_layer_setactive(gpd, new_layer);
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate Layer";
+ ot->idname = "GPENCIL_OT_layer_duplicate";
+ ot->description = "Make a copy of the active Grease Pencil layer";
+
+ /* callbacks */
+ ot->exec = gp_layer_copy_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ************************************************ */
+/* Stroke Editing Operators */
+
+/* poll callback for all stroke editing operators */
+static int gp_stroke_edit_poll(bContext *C)
+{
+ /* NOTE: this is a bit slower, but is the most accurate... */
+ return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
+}
+
+/* ************** Duplicate Selected Strokes **************** */
+
+/* Make copies of selected point segments in a selected stroke */
+static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes)
+{
+ bGPDspoint *pt;
+ int i;
+
+ int start_idx = -1;
+
+
+ /* Step through the original stroke's points:
+ * - We accumulate selected points (from start_idx to current index)
+ * and then convert that to a new stroke
+ */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ /* searching for start, are waiting for end? */
+ if (start_idx == -1) {
+ /* is this the first selected point for a new island? */
+ if (pt->flag & GP_SPOINT_SELECT) {
+ start_idx = i;
+ }
+ }
+ else {
+ size_t len = 0;
+
+ /* is this the end of current island yet?
+ * 1) Point i-1 was the last one that was selected
+ * 2) Point i is the last in the array
+ */
+ if ((pt->flag & GP_SPOINT_SELECT) == 0) {
+ len = i - start_idx;
+ }
+ else if (i == gps->totpoints - 1) {
+ len = i - start_idx + 1;
+ }
+ //printf("copying from %d to %d = %d\n", start_idx, i, len);
+
+ /* make copies of the relevant data */
+ if (len) {
+ bGPDstroke *gpsd;
+
+ /* make a stupid copy first of the entire stroke (to get the flags too) */
+ gpsd = MEM_dupallocN(gps);
+
+ /* now, make a new points array, and copy of the relevant parts */
+ gpsd->points = MEM_callocN(sizeof(bGPDspoint) * len, "gps stroke points copy");
+ memcpy(gpsd->points, gps->points + start_idx, sizeof(bGPDspoint) * len);
+ gpsd->totpoints = len;
+
+ /* add to temp buffer */
+ gpsd->next = gpsd->prev = NULL;
+ BLI_addtail(new_strokes, gpsd);
+
+ /* cleanup + reset for next */
+ start_idx = -1;
+ }
+ }
+ }
+}
+
+static int gp_duplicate_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for each visible (and editable) layer's selected strokes,
+ * copy the strokes into a temporary buffer, then append
+ * once all done
+ */
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ ListBase new_strokes = {NULL, NULL};
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+
+ if (gpf == NULL)
+ continue;
+
+ /* make copies of selected strokes, and deselect these once we're done */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ if (gps->totpoints == 1) {
+ /* Special Case: If there's just a single point in this stroke... */
+ bGPDstroke *gpsd;
+
+ /* make direct copies of the stroke and its points */
+ gpsd = MEM_dupallocN(gps);
+ gpsd->points = MEM_dupallocN(gps->points);
+
+ /* add to temp buffer */
+ gpsd->next = gpsd->prev = NULL;
+ BLI_addtail(&new_strokes, gpsd);
+ }
+ else {
+ /* delegate to a helper, as there's too much to fit in here (for copying subsets)... */
+ gp_duplicate_points(gps, &new_strokes);
+ }
+
+ /* deselect original stroke, or else the originals get moved too
+ * (when using the copy + move macro)
+ */
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ }
+
+ /* add all new strokes in temp buffer to the frame (preventing double-copies) */
+ BLI_movelisttolist(&gpf->strokes, &new_strokes);
+ BLI_assert(new_strokes.first == NULL);
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate Strokes";
+ ot->idname = "GPENCIL_OT_duplicate";
+ ot->description = "Duplicate the selected Grease Pencil strokes";
+
+ /* callbacks */
+ ot->exec = gp_duplicate_exec;
+ ot->poll = gp_stroke_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ******************* Copy/Paste Strokes ************************* */
+/* Grease Pencil stroke data copy/paste buffer:
+ * - The copy operation collects all segments of selected strokes,
+ * dumping "ready to be copied" copies of the strokes into the buffer.
+ * - The paste operation makes a copy of those elements, and adds them
+ * to the active layer. This effectively flattens down the strokes
+ * from several different layers into a single layer.
+ */
+
+/* list of bGPDstroke instances */
+static ListBase gp_strokes_copypastebuf = {NULL, NULL};
+
+/* Free copy/paste buffer data */
+void ED_gpencil_strokes_copybuf_free(void)
+{
+ bGPDstroke *gps, *gpsn;
+
+ for (gps = gp_strokes_copypastebuf.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ MEM_freeN(gps->points);
+ BLI_freelinkN(&gp_strokes_copypastebuf, gps);
+ }
+
+ gp_strokes_copypastebuf.first = gp_strokes_copypastebuf.last = NULL;
+}
+
+/* --------------------- */
+/* Copy selected strokes */
+
+static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* clear the buffer first */
+ ED_gpencil_strokes_copybuf_free();
+
+ /* for each visible (and editable) layer's selected strokes,
+ * copy the strokes into a temporary buffer, then append
+ * once all done
+ */
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+
+ if (gpf == NULL)
+ continue;
+
+ /* make copies of selected strokes, and deselect these once we're done */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ if (gps->totpoints == 1) {
+ /* Special Case: If there's just a single point in this stroke... */
+ bGPDstroke *gpsd;
+
+ /* make direct copies of the stroke and its points */
+ gpsd = MEM_dupallocN(gps);
+ gpsd->points = MEM_dupallocN(gps->points);
+
+ /* add to temp buffer */
+ gpsd->next = gpsd->prev = NULL;
+ BLI_addtail(&gp_strokes_copypastebuf, gpsd);
+ }
+ else {
+ /* delegate to a helper, as there's too much to fit in here (for copying subsets)... */
+ gp_duplicate_points(gps, &gp_strokes_copypastebuf);
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* done - no updates needed */
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_copy(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Copy Strokes";
+ ot->idname = "GPENCIL_OT_copy";
+ ot->description = "Copy selected Grease Pencil points and strokes";
+
+ /* callbacks */
+ ot->exec = gp_strokes_copy_exec;
+ ot->poll = gp_stroke_edit_poll;
+
+ /* flags */
+ //ot->flag = OPTYPE_REGISTER;
+}
+
+/* --------------------- */
+/* Paste selected strokes */
+
+static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ bGPDframe *gpf;
+
+ /* check for various error conditions */
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+ else if (gp_strokes_copypastebuf.first == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No strokes to paste, select and copy some points before trying again");
+ return OPERATOR_CANCELLED;
+ }
+ else if (gpl == NULL) {
+ /* no active layer - let's just create one */
+ gpl = gpencil_layer_addnew(gpd, DATA_("GP_Layer"), 1);
+ }
+ else if (gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) {
+ BKE_report(op->reports, RPT_ERROR, "Can not paste strokes when active layer is hidden or locked");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Deselect all strokes first */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ CTX_DATA_END;
+
+ /* Ensure we have a frame to draw into
+ * NOTE: Since this is an op which creates strokes,
+ * we are obliged to add a new frame if one
+ * doesn't exist already
+ */
+ gpf = gpencil_layer_getframe(gpl, CFRA, true);
+
+ if (gpf) {
+ bGPDstroke *gps;
+
+ /* Copy each stroke into the layer */
+ for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
+ bGPDstroke *new_stroke = MEM_dupallocN(gps);
+
+ new_stroke->points = MEM_dupallocN(gps->points);
+ new_stroke->next = new_stroke->prev = NULL;
+
+ BLI_addtail(&gpf->strokes, new_stroke);
+ }
+ }
+
+ /* updates */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_paste(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Paste Strokes";
+ ot->idname = "GPENCIL_OT_paste";
+ ot->description = "Paste previously copied strokes into active layer";
+
+ /* callbacks */
+ ot->exec = gp_strokes_paste_exec;
+ ot->poll = gp_stroke_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* ******************* Delete Active Frame ************************ */
static int gp_actframe_delete_poll(bContext *C)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *gpl = gpencil_layer_getactive(gpd);
-
+
/* only if there's an active layer with an active frame */
return (gpl && gpl->actframe);
}
@@ -352,7 +871,7 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *gpl = gpencil_layer_getactive(gpd);
bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0);
-
+
/* if there's no existing Grease-Pencil data there, add some */
if (gpd == NULL) {
BKE_report(op->reports, RPT_ERROR, "No grease pencil data");
@@ -362,13 +881,13 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No active frame to delete");
return OPERATOR_CANCELLED;
}
-
+
/* delete it... */
gpencil_layer_delframe(gpl, gpf);
-
+
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -378,13 +897,315 @@ void GPENCIL_OT_active_frame_delete(wmOperatorType *ot)
ot->name = "Delete Active Frame";
ot->idname = "GPENCIL_OT_active_frame_delete";
ot->description = "Delete the active frame for the active Grease Pencil datablock";
+
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* callbacks */
ot->exec = gp_actframe_delete_exec;
ot->poll = gp_actframe_delete_poll;
}
+/* ******************* Delete Operator ************************ */
+
+typedef enum eGP_DeleteMode {
+ /* delete selected stroke points */
+ GP_DELETEOP_POINTS = 0,
+ /* delete selected strokes */
+ GP_DELETEOP_STROKES = 1,
+ /* delete active frame */
+ GP_DELETEOP_FRAME = 2,
+ /* delete selected stroke points (without splitting stroke) */
+ GP_DELETEOP_POINTS_DISSOLVE = 3,
+} eGP_DeleteMode;
+
+
+/* Delete selected strokes */
+static int gp_delete_selected_strokes(bContext *C)
+{
+ bool changed = false;
+
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL)
+ continue;
+
+ /* simply delete strokes which are selected */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* free stroke memory arrays, then stroke itself */
+ if (gps->points) MEM_freeN(gps->points);
+ BLI_freelinkN(&gpf->strokes, gps);
+
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+/* Delete selected points but keep the stroke */
+static int gp_dissolve_selected_points(bContext *C)
+{
+ bool changed = false;
+
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL)
+ continue;
+
+ /* simply delete points from selected strokes
+ * NOTE: we may still have to remove the stroke if it ends up having no points!
+ */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ int tot = gps->totpoints; /* number of points in new buffer */
+
+ /* First Pass: Count how many points are selected (i.e. how many to remove) */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* selected point - one of the points to remove */
+ tot--;
+ }
+ }
+
+ /* if no points are left, we simply delete the entire stroke */
+ if (tot <= 0) {
+ /* remove the entire stroke */
+ MEM_freeN(gps->points);
+ BLI_freelinkN(&gpf->strokes, gps);
+ }
+ else {
+ /* just copy all unselected into a smaller buffer */
+ bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot, "new gp stroke points copy");
+ bGPDspoint *npt = new_points;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if ((pt->flag & GP_SPOINT_SELECT) == 0) {
+ *npt = *pt;
+ npt++;
+ }
+ }
+
+ /* free the old buffer */
+ MEM_freeN(gps->points);
+
+ /* save the new buffer */
+ gps->points = new_points;
+ gps->totpoints = tot;
+
+ /* deselect the stroke, since none of its selected points will still be selected */
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+/* Split selected strokes into segments, splitting on selected points */
+static int gp_delete_selected_points(bContext *C)
+{
+ bool changed = false;
+
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL)
+ continue;
+
+ /* simply delete strokes which are selected */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ /* The algorithm used here is as follows:
+ * 1) We firstly identify the number of "islands" of non-selected points
+ * which will all end up being in new strokes.
+ * - In the most extreme case (i.e. every other vert is a 1-vert island),
+ * we have at most n / 2 islands
+ * - Once we start having larger islands than that, the number required
+ * becomes much less
+ * 2) Each island gets converted to a new stroke
+ */
+ typedef struct tGPDeleteIsland {
+ int start_idx;
+ int end_idx;
+ } tGPDeleteIsland;
+
+ tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands");
+ bool in_island = false;
+ int num_islands = 0;
+
+ /* First Pass: Identify start/end of islands */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* selected - stop accumulating to island */
+ in_island = false;
+ }
+ else {
+ /* unselected - start of a new island? */
+ int idx;
+
+ if (in_island) {
+ /* extend existing island */
+ idx = num_islands - 1;
+ islands[idx].end_idx = i;
+ }
+ else {
+ /* start of new island */
+ in_island = true;
+ num_islands++;
+
+ idx = num_islands - 1;
+ islands[idx].start_idx = islands[idx].end_idx = i;
+ }
+ }
+ }
+
+ /* Watch out for special case where No islands = All points selected = Delete Stroke only */
+ if (num_islands) {
+ /* there are islands, so create a series of new strokes, adding them before the "next" stroke */
+ int idx;
+
+ /* deselect old stroke, since it will be used as template for the new strokes */
+ gps->flag &= ~GP_STROKE_SELECT;
+
+ /* create each new stroke... */
+ for (idx = 0; idx < num_islands; idx++) {
+ tGPDeleteIsland *island = &islands[idx];
+ bGPDstroke *new_stroke = MEM_dupallocN(gps);
+
+ /* compute new buffer size (+ 1 needed as the endpoint index is "inclusive") */
+ new_stroke->totpoints = island->end_idx - island->start_idx + 1;
+ new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, "gp delete stroke fragment");
+
+ /* copy over the relevant points */
+ memcpy(new_stroke->points, gps->points + island->start_idx, sizeof(bGPDspoint) * new_stroke->totpoints);
+
+ /* add new stroke to the frame */
+ if (gpsn) {
+ BLI_insertlinkbefore(&gpf->strokes, gpsn, new_stroke);
+ }
+ else {
+ BLI_addtail(&gpf->strokes, new_stroke);
+ }
+ }
+ }
+
+ /* free islands */
+ MEM_freeN(islands);
+
+ /* Delete the old stroke */
+ MEM_freeN(gps->points);
+ BLI_freelinkN(&gpf->strokes, gps);
+
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+
+static int gp_delete_exec(bContext *C, wmOperator *op)
+{
+ eGP_DeleteMode mode = RNA_enum_get(op->ptr, "type");
+ int result = OPERATOR_CANCELLED;
+
+ switch (mode) {
+ case GP_DELETEOP_STROKES: /* selected strokes */
+ result = gp_delete_selected_strokes(C);
+ break;
+
+ case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */
+ result = gp_delete_selected_points(C);
+ break;
+
+ case GP_DELETEOP_POINTS_DISSOLVE: /* selected points (without splitting the stroke) */
+ result = gp_dissolve_selected_points(C);
+ break;
+
+ case GP_DELETEOP_FRAME: /* active frame */
+ result = gp_actframe_delete_exec(C, op);
+ break;
+ }
+
+ return result;
+}
+
+void GPENCIL_OT_delete(wmOperatorType *ot)
+{
+ static EnumPropertyItem prop_gpencil_delete_types[] = {
+ {GP_DELETEOP_POINTS, "POINTS", 0, "Points", "Delete selected points and split strokes into segments"},
+ {GP_DELETEOP_STROKES, "STROKES", 0, "Strokes", "Delete selected strokes"},
+ {GP_DELETEOP_FRAME, "FRAME", 0, "Frame", "Delete active frame"},
+ {0, "", 0, NULL, NULL},
+ {GP_DELETEOP_POINTS_DISSOLVE, "DISSOLVE_POINTS", 0, "Dissolve Points",
+ "Delete selected points without splitting strokes"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Delete...";
+ ot->idname = "GPENCIL_OT_delete";
+ ot->description = "Delete selected Grease Pencil strokes, vertices, or frames";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gp_delete_exec;
+ ot->poll = gp_stroke_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* props */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_delete_types, 0, "Type", "Method used for deleting Grease Pencil data");
+}
+
/* ************************************************ */
/* Grease Pencil to Data Operator */
@@ -437,7 +1258,7 @@ static EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), PointerRN
/* --- */
-/* convert the coordinates from the given stroke point into 3d-coordinates
+/* convert the coordinates from the given stroke point into 3d-coordinates
* - assumes that the active space is the 3D-View
*/
static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoint *pt, float p3d[3], rctf *subrect)
@@ -445,7 +1266,7 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
-
+
if (gps->flag & GP_STROKE_3DSPACE) {
/* directly use 3d-coordinates */
copy_v3_v3(p3d, &pt->x);
@@ -453,7 +1274,7 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin
else {
const float *fp = ED_view3d_cursor3d_get(scene, v3d);
float mvalf[2];
-
+
/* get screen coordinate */
if (gps->flag & GP_STROKE_2DSPACE) {
View2D *v2d = &ar->v2d;
@@ -469,7 +1290,7 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin
mvalf[1] = (float)pt->y / 100.0f * ar->winy;
}
}
-
+
ED_view3d_win_to_3d(ar, fp, mvalf, p3d);
}
}
@@ -485,19 +1306,19 @@ typedef struct tGpTimingData {
bool realtime; /* Will overwrite end_frame in case of Original or CustomGap timing... */
float gap_duration, gap_randomness; /* To be used with CustomGap mode*/
int seed;
-
+
/* Data set from points, used to compute final timing FCurve */
int num_points, cur_point;
-
+
/* Distances */
float *dists;
float tot_dist;
-
+
/* Times */
float *times; /* Note: Gap times will be negative! */
float tot_time, gap_tot_time;
double inittime;
-
+
/* Only used during creation of dists & times lists. */
float offset_time;
} tGpTimingData;
@@ -508,9 +1329,9 @@ typedef struct tGpTimingData {
static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr)
{
float *tmp;
-
+
BLI_assert(nbr > gtd->num_points);
-
+
/* distances */
tmp = gtd->dists;
gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__);
@@ -518,7 +1339,7 @@ static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr)
memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points);
MEM_freeN(tmp);
}
-
+
/* times */
tmp = gtd->times;
gtd->times = MEM_callocN(sizeof(float) * nbr, __func__);
@@ -526,7 +1347,7 @@ static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr)
memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points);
MEM_freeN(tmp);
}
-
+
gtd->num_points = nbr;
}
@@ -536,7 +1357,7 @@ static void gp_timing_data_add_point(tGpTimingData *gtd, const double stroke_ini
{
float delta_time = 0.0f;
const int cur_point = gtd->cur_point;
-
+
if (!cur_point) {
/* Special case, first point, if time is not 0.0f we have to compensate! */
gtd->offset_time = -time;
@@ -546,18 +1367,18 @@ static void gp_timing_data_add_point(tGpTimingData *gtd, const double stroke_ini
/* This is a gap, negative value! */
gtd->times[cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time);
delta_time = -gtd->times[cur_point] - gtd->times[cur_point - 1];
-
+
gtd->gap_tot_time += delta_time;
}
else {
gtd->times[cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time);
delta_time = gtd->times[cur_point] - fabsf(gtd->times[cur_point - 1]);
}
-
+
gtd->tot_time += delta_time;
gtd->tot_dist += delta_dist;
gtd->dists[cur_point] = gtd->tot_dist;
-
+
gtd->cur_point++;
}
@@ -572,7 +1393,7 @@ static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx
float *next_delta_time)
{
int j;
-
+
for (j = idx + 1; j < gtd->num_points; j++) {
if (gtd->times[j] < 0) {
gtd->times[j] = -gtd->times[j];
@@ -591,16 +1412,16 @@ static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx
}
else {
float delta, min, max;
-
+
/* This code ensures that if the first gaps have been shorter than average gap_duration,
* next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa!
*/
delta = delta_time - (gtd->gap_duration * (*nbr_done_gaps));
-
+
/* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */
min = -gtd->gap_randomness - delta;
CLAMP(min, -gtd->gap_randomness, 0.0f);
-
+
/* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */
max = gtd->gap_randomness - delta;
CLAMP(max, 0.0f, gtd->gap_randomness);
@@ -615,7 +1436,7 @@ static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx
break;
}
}
-
+
return j - 1;
}
@@ -623,7 +1444,7 @@ static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rn
{
int i;
float delta_time = 0.0f;
-
+
for (i = 0; i < gtd->num_points; i++) {
if (gtd->times[i] < 0 && i) {
(*nbr_gaps)++;
@@ -636,7 +1457,7 @@ static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rn
}
}
gtd->tot_time -= delta_time;
-
+
*tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration;
gtd->tot_time += *tot_gaps_time;
if (G.debug & G_DEBUG) {
@@ -653,18 +1474,18 @@ static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerR
{
/* Use actual recorded timing! */
const float time_start = (float)gtd->start_frame;
-
+
float last_valid_time = 0.0f;
int end_stroke_idx = -1, start_stroke_idx = 0;
float end_stroke_time = 0.0f;
-
+
/* CustomGaps specific */
float delta_time = 0.0f, next_delta_time = 0.0f;
int nbr_done_gaps = 0;
-
+
int i;
float cfra;
-
+
/* This is a bit tricky, as:
* - We can't add arbitrarily close points on FCurve (in time).
* - We *must* have all "caps" points of all strokes in FCurve, as much as possible!
@@ -680,11 +1501,11 @@ static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerR
/* This one should *never* be negative! */
end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range);
}
-
+
/* Simple proportional stuff... */
cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen;
cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range);
-
+
/* And now, the checks about timing... */
if (i == start_stroke_idx) {
/* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and
@@ -735,43 +1556,43 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu
PointerRNA ptr;
PropertyRNA *prop = NULL;
int nbr_gaps = 0, i;
-
+
if (gtd->mode == GP_STROKECONVERT_TIMING_NONE)
return;
-
+
/* gap_duration and gap_randomness are in frames, but we need seconds!!! */
gtd->gap_duration = FRA2TIME(gtd->gap_duration);
gtd->gap_randomness = FRA2TIME(gtd->gap_randomness);
-
+
/* Enable path! */
cu->flag |= CU_PATH;
cu->pathlen = gtd->frame_range;
-
+
/* Get RNA pointer to read/write path time values */
RNA_id_pointer_create((ID *)cu, &ptr);
prop = RNA_struct_find_property(&ptr, "eval_time");
-
+
/* Ensure we have an F-Curve to add keyframes to */
act = verify_adt_action((ID *)cu, true);
fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, true);
-
+
if (G.debug & G_DEBUG) {
printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
for (i = 0; i < gtd->num_points; i++) {
printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
}
}
-
+
if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) {
float cfra;
-
+
/* Linear extrapolation! */
fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
-
+
cu->ctime = 0.0f;
cfra = (float)gtd->start_frame;
insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
-
+
cu->ctime = cu->pathlen;
if (gtd->realtime) {
cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
@@ -785,35 +1606,35 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu
/* Use actual recorded timing! */
RNG *rng = BLI_rng_new(0);
float time_range;
-
+
/* CustomGaps specific */
float tot_gaps_time = 0.0f;
-
+
/* Pre-process gaps, in case we don't want to keep their original timing */
if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
gp_stroke_path_animation_preprocess_gaps(gtd, rng, &nbr_gaps, &tot_gaps_time);
}
-
+
if (gtd->realtime) {
time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
}
else {
time_range = (float)(gtd->end_frame - gtd->start_frame);
}
-
+
if (G.debug & G_DEBUG) {
printf("GP Stroke Path Conversion: Starting keying!\n");
}
-
+
gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, rng, time_range,
nbr_gaps, tot_gaps_time);
-
+
BLI_rng_free(rng);
}
-
+
/* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */
calchandles_fcurve(fcu);
-
+
if (G.debug & G_DEBUG) {
printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
for (i = 0; i < gtd->num_points; i++) {
@@ -821,9 +1642,9 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu
}
printf("\n\n");
}
-
+
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
+
/* send updates */
DAG_id_tag_update(&cu->id, 0);
}
@@ -843,7 +1664,7 @@ static void gp_stroke_to_path_add_point(tGpTimingData *gtd, BPoint *bp, const fl
{
copy_v3_v3(bp->vec, p);
bp->vec[3] = 1.0f;
-
+
/* set settings */
bp->f1 = SELECT;
bp->radius = width * rad_fac;
@@ -855,7 +1676,7 @@ static void gp_stroke_to_path_add_point(tGpTimingData *gtd, BPoint *bp, const fl
else if (bp->weight > minmax_weights[1]) {
minmax_weights[1] = bp->weight;
}
-
+
/* Update timing data */
if (do_gtd) {
gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p));
@@ -872,7 +1693,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE);
const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0);
int i, old_nbp = 0;
-
+
/* create new 'nurb' or extend current one within the curve */
if (nu) {
old_nbp = nu->pntsu;
@@ -884,7 +1705,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
}
else {
nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)");
-
+
nu->pntsu = gps->totpoints + add_start_end_points;
nu->pntsv = 1;
nu->orderu = 2; /* point-to-point! */
@@ -893,16 +1714,16 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
nu->resolu = cu->resolu;
nu->resolv = cu->resolv;
nu->knotsu = NULL;
-
+
nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints");
-
+
stitch = false; /* Security! */
}
-
+
if (do_gtd) {
gp_timing_data_set_nbr(gtd, nu->pntsu);
}
-
+
/* If needed, make the link between both strokes with two zero-radius additional points */
/* About "zero-radius" point interpolations:
* - If we have at least two points in current curve (most common case), we linearly extrapolate
@@ -915,16 +1736,16 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
if (curnu && !stitch && old_nbp) {
float p1[3], p2[3], p[3], next_p[3];
float dt1 = 0.0f, dt2 = 0.0f;
-
+
BLI_assert(gps->prev != NULL);
-
+
prev_bp = NULL;
if ((old_nbp > 1) && (gps->prev->totpoints > 1)) {
/* Only use last curve segment if previous stroke was not a single-point one! */
prev_bp = &nu->bp[old_nbp - 2];
}
bp = &nu->bp[old_nbp - 1];
-
+
/* First point */
gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect);
if (prev_bp) {
@@ -943,7 +1764,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
bp++;
gp_stroke_to_path_add_point(gtd, bp, p1, (bp - 1)->vec, do_gtd, gps->prev->inittime, dt1,
0.0f, rad_fac, minmax_weights);
-
+
/* Second point */
/* Note dt2 is always negative, which marks the gap. */
if (gps->totpoints > 1) {
@@ -961,13 +1782,13 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
}
bp++;
gp_stroke_to_path_add_point(gtd, bp, p2, p1, do_gtd, gps->inittime, dt2, 0.0f, rad_fac, minmax_weights);
-
+
old_nbp += 2;
}
else if (add_start_point) {
float p[3], next_p[3];
float dt = 0.0f;
-
+
gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect);
if (gps->totpoints > 1) {
gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect);
@@ -985,14 +1806,14 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
* would not work (it would be *before* gtd->inittime, which is not supported currently).
*/
gp_stroke_to_path_add_point(gtd, bp, p, p, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights);
-
+
old_nbp++;
}
-
+
if (old_nbp) {
prev_bp = &nu->bp[old_nbp - 1];
}
-
+
/* add points */
for (i = (stitch) ? 1 : 0, pt = &gps->points[(stitch) ? 1 : 0], bp = &nu->bp[old_nbp];
i < gps->totpoints;
@@ -1000,20 +1821,20 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
{
float p[3];
float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC;
-
+
/* get coordinates to add at */
gp_strokepoint_convertcoords(C, gps, pt, p, subrect);
-
+
gp_stroke_to_path_add_point(gtd, bp, p, (prev_bp) ? prev_bp->vec : p, do_gtd, gps->inittime, pt->time,
width, rad_fac, minmax_weights);
-
+
prev_bp = bp;
}
if (add_end_point) {
float p[3];
float dt = 0.0f;
-
+
if (gps->totpoints > 1) {
interp_v3_v3v3(p, prev_bp->vec, (prev_bp - 1)->vec, -GAP_DFAC);
if (do_gtd) {
@@ -1029,7 +1850,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
/* Note bp has already been incremented in main loop above, so it points to the right place. */
gp_stroke_to_path_add_point(gtd, bp, p, prev_bp->vec, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights);
}
-
+
/* add nurb to curve */
if (!curnu || !*curnu) {
BLI_addtail(&cu->nurb, nu);
@@ -1037,7 +1858,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
if (curnu) {
*curnu = nu;
}
-
+
BKE_nurb_knot_calc_u(nu);
}
@@ -1052,7 +1873,7 @@ static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt,
copy_v3_v3(bezt->vec[0], h1);
copy_v3_v3(bezt->vec[1], p);
copy_v3_v3(bezt->vec[2], h2);
-
+
/* set settings */
bezt->h1 = bezt->h2 = HD_FREE;
bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
@@ -1065,7 +1886,7 @@ static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt,
else if (bezt->weight > minmax_weights[1]) {
minmax_weights[1] = bezt->weight;
}
-
+
/* Update timing data */
if (do_gtd) {
gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p));
@@ -1073,8 +1894,8 @@ static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt,
}
static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
- float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point,
- const bool add_end_point, tGpTimingData *gtd)
+ float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point,
+ const bool add_end_point, tGpTimingData *gtd)
{
bGPDspoint *pt;
Nurb *nu = (curnu) ? *curnu : NULL;
@@ -1083,7 +1904,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0);
float p3d_cur[3], p3d_prev[3], p3d_next[3], h1[3], h2[3];
const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE);
-
+
/* create new 'nurb' or extend current one within the curve */
if (nu) {
old_nbezt = nu->pntsu;
@@ -1095,22 +1916,22 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
}
else {
nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)");
-
+
nu->pntsu = gps->totpoints + add_start_end_points;
nu->resolu = 12;
nu->resolv = 12;
nu->type = CU_BEZIER;
nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * nu->pntsu, "bezts");
-
+
stitch = false; /* Security! */
}
-
+
if (do_gtd) {
gp_timing_data_set_nbr(gtd, nu->pntsu);
}
-
+
tot = gps->totpoints;
-
+
/* get initial coordinates */
pt = gps->points;
if (tot) {
@@ -1122,11 +1943,11 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect);
}
}
-
+
/* If needed, make the link between both strokes with two zero-radius additional points */
if (curnu && old_nbezt) {
BLI_assert(gps->prev != NULL);
-
+
/* Update last point's second handle */
if (stitch) {
bezt = &nu->bezt[old_nbezt - 1];
@@ -1134,7 +1955,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
copy_v3_v3(bezt->vec[2], h2);
pt++;
}
-
+
/* Create "link points" */
/* About "zero-radius" point interpolations:
* - If we have at least two points in current curve (most common case), we linearly extrapolate
@@ -1147,14 +1968,14 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
else {
float p1[3], p2[3];
float dt1 = 0.0f, dt2 = 0.0f;
-
+
prev_bezt = NULL;
if ((old_nbezt > 1) && (gps->prev->totpoints > 1)) {
/* Only use last curve segment if previous stroke was not a single-point one! */
prev_bezt = &nu->bezt[old_nbezt - 2];
}
bezt = &nu->bezt[old_nbezt - 1];
-
+
/* First point */
if (prev_bezt) {
interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC);
@@ -1169,7 +1990,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC);
}
}
-
+
/* Second point */
/* Note dt2 is always negative, which marks the gap. */
if (tot > 1) {
@@ -1184,25 +2005,25 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC);
}
}
-
+
/* Second handle of last point of previous stroke. */
interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC);
copy_v3_v3(bezt->vec[2], h2);
-
+
/* First point */
interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC);
interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC);
bezt++;
gp_stroke_to_bezier_add_point(gtd, bezt, p1, h1, h2, (bezt - 1)->vec[1], do_gtd, gps->prev->inittime, dt1,
0.0f, rad_fac, minmax_weights);
-
+
/* Second point */
interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC);
interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC);
bezt++;
gp_stroke_to_bezier_add_point(gtd, bezt, p2, h1, h2, p1, do_gtd, gps->inittime, dt2,
0.0f, rad_fac, minmax_weights);
-
+
old_nbezt += 2;
copy_v3_v3(p3d_prev, p2);
}
@@ -1210,7 +2031,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
else if (add_start_point) {
float p[3];
float dt = 0.0f;
-
+
if (gps->totpoints > 1) {
interp_v3_v3v3(p, p3d_cur, p3d_next, -GAP_DFAC);
if (do_gtd) {
@@ -1227,51 +2048,51 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
bezt = &nu->bezt[old_nbezt];
gp_stroke_to_bezier_add_point(gtd, bezt, p, h1, h2, p, do_gtd, gps->inittime, dt,
0.0f, rad_fac, minmax_weights);
-
+
old_nbezt++;
copy_v3_v3(p3d_prev, p);
}
-
+
if (old_nbezt) {
prev_bezt = &nu->bezt[old_nbezt - 1];
}
-
+
/* add points */
for (i = stitch ? 1 : 0, bezt = &nu->bezt[old_nbezt]; i < tot; i++, pt++, bezt++) {
float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC;
-
+
if (i || old_nbezt) {
interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC);
}
else {
interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC);
}
-
+
if (i < tot - 1) {
interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC);
}
else {
interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC);
}
-
+
gp_stroke_to_bezier_add_point(gtd, bezt, p3d_cur, h1, h2, prev_bezt ? prev_bezt->vec[1] : p3d_cur,
do_gtd, gps->inittime, pt->time, width, rad_fac, minmax_weights);
-
+
/* shift coord vects */
copy_v3_v3(p3d_prev, p3d_cur);
copy_v3_v3(p3d_cur, p3d_next);
-
+
if (i + 2 < tot) {
gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect);
}
-
+
prev_bezt = bezt;
}
if (add_end_point) {
float p[3];
float dt = 0.0f;
-
+
if (gps->totpoints > 1) {
interp_v3_v3v3(p, prev_bezt->vec[1], (prev_bezt - 1)->vec[1], -GAP_DFAC);
if (do_gtd) {
@@ -1284,11 +2105,11 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
p[0] += GAP_DFAC; /* Rather arbitrary... */
dt = GAP_DFAC; /* Rather arbitrary too! */
}
-
+
/* Second handle of last point of this stroke. */
interp_v3_v3v3(h2, prev_bezt->vec[1], p, BEZT_HANDLE_FAC);
copy_v3_v3(prev_bezt->vec[2], h2);
-
+
/* The end point */
interp_v3_v3v3(h1, p, prev_bezt->vec[1], BEZT_HANDLE_FAC);
interp_v3_v3v3(h2, p, prev_bezt->vec[1], -BEZT_HANDLE_FAC);
@@ -1296,10 +2117,10 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
gp_stroke_to_bezier_add_point(gtd, bezt, p, h1, h2, prev_bezt->vec[1], do_gtd, gps->inittime, dt,
0.0f, rad_fac, minmax_weights);
}
-
+
/* must calculate handles or else we crash */
BKE_nurb_handles_calc(nu);
-
+
if (!curnu || !*curnu) {
BLI_addtail(&cu->nurb, nu);
}
@@ -1329,7 +2150,7 @@ static void gp_stroke_finalize_curve_endpoints(Curve *cu)
bp[i].weight = bp[i].radius = 0.0f;
}
}
-
+
/* end */
nu = cu->nurb.last;
i = nu->pntsu - 1;
@@ -1353,13 +2174,13 @@ static void gp_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2
const float delta = minmax_weights[0];
float fac;
int i;
-
+
/* when delta == minmax_weights[0] == minmax_weights[1], we get div by zero [#35686] */
if (IS_EQF(delta, minmax_weights[1]))
fac = 1.0f;
else
fac = 1.0f / (minmax_weights[1] - delta);
-
+
for (nu = cu->nurb.first; nu; nu = nu->next) {
if (nu->bezt) {
BezTriple *bezt = nu->bezt;
@@ -1380,10 +2201,10 @@ static int gp_camera_view_subrect(bContext *C, rctf *subrect)
{
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
-
+
if (v3d) {
RegionView3D *rv3d = ar->regiondata;
-
+
/* for camera view set the subrect */
if (rv3d->persp == RV3D_CAMOB) {
Scene *scene = CTX_data_scene(C);
@@ -1391,7 +2212,7 @@ static int gp_camera_view_subrect(bContext *C, rctf *subrect)
return 1;
}
}
-
+
return 0;
}
@@ -1409,57 +2230,57 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
Nurb *nu = NULL;
Base *base_orig = BASACT, *base_new = NULL;
float minmax_weights[2] = {1.0f, 0.0f};
-
+
/* camera framing */
rctf subrect, *subrect_ptr = NULL;
-
+
/* error checking */
if (ELEM(NULL, gpd, gpl, gpf))
return;
-
+
/* only convert if there are any strokes on this layer's frame to convert */
if (BLI_listbase_is_empty(&gpf->strokes))
return;
-
+
/* initialize camera framing */
if (gp_camera_view_subrect(C, &subrect)) {
subrect_ptr = &subrect;
}
-
+
/* init the curve object (remove rotation and get curve data from it)
* - must clear transforms set on object, as those skew our results
*/
ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info);
cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE);
base_new = BKE_scene_base_add(scene, ob);
-
+
cu->flag |= CU_3D;
-
+
gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime;
-
+
/* add points to curve */
for (gps = gpf->strokes.first; gps; gps = gps->next) {
const bool add_start_point = (link_strokes && !(prev_gps));
const bool add_end_point = (link_strokes && !(gps->next));
-
+
/* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, and stitch them to previous one. */
bool stitch = false;
if (prev_gps) {
bGPDspoint *pt1 = &prev_gps->points[prev_gps->totpoints - 1];
bGPDspoint *pt2 = &gps->points[0];
-
+
if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) {
stitch = true;
}
}
-
+
/* Decide whether we connect this stroke to previous one */
if (!(stitch || link_strokes)) {
nu = NULL;
}
-
+
switch (mode) {
- case GP_STROKECONVERT_PATH:
+ case GP_STROKECONVERT_PATH:
gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
add_start_point, add_end_point, gtd);
break;
@@ -1474,26 +2295,26 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
}
prev_gps = gps;
}
-
+
/* If link_strokes, be sure first and last points have a zero weight/size! */
if (link_strokes) {
gp_stroke_finalize_curve_endpoints(cu);
}
-
+
/* Update curve's weights, if needed */
if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) {
gp_stroke_norm_curve_weights(cu, minmax_weights);
}
-
+
/* Create the path animation, if needed */
gp_stroke_path_animation(C, reports, cu, gtd);
-
+
if (mode == GP_STROKECONVERT_POLY) {
for (nu = cu->nurb.first; nu; nu = nu->next) {
BKE_nurb_type_convert(nu, CU_POLY, false);
}
}
-
+
/* set the layer and select */
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;
@@ -1513,17 +2334,17 @@ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOpe
double base_time, cur_time, prev_time = -1.0;
int i;
bool valid = true;
-
+
if (!gpl || !(gpf = gpencil_layer_getframe(gpl, CFRA, 0)) || !(gps = gpf->strokes.first))
return false;
-
+
do {
base_time = cur_time = gps->inittime;
if (cur_time <= prev_time) {
valid = false;
break;
}
-
+
prev_time = cur_time;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
cur_time = base_time + (double)pt->time;
@@ -1536,12 +2357,12 @@ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOpe
}
prev_time = cur_time;
}
-
+
if (!valid) {
break;
}
} while ((gps = gps->next));
-
+
if (op) {
RNA_boolean_set(op->ptr, "use_timing_data", valid);
}
@@ -1553,7 +2374,7 @@ static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UN
{
int start_frame = RNA_int_get(ptr, "start_frame");
int end_frame = RNA_int_get(ptr, "end_frame");
-
+
if (end_frame <= start_frame) {
RNA_int_set(ptr, "end_frame", start_frame + 1);
}
@@ -1566,7 +2387,7 @@ static int gp_convert_poll(bContext *C)
bGPDframe *gpf = NULL;
ScrArea *sa = CTX_wm_area(C);
Scene *scene = CTX_data_scene(C);
-
+
/* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!),
* and if we are not in edit mode!
*/
@@ -1589,19 +2410,19 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
const bool link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes");
bool valid_timing;
tGpTimingData gtd;
-
+
/* check if there's data to work with */
if (gpd == NULL) {
BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on");
return OPERATOR_CANCELLED;
}
-
+
if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) {
BKE_report(op->reports, RPT_WARNING,
"Current Grease Pencil strokes have no valid timing data, most timing options will be hidden!");
}
valid_timing = RNA_property_boolean_get(op->ptr, prop);
-
+
gtd.mode = RNA_enum_get(op->ptr, "timing_mode");
/* Check for illegal timing mode! */
if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) {
@@ -1611,7 +2432,7 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
if (!link_strokes) {
gtd.mode = GP_STROKECONVERT_TIMING_NONE;
}
-
+
/* grab all relevant settings */
gtd.frame_range = RNA_int_get(op->ptr, "frame_range");
gtd.start_frame = RNA_int_get(op->ptr, "start_frame");
@@ -1626,10 +2447,10 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f;
gtd.inittime = 0.0;
gtd.offset_time = 0.0f;
-
+
/* perform conversion */
gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, &gtd);
-
+
/* free temp memory */
if (gtd.dists) {
MEM_freeN(gtd.dists);
@@ -1639,11 +2460,11 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
MEM_freeN(gtd.times);
gtd.times = NULL;
}
-
+
/* notifiers */
WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
+
/* done */
return OPERATOR_FINISHED;
}
@@ -1657,7 +2478,7 @@ static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
float gap_duration = RNA_float_get(ptr, "gap_duration");
float gap_randomness = RNA_float_get(ptr, "gap_randomness");
const bool valid_timing = RNA_boolean_get(ptr, "use_timing_data");
-
+
/* Always show those props */
if (strcmp(prop_id, "type") == 0 ||
strcmp(prop_id, "use_normalize_weights") == 0 ||
@@ -1666,16 +2487,16 @@ static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
{
return true;
}
-
+
/* Never show this prop */
if (strcmp(prop_id, "use_timing_data") == 0)
return false;
-
+
if (link_strokes) {
/* Only show when link_stroke is true */
if (strcmp(prop_id, "timing_mode") == 0)
return true;
-
+
if (timing_mode != GP_STROKECONVERT_TIMING_NONE) {
/* Only show when link_stroke is true and stroke timing is enabled */
if (strcmp(prop_id, "frame_range") == 0 ||
@@ -1683,31 +2504,31 @@ static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
{
return true;
}
-
+
/* Only show if we have valid timing data! */
if (valid_timing && strcmp(prop_id, "use_realtime") == 0)
return true;
-
+
/* Only show if realtime or valid_timing is false! */
if ((!realtime || !valid_timing) && strcmp(prop_id, "end_frame") == 0)
return true;
-
+
if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
/* Only show for custom gaps! */
if (strcmp(prop_id, "gap_duration") == 0)
return true;
-
+
/* Only show randomness for non-null custom gaps! */
if (strcmp(prop_id, "gap_randomness") == 0 && (gap_duration > 0.0f))
return true;
-
+
/* Only show seed for randomize action! */
if (strcmp(prop_id, "seed") == 0 && (gap_duration > 0.0f) && (gap_randomness > 0.0f))
return true;
}
}
}
-
+
/* Else, hidden! */
return false;
}
@@ -1717,9 +2538,9 @@ static void gp_convert_ui(bContext *C, wmOperator *op)
uiLayout *layout = op->layout;
wmWindowManager *wm = CTX_wm_manager(C);
PointerRNA ptr;
-
+
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-
+
/* Main auto-draw call */
uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, '\0');
}
@@ -1727,35 +2548,35 @@ static void gp_convert_ui(bContext *C, wmOperator *op)
void GPENCIL_OT_convert(wmOperatorType *ot)
{
PropertyRNA *prop;
-
+
/* identifiers */
ot->name = "Convert Grease Pencil";
ot->idname = "GPENCIL_OT_convert";
ot->description = "Convert the active Grease Pencil layer to a new Curve Object";
-
+
/* callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = gp_convert_layer_exec;
ot->poll = gp_convert_poll;
ot->ui = gp_convert_ui;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to");
-
+
RNA_def_boolean(ot->srna, "use_normalize_weights", true, "Normalize Weight",
"Normalize weight (set from stroke width)");
RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 1000.0f, "Radius Fac",
"Multiplier for the points' radii (set from stroke width)", 0.0f, 10.0f);
RNA_def_boolean(ot->srna, "use_link_strokes", true, "Link Strokes",
"Whether to link strokes with zero-radius sections of curves");
-
+
prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL,
"Timing Mode", "How to use timing data stored in strokes");
RNA_def_enum_funcs(prop, rna_GPConvert_mode_items);
-
+
RNA_def_int(ot->srna, "frame_range", 100, 1, 10000, "Frame Range",
"The duration of evaluation of the path control curve", 1, 1000);
RNA_def_int(ot->srna, "start_frame", 1, 1, 100000, "Start Frame",
@@ -1765,7 +2586,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot)
prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame",
"The end frame of the path control curve (if Realtime is not set)", 1, 100000);
RNA_def_property_update_runtime(prop, gp_convert_set_end_frame);
-
+
RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 10000.0f, "Gap Duration",
"Custom Gap mode: (Average) length of gaps, in frames "
"(Note: Realtime value, will be scaled if Realtime is not set)", 0.0f, 1000.0f);
@@ -1773,7 +2594,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot)
"Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f);
RNA_def_int(ot->srna, "seed", 0, 0, 1000, "Random Seed",
"Custom Gap mode: Random generator seed", 0, 100);
-
+
/* Note: Internal use, this one will always be hidden by UI code... */
prop = RNA_def_boolean(ot->srna, "use_timing_data", false, "Has Valid Timing",
"Whether the converted Grease Pencil layer has valid timing data (internal use)");
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 28eb1355caf..56420434494 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -31,15 +31,74 @@
#ifndef __GPENCIL_INTERN_H__
#define __GPENCIL_INTERN_H__
-/* internal exports only */
+#include "DNA_vec_types.h"
-/* ***************************************************** */
-/* Operator Defines */
+/* internal exports only */
struct bGPdata;
+struct bGPDstroke;
+struct bGPDspoint;
+
+struct ARegion;
+struct View2D;
struct wmOperatorType;
+
+/* ***************************************************** */
+/* Internal API */
+
+/* Stroke Coordinates API ------------------------------ */
+/* gpencil_utils.c */
+
+typedef struct GP_SpaceConversion {
+ struct bGPdata *gpd;
+ struct bGPDlayer *gpl;
+
+ struct ScrArea *sa;
+ struct ARegion *ar;
+ struct View2D *v2d;
+
+ rctf *subrect; /* for using the camera rect within the 3d view */
+ rctf subrect_data;
+
+ float mat[4][4]; /* transform matrix on the strokes (introduced in [b770964]) */
+} GP_SpaceConversion;
+
+
+/**
+ * Check whether a given stroke segment is inside a circular brush
+ *
+ * \param mval The current screen-space coordinates (midpoint) of the brush
+ * \param mvalo The previous screen-space coordinates (midpoint) of the brush (NOT CURRENTLY USED)
+ * \param rad The radius of the brush
+ *
+ * \param x0, y0 The screen-space x and y coordinates of the start of the stroke segment
+ * \param x1, y1 The screen-space x and y coordinates of the end of the stroke segment
+ */
+bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]),
+ int rad, int x0, int y0, int x1, int y1);
+
+
+/**
+ * Init settings for stroke point space conversions
+ *
+ * \param[out] r_gsc The space conversion settings struct, populated with necessary params
+ */
+void gp_point_conversion_init(struct bContext *C, GP_SpaceConversion *r_gsc);
+
+/**
+ * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
+ *
+ * \param[out] r_x The screen-space x-coordinate of the point
+ * \param[out] r_y The screen-space y-coordinate of the point
+ */
+void gp_point_to_xy(GP_SpaceConversion *settings, struct bGPDstroke *gps, struct bGPDspoint *pt,
+ int *r_x, int *r_y);
+
+/* ***************************************************** */
+/* Operator Defines */
+
/* drawing ---------- */
void GPENCIL_OT_draw(struct wmOperatorType *ot);
@@ -52,12 +111,32 @@ typedef enum eGPencil_PaintModes {
GP_PAINTMODE_DRAW_POLY
} eGPencil_PaintModes;
+/* stroke editing ----- */
+
+void GPENCIL_OT_select(struct wmOperatorType *ot);
+void GPENCIL_OT_select_all(struct wmOperatorType *ot);
+void GPENCIL_OT_select_circle(struct wmOperatorType *ot);
+void GPENCIL_OT_select_border(struct wmOperatorType *ot);
+void GPENCIL_OT_select_lasso(struct wmOperatorType *ot);
+
+void GPENCIL_OT_select_linked(struct wmOperatorType *ot);
+void GPENCIL_OT_select_more(struct wmOperatorType *ot);
+void GPENCIL_OT_select_less(struct wmOperatorType *ot);
+
+void GPENCIL_OT_duplicate(struct wmOperatorType *ot);
+void GPENCIL_OT_delete(struct wmOperatorType *ot);
+void GPENCIL_OT_copy(struct wmOperatorType *ot);
+void GPENCIL_OT_paste(struct wmOperatorType *ot);
+
/* buttons editing --- */
void GPENCIL_OT_data_add(struct wmOperatorType *ot);
void GPENCIL_OT_data_unlink(struct wmOperatorType *ot);
void GPENCIL_OT_layer_add(struct wmOperatorType *ot);
+void GPENCIL_OT_layer_remove(struct wmOperatorType *ot);
+void GPENCIL_OT_layer_move(struct wmOperatorType *ot);
+void GPENCIL_OT_layer_duplicate(struct wmOperatorType *ot);
void GPENCIL_OT_active_frame_delete(struct wmOperatorType *ot);
@@ -76,17 +155,17 @@ void gpencil_undo_finish(void);
/* This struct defines a structure used for quick access */
typedef struct bActListElem {
struct bActListElem *next, *prev;
-
+
void *data; /* source data this elem represents */
int type; /* one of the ACTTYPE_* values */
int flag; /* copy of elem's flags for quick access */
int index; /* copy of adrcode where applicable */
-
+
void *key_data; /* motion data - ipo or ipo-curve */
short datatype; /* type of motion data to expect */
-
+
struct bActionGroup *grp; /* action group that owns the channel */
-
+
void *owner; /* will either be an action channel or fake ipo-channel (for keys) */
short ownertype; /* type of owner */
} bActListElem;
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 75ff0895931..6bba7d4f17d 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -36,40 +36,189 @@
#include "BLI_blenlib.h"
+#include "BKE_context.h"
+
+#include "DNA_gpencil_types.h"
+
#include "WM_api.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "ED_gpencil.h"
+#include "ED_object.h"
+#include "ED_transform.h"
#include "gpencil_intern.h"
/* ****************************************** */
-/* Generic Editing Keymap */
+/* Grease Pencil Keymaps */
-void ED_keymap_gpencil(wmKeyConfig *keyconf)
+/* Generic Drawing Keymap */
+static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil", 0, 0);
wmKeyMapItem *kmi;
- /* Draw */
-
+ /* Draw --------------------------------------- */
/* draw */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, 0, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
-
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
/* draw - straight lines */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_CTRL, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_STRAIGHT);
-
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
/* draw - poly lines */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, KM_CTRL, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_POLY);
-
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
/* erase */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, 0, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
+ /* Viewport Tools ------------------------------- */
+
+ /* Enter EditMode */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, 0, DKEY);
+ RNA_string_set(kmi->ptr, "data_path", "gpencil_data.use_stroke_edit_mode");
+
+ /* Pie Menu - For standard tools */
+ WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_tool_palette", QKEY, KM_PRESS, 0, DKEY);
+ WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_settings_palette", WKEY, KM_PRESS, 0, DKEY);
+}
+
+/* ==================== */
+
+/* Poll callback for stroke editing mode */
+static int gp_stroke_editmode_poll(bContext *C)
+{
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ return (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE));
+}
+
+/* Stroke Editing Keymap - Only when editmode is enabled */
+static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Edit Mode", 0, 0);
+ wmKeyMapItem *kmi;
+
+ /* set poll callback - so that this keymap only gets enabled when stroke editmode is enabled */
+ keymap->poll = gp_stroke_editmode_poll;
+
+ /* ----------------------------------------------- */
+
+ /* Exit EditMode */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "gpencil_data.use_stroke_edit_mode");
+
+ /* Brush Settings */
+ /* NOTE: We cannot expose these in the standard keymap, as they will interfere with regular hotkeys
+ * in other modes. However, when we are dealing with Stroke Edit Mode, we know for certain
+ * that the only data being edited is that of the Grease Pencil strokes
+ */
+
+ /* FKEY = Eraser Radius */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path_primary", "user_preferences.edit.grease_pencil_eraser_radius");
+
+ /* Selection ------------------------------------- */
+ /* select all */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_all", AKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
+
+ /* circle select */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_circle", CKEY, KM_PRESS, 0, 0);
+
+ /* border select */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_border", BKEY, KM_PRESS, 0, 0);
+
+ /* lasso select */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT | KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "deselect", true);
+
+ /* normal select */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+ RNA_boolean_set(kmi->ptr, "toggle", true);
+
+ /* whole stroke select */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "entire_strokes", true);
+
+ /* select linked */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* select more/less */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
+
+
+ /* Editing ----------------------------------------- */
+
+ /* duplicate and move selected points */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
+
+ /* delete */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "GPENCIL_OT_delete", DELKEY, KM_PRESS, 0, 0);
+
+ /* copy + paste */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
+
+#ifdef __APPLE__
+ WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
+ WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
+#endif
+
+ /* Transform Tools */
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", GKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_rotate", RKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_resize", SKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_mirror", MKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_bend", WKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ WM_keymap_add_item(keymap, "TRANSFORM_OT_tosphere", SKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ WM_keymap_add_item(keymap, "TRANSFORM_OT_shear", SKEY, KM_PRESS, KM_ALT | KM_CTRL | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "gpencil_strokes", true);
+
+ /* Proportional Editing */
+ ED_keymap_proportional_cycle(keyconf, keymap);
+ ED_keymap_proportional_editmode(keyconf, keymap, true);
+}
+
+/* ==================== */
+
+void ED_keymap_gpencil(wmKeyConfig *keyconf)
+{
+ ed_keymap_gpencil_general(keyconf);
+ ed_keymap_gpencil_editing(keyconf);
}
/* ****************************************** */
@@ -80,18 +229,51 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_draw);
+ /* Editing (Strokes) ------------ */
+
+ WM_operatortype_append(GPENCIL_OT_select);
+ WM_operatortype_append(GPENCIL_OT_select_all);
+ WM_operatortype_append(GPENCIL_OT_select_circle);
+ WM_operatortype_append(GPENCIL_OT_select_border);
+ WM_operatortype_append(GPENCIL_OT_select_lasso);
+
+ WM_operatortype_append(GPENCIL_OT_select_linked);
+ WM_operatortype_append(GPENCIL_OT_select_more);
+ WM_operatortype_append(GPENCIL_OT_select_less);
+
+ WM_operatortype_append(GPENCIL_OT_duplicate);
+ WM_operatortype_append(GPENCIL_OT_delete);
+ WM_operatortype_append(GPENCIL_OT_copy);
+ WM_operatortype_append(GPENCIL_OT_paste);
+
/* Editing (Buttons) ------------ */
WM_operatortype_append(GPENCIL_OT_data_add);
WM_operatortype_append(GPENCIL_OT_data_unlink);
WM_operatortype_append(GPENCIL_OT_layer_add);
+ WM_operatortype_append(GPENCIL_OT_layer_remove);
+ WM_operatortype_append(GPENCIL_OT_layer_move);
+ WM_operatortype_append(GPENCIL_OT_layer_duplicate);
WM_operatortype_append(GPENCIL_OT_active_frame_delete);
WM_operatortype_append(GPENCIL_OT_convert);
-
+
/* Editing (Time) --------------- */
}
+void ED_operatormacros_gpencil(void)
+{
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("GPENCIL_OT_duplicate_move", "Duplicate Strokes",
+ "Make copies of the selected Grease Pencil strokes and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "GPENCIL_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(otmacro->ptr, "gpencil_strokes", true);
+}
+
/* ****************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 7c1976df3e0..e6f6644fd24 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -27,6 +27,7 @@
* \ingroup edgpencil
*/
+
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
@@ -86,11 +87,13 @@ typedef struct tGPsdata {
rctf *subrect; /* for using the camera rect within the 3d view */
rctf subrect_data;
+ GP_SpaceConversion gsc; /* settings to pass to gp_points_to_xy() */
+
PointerRNA ownerPtr; /* pointer to owner of gp-datablock */
bGPdata *gpd; /* gp-datablock layer comes from */
bGPDlayer *gpl; /* layer we're working on */
bGPDframe *gpf; /* frame we're working on */
-
+
short status; /* current status of painting */
short paintmode; /* mode for painting */
@@ -110,7 +113,7 @@ typedef struct tGPsdata {
double inittime; /* Used when converting to path */
double curtime; /* Used when converting to path */
double ocurtime; /* Used when converting to path */
-
+
float imat[4][4]; /* inverted transformation matrix applying when converting coords from screen-space
* to region space */
float mat[4][4];
@@ -219,7 +222,7 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3])
if (p->ownerPtr.type == &RNA_Object) {
Object *ob = (Object *)p->ownerPtr.data;
- /* active Object
+ /* active Object
* - use relative distance of 3D-cursor from object center
*/
sub_v3_v3v3(vec, fp, ob->loc);
@@ -244,13 +247,13 @@ static bool gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2])
if (p->gpd->sbuffer_size == 0)
return true;
- /* check if mouse moved at least certain distance on both axes (best case)
+ /* check if mouse moved at least certain distance on both axes (best case)
* - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand
*/
else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX))
return true;
- /* check if the distance since the last point is significant enough
+ /* check if the distance since the last point is significant enough
* - prevents points being added too densely
* - distance here doesn't use sqrt to prevent slowness... we should still be safe from overflows though
*/
@@ -280,7 +283,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
float rvec[3], dvec[3];
float mval_f[2] = {UNPACK2(mval)};
float zfac;
-
+
/* Current method just converts each point in screen-coordinates to
* 3D-coordinates using the 3D-cursor as reference. In general, this
* works OK, but it could of course be improved.
@@ -292,7 +295,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
gp_get_3d_reference(p, rvec);
zfac = ED_view3d_calc_zfac(p->ar->regiondata, rvec, NULL);
-
+
if (ED_view3d_project_float_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
sub_v2_v2v2(mval_f, mval_prj, mval_f);
ED_view3d_win_to_delta(p->ar, mval_f, dvec, zfac);
@@ -328,7 +331,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
{
bGPdata *gpd = p->gpd;
tGPspoint *pt;
-
+
/* check painting mode */
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
/* straight lines only - i.e. only store start and end point in buffer */
@@ -345,7 +348,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
gpd->sbuffer_size++;
}
else {
- /* normally, we just reset the endpoint to the latest value
+ /* normally, we just reset the endpoint to the latest value
* - assume that pointers for this are always valid...
*/
pt = ((tGPspoint *)(gpd->sbuffer) + 1);
@@ -439,7 +442,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
return GP_STROKEADD_NORMAL;
}
-
+
/* return invalid state for now... */
return GP_STROKEADD_INVALID;
}
@@ -459,12 +462,12 @@ static void gp_stroke_smooth(tGPsdata *p)
if ((cmx <= 2) || (gpd->sbuffer == NULL))
return;
- /* Calculate smoothing coordinates using weighted-averages
+ /* Calculate smoothing coordinates using weighted-averages
* WARNING: we do NOT smooth first and last points (to avoid shrinkage)
*/
spt = (tGPspoint *)gpd->sbuffer;
- /* This (tmp_spt) small array stores the last two points' original coordinates,
+ /* This (tmp_spt) small array stores the last two points' original coordinates,
* as we don't want to use already averaged ones! It is used as a cyclic buffer...
*/
tmp_spt[0] = *spt;
@@ -483,7 +486,7 @@ static void gp_stroke_smooth(tGPsdata *p)
}
}
-/* simplify a stroke (in buffer) before storing it
+/* simplify a stroke (in buffer) before storing it
* - applies a reverse Chaikin filter
* - code adapted from etch-a-ton branch (editarmature_sketch.c)
*/
@@ -503,7 +506,7 @@ static void gp_stroke_simplify(tGPsdata *p)
if ((num_points <= 4) || (old_points == NULL))
return;
- /* clear buffer (but don't free mem yet) so that we can write to it
+ /* clear buffer (but don't free mem yet) so that we can write to it
* - firstly set sbuffer to NULL, so a new one is allocated
* - secondly, reset flag after, as it gets cleared auto
*/
@@ -570,7 +573,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
int depth_margin = (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 4 : 0;
- /* get total number of points to allocate space for
+ /* get total number of points to allocate space for
* - drawing straight-lines only requires the endpoints
*/
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)
@@ -626,7 +629,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
pt++;
}
-
+
if (totelem == 2) {
/* last point if applicable */
ptc = ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1);
@@ -747,7 +750,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i)
/* free stroke points, then stroke */
MEM_freeN(pt_tmp);
BLI_freelinkN(&gpf->strokes, gps);
-
+
/* nothing left in stroke, so stop */
return 1;
}
@@ -853,8 +856,7 @@ static float view3d_point_depth(const RegionView3D *rv3d, const float co[3])
}
}
-static bool gp_stroke_eraser_is_occluded(tGPsdata *p,
- const bGPDspoint *pt, const int x, const int y)
+static bool gp_stroke_eraser_is_occluded(tGPsdata *p, const bGPDspoint *pt, const int x, const int y)
{
if ((p->sa->spacetype == SPACE_VIEW3D) &&
(p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH))
@@ -862,11 +864,11 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p,
RegionView3D *rv3d = p->ar->regiondata;
const int mval[2] = {x, y};
float mval_3d[3];
-
+
if (ED_view3d_autodist_simple(p->ar, mval, mval_3d, 0, NULL)) {
const float depth_mval = view3d_point_depth(rv3d, mval_3d);
const float depth_pt = view3d_point_depth(rv3d, &pt->x);
-
+
if (depth_pt > depth_mval) {
return true;
}
@@ -875,58 +877,6 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p,
return false;
}
-/* eraser tool - check if part of stroke occurs within last segment drawn by eraser */
-static short gp_stroke_eraser_strokeinside(const int mval[2], const int UNUSED(mvalo[2]),
- int rad, int x0, int y0, int x1, int y1)
-{
- /* simple within-radius check for now */
- const float mval_fl[2] = {mval[0], mval[1]};
- const float screen_co_a[2] = {x0, y0};
- const float screen_co_b[2] = {x1, y1};
-
- if (edge_inside_circle(mval_fl, rad, screen_co_a, screen_co_b)) {
- return true;
- }
-
- /* not inside */
- return false;
-}
-
-static void gp_point_to_xy(tGPsdata *p, bGPDstroke *gps, bGPDspoint *pt,
- int *r_x, int *r_y)
-{
- ARegion *ar = p->ar;
- View2D *v2d = p->v2d;
- rctf *subrect = p->subrect;
- int xyval[2];
-
- if (gps->flag & GP_STROKE_3DSPACE) {
- if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- *r_x = xyval[0];
- *r_y = xyval[1];
- }
- else {
- *r_x = V2D_IS_CLIPPED;
- *r_y = V2D_IS_CLIPPED;
- }
- }
- else if (gps->flag & GP_STROKE_2DSPACE) {
- float vec[3] = {pt->x, pt->y, 0.0f};
- mul_m4_v3(p->mat, vec);
- UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], r_x, r_y);
- }
- else {
- if (subrect == NULL) { /* normal 3D view */
- *r_x = (int)(pt->x / 100 * ar->winx);
- *r_y = (int)(pt->y / 100 * ar->winy);
- }
- else { /* camera view, use subrect */
- *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin;
- *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin;
- }
- }
-}
-
/* eraser tool - evaluation per stroke */
/* TODO: this could really do with some optimization (KD-Tree/BVH?) */
@@ -940,12 +890,12 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
if (gps->totpoints == 0) {
/* just free stroke */
- if (gps->points)
+ if (gps->points)
MEM_freeN(gps->points);
BLI_freelinkN(&gpf->strokes, gps);
}
else if (gps->totpoints == 1) {
- gp_point_to_xy(p, gps, gps->points, &x0, &y0);
+ gp_point_to_xy(&p->gsc, gps, gps->points, &x0, &y0);
/* do boundbox check first */
if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) {
@@ -958,7 +908,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
}
}
else {
- /* loop over the points in the stroke, checking for intersections
+ /* loop over the points in the stroke, checking for intersections
* - an intersection will require the stroke to be split
*/
for (i = 0; (i + 1) < gps->totpoints; i++) {
@@ -966,8 +916,8 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
pt1 = gps->points + i;
pt2 = gps->points + i + 1;
- gp_point_to_xy(p, gps, pt1, &x0, &y0);
- gp_point_to_xy(p, gps, pt2, &x1, &y1);
+ gp_point_to_xy(&p->gsc, gps, pt1, &x0, &y0);
+ gp_point_to_xy(&p->gsc, gps, pt2, &x1, &y1);
/* check that point segment of the boundbox of the eraser stroke */
if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) ||
@@ -977,7 +927,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
* eraser region (either within stroke painted, or on its lines)
* - this assumes that linewidth is irrelevant
*/
- if (gp_stroke_eraser_strokeinside(mval, mvalo, rad, x0, y0, x1, y1)) {
+ if (gp_stroke_inside_circle(mval, mvalo, rad, x0, y0, x1, y1)) {
if ((gp_stroke_eraser_is_occluded(p, pt1, x0, y0) == false) ||
(gp_stroke_eraser_is_occluded(p, pt2, x1, y1) == false))
{
@@ -1003,16 +953,16 @@ static void gp_stroke_doeraser(tGPsdata *p)
rect.ymin = p->mval[1] - p->radius;
rect.xmax = p->mval[0] + p->radius;
rect.ymax = p->mval[1] + p->radius;
-
+
if (p->sa->spacetype == SPACE_VIEW3D) {
if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) {
View3D *v3d = p->sa->spacedata.first;
-
+
view3d_region_operator_needs_opengl(p->win, p->ar);
ED_view3d_autodist_init(p->scene, p->ar, v3d, 0);
}
}
-
+
/* loop over strokes, checking segments for intersections */
for (gps = gpf->strokes.first; gps; gps = gpn) {
gpn = gps->next;
@@ -1043,7 +993,7 @@ static void gp_session_validatebuffer(tGPsdata *p)
/* reset flags */
gpd->sbuffer_sflag = 0;
-
+
/* reset inittime */
p->inittime = 0.0;
}
@@ -1066,8 +1016,9 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
/* pass on current scene and window */
p->scene = CTX_data_scene(C);
p->win = CTX_wm_window(C);
-
+
unit_m4(p->imat);
+ unit_m4(p->mat);
switch (curarea->spacetype) {
/* supported views first */
@@ -1076,7 +1027,7 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
/* View3D *v3d = curarea->spacedata.first; */
/* RegionView3D *rv3d = ar->regiondata; */
- /* set current area
+ /* set current area
* - must verify that region data is 3D-view (and not something else)
*/
p->sa = curarea;
@@ -1154,7 +1105,9 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
p->imat[3][0] -= marker->pos[0];
p->imat[3][1] -= marker->pos[1];
}
+
invert_m4_m4(p->mat, p->imat);
+ copy_m4_m4(p->gsc.mat, p->mat);
break;
}
/* unsupported views */
@@ -1199,10 +1152,10 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
static tGPsdata *gp_session_initpaint(bContext *C)
{
tGPsdata *p = NULL;
-
+
/* create new context data */
p = MEM_callocN(sizeof(tGPsdata), "GPencil Drawing Data");
-
+
gp_session_initdata(C, p);
/* return context data for running paint operator */
@@ -1233,7 +1186,7 @@ static void gp_session_cleanup(tGPsdata *p)
/* init new stroke */
static void gp_paint_initstroke(tGPsdata *p, short paintmode)
-{
+{
/* get active layer (or add a new one if non-existent) */
p->gpl = gpencil_layer_getactive(p->gpd);
if (p->gpl == NULL) {
@@ -1248,7 +1201,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode)
printf("Error: Cannot paint on locked layer\n");
return;
}
-
+
/* get active frame (add a new one if not matching frame) */
p->gpf = gpencil_layer_getframe(p->gpl, p->scene->r.cfra, 1);
if (p->gpf == NULL) {
@@ -1264,7 +1217,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode)
p->paintmode = paintmode;
if (p->paintmode == GP_PAINTMODE_ERASER) {
p->gpd->sbuffer_sflag |= GP_STROKE_ERASER;
-
+
/* check if we should respect depth while erasing */
if (p->sa->spacetype == SPACE_VIEW3D) {
if (p->gpl->flag & GP_LAYER_NO_XRAY) {
@@ -1272,11 +1225,11 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode)
}
}
}
-
+
/* set 'initial run' flag, which is only used to denote when a new stroke is starting */
p->flags |= GP_PAINTFLAG_FIRSTRUN;
-
+
/* when drawing in the camera view, in 2D space, set the subrect */
if (!(p->gpd->flag & GP_DATA_VIEWALIGN)) {
if (p->sa->spacetype == SPACE_VIEW3D) {
@@ -1290,7 +1243,21 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode)
}
}
}
-
+
+ /* init stroke point space-conversion settings... */
+ p->gsc.gpd = p->gpd;
+ p->gsc.gpl = p->gpl;
+
+ p->gsc.sa = p->sa;
+ p->gsc.ar = p->ar;
+ p->gsc.v2d = p->v2d;
+
+ p->gsc.subrect_data = p->subrect_data;
+ p->gsc.subrect = p->subrect;
+
+ copy_m4_m4(p->gsc.mat, p->mat);
+
+
/* check if points will need to be made in view-aligned space */
if (p->gpd->flag & GP_DATA_VIEWALIGN) {
switch (p->sa->spacetype) {
@@ -1340,7 +1307,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode)
/* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
static void gp_paint_strokeend(tGPsdata *p)
{
- /* for surface sketching, need to set the right OpenGL context stuff so that
+ /* for surface sketching, need to set the right OpenGL context stuff so that
* the conversions will project the values correctly...
*/
if (gpencil_project_check(p)) {
@@ -1395,13 +1362,18 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
glTranslatef((float)x, (float)y, 0.0f);
- glColor4ub(255, 255, 255, 128);
-
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
+ glColor4ub(255, 100, 100, 20);
+ glutil_draw_filled_arc(0.0, M_PI * 2.0, p->radius, 40);
+
+ setlinestyle(6);
+
+ glColor4ub(255, 100, 100, 200);
glutil_draw_lined_arc(0.0, M_PI * 2.0, p->radius, 40);
+ setlinestyle(0);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
@@ -1419,7 +1391,7 @@ static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short en
}
else if (enable) {
/* enable cursor */
- p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
+ p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
NULL, /* XXX */
gpencil_draw_eraser, p);
}
@@ -1526,13 +1498,13 @@ static void gpencil_draw_status_indicators(tGPsdata *p)
ED_area_headerprint(p->sa, IFACE_("Grease Pencil Freehand Session: Hold and drag LMB to draw | "
"ESC/Enter to end"));
break;
-
+
default: /* unhandled future cases */
ED_area_headerprint(p->sa, IFACE_("Grease Pencil Session: ESC/Enter to end"));
break;
}
break;
-
+
case GP_STATUS_ERROR:
case GP_STATUS_DONE:
/* clear status string */
@@ -1626,15 +1598,6 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event)
else
p->pressure = 1.0f;
- /* fill in stroke data (not actually used directly by gpencil_draw_apply) */
- RNA_collection_add(op->ptr, "stroke", &itemptr);
-
- mousef[0] = p->mval[0];
- mousef[1] = p->mval[1];
- RNA_float_set_array(&itemptr, "mouse", mousef);
- RNA_float_set(&itemptr, "pressure", p->pressure);
- RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN));
-
/* special exception for start of strokes (i.e. maybe for just a dot) */
if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
@@ -1651,6 +1614,15 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event)
return;
}
+ /* fill in stroke data (not actually used directly by gpencil_draw_apply) */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+
+ mousef[0] = p->mval[0];
+ mousef[1] = p->mval[1];
+ RNA_float_set_array(&itemptr, "mouse", mousef);
+ RNA_float_set(&itemptr, "pressure", p->pressure);
+ RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN));
+
RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
/* apply the current latest drawing point */
@@ -1721,7 +1693,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
gpencil_draw_apply(op, p);
}
RNA_END;
-
+
/* printf("\tGP - done\n"); */
/* cleanup */
@@ -1747,7 +1719,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
/* try to initialize context data needed while drawing */
if (!gpencil_draw_init(C, op)) {
- if (op->customdata)
+ if (op->customdata)
MEM_freeN(op->customdata);
if (G.debug & G_DEBUG)
printf("\tGP - no valid data\n");
@@ -1755,12 +1727,12 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
}
else
p = op->customdata;
-
+
/* TODO: set any additional settings that we can take from the events?
* TODO? if tablet is erasing, force eraser to be on? */
-
+
/* TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway... */
-
+
/* if eraser is on, draw radial aid */
if (p->paintmode == GP_PAINTMODE_ERASER) {
gpencil_draw_toggle_eraser_cursor(C, p, true);
@@ -1772,11 +1744,8 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
else
WM_cursor_modal_set(win, BC_PAINTBRUSHCURSOR);
- /* special hack: if there was an initial event, then we were invoked via a hotkey, and
- * painting should start immediately. Otherwise, this was called from a toolbar, in which
- * case we should wait for the mouse to be clicked.
- */
- if (event->val == KM_PRESS) {
+ /* only start drawing immediately if we're allowed to do so... */
+ if (RNA_boolean_get(op->ptr, "wait_for_input") == false) {
/* hotkey invoked - start drawing */
/* printf("\tGP - set first spot\n"); */
p->status = GP_STATUS_PAINTING;
@@ -1833,15 +1802,15 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
static void gpencil_stroke_end(wmOperator *op)
{
tGPsdata *p = op->customdata;
-
+
gp_paint_cleanup(p);
-
+
gpencil_undo_push(p->gpd);
-
+
gp_session_cleanup(p);
-
+
p->status = GP_STATUS_IDLING;
-
+
p->gpd = NULL;
p->gpl = NULL;
p->gpf = NULL;
@@ -1865,11 +1834,14 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* better in tools that immediately apply
* in 3D space.
*/
-
+
/* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */
if (ISKEYBOARD(event->type)) {
- if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY)) {
- /* allow some keys - for frame changing: [#33412] */
+ if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY, ZKEY)) {
+ /* allow some keys:
+ * - for frame changing [#33412]
+ * - for undo (during sketching sessions)
+ */
}
else {
estate = OPERATOR_RUNNING_MODAL;
@@ -1878,7 +1850,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
//printf("\tGP - handle modal event...\n");
- /* exit painting mode (and/or end current stroke)
+ /* exit painting mode (and/or end current stroke)
* NOTE: cannot do RIGHTMOUSE (as is standard for canceling) as that would break polyline [#32647]
*/
if (ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) {
@@ -1888,7 +1860,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
estate = OPERATOR_FINISHED;
}
- /* toggle painting mode upon mouse-button movement
+ /* toggle painting mode upon mouse-button movement
* - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox only)
* - RIGHTMOUSE = polyline (hotkey) / eraser (all)
* (Disabling RIGHTMOUSE case here results in bugs like [#32647])
@@ -1898,7 +1870,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (p->status == GP_STATUS_PAINTING) {
int sketch = 0;
- /* basically, this should be mouse-button up = end stroke
+ /* basically, this should be mouse-button up = end stroke
* BUT what happens next depends on whether we 'painting sessions' is enabled
*/
sketch |= GPENCIL_SKETCH_SESSIONS_ON(p->scene);
@@ -1967,12 +1939,12 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
case PADPLUSKEY:
p->radius += 5;
break;
-
+
case WHEELUPMOUSE: /* smaller */
case PADMINUS:
p->radius -= 5;
- if (p->radius < 0)
+ if (p->radius < 0)
p->radius = 0;
break;
}
@@ -1983,7 +1955,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* event handled, so just tag as running modal */
estate = OPERATOR_RUNNING_MODAL;
}
- /* there shouldn't be any other events, but just in case there are, let's swallow them
+ /* there shouldn't be any other events, but just in case there are, let's swallow them
* (i.e. to prevent problems with undo)
*/
else {
@@ -2006,7 +1978,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
gpencil_draw_exit(C, op);
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
break;
-
+
case OPERATOR_CANCELLED:
gpencil_draw_exit(C, op);
break;
@@ -2053,6 +2025,8 @@ void GPENCIL_OT_draw(wmOperatorType *ot)
/* settings for drawing */
ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements");
-
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+
+ /* NOTE: wait for input is enabled by default, so that all UI code can work properly without needing users to know about this */
+ RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Wait for first click instead of painting immediately");
}
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
new file mode 100644
index 00000000000..7967d6a4d95
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -0,0 +1,943 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/gpencil/gpencil_select.c
+ * \ingroup edgpencil
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_lasso.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_library.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_view2d.h"
+
+#include "ED_gpencil.h"
+#include "ED_view3d.h"
+#include "ED_keyframing.h"
+
+#include "gpencil_intern.h"
+
+/* ********************************************** */
+/* Polling callbacks */
+
+static int gpencil_select_poll(bContext *C)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ /* only if there's an active layer with an active frame */
+ return (gpl && gpl->actframe);
+}
+
+/* ********************************************** */
+/* Select All Operator */
+
+static int gpencil_select_all_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ int action = RNA_enum_get(op->ptr, "action");
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for "toggle", test for existing selected strokes */
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ if (gps->flag & GP_STROKE_SELECT) {
+ action = SEL_DESELECT;
+ break; // XXX: this only gets out of the inner loop...
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* if deselecting, we need to deselect strokes across all frames
+ * - Currently, an exception is only given for deselection
+ * Selecting and toggling should only affect what's visible,
+ * while deselecting helps clean up unintended/forgotten
+ * stuff on other frames
+ */
+ if (action == SEL_DESELECT) {
+ /* deselect strokes across editable layers
+ * NOTE: we limit ourselves to editable layers, since once a layer is "locked/hidden
+ * nothing should be able to touch it
+ */
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *gpf;
+
+ /* deselect all strokes on all frames */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ bGPDstroke *gps;
+
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+ else {
+ /* select or deselect all strokes */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+ bool selected = false;
+
+ /* Change selection status of all points, then make the stroke match */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ switch (action) {
+ case SEL_SELECT:
+ pt->flag |= GP_SPOINT_SELECT;
+ break;
+ //case SEL_DESELECT:
+ // pt->flag &= ~GP_SPOINT_SELECT;
+ // break;
+ case SEL_INVERT:
+ pt->flag ^= GP_SPOINT_SELECT;
+ break;
+ }
+
+ if (pt->flag & GP_SPOINT_SELECT)
+ selected = true;
+ }
+
+ /* Change status of stroke */
+ if (selected)
+ gps->flag |= GP_STROKE_SELECT;
+ else
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ CTX_DATA_END;
+ }
+
+ /* updates */
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "(De)select All Strokes";
+ ot->idname = "GPENCIL_OT_select_all";
+ ot->description = "Change selection of all Grease Pencil strokes currently visible";
+
+ /* callbacks */
+ ot->exec = gpencil_select_all_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ WM_operator_properties_select_all(ot);
+}
+
+/* ********************************************** */
+/* Select Linked */
+
+static int gpencil_select_linked_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* select all points in selected strokes */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "GPENCIL_OT_select_linked";
+ ot->description = "Select all points in same strokes as already selected points";
+
+ /* callbacks */
+ ot->exec = gpencil_select_linked_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+/* Select More */
+
+static int gpencil_select_more_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+ bool prev_sel;
+
+ /* First Pass: Go in forward order, expanding selection if previous was selected (pre changes)...
+ * - This pass covers the "after" edges of selection islands
+ */
+ prev_sel = false;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* selected point - just set flag for next point */
+ prev_sel = true;
+ }
+ else {
+ /* unselected point - expand selection if previous was selected... */
+ if (prev_sel) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ prev_sel = false;
+ }
+ }
+
+ /* Second Pass: Go in reverse order, doing the same as before (except in opposite order)
+ * - This pass covers the "before" edges of selection islands
+ */
+ prev_sel = false;
+ for (pt -= 1; i > 0; i--, pt--) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ prev_sel = true;
+ }
+ else {
+ /* unselected point - expand selection if previous was selected... */
+ if (prev_sel) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ prev_sel = false;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_more(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "GPENCIL_OT_select_more";
+ ot->description = "Grow sets of selected Grease Pencil points";
+
+ /* callbacks */
+ ot->exec = gpencil_select_more_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+/* Select Less */
+
+static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+ bool prev_sel;
+
+ /* First Pass: Go in forward order, shrinking selection if previous was not selected (pre changes)...
+ * - This pass covers the "after" edges of selection islands
+ */
+ prev_sel = false;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* shrink if previous wasn't selected */
+ if (prev_sel == false) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ prev_sel = true;
+ }
+ else {
+ /* mark previous as being unselected - and hence, is trigger for shrinking */
+ prev_sel = false;
+ }
+ }
+
+ /* Second Pass: Go in reverse order, doing the same as before (except in opposite order)
+ * - This pass covers the "before" edges of selection islands
+ */
+ prev_sel = false;
+ for (pt -= 1; i > 0; i--, pt--) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* shrink if previous wasn't selected */
+ if (prev_sel == false) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ prev_sel = true;
+ }
+ else {
+ /* mark previous as being unselected - and hence, is trigger for shrinking */
+ prev_sel = false;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_less(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "GPENCIL_OT_select_less";
+ ot->description = "Shrink sets of selected Grease Pencil points";
+
+ /* callbacks */
+ ot->exec = gpencil_select_less_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+/* Circle Select Operator */
+
+/* Helper to check if a given stroke is within the area */
+/* NOTE: Code here is adapted (i.e. copied directly) from gpencil_paint.c::gp_stroke_eraser_dostroke()
+ * It would be great to de-duplicate the logic here sometime, but that can wait...
+ */
+static bool gp_stroke_do_circle_sel(bGPDstroke *gps, GP_SpaceConversion *gsc,
+ const int mx, const int my, const int radius,
+ const bool select, rcti *rect)
+{
+ bGPDspoint *pt1, *pt2;
+ int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
+ int i;
+ bool changed = false;
+
+ if (gps->totpoints == 1) {
+ gp_point_to_xy(gsc, gps, gps->points, &x0, &y0);
+
+ /* do boundbox check first */
+ if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) {
+ /* only check if point is inside */
+ if (((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius * radius) {
+ /* change selection */
+ if (select) {
+ gps->points->flag |= GP_SPOINT_SELECT;
+ gps->flag |= GP_STROKE_SELECT;
+ }
+ else {
+ gps->points->flag &= ~GP_SPOINT_SELECT;
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+
+ return true;
+ }
+ }
+ }
+ else {
+ /* Loop over the points in the stroke, checking for intersections
+ * - an intersection means that we touched the stroke
+ */
+ for (i = 0; (i + 1) < gps->totpoints; i++) {
+ /* get points to work with */
+ pt1 = gps->points + i;
+ pt2 = gps->points + i + 1;
+
+ gp_point_to_xy(gsc, gps, pt1, &x0, &y0);
+ gp_point_to_xy(gsc, gps, pt2, &x1, &y1);
+
+ /* check that point segment of the boundbox of the selection stroke */
+ if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) ||
+ ((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1)))
+ {
+ int mval[2] = {mx, my};
+ int mvalo[2] = {mx, my}; /* dummy - this isn't used... */
+
+ /* check if point segment of stroke had anything to do with
+ * eraser region (either within stroke painted, or on its lines)
+ * - this assumes that linewidth is irrelevant
+ */
+ if (gp_stroke_inside_circle(mval, mvalo, radius, x0, y0, x1, y1)) {
+ /* change selection of stroke, and then of both points
+ * (as the last point otherwise wouldn't get selected
+ * as we only do n-1 loops through)
+ */
+ if (select) {
+ pt1->flag |= GP_SPOINT_SELECT;
+ pt2->flag |= GP_SPOINT_SELECT;
+
+ changed = true;
+ }
+ else {
+ pt1->flag &= ~GP_SPOINT_SELECT;
+ pt2->flag &= ~GP_SPOINT_SELECT;
+
+ changed = true;
+ }
+ }
+ }
+ }
+
+ /* Ensure that stroke selection is in sync with its points */
+ gpencil_stroke_sync_selection(gps);
+ }
+
+ return changed;
+}
+
+
+static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa = CTX_wm_area(C);
+
+ const int mx = RNA_int_get(op->ptr, "x");
+ const int my = RNA_int_get(op->ptr, "y");
+ const int radius = RNA_int_get(op->ptr, "radius");
+
+ const int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
+ const bool select = (gesture_mode == GESTURE_MODAL_SELECT);
+
+ GP_SpaceConversion gsc = {NULL};
+ rcti rect = {0}; /* for bounding rect around circle (for quicky intersection testing) */
+
+ bool changed = false;
+
+
+ /* sanity checks */
+ if (sa == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active area");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+
+ /* rect is rectangle of selection circle */
+ rect.xmin = mx - radius;
+ rect.ymin = my - radius;
+ rect.xmax = mx + radius;
+ rect.ymax = my + radius;
+
+
+ /* find visible strokes, and select if hit */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ changed |= gp_stroke_do_circle_sel(gps, &gsc, mx, my, radius, select, &rect);
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ if (changed) {
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_circle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Circle Select";
+ ot->description = "Select Grease Pencil strokes using brush selection";
+ ot->idname = "GPENCIL_OT_select_circle";
+
+ /* callbacks */
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->exec = gpencil_circle_select_exec;
+ ot->poll = gpencil_select_poll;
+ ot->cancel = WM_gesture_circle_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "radius", 1, 1, INT_MAX, "Radius", "", 1, INT_MAX);
+ RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX);
+}
+
+/* ********************************************** */
+/* Box Selection */
+
+static int gpencil_border_select_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa = CTX_wm_area(C);
+
+ const int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
+ const bool select = (gesture_mode == GESTURE_MODAL_SELECT);
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ GP_SpaceConversion gsc = {NULL};
+ rcti rect = {0};
+
+ bool changed = false;
+
+
+ /* sanity checks */
+ if (sa == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active area");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+
+ /* deselect all strokes first? */
+ if (select && !extend) {
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ CTX_DATA_END;
+ }
+
+ /* get settings from operator */
+ WM_operator_properties_border_to_rcti(op, &rect);
+
+ /* select/deselect points */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ int x0, y0;
+
+ /* convert point coords to screenspace */
+ gp_point_to_xy(&gsc, gps, pt, &x0, &y0);
+
+ /* test if in selection rect */
+ if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&rect, x0, y0)) {
+ if (select) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ changed = true;
+ }
+ }
+
+ /* Ensure that stroke selection is in sync with its points */
+ gpencil_stroke_sync_selection(gps);
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ if (changed) {
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Border Select";
+ ot->description = "Select Grease Pencil strokes within a rectangular region";
+ ot->idname = "GPENCIL_OT_select_border";
+
+ /* callbacks */
+ ot->invoke = WM_border_select_invoke;
+ ot->exec = gpencil_border_select_exec;
+ ot->modal = WM_border_select_modal;
+ ot->cancel = WM_border_select_cancel;
+
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* rna */
+ WM_operator_properties_gesture_border(ot, true);
+}
+
+/* ********************************************** */
+/* Lasso */
+
+static int gpencil_lasso_select_exec(bContext *C, wmOperator *op)
+{
+ GP_SpaceConversion gsc = {NULL};
+ rcti rect = {0};
+
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool select = !RNA_boolean_get(op->ptr, "deselect");
+
+ int mcords_tot;
+ const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
+
+ bool changed = false;
+
+ /* sanity check */
+ if (mcords == NULL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* compute boundbox of lasso (for faster testing later) */
+ BLI_lasso_boundbox(&rect, mcords, mcords_tot);
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+ /* deselect all strokes first? */
+ if (select && !extend) {
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ CTX_DATA_END;
+ }
+
+ /* select/deselect points */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ int x0, y0;
+
+ /* convert point coords to screenspace */
+ gp_point_to_xy(&gsc, gps, pt, &x0, &y0);
+
+ /* test if in lasso boundbox + within the lasso noose */
+ if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&rect, x0, y0) &&
+ BLI_lasso_is_point_inside(mcords, mcords_tot, x0, y0, INT_MAX))
+ {
+ if (select) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ changed = true;
+ }
+ }
+
+ /* Ensure that stroke selection is in sync with its points */
+ gpencil_stroke_sync_selection(gps);
+ }
+ CTX_DATA_END;
+
+ /* cleanup */
+ MEM_freeN((void *)mcords);
+
+ /* updates */
+ if (changed) {
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_lasso(wmOperatorType *ot)
+{
+ ot->name = "Lasso Select Strokes";
+ ot->description = "Select Grease Pencil strokes using lasso selection";
+ ot->idname = "GPENCIL_OT_select_lasso";
+
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = gpencil_lasso_select_exec;
+ ot->poll = gpencil_select_poll;
+ ot->cancel = WM_gesture_lasso_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect rather than select items");
+ RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection instead of deselecting everything first");
+}
+
+/* ********************************************** */
+/* Mouse Click to Select */
+
+static int gpencil_select_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa = CTX_wm_area(C);
+
+ /* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */
+ const float radius = 0.75f * U.widget_unit;
+ const int radius_squared = (int)(radius * radius);
+
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool deselect = RNA_boolean_get(op->ptr, "deselect");
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ bool whole = RNA_boolean_get(op->ptr, "entire_strokes");
+
+ int location[2] = {0};
+ int mx, my;
+
+ GP_SpaceConversion gsc = {NULL};
+
+ bGPDstroke *hit_stroke = NULL;
+ bGPDspoint *hit_point = NULL;
+
+ /* sanity checks */
+ if (sa == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active area");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
+
+ /* get mouse location */
+ RNA_int_get_array(op->ptr, "location", location);
+
+ mx = location[0];
+ my = location[1];
+
+ /* First Pass: Find stroke point which gets hit */
+ /* XXX: maybe we should go from the top of the stack down instead... */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ bGPDspoint *pt;
+ int i;
+ int hit_index = -1;
+
+ /* firstly, check for hit-point */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ int x0, y0;
+
+ gp_point_to_xy(&gsc, gps, pt, &x0, &y0);
+
+ /* do boundbox check first */
+ if (!ELEM(V2D_IS_CLIPPED, x0, x0)) {
+ /* only check if point is inside */
+ if (((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius_squared) {
+ hit_stroke = gps;
+ hit_point = pt;
+ break;
+ }
+ }
+ }
+
+ /* skip to next stroke if nothing found */
+ if (hit_index == -1)
+ continue;
+ }
+ CTX_DATA_END;
+
+ /* Abort if nothing hit... */
+ if (ELEM(NULL, hit_stroke, hit_point)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* adjust selection behaviour - for toggle option */
+ if (toggle) {
+ deselect = (hit_point->flag & GP_SPOINT_SELECT) != 0;
+ }
+
+ /* If not extending selection, deselect everything else */
+ if (extend == false) {
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ /* deselect stroke and its points if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ /* deselect points */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ /* deselect stroke itself too */
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* Perform selection operations... */
+ if (whole) {
+ bGPDspoint *pt;
+ int i;
+
+ /* entire stroke's points */
+ for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) {
+ if (deselect == false)
+ pt->flag |= GP_SPOINT_SELECT;
+ else
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ /* stroke too... */
+ if (deselect == false)
+ hit_stroke->flag |= GP_STROKE_SELECT;
+ else
+ hit_stroke->flag &= ~GP_STROKE_SELECT;
+ }
+ else {
+ /* just the point (and the stroke) */
+ if (deselect == false) {
+ /* we're adding selection, so selection must be true */
+ hit_point->flag |= GP_SPOINT_SELECT;
+ hit_stroke->flag |= GP_STROKE_SELECT;
+ }
+ else {
+ /* deselect point */
+ hit_point->flag &= ~GP_SPOINT_SELECT;
+
+ /* ensure that stroke is selected correctly */
+ gpencil_stroke_sync_selection(hit_stroke);
+ }
+ }
+
+ /* updates */
+ if (hit_point != NULL) {
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ RNA_int_set_array(op->ptr, "location", event->mval);
+ return gpencil_select_exec(C, op);
+}
+
+void GPENCIL_OT_select(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select";
+ ot->description = "Select Grease Pencil strokes and/or stroke points";
+ ot->idname = "GPENCIL_OT_select";
+
+ /* callbacks */
+ ot->invoke = gpencil_select_invoke;
+ ot->exec = gpencil_select_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flag */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_mouse_select(ot);
+
+ prop = RNA_def_boolean(ot->srna, "entire_strokes", false, "Entire Strokes", "Select entire strokes instead of just the nearest stroke vertex");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, INT_MIN, INT_MAX, "Location", "Mouse location", INT_MIN, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+}
+
+/* ********************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c
index ff92d69f39d..5f0647fb43d 100644
--- a/source/blender/editors/gpencil/gpencil_undo.c
+++ b/source/blender/editors/gpencil/gpencil_undo.c
@@ -29,6 +29,7 @@
* \ingroup edgpencil
*/
+
#include <stdlib.h>
#include <string.h>
@@ -53,7 +54,7 @@
typedef struct bGPundonode {
struct bGPundonode *next, *prev;
-
+
char name[BKE_UNDO_STR_MAX];
struct bGPdata *gpd;
} bGPundonode;
@@ -69,9 +70,9 @@ int ED_gpencil_session_active(void)
int ED_undo_gpencil_step(bContext *C, int step, const char *name)
{
bGPdata **gpd_ptr = NULL, *new_gpd = NULL;
-
+
gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
-
+
if (step == 1) { /* undo */
//printf("\t\tGP - undo step\n");
if (cur_node->prev) {
@@ -90,18 +91,18 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name)
}
}
}
-
+
if (new_gpd) {
if (gpd_ptr) {
if (*gpd_ptr) {
bGPdata *gpd = *gpd_ptr;
bGPDlayer *gpl, *gpld;
-
+
free_gpencil_layers(&gpd->layers);
-
+
/* copy layers */
BLI_listbase_clear(&gpd->layers);
-
+
for (gpl = new_gpd->layers.first; gpl; gpl = gpl->next) {
/* make a copy of source layer and its data */
gpld = gpencil_layer_duplicate(gpl);
@@ -110,9 +111,9 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name)
}
}
}
-
+
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
+
return OPERATOR_FINISHED;
}
@@ -124,46 +125,56 @@ void gpencil_undo_init(bGPdata *gpd)
void gpencil_undo_push(bGPdata *gpd)
{
bGPundonode *undo_node;
-
+
//printf("\t\tGP - undo push\n");
-
+
if (cur_node) {
/* remove all un-done nodes from stack */
undo_node = cur_node->next;
-
+
while (undo_node) {
bGPundonode *next_node = undo_node->next;
-
+
+ /* HACK: animdata wasn't duplicated, so it shouldn't be freed here,
+ * or else the real copy will segfault when accessed
+ */
+ undo_node->gpd->adt = NULL;
+
BKE_gpencil_free(undo_node->gpd);
MEM_freeN(undo_node->gpd);
-
+
BLI_freelinkN(&undo_nodes, undo_node);
-
+
undo_node = next_node;
}
}
-
+
/* create new undo node */
undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node");
- undo_node->gpd = gpencil_data_duplicate(gpd);
-
+ undo_node->gpd = gpencil_data_duplicate(gpd, true);
+
cur_node = undo_node;
-
+
BLI_addtail(&undo_nodes, undo_node);
}
void gpencil_undo_finish(void)
{
bGPundonode *undo_node = undo_nodes.first;
-
+
while (undo_node) {
+ /* HACK: animdata wasn't duplicated, so it shouldn't be freed here,
+ * or else the real copy will segfault when accessed
+ */
+ undo_node->gpd->adt = NULL;
+
BKE_gpencil_free(undo_node->gpd);
MEM_freeN(undo_node->gpd);
-
+
undo_node = undo_node->next;
}
-
+
BLI_freelistN(&undo_nodes);
-
+
cur_node = NULL;
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
new file mode 100644
index 00000000000..4a913c3d2e5
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -0,0 +1,166 @@
+/*
+ * ***** 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
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/gpencil/gpencil_utils.c
+ * \ingroup edgpencil
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_library.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_view2d.h"
+
+#include "ED_gpencil.h"
+#include "ED_view3d.h"
+
+#include "gpencil_intern.h"
+
+/* ******************************************************** */
+
+/* Check if part of stroke occurs within last segment drawn by eraser */
+bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]),
+ int rad, int x0, int y0, int x1, int y1)
+{
+ /* simple within-radius check for now */
+ const float mval_fl[2] = {mval[0], mval[1]};
+ const float screen_co_a[2] = {x0, y0};
+ const float screen_co_b[2] = {x1, y1};
+
+ if (edge_inside_circle(mval_fl, rad, screen_co_a, screen_co_b)) {
+ return true;
+ }
+
+ /* not inside */
+ return false;
+}
+
+/* ******************************************************** */
+
+/* Init handling for space-conversion function (from passed-in parameters) */
+void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ /* zero out the storage (just in case) */
+ memset(r_gsc, 0, sizeof(GP_SpaceConversion));
+ unit_m4(r_gsc->mat);
+
+ /* store settings */
+ r_gsc->sa = sa;
+ r_gsc->ar = ar;
+ r_gsc->v2d = &ar->v2d;
+
+ /* init region-specific stuff */
+ if (sa->spacetype == SPACE_VIEW3D) {
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = (View3D *)CTX_wm_space_data(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* init 3d depth buffers */
+ view3d_operator_needs_opengl(C);
+
+ view3d_region_operator_needs_opengl(win, ar);
+ ED_view3d_autodist_init(scene, ar, v3d, 0);
+
+ /* for camera view set the subrect */
+ if (rv3d->persp == RV3D_CAMOB) {
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &r_gsc->subrect_data, true); /* no shift */
+ r_gsc->subrect = &r_gsc->subrect_data;
+ }
+ }
+}
+
+
+/* Convert Grease Pencil points to screen-space values */
+void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
+ int *r_x, int *r_y)
+{
+ ARegion *ar = gsc->ar;
+ View2D *v2d = gsc->v2d;
+ rctf *subrect = gsc->subrect;
+ int xyval[2];
+
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ *r_x = xyval[0];
+ *r_y = xyval[1];
+ }
+ else {
+ *r_x = V2D_IS_CLIPPED;
+ *r_y = V2D_IS_CLIPPED;
+ }
+ }
+ else if (gps->flag & GP_STROKE_2DSPACE) {
+ float vec[3] = {pt->x, pt->y, 0.0f};
+ mul_m4_v3(gsc->mat, vec);
+ UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], r_x, r_y);
+ }
+ else {
+ if (subrect == NULL) { /* normal 3D view */
+ *r_x = (int)(pt->x / 100 * ar->winx);
+ *r_y = (int)(pt->y / 100 * ar->winy);
+ }
+ else { /* camera view, use subrect */
+ *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin;
+ *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin;
+ }
+ }
+}
+
+/* ******************************************************** */
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index 2acba04368c..b06af01bab6 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -56,14 +56,20 @@ void cpack(unsigned int x);
# define glMultMatrixf(x) \
glMultMatrixf(_Generic((x), \
float *: (float *)(x), \
+ float [16]: (float *)(x), \
float (*)[4]: (float *)(x), \
+ float [4][4]: (float *)(x), \
const float *: (float *)(x), \
- const float (*)[4]: (float *)(x)) \
+ const float [16]: (float *)(x), \
+ const float (*)[4]: (float *)(x), \
+ const float [4][4]: (float *)(x)) \
)
# define glLoadMatrixf(x) \
glLoadMatrixf(_Generic((x), \
float *: (float *)(x), \
- float (*)[4]: (float *)(x)) \
+ float [16]: (float *)(x), \
+ float (*)[4]: (float *)(x), \
+ float [4][4]: (float *)(x)) \
)
#else
# define glMultMatrixf(x) glMultMatrixf((float *)(x))
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 956ec308daa..50581429700 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -159,6 +159,7 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_DSLAT,
ANIMTYPE_DSLINESTYLE,
ANIMTYPE_DSSPK,
+ ANIMTYPE_DSGPENCIL,
ANIMTYPE_SHAPEKEY,
@@ -457,7 +458,7 @@ void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level);
/* Draw the given channel */
void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc);
/* Draw the widgets for the given channel */
-void ANIM_channel_draw_widgets(struct bContext *C, bAnimContext *ac, bAnimListElem *ale, struct uiBlock *block, float yminc, float ymaxc, size_t channel_index);
+void ANIM_channel_draw_widgets(const struct bContext *C, bAnimContext *ac, bAnimListElem *ale, struct uiBlock *block, float yminc, float ymaxc, size_t channel_index);
/* ------------------------ Editing API -------------------------- */
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 05fb76b7aea..b0d1be1bf5d 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -30,6 +30,7 @@
#ifndef __ED_GPENCIL_H__
#define __ED_GPENCIL_H__
+struct ID;
struct ListBase;
struct bContext;
struct bScreen;
@@ -38,11 +39,11 @@ struct ARegion;
struct View3D;
struct SpaceNode;
struct SpaceSeq;
+struct Object;
struct bGPdata;
struct bGPDlayer;
struct bGPDframe;
struct PointerRNA;
-struct Panel;
struct ImBuf;
struct wmKeyConfig;
@@ -65,14 +66,32 @@ typedef struct tGPspoint {
/* ----------- Grease Pencil Tools/Context ------------- */
+/* Context-dependent */
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);
+
+/* Context independent (i.e. each required part is passed in instead) */
+struct bGPdata **ED_gpencil_data_get_pointers_direct(struct ID *screen_id, struct Scene *scene,
+ struct ScrArea *sa, struct Object *ob,
+ struct PointerRNA *ptr);
+struct bGPdata *ED_gpencil_data_get_active_direct(struct ID *screen_id, struct Scene *scene,
+ struct ScrArea *sa, struct Object *ob);
+
+/* 3D View */
struct bGPdata *ED_gpencil_data_get_active_v3d(struct Scene *scene, struct View3D *v3d);
/* ----------- Grease Pencil Operators ----------------- */
void ED_keymap_gpencil(struct wmKeyConfig *keyconf);
+
void ED_operatortypes_gpencil(void);
+void ED_operatormacros_gpencil(void);
+
+/* ------------- Copy-Paste Buffers -------------------- */
+
+/* Strokes copybuf */
+void ED_gpencil_strokes_copybuf_free(void);
+
/* ------------ Grease-Pencil Drawing API ------------------ */
/* drawgpencil.c */
@@ -80,10 +99,8 @@ void ED_operatortypes_gpencil(void);
void ED_gpencil_draw_2dimage(const struct bContext *C);
void ED_gpencil_draw_view2d(const struct bContext *C, bool onlyv2d);
void ED_gpencil_draw_view3d(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, bool only3d);
-void ED_gpencil_draw_ex(struct bGPdata *gpd, int winx, int winy, const int cfra);
-
-void ED_gpencil_panel_standard_header(const struct bContext *C, struct Panel *pa);
-void ED_gpencil_panel_standard(const struct bContext *C, struct Panel *pa);
+void ED_gpencil_draw_ex(struct Scene *scene, struct bGPdata *gpd, int winx, int winy,
+ const int cfra, const char spacetype);
/* ----------- Grease-Pencil AnimEdit API ------------------ */
bool ED_gplayer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene,
@@ -99,6 +116,8 @@ void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode
bool ED_gplayer_frames_delete(struct bGPDlayer *gpl);
void ED_gplayer_frames_duplicate(struct bGPDlayer *gpl);
+void ED_gplayer_frames_keytype_set(struct bGPDlayer *gpl, short type);
+
void ED_gplayer_snap_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode);
#if 0
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index a9995de068e..1188ecd0aa5 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -79,5 +79,7 @@ int ED_space_image_maskedit_mask_poll(struct bContext *C);
void ED_image_draw_info(struct Scene *scene, struct ARegion *ar, bool color_manage, bool use_default_view, int channels, int x, int y,
const unsigned char cp[4], const float fp[4], const float linearcol[4], int *zp, float *zpf);
+bool ED_space_image_show_cache(struct SpaceImage *sima);
+
#endif /* __ED_IMAGE_H__ */
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
index 58a262e150a..0359153317b 100644
--- a/source/blender/editors/include/ED_keyframes_draw.h
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -120,8 +120,9 @@ void draw_object_channel(struct View2D *v2d, struct bDopeSheet *ads, struct Obje
void draw_scene_channel(struct View2D *v2d, struct bDopeSheet *ads, struct Scene *sce, float ypos);
/* DopeSheet Summary */
void draw_summary_channel(struct View2D *v2d, struct bAnimContext *ac, float ypos);
-/* Grease Pencil Layer */
-// XXX not restored
+/* Grease Pencil datablock summary */
+void draw_gpencil_channel(struct View2D *v2d, struct bDopeSheet *ads, struct bGPdata *gpd, float ypos);
+/* Grease Pencil Layer */
void draw_gpl_channel(struct View2D *v2d, struct bDopeSheet *ads, struct bGPDlayer *gpl, float ypos);
/* Mask Layer */
void draw_masklay_channel(struct View2D *v2d, struct bDopeSheet *ads, struct MaskLayer *masklay, float ypos);
@@ -139,11 +140,11 @@ void ob_to_keylist(struct bDopeSheet *ads, struct Object *ob, struct DLRBT_Tree
void scene_to_keylist(struct bDopeSheet *ads, struct Scene *sce, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
/* DopeSheet Summary */
void summary_to_keylist(struct bAnimContext *ac, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
+/* Grease Pencil datablock summary */
+void gpencil_to_keylist(struct bDopeSheet *ads, struct bGPdata *gpd, struct DLRBT_Tree *keys);
/* Grease Pencil Layer */
-// XXX not restored
void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, struct DLRBT_Tree *keys);
/* Mask */
-// XXX not restored
void mask_to_keylist(struct bDopeSheet *UNUSED(ads), struct MaskLayer *masklay, struct DLRBT_Tree *keys);
/* ActKeyColumn API ---------------- */
diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h
index 197191b4f96..adf82acb399 100644
--- a/source/blender/editors/include/ED_keyframes_edit.h
+++ b/source/blender/editors/include/ED_keyframes_edit.h
@@ -58,6 +58,7 @@ typedef enum eEditKeyframes_Validate {
BEZT_OK_VALUERANGE,
BEZT_OK_REGION,
BEZT_OK_REGION_LASSO,
+ BEZT_OK_REGION_CIRCLE,
} eEditKeyframes_Validate;
/* ------------ */
@@ -107,6 +108,14 @@ struct KeyframeEdit_LassoData {
int mcords_tot;
};
+/* use with BEZT_OK_REGION_CIRCLE */
+struct KeyframeEdit_CircleData {
+ const rctf *rectf_scaled;
+ const rctf *rectf_view;
+ float mval[2];
+ float radius_squared;
+};
+
/* ************************************************ */
/* Non-Destuctive Editing API (keyframes_edit.c) */
@@ -261,7 +270,7 @@ void sample_fcurve(struct FCurve *fcu);
void free_anim_copybuf(void);
short copy_animedit_keys(struct bAnimContext *ac, ListBase *anim_data);
short paste_animedit_keys(struct bAnimContext *ac, ListBase *anim_data,
- const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode);
+ const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip);
/* ************************************************ */
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 5c7b3c531be..e5b5e79875d 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -293,7 +293,7 @@ bool ANIM_paste_driver(struct ReportList *reports, struct ID *id, const char rna
(U.autokey_flag & AUTOKEY_FLAG_##flag))
/* auto-keyframing feature - checks for whether anything should be done for the current frame */
-int autokeyframe_cfra_can_key(struct Scene *scene, struct ID *id);
+bool autokeyframe_cfra_can_key(struct Scene *scene, struct ID *id);
/* ************ Keyframe Checking ******************** */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 2b4fa1b9196..8eb7fdf0c40 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -220,14 +220,8 @@ void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
#define WEIGHT_SUBTRACT 3
bool ED_vgroup_sync_from_pose(struct Object *ob);
-struct bDeformGroup *ED_vgroup_add(struct Object *ob);
-struct bDeformGroup *ED_vgroup_add_name(struct Object *ob, const char *name);
-void ED_vgroup_delete(struct Object *ob, struct bDeformGroup *defgroup);
-void ED_vgroup_clear(struct Object *ob);
void ED_vgroup_select_by_name(struct Object *ob, const char *name);
-bool ED_vgroup_data_create(struct ID *id);
void ED_vgroup_data_clamp_range(struct ID *id, const int total);
-bool ED_vgroup_array_get(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot);
bool ED_vgroup_array_copy(struct Object *ob, struct Object *ob_from);
bool ED_vgroup_parray_alloc(struct ID *id, struct MDeformVert ***dvert_arr, int *dvert_tot,
const bool use_vert_sel);
@@ -244,8 +238,6 @@ void ED_vgroup_mirror(struct Object *ob,
const bool all_vgroups, const bool use_topology,
int *r_totmirr, int *r_totfail);
-bool ED_vgroup_object_is_edit_mode(struct Object *ob);
-
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode);
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum);
float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 39586039e8f..900da3ee07c 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -209,12 +209,6 @@ bool ED_object_multires_update_totlevels_cb(struct Object *ob, void *totlevel_v)
/* object_select.c */
void ED_object_select_linked_by_id(struct bContext *C, struct ID *id);
-
-bool *ED_vgroup_subset_from_select_type(struct Object *ob, enum eVGroupSelect subset_type,
- int *r_vgroup_tot, int *r_subset_count);
-void ED_vgroup_subset_to_index_array(const bool *vgroup_validmap, const int vgroup_tot,
- int *r_vgroup_subset_map);
-
struct EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
const struct bContext *C,
struct PointerRNA *ptr,
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index ab1dbabe793..de3843c91eb 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -40,6 +40,7 @@ struct ScrArea;
struct RegionView3D;
struct RenderEngine;
struct View3D;
+struct wmWindowManager;
/* render_ops.c */
@@ -52,7 +53,7 @@ void ED_render_engine_changed(struct Main *bmain);
void ED_render_engine_area_exit(struct ScrArea *sa);
void ED_render_scene_update(struct Main *bmain, struct Scene *scene, int updated);
-void ED_viewport_render_kill_jobs(const struct bContext *C, bool free_database);
+void ED_viewport_render_kill_jobs(struct wmWindowManager *wm, struct Main *bmain, bool free_database);
struct Scene *ED_render_job_get_scene(const struct bContext *C);
/* Render the preview
@@ -71,8 +72,9 @@ void ED_preview_init_dbase(void);
void ED_preview_free_dbase(void);
void ED_preview_shader_job(const struct bContext *C, void *owner, struct ID *id, struct ID *parent, struct MTex *slot, int sizex, int sizey, int method);
+void ED_preview_icon_render(struct Scene *scene, struct ID *id, unsigned int *rect, int sizex, int sizey);
void ED_preview_icon_job(const struct bContext *C, void *owner, struct ID *id, unsigned int *rect, int sizex, int sizey);
-void ED_preview_kill_jobs(const struct bContext *C);
+void ED_preview_kill_jobs(struct wmWindowManager *wm, struct Main *bmain);
void ED_preview_draw(const struct bContext *C, void *idp, void *parentp, void *slot, rcti *rect);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index ed2465647da..b790c656b61 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -107,6 +107,7 @@ void ED_screen_set_subwinactive(struct bContext *C, struct wmEvent *event);
void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable);
void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh);
+void ED_screen_retore_temp_type(struct bContext *C, ScrArea *sa, bool is_screen_change);
ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type);
void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa);
void ED_screen_full_restore(struct bContext *C, ScrArea *sa);
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index 85ff9b5d246..d3b1a824104 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -34,6 +34,7 @@ struct ARegion;
struct bContext;
struct Object;
struct RegionView3D;
+struct Scene;
struct ViewContext;
struct rcti;
@@ -41,8 +42,6 @@ struct rcti;
void ED_operatortypes_sculpt(void);
void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *ar,
struct RegionView3D *rv3d, struct Object *ob);
-void ED_sculpt_stroke_get_average(struct Object *ob, float stroke[3]);
-bool ED_sculpt_minmax(struct bContext *C, float min[3], float max[3]);
int ED_sculpt_mask_box_select(struct bContext *C, struct ViewContext *vc, const struct rcti *rect, bool select, bool extend);
#endif /* __ED_SCULPT_H__ */
diff --git a/source/blender/editors/include/ED_sequencer.h b/source/blender/editors/include/ED_sequencer.h
index 4e9d67df61e..94885c2abe0 100644
--- a/source/blender/editors/include/ED_sequencer.h
+++ b/source/blender/editors/include/ED_sequencer.h
@@ -27,6 +27,7 @@
#ifndef __ED_SEQUENCER_H__
#define __ED_SEQUENCER_H__
+struct bContext;
struct Scene;
struct Sequence;
struct SpaceSeq;
@@ -39,7 +40,12 @@ bool ED_space_sequencer_check_show_maskedit(struct SpaceSeq *sseq, struct Scene
int ED_space_sequencer_maskedit_poll(struct bContext *C);
bool ED_space_sequencer_check_show_imbuf(struct SpaceSeq *sseq);
+bool ED_space_sequencer_check_show_strip(struct SpaceSeq *sseq);
void ED_operatormacros_sequencer(void);
+Sequence *ED_sequencer_special_preview_get(void);
+void ED_sequencer_special_preview_set(struct bContext *C, const int mval[2]);
+void ED_sequencer_special_preview_clear(void);
+
#endif /* __ED_SEQUENCER_H__ */
diff --git a/source/blender/editors/include/ED_text.h b/source/blender/editors/include/ED_text.h
index 9a36cb3d6ab..5df7d9cfaef 100644
--- a/source/blender/editors/include/ED_text.h
+++ b/source/blender/editors/include/ED_text.h
@@ -31,8 +31,11 @@
#define __ED_TEXT_H__
struct bContext;
+struct SpaceText;
+struct ARegion;
void ED_text_undo_step(struct bContext *C, int step);
+bool ED_text_region_location_from_cursor(struct SpaceText *st, struct ARegion *ar, const int cursor_co[2], int r_pixel_co[2]);
#endif /* __ED_TEXT_H__ */
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index daa6864b5aa..cf848098188 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -99,6 +99,7 @@ enum TfmMode {
#define CTX_MOVIECLIP (1 << 6)
#define CTX_MASK (1 << 7)
#define CTX_PAINT_CURVE (1 << 8)
+#define CTX_GPENCIL_STROKES (1 << 9)
/* Standalone call to get the transformation center corresponding to the current situation
* returns 1 if successful, 0 otherwise (usually means there's no selection)
@@ -146,6 +147,7 @@ int BIF_countTransformOrientation(const struct bContext *C);
#define P_CORRECT_UV (1 << 8)
#define P_NO_DEFAULTS (1 << 10)
#define P_NO_TEXSPACE (1 << 11)
+#define P_GPENCIL_EDIT (1 << 12)
void Transform_Properties(struct wmOperatorType *ot, int flags);
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index bf3b18e143e..3e8f234e979 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -94,6 +94,8 @@ void uvedit_uv_select_disable(struct BMEditMesh *em, struct Scene *scene, struct
bool ED_uvedit_nearest_uv(struct Scene *scene, struct Object *obedit, struct Image *ima,
const float co[2], float r_uv[2]);
+void ED_uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMesh *em, float *aspx, float *aspy);
+
/* uvedit_unwrap_ops.c */
void ED_uvedit_live_unwrap_begin(struct Scene *scene, struct Object *obedit);
void ED_uvedit_live_unwrap_re_solve(void);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index bd4f37cfb1e..76ad4ba7bdb 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -309,7 +309,7 @@ void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct AR
struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag,
bool draw_background, int alpha_mode, char err_out[256]);
struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype,
- bool use_solid_tex, bool draw_background, int alpha_mode, char err_out[256]);
+ bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, char err_out[256]);
void ED_view3d_offscreen_sky_color_get(struct Scene *scene, float sky_color[3]);
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 618fa44349e..fa349c4f006 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -589,8 +589,8 @@ DEF_ICON(MOD_WARP)
DEF_ICON(MOD_SKIN)
DEF_ICON(MOD_TRIANGULATE)
DEF_ICON(MOD_WIREFRAME)
+DEF_ICON(MOD_DATA_TRANSFER)
#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK167)
DEF_ICON(BLANK168)
DEF_ICON(BLANK169)
DEF_ICON(BLANK170)
@@ -876,8 +876,8 @@ DEF_ICON(FORWARD)
DEF_ICON(BLANK312)
DEF_ICON(BLANK313)
DEF_ICON(BLANK314)
- DEF_ICON(BLANK315)
#endif
+DEF_ICON(FILE_HIDDEN)
DEF_ICON(FILE_BACKUP)
DEF_ICON(DISK_DRIVE)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index d93872d81ff..8789e837f17 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -159,31 +159,32 @@ enum {
/* but->flag - general state flags. */
enum {
/* warning, the first 6 flags are internal */
- UI_BUT_ICON_SUBMENU = (1 << 6),
- UI_BUT_ICON_PREVIEW = (1 << 7),
-
- UI_BUT_NODE_LINK = (1 << 8),
- UI_BUT_NODE_ACTIVE = (1 << 9),
- UI_BUT_DRAG_LOCK = (1 << 10),
- UI_BUT_DISABLED = (1 << 11),
- UI_BUT_COLOR_LOCK = (1 << 12),
- UI_BUT_ANIMATED = (1 << 13),
- UI_BUT_ANIMATED_KEY = (1 << 14),
- UI_BUT_DRIVEN = (1 << 15),
- UI_BUT_REDALERT = (1 << 16),
- UI_BUT_INACTIVE = (1 << 17),
- UI_BUT_LAST_ACTIVE = (1 << 18),
- UI_BUT_UNDO = (1 << 19),
- UI_BUT_IMMEDIATE = (1 << 20),
- UI_BUT_NO_UTF8 = (1 << 21),
-
- UI_BUT_VEC_SIZE_LOCK = (1 << 22), /* used to flag if color hsv-circle should keep luminance */
- UI_BUT_COLOR_CUBIC = (1 << 23), /* cubic saturation for the color wheel */
- UI_BUT_LIST_ITEM = (1 << 24), /* This but is "inside" a list item (currently used to change theme colors). */
- 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 */
+ UI_BUT_ICON_SUBMENU = (1 << 6),
+ UI_BUT_ICON_PREVIEW = (1 << 7),
+
+ UI_BUT_NODE_LINK = (1 << 8),
+ UI_BUT_NODE_ACTIVE = (1 << 9),
+ UI_BUT_DRAG_LOCK = (1 << 10),
+ UI_BUT_DISABLED = (1 << 11),
+ UI_BUT_COLOR_LOCK = (1 << 12),
+ UI_BUT_ANIMATED = (1 << 13),
+ UI_BUT_ANIMATED_KEY = (1 << 14),
+ UI_BUT_DRIVEN = (1 << 15),
+ UI_BUT_REDALERT = (1 << 16),
+ UI_BUT_INACTIVE = (1 << 17),
+ UI_BUT_LAST_ACTIVE = (1 << 18),
+ UI_BUT_UNDO = (1 << 19),
+ UI_BUT_IMMEDIATE = (1 << 20),
+ UI_BUT_NO_UTF8 = (1 << 21),
+
+ UI_BUT_VEC_SIZE_LOCK = (1 << 22), /* used to flag if color hsv-circle should keep luminance */
+ UI_BUT_COLOR_CUBIC = (1 << 23), /* cubic saturation for the color wheel */
+ UI_BUT_LIST_ITEM = (1 << 24), /* This but is "inside" a list item (currently used to change theme colors). */
+ 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 */
+ UI_BUT_TEXTEDIT_UPDATE = (1 << 29), /* when widget is in textedit mode, update value on each char stroke */
};
#define UI_PANEL_WIDTH 340
@@ -266,12 +267,12 @@ typedef enum {
UI_BTYPE_CURVE = (32 << 9),
UI_BTYPE_LISTBOX = (36 << 9),
UI_BTYPE_LISTROW = (37 << 9),
+ UI_BTYPE_HSVCIRCLE = (38 << 9),
UI_BTYPE_TRACK_PREVIEW = (40 << 9),
/* buttons with value >= UI_BTYPE_SEARCH_MENU don't get undo pushes */
UI_BTYPE_SEARCH_MENU = (41 << 9),
UI_BTYPE_EXTRA = (42 << 9),
- UI_BTYPE_HSVCIRCLE = (43 << 9),
UI_BTYPE_HOTKEY_EVENT = (46 << 9),
UI_BTYPE_IMAGE = (47 << 9), /* non-interactive image, used for splash screen */
UI_BTYPE_HISTOGRAM = (48 << 9),
@@ -313,6 +314,7 @@ void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx,
void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad);
void UI_draw_roundbox_shade_x(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
void UI_draw_roundbox_shade_y(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight);
+void UI_draw_text_underline(int pos_x, int pos_y, int len, int height);
/* state for scrolldrawing */
#define UI_SCROLL_PRESSED (1 << 0)
@@ -945,6 +947,7 @@ void uiItemS(uiLayout *layout); /* separator */
void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg);
void uiItemMenuEnumO(uiLayout *layout, struct bContext *C, const char *opname, const char *propname, const char *name, int icon);
+void uiItemMenuEnumR_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon);
void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon);
/* UI Operators */
@@ -999,6 +1002,7 @@ void UI_butstore_free(uiBlock *block, uiButStore *bs);
bool UI_butstore_is_valid(uiButStore *bs);
bool UI_butstore_is_registered(uiBlock *block, uiBut *but);
void UI_butstore_register(uiButStore *bs_handle, uiBut **but_p);
+bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *but_src);
void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p);
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 6104505ef58..74927428363 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -33,6 +33,7 @@
#define __UI_INTERFACE_ICONS_H__
struct bContext;
+struct ID;
struct Image;
struct ImBuf;
struct World;
@@ -63,6 +64,9 @@ void UI_icons_init(int first_dyn_id);
int UI_icon_get_width(int icon_id);
int UI_icon_get_height(int icon_id);
+void UI_id_icon_render(
+ const struct bContext *C, struct Scene *scene, struct ID *id, const bool big, const bool use_job);
+
void UI_icon_draw(float x, float y, int icon_id);
void UI_icon_draw_preview(float x, float y, int icon_id);
void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 8e37e871501..d289e90c257 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -111,6 +111,8 @@ enum {
TH_FACE_DOT,
TH_FACEDOT_SIZE,
TH_CFRAME,
+ TH_TIME_KEYFRAME,
+ TH_TIME_GP_KEYFRAME,
TH_NURB_ULINE,
TH_NURB_VLINE,
TH_NURB_SEL_ULINE,
@@ -207,6 +209,10 @@ enum {
TH_HANDLE_VERTEX_SELECT,
TH_HANDLE_VERTEX_SIZE,
+ TH_GP_VERTEX,
+ TH_GP_VERTEX_SELECT,
+ TH_GP_VERTEX_SIZE,
+
TH_DOPESHEET_CHANNELOB,
TH_DOPESHEET_CHANNELSUBOB,
@@ -266,7 +272,7 @@ enum {
TH_NLA_SOUND,
TH_NLA_SOUND_SEL,
- TH_EMBOSS,
+ TH_WIDGET_EMBOSS,
TH_AXIS_X, /* X/Y/Z Axis */
TH_AXIS_Y,
@@ -295,6 +301,11 @@ enum {
struct bTheme;
struct PointerRNA;
+struct bThemeState {
+ struct bTheme *theme;
+ int spacetype, regionid;
+};
+
// THE CODERS API FOR THEMES:
// sets the color
@@ -354,6 +365,9 @@ void UI_SetTheme(int spacetype, int regionid);
// get current theme
struct bTheme *UI_GetTheme(void);
+void UI_Theme_Store(struct bThemeState *theme_state);
+void UI_Theme_Restore(struct bThemeState *theme_state);
+
// return shadow width outside menus and popups */
int UI_ThemeMenuShadowWidth(void);
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index b921d17104c..972eca747b9 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -71,6 +71,12 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
+if(WIN32)
+ if(WITH_INPUT_IME)
+ add_definitions(-DWITH_INPUT_IME)
+ endif()
+endif()
+
add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_editor_interface "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/interface/SConscript b/source/blender/editors/interface/SConscript
index 303ab7ff286..5af8bba5a9f 100644
--- a/source/blender/editors/interface/SConscript
+++ b/source/blender/editors/interface/SConscript
@@ -48,6 +48,10 @@ incs = [
defs = env['BF_GL_DEFINITIONS']
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'win64-mingw'):
+ if env['WITH_BF_IME']:
+ defs.append('WITH_INPUT_IME')
+
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 93f5a8e58d6..0b1d1c8c30c 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -209,6 +209,11 @@ void ui_window_to_region(const ARegion *ar, int *x, int *y)
*y -= ar->winrct.ymin;
}
+void ui_region_to_window(const ARegion *ar, int *x, int *y)
+{
+ *x += ar->winrct.xmin;
+ *y += ar->winrct.ymin;
+}
/* ******************* block calc ************************* */
void ui_block_translate(uiBlock *block, int x, int y)
@@ -723,6 +728,10 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBu
ui_but_update_linklines(block, oldbut, but);
+ if (!BLI_listbase_is_empty(&block->butstore)) {
+ UI_butstore_register_update(block, oldbut, but);
+ }
+
/* move/copy string from the new button to the old */
/* needed for alt+mouse wheel over enums */
if (but->str != but->strdata) {
@@ -1712,6 +1721,9 @@ bool ui_but_is_bool(const uiBut *but)
if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_BOOLEAN)
return true;
+ if ((but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) && (but->type == UI_BTYPE_ROW))
+ return true;
+
return false;
}
@@ -2152,6 +2164,32 @@ bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double
return ok;
}
+/* just the assignment/free part */
+static void ui_but_string_set_internal(uiBut *but, const char *str, size_t str_len)
+{
+ BLI_assert(str_len == strlen(str));
+ BLI_assert(but->str == NULL);
+ str_len += 1;
+
+ if (str_len > UI_MAX_NAME_STR) {
+ but->str = MEM_mallocN(str_len, "ui_def_but str");
+ }
+ else {
+ but->str = but->strdata;
+ }
+ memcpy(but->str, str, str_len);
+}
+
+static void ui_but_string_free_internal(uiBut *but)
+{
+ if (but->str) {
+ if (but->str != but->strdata) {
+ MEM_freeN(but->str);
+ }
+ /* must call 'ui_but_string_set_internal' after */
+ but->str = NULL;
+ }
+}
bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
{
@@ -2599,9 +2637,13 @@ void ui_but_update(uiBut *but)
UI_GET_BUT_VALUE_INIT(but, value);
if (value < (double)but->hardmin) ui_but_value_set(but, but->hardmin);
else if (value > (double)but->hardmax) ui_but_value_set(but, but->hardmax);
+
+ /* max must never be smaller than min! Both being equal is allowed though */
+ BLI_assert(but->softmin <= but->softmax &&
+ but->hardmin <= but->hardmax);
break;
- case UI_BTYPE_ICON_TOGGLE:
+ case UI_BTYPE_ICON_TOGGLE:
case UI_BTYPE_ICON_TOGGLE_N:
if (!but->rnaprop || (RNA_property_flag(but->rnaprop) & PROP_ICONS_CONSECUTIVE)) {
if (but->flag & UI_SELECT) but->iconadd = 1;
@@ -2631,7 +2673,9 @@ void ui_but_update(uiBut *but)
if (RNA_property_enum_name_gettexted(but->block->evil_C,
&but->rnapoin, but->rnaprop, value, &buf))
{
- BLI_strncpy(but->str, buf, sizeof(but->strdata));
+ size_t slen = strlen(buf);
+ ui_but_string_free_internal(but);
+ ui_but_string_set_internal(but, buf, slen);
}
}
}
@@ -3039,13 +3083,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
but->retval = retval;
slen = strlen(str);
- if (slen >= UI_MAX_NAME_STR) {
- but->str = MEM_mallocN(slen + 1, "ui_def_but str");
- }
- else {
- but->str = but->strdata;
- }
- memcpy(but->str, str, slen + 1);
+ ui_but_string_set_internal(but, str, slen);
but->rect.xmin = x;
but->rect.ymin = y;
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 7e7806f6ada..24a30ebe3d8 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -34,13 +34,11 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
-#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_animsys.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_nla.h"
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 4dd952f0753..bcd9b9a5547 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -395,6 +395,12 @@ void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad)
ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA);
}
+void UI_draw_text_underline(int pos_x, int pos_y, int len, int height)
+{
+ int ofs_y = 4 * U.pixelsize;
+ glRecti(pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
+}
+
/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 7fed3772389..d7a4720d595 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -40,6 +40,7 @@
#include "BKE_screen.h"
#include "BKE_report.h"
#include "BKE_idcode.h"
+#include "BKE_unit.h"
#include "RNA_access.h"
@@ -64,6 +65,42 @@
#include "ED_screen.h"
#include "ED_view3d.h"
+/* -------------------------------------------------------------------- */
+/* Utility Functions
+ */
+/** \name Generic Shared Functions
+ * \{ */
+
+static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, const char *name)
+{
+ int width;
+ wmWindow *win = CTX_wm_window(C);
+ int x = win->eventstate->x;
+ int y = win->eventstate->y;
+
+ if ((name[0] == '\0') ||
+ (BLI_rcti_isect_pt(&ar->winrct, x, y) == false))
+ {
+ return;
+ }
+
+ width = UI_fontstyle_string_width(name);
+ x = x - ar->winrct.xmin;
+ y = y - ar->winrct.ymin;
+
+ y += 20;
+
+ glColor4ub(0, 0, 0, 50);
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL | UI_RB_ALPHA);
+ UI_draw_roundbox(x, y, x + width + 8, y + 15, 4);
+
+ glColor4ub(255, 255, 255, 255);
+ UI_draw_string(x + 4, y + 4, name);
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
/* Eyedropper
@@ -328,7 +365,7 @@ void UI_OT_eyedropper_color(wmOperatorType *ot)
/* identifiers */
ot->name = "Eyedropper";
ot->idname = "UI_OT_eyedropper_color";
- ot->description = "Sample a color from the Blender Window to store in a property";
+ ot->description = "Sample a data-block from the 3D view";
/* api callbacks */
ot->invoke = eyedropper_invoke;
@@ -369,31 +406,7 @@ typedef struct DataDropper {
static void datadropper_draw_cb(const struct bContext *C, ARegion *ar, void *arg)
{
DataDropper *ddr = arg;
- int width;
- const char *name = ddr->name;
- wmWindow *win = CTX_wm_window(C);
- int x = win->eventstate->x;
- int y = win->eventstate->y;
-
- if ((name[0] == '\0') ||
- (BLI_rcti_isect_pt(&ar->winrct, x, y) == false))
- {
- return;
- }
-
- width = UI_fontstyle_string_width(name);
- x = x - ar->winrct.xmin;
- y = y - ar->winrct.ymin;
-
- y += 20;
-
- glColor4ub(0, 0, 0, 50);
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL | UI_RB_ALPHA);
- UI_draw_roundbox(x, y, x + width + 8, y + 15, 4);
-
- glColor4ub(255, 255, 255, 255);
- UI_draw_string(x + 4, y + 4, name);
+ eyedropper_draw_cursor_text(C, ar, ddr->name);
}
@@ -643,3 +656,309 @@ void UI_OT_eyedropper_id(wmOperatorType *ot)
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/* Depth Dropper
+ *
+ * note: depthdropper is only internal name to avoid confusion in this file
+ */
+
+/** \name Eyedropper (Depth)
+ * \{ */
+
+typedef struct DepthDropper {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ bool accum_start; /* has mouse been presed */
+ float accum_depth;
+ int accum_tot;
+
+ ARegionType *art;
+ void *draw_handle_pixel;
+ char name[200];
+} DepthDropper;
+
+
+static void depthdropper_draw_cb(const struct bContext *C, ARegion *ar, void *arg)
+{
+ DepthDropper *ddr = arg;
+ eyedropper_draw_cursor_text(C, ar, ddr->name);
+}
+
+
+static int depthdropper_init(bContext *C, wmOperator *op)
+{
+ DepthDropper *ddr;
+ int index_dummy;
+
+ SpaceType *st;
+ ARegionType *art;
+
+ st = BKE_spacetype_from_id(SPACE_VIEW3D);
+ art = BKE_regiontype_from_id(st, RGN_TYPE_WINDOW);
+
+ op->customdata = ddr = MEM_callocN(sizeof(DepthDropper), "DepthDropper");
+
+ UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &index_dummy);
+
+ /* fallback to the active camera's dof */
+ if (ddr->prop == NULL) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (rv3d->persp == RV3D_CAMOB) {
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->camera && v3d->camera->data && (((ID *)v3d->camera->data)->lib == NULL)) {
+ RNA_id_pointer_create(v3d->camera->data, &ddr->ptr);
+ ddr->prop = RNA_struct_find_property(&ddr->ptr, "dof_distance");
+ }
+ }
+ }
+
+ if ((ddr->ptr.data == NULL) ||
+ (ddr->prop == NULL) ||
+ (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
+ (RNA_property_type(ddr->prop) != PROP_FLOAT))
+ {
+ return false;
+ }
+
+ ddr->art = art;
+ ddr->draw_handle_pixel = ED_region_draw_cb_activate(art, depthdropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);
+
+ return true;
+}
+
+static void depthdropper_exit(bContext *C, wmOperator *op)
+{
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ if (op->customdata) {
+ DepthDropper *ddr = (DepthDropper *)op->customdata;
+
+ if (ddr->art) {
+ ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel);
+ }
+
+ MEM_freeN(op->customdata);
+
+ op->customdata = NULL;
+ }
+}
+
+static void depthdropper_cancel(bContext *C, wmOperator *op)
+{
+ depthdropper_exit(C, op);
+}
+
+/* *** depthdropper id helper functions *** */
+/**
+ * \brief get the ID from the screen.
+ *
+ */
+static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth)
+{
+
+ /* we could use some clever */
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa;
+ Scene *scene = win->screen->scene;
+ UnitSettings *unit = &scene->unit;
+ const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
+
+ ScrArea *area_prev = CTX_wm_area(C);
+ ARegion *ar_prev = CTX_wm_region(C);
+
+ ddr->name[0] = '\0';
+
+ for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ View3D *v3d = sa->spacedata.first;
+ RegionView3D *rv3d = ar->regiondata;
+ /* weak, we could pass in some reference point */
+ const float *view_co = v3d->camera ? v3d->camera->obmat[3] : rv3d->viewinv[3];
+ const int mval[2] = {
+ mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+ float co[3];
+
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ /* grr, always draw else we leave stale text */
+ ED_region_tag_redraw(ar);
+
+ view3d_operator_needs_opengl(C);
+
+ if (ED_view3d_autodist(scene, ar, v3d, mval, co, true, NULL)) {
+ const float mval_center_fl[2] = {
+ (float)ar->winx / 2,
+ (float)ar->winy / 2};
+ float co_align[3];
+
+ /* quick way to get view-center aligned point */
+ ED_view3d_win_to_3d(ar, co, mval_center_fl, co_align);
+
+ *r_depth = len_v3v3(view_co, co_align);
+
+ bUnit_AsString(ddr->name, sizeof(ddr->name),
+ (double)*r_depth,
+ 4, unit->system, B_UNIT_LENGTH, do_split, false);
+ }
+ else {
+ BLI_strncpy(ddr->name, "Nothing under cursor", sizeof(ddr->name));
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ CTX_wm_area_set(C, area_prev);
+ CTX_wm_region_set(C, ar_prev);
+}
+
+/* sets the sample depth RGB, maintaining A */
+static void depthdropper_depth_set(bContext *C, DepthDropper *ddr, const float depth)
+{
+ RNA_property_float_set(&ddr->ptr, ddr->prop, depth);
+ RNA_property_update(C, &ddr->ptr, ddr->prop);
+}
+
+/* set sample from accumulated values */
+static void depthdropper_depth_set_accum(bContext *C, DepthDropper *ddr)
+{
+ float depth;
+ depth = ddr->accum_depth * 1.0f / (float)ddr->accum_tot;
+ depthdropper_depth_set(C, ddr, depth);
+}
+
+/* single point sample & set */
+static void depthdropper_depth_sample(bContext *C, DepthDropper *ddr, int mx, int my)
+{
+ float depth = -1.0f;
+ if (depth != -1.0f) {
+ depthdropper_depth_sample_pt(C, ddr, mx, my, &depth);
+ depthdropper_depth_set(C, ddr, depth);
+ }
+}
+
+static void depthdropper_depth_sample_accum(bContext *C, DepthDropper *ddr, int mx, int my)
+{
+ float depth = -1.0f;
+ depthdropper_depth_sample_pt(C, ddr, mx, my, &depth);
+ if (depth != -1.0f) {
+ ddr->accum_depth += depth;
+ ddr->accum_tot++;
+ }
+}
+
+/* main modal status check */
+static int depthdropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ DepthDropper *ddr = (DepthDropper *)op->customdata;
+
+ switch (event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ depthdropper_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ if (ddr->accum_tot == 0) {
+ depthdropper_depth_sample(C, ddr, event->x, event->y);
+ }
+ else {
+ depthdropper_depth_set_accum(C, ddr);
+ }
+ depthdropper_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else if (event->val == KM_PRESS) {
+ /* enable accum and make first sample */
+ ddr->accum_start = true;
+ depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
+ }
+ break;
+ case MOUSEMOVE:
+ if (ddr->accum_start) {
+ /* button is pressed so keep sampling */
+ depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
+ depthdropper_depth_set_accum(C, ddr);
+ }
+ break;
+ case SPACEKEY:
+ if (event->val == KM_RELEASE) {
+ ddr->accum_tot = 0;
+ ddr->accum_depth = 0.0f;
+ depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
+ depthdropper_depth_set_accum(C, ddr);
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Modal Operator init */
+static int depthdropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ /* init */
+ if (depthdropper_init(C, op)) {
+ WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ depthdropper_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+}
+
+/* Repeat operator */
+static int depthdropper_exec(bContext *C, wmOperator *op)
+{
+ /* init */
+ if (depthdropper_init(C, op)) {
+ /* cleanup */
+ depthdropper_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static int depthdropper_poll(bContext *C)
+{
+ if (!CTX_wm_window(C)) return 0;
+ else return 1;
+}
+
+void UI_OT_eyedropper_depth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Eyedropper Depth";
+ ot->idname = "UI_OT_eyedropper_depth";
+ ot->description = "Sample depth from the 3D view";
+
+ /* api callbacks */
+ ot->invoke = depthdropper_invoke;
+ ot->modal = depthdropper_modal;
+ ot->cancel = depthdropper_cancel;
+ ot->exec = depthdropper_exec;
+ ot->poll = depthdropper_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
+
+ /* properties */
+}
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index c841370a8fd..98b065dabcf 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -87,6 +87,10 @@
#include "WM_api.h"
#include "WM_types.h"
+#ifdef WITH_INPUT_IME
+# include "wm_window.h"
+#endif
+
/* place the mouse at the scaled down location when un-grabbing */
#define USE_CONT_MOUSE_CORRECT
/* support dragging toggle buttons */
@@ -103,6 +107,9 @@
#define UI_MAX_PASSWORD_STR 128
+/* This hack is needed because we don't have a good way to re-reference keymap items once added: T42944 */
+#define USE_KEYMAP_ADD_HACK
+
/* proto */
static void ui_but_smart_controller_add(bContext *C, uiBut *from, uiBut *to);
static void ui_but_link_add(bContext *C, uiBut *from, uiBut *to);
@@ -777,11 +784,18 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
ui_but_string_set(C, but, data->str);
ui_but_update(but);
- /* give butfunc the original text too */
- /* feature used for bone renaming, channels, etc */
- /* afterfunc frees origstr */
- but->rename_orig = data->origstr;
- data->origstr = NULL;
+ /* give butfunc a copy of the original text too.
+ * feature used for bone renaming, channels, etc.
+ * afterfunc frees rename_orig */
+ if (data->origstr && (but->flag & UI_BUT_TEXTEDIT_UPDATE)) {
+ /* In this case, we need to keep origstr available, to restore real org string in case we cancel after
+ * having typed something already. */
+ but->rename_orig = BLI_strdup(data->origstr);
+ }
+ else {
+ but->rename_orig = data->origstr;
+ data->origstr = NULL;
+ }
ui_apply_but_func(C, but);
data->retval = but->retval;
@@ -2425,8 +2439,52 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in
return changed;
}
+#ifdef WITH_INPUT_IME
+/* enable ime, and set up uibut ime data */
+static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but))
+{
+ /* XXX Is this really needed? */
+ int x, y;
+
+ BLI_assert(win->ime_data == NULL);
+
+ /* enable IME and position to cursor, it's a trick */
+ x = win->eventstate->x;
+ /* flip y and move down a bit, prevent the IME panel cover the edit button */
+ y = win->eventstate->y - 12;
+
+ wm_window_IME_begin(win, x, y, 0, 0, true);
+}
+
+/* disable ime, and clear uibut ime data */
+static void ui_textedit_ime_end(wmWindow *win, uiBut *UNUSED(but))
+{
+ wm_window_IME_end(win);
+}
+
+void ui_but_ime_reposition(uiBut *but, int x, int y, bool complete)
+{
+ BLI_assert(but->active);
+
+ ui_region_to_window(but->active->region, &x, &y);
+ wm_window_IME_begin(but->active->window, x, y - 4, 0, 0, complete);
+}
+
+/* should be ui_but_ime_data_get */
+wmIMEData *ui_but_get_ime_data(uiBut *but)
+{
+ if (but->active && but->active->window) {
+ return but->active->window->ime_data;
+ }
+ else {
+ return NULL;
+ }
+}
+#endif /* WITH_INPUT_IME */
+
static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
{
+ wmWindow *win = CTX_wm_window(C);
int len;
if (data->str) {
@@ -2482,12 +2540,18 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
but->flag &= ~UI_BUT_REDALERT;
ui_but_update(but);
-
- WM_cursor_modal_set(CTX_wm_window(C), BC_TEXTEDITCURSOR);
+
+ WM_cursor_modal_set(win, BC_TEXTEDITCURSOR);
+
+#ifdef WITH_INPUT_IME
+ ui_textedit_ime_begin(win, but);
+#endif
}
static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
{
+ wmWindow *win = CTX_wm_window(C);
+
if (but) {
if (ui_but_is_utf8(but)) {
int strip = BLI_utf8_invalid_strip(but->editstr, strlen(but->editstr));
@@ -2518,7 +2582,13 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
but->pos = -1;
}
- WM_cursor_modal_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(win);
+
+#ifdef WITH_INPUT_IME
+ if (win->ime_data) {
+ ui_textedit_ime_end(win, but);
+ }
+#endif
}
static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data)
@@ -2583,6 +2653,14 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
int retval = WM_UI_HANDLER_CONTINUE;
bool changed = false, inbox = false, update = false;
+#ifdef WITH_INPUT_IME
+ wmWindow *win = CTX_wm_window(C);
+ wmIMEData *ime_data = win->ime_data;
+ bool is_ime_composing = ime_data && ime_data->is_ime_composing;
+#else
+ bool is_ime_composing = false;
+#endif
+
switch (event->type) {
case MOUSEMOVE:
case MOUSEPAN:
@@ -2603,6 +2681,12 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
case RIGHTMOUSE:
case ESCKEY:
if (event->val == KM_PRESS) {
+#ifdef WITH_INPUT_IME
+ /* skips button handling since it is not wanted */
+ if (is_ime_composing) {
+ break;
+ }
+#endif
data->cancel = true;
data->escapecancel = true;
button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -2660,7 +2744,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
}
}
- if (event->val == KM_PRESS) {
+ if (event->val == KM_PRESS && !is_ime_composing) {
switch (event->type) {
case VKEY:
case XKEY:
@@ -2776,7 +2860,15 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
break;
}
- if ((event->ascii || event->utf8_buf[0]) && (retval == WM_UI_HANDLER_CONTINUE)) {
+ if ((event->ascii || event->utf8_buf[0]) &&
+ (retval == WM_UI_HANDLER_CONTINUE)
+#ifdef WITH_INPUT_IME
+ &&
+ !is_ime_composing &&
+ !WM_event_is_ime_switch(event)
+#endif
+ )
+ {
char ascii = event->ascii;
const char *utf8_buf = event->utf8_buf;
@@ -2806,10 +2898,30 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
retval = WM_UI_HANDLER_BREAK;
}
- /* textbutton with magnifier icon: do live update for search button */
- if (but->icon == ICON_VIEWZOOM)
+ /* textbutton with this flag: do live update (e.g. for search buttons) */
+ if (but->flag & UI_BUT_TEXTEDIT_UPDATE) {
update = true;
+ }
+ }
+
+#ifdef WITH_INPUT_IME
+ if (event->type == WM_IME_COMPOSITE_START || event->type == WM_IME_COMPOSITE_EVENT) {
+ changed = true;
+
+ if (event->type == WM_IME_COMPOSITE_START && but->selend > but->selsta) {
+ ui_textedit_delete_selection(but, data);
+ }
+ if (event->type == WM_IME_COMPOSITE_EVENT && ime_data->result_len) {
+ ui_textedit_type_buf(
+ but, data,
+ ime_data->str_result,
+ ime_data->result_len);
+ }
}
+ else if (event->type == WM_IME_COMPOSITE_END) {
+ changed = true;
+ }
+#endif
if (changed) {
/* only update when typing for TAB key */
@@ -3063,10 +3175,10 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
}
}
else if (data->state == BUTTON_STATE_WAIT_KEY_EVENT) {
-
- if (event->type == MOUSEMOVE)
+ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
return WM_UI_HANDLER_CONTINUE;
-
+ }
+
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
/* only cancel if click outside the button */
if (ui_but_contains_point_px(but->active->region, but, event->x, event->y) == 0) {
@@ -5694,6 +5806,10 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
return block;
}
+#ifdef USE_KEYMAP_ADD_HACK
+static int g_kmi_id_hack;
+#endif
+
static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -5734,7 +5850,10 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE);
UI_block_bounds_set_popup(block, 6, -50, 26);
-
+
+#ifdef USE_KEYMAP_ADD_HACK
+ g_kmi_id_hack = kmi_id;
+#endif
return block;
}
@@ -5743,9 +5862,20 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1)
uiBut *but = (uiBut *)arg1;
wmKeyMap *km;
wmKeyMapItem *kmi;
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
- int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
-
+#ifndef USE_KEYMAP_ADD_HACK
+ IDProperty *prop;
+#endif
+ int kmi_id;
+
+#ifdef USE_KEYMAP_ADD_HACK
+ km = WM_keymap_guess_opname(C, but->optype->idname);
+ kmi_id = g_kmi_id_hack;
+ UNUSED_VARS(but);
+#else
+ prop = (but->opptr) ? but->opptr->data : NULL;
+ kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
+#endif
+
kmi = WM_keymap_item_find_id(km, kmi_id);
WM_keymap_remove_item(km, kmi);
}
@@ -6161,6 +6291,16 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
}
}
+ else if (but->type == UI_BTYPE_NUM) {
+ if (but->rnaprop &&
+ (RNA_property_type(but->rnaprop) == PROP_FLOAT) &&
+ (RNA_property_subtype(but->rnaprop) & PROP_UNIT_LENGTH) &&
+ (RNA_property_array_check(but->rnaprop) == false))
+ {
+ WM_operator_name_call(C, "UI_OT_eyedropper_depth", WM_OP_INVOKE_DEFAULT, NULL);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
}
}
/* handle keyframing */
@@ -6256,6 +6396,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case UI_BTYPE_TOGGLE_N:
case UI_BTYPE_CHECKBOX:
case UI_BTYPE_CHECKBOX_N:
+ case UI_BTYPE_ROW:
retval = ui_do_but_TOG(C, but, data, event);
break;
case UI_BTYPE_SCROLL:
@@ -6278,7 +6419,6 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
break;
case UI_BTYPE_ROUNDBOX:
case UI_BTYPE_LABEL:
- case UI_BTYPE_ROW:
case UI_BTYPE_IMAGE:
case UI_BTYPE_PROGRESS_BAR:
case UI_BTYPE_NODE_SOCKET:
@@ -9087,6 +9227,7 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata)
ui_popup_block_free(C, menu);
UI_popup_handlers_remove(&win->modalhandlers, menu);
+ CTX_wm_menu_set(C, NULL);
#ifdef USE_DRAG_TOGGLE
{
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 51dd9166e46..679681cb372 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -51,6 +51,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_icons.h"
+#include "BKE_appdir.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -587,7 +588,7 @@ static void init_internal_icons(void)
#if 0 // temp disabled
if ((btheme != NULL) && btheme->tui.iconfile[0]) {
- char *icondir = BLI_get_folder(BLENDER_DATAFILES, "icons");
+ char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
char iconfilestr[FILE_MAX];
if (icondir) {
@@ -702,12 +703,12 @@ static void init_iconfile_list(struct ListBase *list)
const char *icondir;
BLI_listbase_clear(list);
- icondir = BLI_get_folder(BLENDER_DATAFILES, "icons");
+ icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
if (icondir == NULL)
return;
- totfile = BLI_dir_contents(icondir, &dir);
+ totfile = BLI_filelist_dir_contents(icondir, &dir);
for (i = 0; i < totfile; i++) {
if ((dir[i].type & S_IFREG)) {
@@ -755,7 +756,7 @@ static void init_iconfile_list(struct ListBase *list)
}
}
- BLI_free_filelist(dir, totfile);
+ BLI_filelist_free(dir, totfile, NULL);
dir = NULL;
}
@@ -930,7 +931,8 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
/* only called when icon has changed */
/* only call with valid pointer from UI_icon_draw */
-static void icon_set_image(bContext *C, ID *id, PreviewImage *prv_img, enum eIconSizes size)
+static void icon_set_image(
+ const bContext *C, Scene *scene, ID *id, PreviewImage *prv_img, enum eIconSizes size, const bool use_job)
{
if (!prv_img) {
if (G.debug & G_DEBUG)
@@ -940,8 +942,17 @@ static void icon_set_image(bContext *C, ID *id, PreviewImage *prv_img, enum eIco
icon_create_rect(prv_img, size);
- ED_preview_icon_job(C, prv_img, id, prv_img->rect[size],
- prv_img->w[size], prv_img->h[size]);
+ if (use_job) {
+ /* Job (background) version */
+ ED_preview_icon_job(C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
+ }
+ else {
+ if (!scene) {
+ scene = CTX_data_scene(C);
+ }
+ /* Immediate version */
+ ED_preview_icon_render(scene, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
+ }
}
PreviewImage *UI_icon_to_preview(int icon_id)
@@ -1148,29 +1159,30 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al
}
}
-static void ui_id_preview_image_render_size(bContext *C, ID *id, PreviewImage *pi, int size)
+static void ui_id_preview_image_render_size(
+ const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job)
{
if ((pi->changed[size] || !pi->rect[size])) { /* changed only ever set by dynamic icons */
/* create the rect if necessary */
- icon_set_image(C, id, pi, size);
+ icon_set_image(C, scene, id, pi, size, use_job);
pi->changed[size] = 0;
}
}
-static void ui_id_icon_render(bContext *C, ID *id, const bool big)
+void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big, const bool use_job)
{
PreviewImage *pi = BKE_previewimg_get(id);
if (pi) {
if (big)
- ui_id_preview_image_render_size(C, id, pi, ICON_SIZE_PREVIEW); /* bigger preview size */
+ ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_PREVIEW, use_job); /* bigger preview size */
else
- ui_id_preview_image_render_size(C, id, pi, ICON_SIZE_ICON); /* icon size */
+ ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_ICON, use_job); /* icon size */
}
}
-static void ui_id_brush_render(bContext *C, ID *id)
+static void ui_id_brush_render(const bContext *C, ID *id)
{
PreviewImage *pi = BKE_previewimg_get(id);
enum eIconSizes i;
@@ -1182,14 +1194,14 @@ static void ui_id_brush_render(bContext *C, ID *id)
/* check if rect needs to be created; changed
* only set by dynamic icons */
if ((pi->changed[i] || !pi->rect[i])) {
- icon_set_image(C, id, pi, i);
+ icon_set_image(C, NULL, id, pi, i, true);
pi->changed[i] = 0;
}
}
}
-static int ui_id_brush_get_icon(bContext *C, ID *id)
+static int ui_id_brush_get_icon(const bContext *C, ID *id)
{
Brush *br = (Brush *)id;
@@ -1242,7 +1254,7 @@ static int ui_id_brush_get_icon(bContext *C, ID *id)
return id->icon_id;
}
-int ui_id_icon_get(bContext *C, ID *id, const bool big)
+int ui_id_icon_get(const bContext *C, ID *id, const bool big)
{
int iconid = 0;
@@ -1258,7 +1270,7 @@ int ui_id_icon_get(bContext *C, ID *id, const bool big)
case ID_LA: /* fall through */
iconid = BKE_icon_getid(id);
/* checks if not exists, or changed */
- ui_id_icon_render(C, id, big);
+ UI_id_icon_render(C, NULL, id, big, true);
break;
default:
break;
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 328822e47ef..54ba3d784d1 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -433,6 +433,7 @@ extern void ui_block_to_window_rctf(const struct ARegion *ar, uiBlock *block, rc
extern void ui_window_to_block_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y);
extern void ui_window_to_block(const struct ARegion *ar, uiBlock *block, int *x, int *y);
extern void ui_window_to_region(const ARegion *ar, int *x, int *y);
+extern void ui_region_to_window(const struct ARegion *ar, int *x, int *y);
extern double ui_but_value_get(uiBut *but);
extern void ui_but_value_set(uiBut *but, double value);
@@ -627,6 +628,11 @@ void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa);
uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new);
uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new);
+#ifdef WITH_INPUT_IME
+void ui_but_ime_reposition(uiBut *but, int x, int y, bool complete);
+struct wmIMEData *ui_but_get_ime_data(uiBut *but);
+#endif
+
/* interface_widgets.c */
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);
@@ -653,7 +659,7 @@ void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *na
void uiStyleInit(void);
/* interface_icons.c */
-int ui_id_icon_get(struct bContext *C, struct ID *id, const bool big);
+int ui_id_icon_get(const struct bContext *C, struct ID *id, const bool big);
/* resources.c */
void init_userdef_do_versions(void);
@@ -688,5 +694,6 @@ void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, fl
/* interface_eyedropper.c */
void UI_OT_eyedropper_color(struct wmOperatorType *ot);
void UI_OT_eyedropper_id(struct wmOperatorType *ot);
+void UI_OT_eyedropper_depth(struct wmOperatorType *ot);
#endif /* __INTERFACE_INTERN_H__ */
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 2d952d66638..f02c6a234a9 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -904,7 +904,7 @@ 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;
+ uiLayout *split = NULL;
uiLayout *target;
if (radial) {
@@ -1450,8 +1450,8 @@ typedef struct CollItemSearch {
static int sort_search_items_list(const void *a, const void *b)
{
- CollItemSearch *cis1 = (CollItemSearch *)a;
- CollItemSearch *cis2 = (CollItemSearch *)b;
+ const CollItemSearch *cis1 = (CollItemSearch *)a;
+ const CollItemSearch *cis2 = (CollItemSearch *)b;
if (BLI_strcasecmp(cis1->name, cis2->name) > 0)
return 1;
@@ -1492,7 +1492,7 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, const char *s
BLI_strncpy(name_ui, id->name + 2, sizeof(name_ui));
#endif
name = BLI_strdup(name_ui);
- iconid = ui_id_icon_get((bContext *)C, id, false);
+ iconid = ui_id_icon_get(C, id, false);
}
else {
name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */
@@ -1922,17 +1922,9 @@ static void menu_item_enum_rna_menu(bContext *UNUSED(C), uiLayout *layout, void
layout->root->block->flag |= UI_BLOCK_IS_FLIP;
}
-void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon)
+void uiItemMenuEnumR_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon)
{
MenuItemLevel *lvl;
- PropertyRNA *prop;
-
- prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- ui_item_disabled(layout, propname);
- RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
if (!name)
name = RNA_property_ui_name(prop);
@@ -1941,12 +1933,26 @@ void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propn
lvl = MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel");
lvl->rnapoin = *ptr;
- BLI_strncpy(lvl->propname, propname, sizeof(lvl->propname));
+ BLI_strncpy(lvl->propname, RNA_property_identifier(prop), sizeof(lvl->propname));
lvl->opcontext = layout->root->opcontext;
ui_item_menu(layout, name, icon, menu_item_enum_rna_menu, NULL, lvl, RNA_property_description(prop), false);
}
+void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop) {
+ ui_item_disabled(layout, propname);
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ uiItemMenuEnumR_prop(layout, ptr, prop, name, icon);
+}
+
/**************************** Layout Items ***************************/
/* single-row layout */
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 4cb587bc1be..074faaa86bc 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -45,7 +45,6 @@
#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"
@@ -950,4 +949,5 @@ void ED_button_operatortypes(void)
/* external */
WM_operatortype_append(UI_OT_eyedropper_color);
WM_operatortype_append(UI_OT_eyedropper_id);
+ WM_operatortype_append(UI_OT_eyedropper_depth);
}
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index fc39b63a71d..e68c86353a3 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -753,9 +753,13 @@ static int find_highest_panel(const void *a1, const void *a2)
const PanelSort *ps1 = a1, *ps2 = a2;
/* stick uppermost header-less panels to the top of the region -
- * prevent them from being sorted */
- if (ps1->pa->sortorder < ps2->pa->sortorder && ps1->pa->type->flag & PNL_NO_HEADER) return -1;
-
+ * prevent them from being sorted (multiple header-less panels have to be sorted though) */
+ if (ps1->pa->type->flag & PNL_NO_HEADER && ps2->pa->type->flag & PNL_NO_HEADER) {
+ /* skip and check for ofs and sortorder below */
+ }
+ else if (ps1->pa->type->flag & PNL_NO_HEADER) return -1;
+ else if (ps2->pa->type->flag & PNL_NO_HEADER) return 1;
+
if (ps1->pa->ofsy + ps1->pa->sizey < ps2->pa->ofsy + ps2->pa->sizey) return 1;
else if (ps1->pa->ofsy + ps1->pa->sizey > ps2->pa->ofsy + ps2->pa->sizey) return -1;
else if (ps1->pa->sortorder > ps2->pa->sortorder) return 1;
@@ -1226,7 +1230,7 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
bool UI_panel_category_is_visible(ARegion *ar)
{
- /* more then one */
+ /* more than one */
return ar->panels_category.first && ar->panels_category.first != ar->panels_category.last;
}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 6a4bf230591..0ec59e4e4cd 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -27,8 +27,6 @@
* \ingroup edinterface
*/
-
-
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
@@ -54,7 +52,6 @@
#include "WM_types.h"
#include "wm_draw.h"
#include "wm_subwindow.h"
-#include "wm_window.h"
#include "RNA_access.h"
@@ -365,7 +362,8 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
/* special case enum rna buttons */
if ((but->type & UI_BTYPE_ROW) && but->rnaprop && RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG) {
- BLI_strncpy(data->lines[data->totline], IFACE_("(Shift-click to select multiple)"), sizeof(data->lines[0]));
+ BLI_strncpy(data->lines[data->totline], IFACE_("(Shift-Click/Drag to select multiple)"),
+ sizeof(data->lines[0]));
data->format[data->totline].color_id = UI_TIP_LC_NORMAL;
data->totline++;
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index d2aa463e3ff..8b2ce90dcf5 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -47,7 +47,9 @@
#include "BLF_api.h"
-#include "BLF_translation.h"
+#ifdef WITH_INTERNATIONAL
+# include "BLF_translation.h"
+#endif
#include "UI_interface.h"
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 95cb36a4672..407843d663c 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -31,7 +31,6 @@
#include "MEM_guardedalloc.h"
-#include "DNA_dynamicpaint_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -74,7 +73,6 @@
#include "ED_util.h"
#include "RNA_access.h"
-#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -156,7 +154,7 @@ static void id_search_cb(const bContext *C, void *arg_template, const char *str,
char name_ui[MAX_ID_NAME + 1];
name_uiprefix_id(name_ui, id);
- iconid = ui_id_icon_get((bContext *)C, id, template->preview);
+ iconid = ui_id_icon_get(C, id, template->preview);
if (false == UI_search_item_add(items, name_ui, id, iconid))
break;
@@ -352,6 +350,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_MC: return N_("Browse Movie Clip to be linked");
+ case ID_MSK: return N_("Browse Mask to be linked");
case ID_PAL: return N_("Browse Palette Data to be linked");
case ID_PC: return N_("Browse Paint Curve Data to be linked");
}
@@ -390,6 +390,10 @@ static const char *template_id_context(StructRNA *type)
case ID_BR: return BLF_I18NCONTEXT_ID_BRUSH;
case ID_PA: return BLF_I18NCONTEXT_ID_PARTICLESETTINGS;
case ID_GD: return BLF_I18NCONTEXT_ID_GPENCIL;
+ case ID_MC: return BLF_I18NCONTEXT_ID_MOVIECLIP;
+ case ID_MSK: return BLF_I18NCONTEXT_ID_MASK;
+ case ID_PAL: return BLF_I18NCONTEXT_ID_PALETTE;
+ case ID_PC: return BLF_I18NCONTEXT_ID_PAINTCURVE;
}
}
return BLF_I18NCONTEXT_DEFAULT;
@@ -473,11 +477,12 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
if (id->us > 1) {
char numstr[32];
+ short numstr_len;
- BLI_snprintf(numstr, sizeof(numstr), "%d", id->us);
+ numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", id->us);
- but = uiDefBut(block, UI_BTYPE_BUT, 0, numstr, 0, 0, UI_UNIT_X + ((id->us < 10) ? 0 : 10), UI_UNIT_Y,
- NULL, 0, 0, 0, 0,
+ but = uiDefBut(block, UI_BTYPE_BUT, 0, numstr, 0, 0,
+ numstr_len * 0.2f * UI_UNIT_X + UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
TIP_("Display number of users of this data (click to make a single-user copy)"));
but->flag |= UI_BUT_UNDO;
@@ -2667,7 +2672,7 @@ static void uilist_filter_items_default(struct uiList *ui_list, struct bContext
names = MEM_callocN(sizeof(StringCmp) * len, "StringCmp");
}
if (filter_raw[0]) {
- size_t idx = 0, slen = strlen(filter_raw);
+ size_t slen = strlen(filter_raw);
dyn_data->items_filter_flags = MEM_callocN(sizeof(int) * len, "items_filter_flags");
dyn_data->items_shown = 0;
@@ -2679,15 +2684,7 @@ static void uilist_filter_items_default(struct uiList *ui_list, struct bContext
else {
filter = filter_dyn = MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn");
}
- if (filter_raw[idx] != '*') {
- filter[idx++] = '*';
- }
- memcpy(filter + idx, filter_raw, slen);
- idx += slen;
- if (filter[idx - 1] != '*') {
- filter[idx++] = '*';
- }
- filter[idx] = '\0';
+ BLI_strncpy_ensure_pad(filter, filter_raw, '*', slen + 3);
}
RNA_PROP_BEGIN (dataptr, itemptr, prop)
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 854f1763370..28bd637ae59 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -83,13 +83,21 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
int arraylen = RNA_property_array_length(ptr, prop);
if (arraylen && index == -1) {
- if (ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA))
+ if (ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA)) {
but = uiDefButR_prop(block, UI_BTYPE_COLOR, 0, name, x1, y1, x2, y2, ptr, prop, -1, 0, 0, -1, -1, NULL);
+ }
+ else {
+ return NULL;
+ }
}
else if (RNA_property_subtype(prop) == PROP_PERCENTAGE || RNA_property_subtype(prop) == PROP_FACTOR)
but = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
else
but = uiDefButR_prop(block, UI_BTYPE_NUM, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+
+ if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
+ UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
+ }
break;
}
case PROP_ENUM:
@@ -107,6 +115,10 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
but = uiDefIconTextButR_prop(block, UI_BTYPE_TEXT, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
else
but = uiDefButR_prop(block, UI_BTYPE_TEXT, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+
+ if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
+ UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
+ }
break;
case PROP_POINTER:
{
@@ -390,6 +402,27 @@ void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p)
}
/**
+ * Update the pointer for a registered button.
+ */
+bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *but_src)
+{
+ uiButStore *bs_handle;
+ bool found = false;
+
+ for (bs_handle = block->butstore.first; bs_handle; bs_handle = bs_handle->next) {
+ uiButStoreElem *bs_elem;
+ for (bs_elem = bs_handle->items.first; bs_elem; bs_elem = bs_elem->next) {
+ if (*bs_elem->but_p == but_src) {
+ *bs_elem->but_p = but_dst;
+ found = true;
+ }
+ }
+ }
+
+ return found;
+}
+
+/**
* NULL all pointers, don't free since the owner needs to be able to inspect.
*/
void UI_butstore_clear(uiBlock *block)
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index c9def075666..04a886ba2a8 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -59,6 +59,10 @@
#include "interface_intern.h"
+#ifdef WITH_INPUT_IME
+# include "WM_types.h"
+#endif
+
/* icons are 80% of height of button (16 pixels inside 20 height) */
#define ICON_SIZE_FROM_BUTRECT(rect) (0.8f * BLI_rcti_size_y(rect))
@@ -757,10 +761,9 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
glDrawArrays(GL_QUAD_STRIP, 0, wtb->totvert * 2 + 2);
/* emboss bottom shadow */
- UI_GetThemeColor4ubv(TH_EMBOSS, emboss);
-
if (wtb->emboss) {
- UI_GetThemeColor4ubv(TH_EMBOSS, emboss);
+ UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss);
+
if (emboss[3]) {
glColor4ubv(emboss);
glVertexPointer(2, GL_FLOAT, 0, quad_strip_emboss);
@@ -1232,6 +1235,50 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
}
+#ifdef WITH_INPUT_IME
+static void widget_draw_text_ime_underline(
+ uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, const rcti *rect,
+ const wmIMEData *ime_data, const char *drawstr)
+{
+ int ofs_x, width;
+ int rect_x = BLI_rcti_size_x(rect);
+ int sel_start = ime_data->sel_start, sel_end = ime_data->sel_end;
+
+ if (drawstr[0] != 0) {
+ if (but->pos >= but->ofs) {
+ ofs_x = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->pos - but->ofs);
+ }
+ else {
+ ofs_x = 0;
+ }
+
+ width = BLF_width(fstyle->uifont_id, drawstr + but->ofs,
+ ime_data->composite_len + but->pos - but->ofs);
+
+ glColor4ubv((unsigned char *)wcol->text);
+ UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1);
+
+ /* draw the thick line */
+ if (sel_start != -1 && sel_end != -1) {
+ sel_end -= sel_start;
+ sel_start += but->pos;
+
+ if (sel_start >= but->ofs) {
+ ofs_x = BLF_width(fstyle->uifont_id, drawstr + but->ofs, sel_start - but->ofs);
+ }
+ else {
+ ofs_x = 0;
+ }
+
+ width = BLF_width(fstyle->uifont_id, drawstr + but->ofs,
+ sel_end + sel_start - but->ofs);
+
+ UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2);
+ }
+ }
+}
+#endif /* WITH_INPUT_IME */
+
static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
{
int drawstr_left_len = UI_MAX_DRAW_STR;
@@ -1239,6 +1286,10 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
const char *drawstr_right = NULL;
bool use_right_only = false;
+#ifdef WITH_INPUT_IME
+ const wmIMEData *ime_data;
+#endif
+
UI_fontstyle_set(fstyle);
if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT))
@@ -1266,13 +1317,30 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* max length isn't used in this case,
* we rely on string being NULL terminated. */
drawstr_left_len = INT_MAX;
- drawstr = but->editstr;
+
+#ifdef WITH_INPUT_IME
+ /* FIXME, IME is modifying 'const char *drawstr! */
+ ime_data = ui_but_get_ime_data(but);
+
+ if (ime_data && ime_data->composite_len) {
+ /* insert composite string into cursor pos */
+ BLI_snprintf((char *)drawstr, UI_MAX_DRAW_STR, "%s%s%s",
+ but->editstr, ime_data->str_composite,
+ but->editstr + but->pos);
+ }
+ else
+#endif
+ {
+ drawstr = but->editstr;
+ }
}
}
- /* text button selection and cursor */
+ /* text button selection, cursor, composite underline */
if (but->editstr && but->pos != -1) {
+ int but_pos_ofs;
+ int tx, ty;
/* text button selection */
if ((but->selend - but->selsta) > 0) {
@@ -1298,18 +1366,44 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
/* text cursor */
+ but_pos_ofs = but->pos;
+
+#ifdef WITH_INPUT_IME
+ /* if is ime compositing, move the cursor */
+ if (ime_data && ime_data->composite_len && ime_data->cursor_pos != -1) {
+ but_pos_ofs += ime_data->cursor_pos;
+ }
+#endif
+
if (but->pos >= but->ofs) {
int t;
if (drawstr[0] != 0) {
- t = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->pos - but->ofs);
+ t = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but_pos_ofs - but->ofs);
}
else {
t = 0;
}
glColor3f(0.20, 0.6, 0.9);
- glRecti(rect->xmin + t, rect->ymin + 2, rect->xmin + t + 2, rect->ymax - 2);
+
+ tx = rect->xmin + t + 2;
+ ty = rect->ymin + 2;
+
+ /* draw cursor */
+ glRecti(rect->xmin + t, ty, tx, rect->ymax - 2);
+ }
+
+#ifdef WITH_INPUT_IME
+ if (ime_data && ime_data->composite_len) {
+ /* ime cursor following */
+ if (but->pos >= but->ofs) {
+ ui_but_ime_reposition(but, tx + 5, ty + 3, false);
+ }
+
+ /* composite underline */
+ widget_draw_text_ime_underline(fstyle, wcol, but, rect, ime_data, drawstr);
}
+#endif
}
if (fstyle->kerning == 1)
@@ -2780,7 +2874,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
uiWidgetBase wtb, wtb1;
rcti rect1;
double value;
- float offs, toffs, fac;
+ float offs, toffs, fac = 0;
char outline[3];
widget_init(&wtb);
@@ -2811,7 +2905,9 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
rect1 = *rect;
value = ui_but_value_get(but);
- fac = ((float)value - but->softmin) * (BLI_rcti_size_x(&rect1) - offs) / (but->softmax - but->softmin);
+ if ((but->softmax - but->softmin) > 0) {
+ fac = ((float)value - but->softmin) * (BLI_rcti_size_x(&rect1) - offs) / (but->softmax - but->softmin);
+ }
/* left part of slider, always rounded */
rect1.xmax = rect1.xmin + ceil(offs + U.pixelsize);
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 5573515391d..aa5b2570952 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -45,6 +45,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BKE_appdir.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -60,9 +61,16 @@
/* global for themes */
typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
-static bTheme *theme_active = NULL;
-static int theme_spacetype = SPACE_VIEW3D;
-static int theme_regionid = RGN_TYPE_WINDOW;
+/* be sure to keep 'bThemeState' in sync */
+static struct bThemeState g_theme_state = {
+ NULL,
+ SPACE_VIEW3D,
+ RGN_TYPE_WINDOW,
+};
+
+#define theme_active g_theme_state.theme
+#define theme_spacetype g_theme_state.spacetype
+#define theme_regionid g_theme_state.regionid
void ui_resources_init(void)
{
@@ -371,6 +379,10 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->keyborder_select; break;
case TH_CFRAME:
cp = ts->cframe; break;
+ case TH_TIME_KEYFRAME:
+ cp = ts->time_keyframe; break;
+ case TH_TIME_GP_KEYFRAME:
+ cp = ts->time_gp_keyframe; break;
case TH_NURB_ULINE:
cp = ts->nurb_uline; break;
case TH_NURB_VLINE:
@@ -505,6 +517,17 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_HANDLE_VERTEX_SIZE:
cp = &ts->handle_vertex_size;
break;
+
+ case TH_GP_VERTEX:
+ cp = ts->gp_vertex;
+ break;
+ case TH_GP_VERTEX_SELECT:
+ cp = ts->gp_vertex_select;
+ break;
+ case TH_GP_VERTEX_SIZE:
+ cp = &ts->gp_vertex_size;
+ break;
+
case TH_DOPESHEET_CHANNELOB:
cp = ts->ds_channel;
break;
@@ -619,8 +642,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->nla_sound_sel;
break;
- case TH_EMBOSS:
- cp = btheme->tui.emboss; break;
+ case TH_WIDGET_EMBOSS:
+ cp = btheme->tui.widget_emboss; break;
case TH_AXIS_X:
cp = btheme->tui.xaxis; break;
@@ -663,7 +686,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
}
}
- return (unsigned char *)cp;
+ return (const unsigned char *)cp;
}
/* use this call to init new bone color sets in Theme */
@@ -820,7 +843,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tui.wcol_tooltip.text, 255, 255, 255, 255);
- rgba_char_args_set_fl(btheme->tui.emboss, 1.0f, 1.0f, 1.0f, 0.02f);
+ rgba_char_args_set_fl(btheme->tui.widget_emboss, 1.0f, 1.0f, 1.0f, 0.02f);
rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255);
rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255);
@@ -892,6 +915,9 @@ void ui_theme_init_default(void)
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);
+ rgba_char_args_set(btheme->tv3d.gp_vertex, 0, 0, 0, 255);
+ rgba_char_args_set(btheme->tv3d.gp_vertex_select, 255, 133, 0, 255);
+ btheme->tv3d.gp_vertex_size = 3;
btheme->tv3d.facedot_size = 4;
@@ -1111,6 +1137,9 @@ void ui_theme_init_default(void)
rgba_char_args_set_fl(btheme->ttime.grid, 0.36, 0.36, 0.36, 1.0);
rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); /* sliders */
+ rgba_char_args_set(btheme->ttime.time_keyframe, 0xDD, 0xD7, 0x00, 1.0);
+ rgba_char_args_set(btheme->ttime.time_gp_keyframe, 0xB5, 0xE6, 0x1D, 1.0);
+
/* space node, re-uses syntax and console color storage */
btheme->tnode = btheme->tv3d;
rgba_char_args_set(btheme->tnode.syntaxr, 115, 115, 115, 255); /* wire inner color */
@@ -1193,6 +1222,18 @@ bTheme *UI_GetTheme(void)
return U.themes.first;
}
+/**
+ * for the rare case we need to temp swap in a different theme (offscreen render)
+ */
+void UI_Theme_Store(struct bThemeState *theme_state)
+{
+ *theme_state = g_theme_state;
+}
+void UI_Theme_Restore(struct bThemeState *theme_state)
+{
+ g_theme_state = *theme_state;
+}
+
/* for space windows only */
void UI_ThemeColor(int colorid)
{
@@ -1534,7 +1575,7 @@ void init_userdef_do_versions(void)
}
if (U.mixbufsize == 0) U.mixbufsize = 2048;
if (strcmp(U.tempdir, "/") == 0) {
- BLI_system_temporary_dir(U.tempdir);
+ BKE_tempdir_system_init(U.tempdir);
}
if (U.autokey_mode == 0) {
/* 'add/replace' but not on */
@@ -2498,10 +2539,36 @@ void init_userdef_do_versions(void)
}
}
- if (U.versionfile < 272 || (U.versionfile == 272 && U.subversionfile < 2)) {
+ if (U.versionfile < 272 || (U.versionfile == 272 && U.subversionfile < 3)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set_fl(btheme->tui.emboss, 1.0f, 1.0f, 1.0f, 0.02f);
+ rgba_char_args_set_fl(btheme->tui.widget_emboss, 1.0f, 1.0f, 1.0f, 0.02f);
+ }
+ }
+
+ if (U.versionfile < 273 || (U.versionfile == 273 && U.subversionfile < 1)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ /* Grease Pencil vertex settings */
+ rgba_char_args_set(btheme->tv3d.gp_vertex, 0, 0, 0, 255);
+ rgba_char_args_set(btheme->tv3d.gp_vertex_select, 255, 133, 0, 255);
+ btheme->tv3d.gp_vertex_size = 3;
+
+ rgba_char_args_set(btheme->tseq.gp_vertex, 0, 0, 0, 255);
+ rgba_char_args_set(btheme->tseq.gp_vertex_select, 255, 133, 0, 255);
+ btheme->tseq.gp_vertex_size = 3;
+
+ rgba_char_args_set(btheme->tima.gp_vertex, 0, 0, 0, 255);
+ rgba_char_args_set(btheme->tima.gp_vertex_select, 255, 133, 0, 255);
+ btheme->tima.gp_vertex_size = 3;
+
+ rgba_char_args_set(btheme->tnode.gp_vertex, 0, 0, 0, 255);
+ rgba_char_args_set(btheme->tnode.gp_vertex_select, 255, 133, 0, 255);
+ btheme->tnode.gp_vertex_size = 3;
+
+ /* Timeline Keyframe Indicators */
+ rgba_char_args_set(btheme->ttime.time_keyframe, 0xDD, 0xD7, 0x00, 1.0);
+ rgba_char_args_set(btheme->ttime.time_gp_keyframe, 0xB5, 0xE6, 0x1D, 1.0);
}
}
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index f42e35945d7..de46d47e5a3 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -2305,7 +2305,7 @@ void UI_view2d_text_cache_add(View2D *v2d, float x, float y,
BLI_LINKS_PREPEND(g_v2d_strings, v2s);
- v2s->col.pack = *((int *)col);
+ v2s->col.pack = *((const int *)col);
memset(&v2s->rect, 0, sizeof(v2s->rect));
@@ -2336,7 +2336,7 @@ void UI_view2d_text_cache_add_rectf(View2D *v2d, const rctf *rect_view,
BLI_LINKS_PREPEND(g_v2d_strings, v2s);
- v2s->col.pack = *((int *)col);
+ v2s->col.pack = *((const int *)col);
v2s->rect = rect;
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index bbf4447dd72..491152b02e5 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -298,7 +298,7 @@ void WM_OT_collada_export(wmOperatorType *ot)
ot->ui = wm_collada_export_draw;
- WM_operator_properties_filesel(ot, FOLDERFILE | COLLADAFILE, FILE_BLENDER, FILE_SAVE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_COLLADA, FILE_BLENDER, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
RNA_def_boolean(ot->srna,
@@ -365,6 +365,9 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
{
char filename[FILE_MAX];
int import_units;
+ int find_chains;
+ int fix_orientation;
+ int min_chain_length;
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
BKE_report(op->reports, RPT_ERROR, "No filename given");
@@ -372,10 +375,19 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
}
/* Options panel */
- import_units = RNA_boolean_get(op->ptr, "import_units");
+ import_units = RNA_boolean_get(op->ptr, "import_units");
+ find_chains = RNA_boolean_get(op->ptr, "find_chains");
+ fix_orientation = RNA_boolean_get(op->ptr, "fix_orientation");
+ min_chain_length = RNA_int_get(op->ptr, "min_chain_length");
RNA_string_get(op->ptr, "filepath", filename);
- if (collada_import(C, filename, import_units)) {
+ if (collada_import(
+ C, filename,
+ import_units,
+ find_chains,
+ fix_orientation,
+ min_chain_length))
+ {
return OPERATOR_FINISHED;
}
else {
@@ -395,6 +407,19 @@ static void uiCollada_importSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "import_units", 0, NULL, ICON_NONE);
+
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Armature Options:"), ICON_MESH_DATA);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "fix_orientation", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "find_chains", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "min_chain_length", 0, NULL, ICON_NONE);
}
static void wm_collada_import_draw(bContext *UNUSED(C), wmOperator *op)
@@ -419,13 +444,31 @@ void WM_OT_collada_import(wmOperatorType *ot)
ot->ui = wm_collada_import_draw;
- WM_operator_properties_filesel(ot, FOLDERFILE | COLLADAFILE, FILE_BLENDER, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_COLLADA, FILE_BLENDER, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
RNA_def_boolean(ot->srna,
- "import_units", 0, "Import Units",
- "If disabled match import to Blender's current Unit settings, "
- "otherwise use the settings from the Imported scene");
+ "import_units", 0, "Import Units",
+ "If disabled match import to Blender's current Unit settings, "
+ "otherwise use the settings from the Imported scene");
+
+ RNA_def_boolean(ot->srna,
+ "fix_orientation", 0, "Fix Leaf Bones",
+ "Fix Orientation of Leaf Bones (Collada does only support Joints)");
+
+ RNA_def_boolean(ot->srna,
+ "find_chains", 0, "Find Bone Chains",
+ "Find best matching Bone Chains and ensure bones in chain are connected");
+
+ RNA_def_int(ot->srna,
+ "min_chain_length",
+ 0,
+ 0,
+ INT_MAX,
+ "Minimum Chain Length",
+ "When searching Bone Chains disregard chains of length below this value",
+ 0,
+ INT_MAX);
}
#endif
diff --git a/source/blender/editors/io/io_ops.c b/source/blender/editors/io/io_ops.c
index a33340cc39a..a70a51a60be 100644
--- a/source/blender/editors/io/io_ops.c
+++ b/source/blender/editors/io/io_ops.c
@@ -28,16 +28,13 @@
* \ingroup collada
*/
-
-#include "io_collada.h"
-
-#include "BLI_utildefines.h"
-
-#include "WM_types.h"
-#include "WM_api.h"
-
#include "io_ops.h" /* own include */
+#ifdef WITH_COLLADA
+# include "io_collada.h"
+# include "WM_api.h"
+#endif
+
void ED_operatortypes_io(void)
{
#ifdef WITH_COLLADA
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 93e59f3244e..929c4f74b2f 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -784,7 +784,7 @@ static int slide_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
SlidePointData *slidedata;
if (mask == NULL) {
- return OPERATOR_CANCELLED;
+ return OPERATOR_PASS_THROUGH;
}
slidedata = slide_point_customdata(C, op, event);
@@ -1286,7 +1286,7 @@ static int slide_spline_curvature_invoke(bContext *C, wmOperator *op, const wmEv
SlideSplineCurvatureData *slide_data;
if (mask == NULL) {
- return OPERATOR_CANCELLED;
+ return OPERATOR_PASS_THROUGH;
}
/* Be sure we don't conflict with point slide here. */
diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c
index e02561d839c..4e0aa8f84ae 100644
--- a/source/blender/editors/mask/mask_relationships.c
+++ b/source/blender/editors/mask/mask_relationships.c
@@ -39,7 +39,6 @@
#include "BKE_tracking.h"
#include "DNA_mask_types.h"
-#include "DNA_object_types.h" /* SELECT */
#include "WM_api.h"
#include "WM_types.h"
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 87b429f1165..113f0f71b53 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -31,8 +31,6 @@
#include "BLI_math.h"
#include "BLI_bitmap.h"
-#include "BLF_translation.h"
-
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 3e403387a67..9b1b0b915c1 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -54,18 +54,6 @@
#include "mesh_intern.h" /* own include */
-/* allow accumulated normals to form a new direction but don't
- * accept direct opposite directions else they will cancel each other out */
-static void add_normal_aligned(float nor[3], const float add[3])
-{
- if (dot_v3v3(nor, add) < -0.9999f) {
- sub_v3_v3(nor, add);
- }
- else {
- add_v3_v3(nor, add);
- }
-}
-
static void edbm_extrude_edge_exclude_mirror(
Object *obedit, BMEditMesh *em,
const char hflag,
@@ -137,7 +125,7 @@ static void edbm_extrude_edge_exclude_mirror(
/* 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))
+static bool edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const char hflag)
{
BMOIter siter;
BMIter liter;
@@ -165,14 +153,14 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c
}
if (!EDBM_op_finish(em, &bmop, op, true)) {
- return 0;
+ return false;
}
- return 's'; /* s is shrink/fatten */
+ return true;
}
/* extrudes individual edges */
-static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
+static bool edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char hflag)
{
BMesh *bm = em->bm;
BMOperator bmop;
@@ -191,14 +179,14 @@ static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
if (!EDBM_op_finish(em, &bmop, op, true)) {
- return 0;
+ return false;
}
- return 'n'; /* n is normal grab */
+ return true;
}
/* extrudes individual vertices */
-static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
+static bool edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char hflag)
{
BMOperator bmop;
@@ -214,27 +202,55 @@ static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
if (!EDBM_op_finish(em, &bmop, op, true)) {
- return 0;
+ return false;
+ }
+
+ return true;
+}
+
+static char edbm_extrude_htype_from_em_select(BMEditMesh *em)
+{
+ char htype = BM_ALL_NOLOOP;
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ /* pass */
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ htype &= ~BM_VERT;
+ }
+ else {
+ htype &= ~(BM_VERT | BM_EDGE);
+ }
+
+ if (em->bm->totedgesel == 0) {
+ htype &= ~(BM_EDGE | BM_FACE);
+ }
+ else if (em->bm->totfacesel == 0) {
+ htype &= ~BM_FACE;
}
- return 'g'; /* g is grab */
+ return htype;
}
-static short edbm_extrude_edge_ex(
+static bool edbm_extrude_ex(
Object *obedit, BMEditMesh *em,
- const char hflag, float nor[3],
+ char htype, const char hflag,
const bool use_mirror,
const bool use_select_history)
{
BMesh *bm = em->bm;
BMOIter siter;
BMOperator extop;
- BMFace *f;
BMElem *ele;
+ /* needed to remove the faces left behind */
+ if (htype & BM_FACE) {
+ htype |= BM_EDGE;
+ }
+
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);
+ BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", htype, hflag);
if (use_mirror) {
BMOpSlot *slot_edges_exclude;
@@ -248,61 +264,14 @@ static short edbm_extrude_edge_ex(
BM_SELECT_HISTORY_RESTORE(bm);
BMO_op_exec(bm, &extop);
-
- zero_v3(nor);
- BMO_ITER (ele, &siter, extop.slots_out, "geom.out", BM_ALL) {
+ BMO_ITER (ele, &siter, extop.slots_out, "geom.out", BM_ALL_NOLOOP) {
BM_elem_select_set(bm, ele, true);
-
- if (ele->head.htype == BM_FACE) {
- f = (BMFace *)ele;
- add_normal_aligned(nor, f->no);
- }
}
- normalize_v3(nor);
-
BMO_op_finish(bm, &extop);
- /* grab / normal constraint */
- 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;
- BMEdge *eed;
-
- /* ensure vert flags are consistent for edge selections */
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, hflag)) {
- if (hflag & BM_ELEM_SELECT) {
- BM_vert_select_set(em->bm, eed->v1, true);
- BM_vert_select_set(em->bm, eed->v2, true);
- }
-
- BM_elem_flag_enable(eed->v1, hflag & ~BM_ELEM_SELECT);
- BM_elem_flag_enable(eed->v2, hflag & ~BM_ELEM_SELECT);
- }
- else {
- if (BM_elem_flag_test(eed->v1, hflag) && BM_elem_flag_test(eed->v2, hflag)) {
- if (hflag & BM_ELEM_SELECT) {
- BM_edge_select_set(em->bm, eed, true);
- }
-
- BM_elem_flag_enable(eed, hflag & ~BM_ELEM_SELECT);
- }
- }
- }
-
- return edbm_extrude_edge(obedit, em, hflag, nor);
+ return true;
}
static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
@@ -314,7 +283,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
const int steps = RNA_int_get(op->ptr, "steps");
const float offs = RNA_float_get(op->ptr, "offset");
- float dvec[3], tmat[3][3], bmat[3][3], nor[3] = {0.0, 0.0, 0.0};
+ float dvec[3], tmat[3][3], bmat[3][3];
short a;
/* dvec */
@@ -327,7 +296,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
mul_m3_v3(tmat, dvec);
for (a = 0; a < steps; a++) {
- edbm_extrude_edge_ex(obedit, em, BM_ELEM_SELECT, nor, false, false);
+ edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false);
BMO_op_callf(
em->bm, BMO_FLAG_DEFAULTS,
@@ -362,87 +331,58 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
}
/* generic extern called extruder */
-static int edbm_extrude_mesh(Scene *scene, Object *obedit, BMEditMesh *em, wmOperator *op, float *norin)
+static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op)
{
- short nr, transmode = 0;
- float stacknor[3] = {0.0f, 0.0f, 0.0f};
- float *nor = norin ? norin : stacknor;
-
- zero_v3(nor);
+ bool changed = false;
+ const char htype = edbm_extrude_htype_from_em_select(em);
+ enum {NONE = 0, ELEM_FLAG, VERT_ONLY, EDGE_ONLY} nr;
if (em->selectmode & SCE_SELECT_VERTEX) {
- if (em->bm->totvertsel == 0) nr = 0;
- else if (em->bm->totvertsel == 1) nr = 4;
- else if (em->bm->totedgesel == 0) nr = 4;
- else if (em->bm->totfacesel == 0)
- nr = 3;
- else if (em->bm->totfacesel == 1)
- nr = 1;
- else
- nr = 1;
+ if (em->bm->totvertsel == 0) nr = NONE;
+ else if (em->bm->totvertsel == 1) nr = VERT_ONLY;
+ else if (em->bm->totedgesel == 0) nr = VERT_ONLY;
+ else nr = ELEM_FLAG;
}
else if (em->selectmode & SCE_SELECT_EDGE) {
- if (em->bm->totedgesel == 0) nr = 0;
-
- nr = 1;
+ if (em->bm->totedgesel == 0) nr = NONE;
+ else if (em->bm->totfacesel == 0) nr = EDGE_ONLY;
+ else nr = ELEM_FLAG;
}
else {
- if (em->bm->totfacesel == 0) nr = 0;
- else if (em->bm->totfacesel == 1) nr = 1;
- else
- nr = 1;
+ if (em->bm->totfacesel == 0) nr = NONE;
+ else nr = ELEM_FLAG;
}
- if (nr < 1) return 'g';
-
- if (nr == 1 && (em->selectmode & SCE_SELECT_VERTEX))
- transmode = edbm_extrude_vert(obedit, em, BM_ELEM_SELECT, nor);
- else if (nr == 1) transmode = edbm_extrude_edge(obedit, em, BM_ELEM_SELECT, nor);
- else if (nr == 4) transmode = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT, nor);
- else if (nr == 3) transmode = edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT, nor);
- else transmode = edbm_extrude_discrete_faces(em, op, BM_ELEM_SELECT, nor);
+ switch (nr) {
+ case NONE:
+ return false;
+ case ELEM_FLAG:
+ changed = edbm_extrude_ex(obedit, em, htype, BM_ELEM_SELECT, true, true);
+ break;
+ case VERT_ONLY:
+ changed = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT);
+ break;
+ case EDGE_ONLY:
+ changed = edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT);
+ break;
+ }
- if (transmode == 0) {
- BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
+ if (changed) {
+ return true;
}
else {
-
- /* We need to force immediate calculation here because
- * transform may use derived objects (which are now stale).
- *
- * This shouldn't be necessary, derived queries should be
- * automatically building this data if invalid. Or something.
- */
-// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
- BKE_object_handle_update(G.main->eval_ctx, scene, obedit);
-
- /* individual faces? */
- if (nr == 2) {
-// initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR);
-// Transform();
- }
- else {
-// initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR);
- if (transmode == 'n') {
- mul_m4_v3(obedit->obmat, nor);
- sub_v3_v3v3(nor, nor, obedit->obmat[3]);
-// BIF_setSingleAxisConstraint(nor, "along normal");
- }
-// Transform();
- }
+ BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
+ return false;
}
-
- return transmode;
}
/* extrude without transform */
static int edbm_extrude_region_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- edbm_extrude_mesh(scene, obedit, em, op, NULL);
+ edbm_extrude_mesh(obedit, em, op);
/* This normally happens when pushing undo but modal operators
* like this one don't push undo data until after modal mode is
@@ -476,9 +416,8 @@ static int edbm_extrude_verts_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- float nor[3];
- edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT, nor);
+ edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT);
EDBM_update_generic(em, true, true);
@@ -507,9 +446,8 @@ static int edbm_extrude_edges_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- float nor[3];
- edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT, nor);
+ edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT);
EDBM_update_generic(em, true, true);
@@ -538,9 +476,8 @@ static int edbm_extrude_faces_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- float nor[3];
- edbm_extrude_discrete_faces(em, op, BM_ELEM_SELECT, nor);
+ edbm_extrude_discrete_faces(em, op, BM_ELEM_SELECT);
EDBM_update_generic(em, true, true);
@@ -578,7 +515,6 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
-
use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) &&
(vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE));
@@ -593,6 +529,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
/* call extrude? */
if (done) {
+ const char extrude_htype = edbm_extrude_htype_from_em_select(vc.em);
const bool rot_src = RNA_boolean_get(op->ptr, "rotate_source");
BMEdge *eed;
float vec[3], cent[3], mat[3][3];
@@ -686,7 +623,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
EMBM_project_snap_verts(C, vc.ar, vc.em);
}
- edbm_extrude_edge(vc.obedit, vc.em, BM_ELEM_SELECT, nor);
+ edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, true, true);
EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v matrix=%m3",
BM_ELEM_SELECT, cent, mat);
EDBM_op_callf(vc.em, op, "translate verts=%hv vec=%v",
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index df6776950d7..e2e4638254b 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -38,7 +38,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "WM_api.h"
#include "WM_types.h"
#include "ED_mesh.h"
@@ -334,7 +333,7 @@ static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
BMVert *v_other = BM_edge_other_vert(e, v);
float e_dir[3];
- /* we wan't closest to zero */
+ /* we want closest to zero */
float dot_best = FLT_MAX;
sub_v3_v3v3(e_dir, v_other->co, v->co);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index b08f7ef9613..0a78f299159 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -75,10 +75,16 @@
#define KMAXDIST 10 /* max mouse distance from edge before not detecting it */
+/* WARNING: knife float precision is fragile:
+ * be careful before making changes here see: (T43229, T42864, T42459, T41164).
+ */
#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
+
+#define KNIFE_FLT_EPS_PX_VERT 0.5f
+#define KNIFE_FLT_EPS_PX_EDGE 0.05f
+#define KNIFE_FLT_EPS_PX_FACE 0.05f
typedef struct KnifeColors {
unsigned char line[3];
@@ -97,7 +103,7 @@ typedef struct KnifeVert {
float co[3], cageco[3], sco[2]; /* sco is screen coordinates for cageco */
bool is_face, in_space;
- bool draw;
+ bool is_cut; /* along a cut created by user input (will draw too) */
} KnifeVert;
typedef struct Ref {
@@ -111,7 +117,7 @@ typedef struct KnifeEdge {
ListBase faces;
BMEdge *e /* , *e_old */; /* non-NULL if this is an original edge */
- bool draw;
+ bool is_cut; /* along a cut created by user input (will draw too) */
} KnifeEdge;
typedef struct KnifeLineHit {
@@ -529,7 +535,7 @@ static KnifeVert *knife_split_edge(
newkfe->v1 = kfe->v1;
newkfe->v2 = new_knife_vert(kcd, co, cageco);
- newkfe->v2->draw = 1;
+ newkfe->v2->is_cut = true;
if (kfe->e) {
knife_add_edge_faces_to_vert(kcd, newkfe->v2, kfe->e);
}
@@ -554,7 +560,7 @@ static KnifeVert *knife_split_edge(
knife_add_to_vert_edges(kcd, newkfe);
- newkfe->draw = kfe->draw;
+ newkfe->is_cut = kfe->is_cut;
newkfe->e = kfe->e;
*r_kfe = newkfe;
@@ -603,6 +609,7 @@ static void prepare_linehits_for_cut(KnifeTool_OpData *kcd)
{
KnifeLineHit *linehits, *lhi, *lhj;
int i, j, n;
+ bool is_double = false;
n = kcd->totlinehit;
linehits = kcd->linehits;
@@ -626,7 +633,11 @@ static void prepare_linehits_for_cut(KnifeTool_OpData *kcd)
{
break;
}
- lhj->l = -1.0f;
+
+ if (lhi->kfe == lhj->kfe) {
+ lhj->l = -1.0f;
+ is_double = true;
+ }
}
for (j = i + 1; j < n; j++) {
lhj = &linehits[j];
@@ -635,37 +646,42 @@ static void prepare_linehits_for_cut(KnifeTool_OpData *kcd)
{
break;
}
- if (lhj->kfe || lhi->v == lhj->v) {
+ if ((lhj->kfe && (lhi->kfe == lhj->kfe)) ||
+ (lhi->v == lhj->v))
+ {
lhj->l = -1.0f;
+ is_double = true;
}
}
}
}
- /* delete-in-place loop: copying from pos j to pos i+1 */
- i = 0;
- j = 1;
- while (j < n) {
- lhi = &linehits[i];
- lhj = &linehits[j];
- if (lhj->l == -1.0f) {
- j++; /* skip copying this one */
- }
- else {
- /* copy unless a no-op */
- if (lhi->l == -1.0f) {
- /* could happen if linehits[0] is being deleted */
- memcpy(&linehits[i], &linehits[j], sizeof(KnifeLineHit));
+ if (is_double) {
+ /* delete-in-place loop: copying from pos j to pos i+1 */
+ i = 0;
+ j = 1;
+ while (j < n) {
+ lhi = &linehits[i];
+ lhj = &linehits[j];
+ if (lhj->l == -1.0f) {
+ j++; /* skip copying this one */
}
else {
- if (i + 1 != j)
- memcpy(&linehits[i + 1], &linehits[j], sizeof(KnifeLineHit));
- i++;
+ /* copy unless a no-op */
+ if (lhi->l == -1.0f) {
+ /* could happen if linehits[0] is being deleted */
+ memcpy(&linehits[i], &linehits[j], sizeof(KnifeLineHit));
+ }
+ else {
+ if (i + 1 != j)
+ memcpy(&linehits[i + 1], &linehits[j], sizeof(KnifeLineHit));
+ i++;
+ }
+ j++;
}
- j++;
}
+ kcd->totlinehit = i + 1;
}
- kcd->totlinehit = i + 1;
}
/* Add hit to list of hits in facehits[f], where facehits is a map, if not already there */
@@ -683,6 +699,7 @@ static void add_hit_to_facehits(KnifeTool_OpData *kcd, GHash *facehits, BMFace *
static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, KnifeLineHit *lh2, BMFace *f)
{
KnifeEdge *kfe, *kfe2;
+ BMEdge *e_base;
if ((lh1->v && lh1->v == lh2->v) ||
(lh1->kfe && lh1->kfe == lh2->kfe))
@@ -690,15 +707,25 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife
return;
}
+ /* if the cut is on an edge, just tag that its a cut and return */
+ if ((lh1->v && lh2->v) &&
+ (lh1->v->v && lh2->v && lh2->v->v) &&
+ (e_base = BM_edge_exists(lh1->v->v, lh2->v->v)))
+ {
+ kfe = get_bm_knife_edge(kcd, e_base);
+ kfe->is_cut = true;
+ kfe->e = e_base;
+ return;
+ }
/* Check if edge actually lies within face (might not, if this face is concave) */
- if ((lh1->v && !lh1->kfe) && (lh2->v && !lh2->kfe)) {
+ else if ((lh1->v && !lh1->kfe) && (lh2->v && !lh2->kfe)) {
if (!knife_verts_edge_in_face(lh1->v, lh2->v, f)) {
return;
}
}
kfe = new_knife_edge(kcd);
- kfe->draw = true;
+ kfe->is_cut = true;
kfe->basef = f;
if (lh1->v) {
@@ -711,7 +738,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife
else {
BLI_assert(lh1->f);
kfe->v1 = new_knife_vert(kcd, lh1->hit, lh1->cagehit);
- kfe->v1->draw = true;
+ kfe->v1->is_cut = true;
kfe->v1->is_face = true;
knife_append_list(kcd, &kfe->v1->faces, lh1->f);
lh1->v = kfe->v1; /* record the KnifeVert for this hit */
@@ -727,7 +754,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife
else {
BLI_assert(lh2->f);
kfe->v2 = new_knife_vert(kcd, lh2->hit, lh2->cagehit);
- kfe->v2->draw = true;
+ kfe->v2->is_cut = true;
kfe->v2->is_face = true;
knife_append_list(kcd, &kfe->v2->faces, lh2->f);
lh2->v = kfe->v2; /* record the KnifeVert for this hit */
@@ -748,19 +775,13 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife
static void knife_cut_face(KnifeTool_OpData *kcd, BMFace *f, ListBase *hits)
{
Ref *r;
- KnifeLineHit *lh, *prevlh;
if (BLI_listbase_count_ex(hits, 2) != 2)
return;
- prevlh = NULL;
- for (r = hits->first; r; r = r->next) {
- lh = (KnifeLineHit *)r->ref;
- if (prevlh)
- knife_add_single_cut(kcd, prevlh, lh, f);
- prevlh = lh;
+ for (r = hits->first; r->next; r = r->next) {
+ knife_add_single_cut(kcd, r->ref, r->next->ref, f);
}
-
}
/* User has just left-clicked after the first time.
@@ -1076,7 +1097,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
BLI_mempool_iternew(kcd->kedges, &iter);
for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
- if (!kfe->draw)
+ if (!kfe->is_cut)
continue;
glColor3ubv(kcd->colors.line);
@@ -1098,7 +1119,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
glBegin(GL_POINTS);
BLI_mempool_iternew(kcd->kverts, &iter);
for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
- if (!kfv->draw)
+ if (!kfv->is_cut)
continue;
glColor3ubv(kcd->colors.point);
@@ -1206,9 +1227,82 @@ static void calc_ortho_extent(KnifeTool_OpData *kcd)
kcd->ortho_extent = max_xyz;
}
-/* Check if p is visible (not clipped, not occluded by another face).
- * s in screen projection of p. */
-static bool point_is_visible(KnifeTool_OpData *kcd, const float p[3], const float s[2], bglMats *mats)
+static BMElem *bm_elem_from_knife_vert(KnifeVert *kfv, KnifeEdge **r_kfe)
+{
+ BMElem *ele_test;
+ KnifeEdge *kfe = NULL;
+
+ /* vert? */
+ ele_test = (BMElem *)kfv->v;
+
+ if (r_kfe || ele_test == NULL) {
+ if (kfv->v == NULL) {
+ Ref *ref;
+ for (ref = kfv->edges.first; ref; ref = ref->next) {
+ kfe = ref->ref;
+ if (kfe->e) {
+ *r_kfe = kfe;
+ break;
+ }
+ }
+ }
+ }
+
+ /* edge? */
+ if (ele_test == NULL) {
+ if (kfe) {
+ ele_test = (BMElem *)kfe->e;
+ }
+ }
+
+ /* face? */
+ if (ele_test == NULL) {
+ if (BLI_listbase_is_single(&kfe->faces)) {
+ ele_test = ((Ref *)kfe->faces.first)->ref;
+ }
+ }
+
+ return ele_test;
+}
+
+static BMElem *bm_elem_from_knife_edge(KnifeEdge *kfe)
+{
+ BMElem *ele_test;
+
+ ele_test = (BMElem *)kfe->e;
+
+ if (ele_test == NULL) {
+ ele_test = (BMElem *)kfe->basef;
+ }
+
+ return ele_test;
+}
+
+static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data)
+{
+ switch (((BMElem *)user_data)->head.htype) {
+ case BM_FACE:
+ return (BMFace *)user_data != f;
+ case BM_EDGE:
+ return !BM_edge_in_face((BMEdge *)user_data, f);
+ case BM_VERT:
+ return !BM_vert_in_face((BMVert *)user_data, f);
+ default:
+ return true;
+ }
+}
+
+
+/**
+ * Check if \a p is visible (not clipped, not occluded by another face).
+ * s in screen projection of p.
+ *
+ * \param ele_test Optional vert/edge/face to use when \a p is on the surface of the geometry,
+ * intersecting faces matching this face (or connected when an vert/edge) will be ignored.
+ */
+static bool point_is_visible(
+ KnifeTool_OpData *kcd, const float p[3], const float s[2], bglMats *mats,
+ BMElem *ele_test)
{
BMFace *f_hit;
@@ -1232,7 +1326,7 @@ static bool point_is_visible(KnifeTool_OpData *kcd, const float p[3], const floa
/* make p_ofs a little towards view, so ray doesn't hit p's face. */
sub_v3_v3(view, p);
dist = normalize_v3(view);
- madd_v3_v3v3fl(p_ofs, p, view, KNIFE_FLT_EPSBIG * 3.0f);
+ copy_v3_v3(p_ofs, p);
/* avoid projecting behind the viewpoint */
if (kcd->is_ortho && (kcd->vc.rv3d->persp != RV3D_CAMOB)) {
@@ -1251,9 +1345,19 @@ static bool point_is_visible(KnifeTool_OpData *kcd, const float p[3], const floa
}
/* see if there's a face hit between p1 and the view */
- f_hit = BKE_bmbvh_ray_cast(kcd->bmbvh, p_ofs, view, KNIFE_FLT_EPS, &dist, NULL, NULL);
- if (f_hit)
+ if (ele_test) {
+ f_hit = BKE_bmbvh_ray_cast_filter(
+ kcd->bmbvh, p_ofs, view, KNIFE_FLT_EPS, &dist, NULL, NULL,
+ bm_ray_cast_cb_elem_not_in_face_check, ele_test);
+ }
+ else {
+ f_hit = BKE_bmbvh_ray_cast(
+ kcd->bmbvh, p_ofs, view, KNIFE_FLT_EPS, &dist, NULL, NULL);
+ }
+
+ if (f_hit) {
return false;
+ }
}
return true;
@@ -1295,6 +1399,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
SmallHashIter hiter;
KnifeLineHit hit;
void *val;
+ void **val_p;
float plane_cos[12];
float s[2], se1[2], se2[2], sint[2];
float r1[3], r2[3];
@@ -1302,7 +1407,6 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
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;
@@ -1383,6 +1487,11 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
ls = (BMLoop **)kcd->em->looptris[result->indexA];
f = ls[0]->f;
set_lowest_face_tri(kcd, f, result->indexA);
+
+ /* occlude but never cut unselected faces (when only_select is used) */
+ if (kcd->only_select && !BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ continue;
+ }
/* for faces, store index of lowest hit looptri in hash */
if (BLI_smallhash_haskey(&faces, (uintptr_t)f)) {
continue;
@@ -1397,27 +1506,18 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
continue;
BLI_smallhash_insert(&kfes, (uintptr_t)kfe, kfe);
v = kfe->v1;
- if (!BLI_smallhash_haskey(&kfvs, (uintptr_t)v))
- BLI_smallhash_insert(&kfvs, (uintptr_t)v, v);
+ BLI_smallhash_reinsert(&kfvs, (uintptr_t)v, v);
v = kfe->v2;
- if (!BLI_smallhash_haskey(&kfvs, (uintptr_t)v))
- BLI_smallhash_insert(&kfvs, (uintptr_t)v, v);
+ BLI_smallhash_reinsert(&kfvs, (uintptr_t)v, v);
}
}
/* Now go through the candidates and find intersections */
/* These tolerances, in screen space, are for intermediate hits, as ends are already snapped to screen */
- {
- /* 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 = KNIFE_FLT_EPS_PX_VERT;
+ line_tol = KNIFE_FLT_EPS_PX_EDGE;
+ face_tol = KNIFE_FLT_EPS_PX_FACE;
vert_tol_sq = vert_tol * vert_tol;
line_tol_sq = line_tol * line_tol;
@@ -1426,44 +1526,55 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
/* Assume these tolerances swamp floating point rounding errors in calculations below */
/* first look for vertex hits */
- for (val = BLI_smallhash_iternew(&kfvs, &hiter, (uintptr_t *)&v); val;
- val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&v))
+ for (val_p = BLI_smallhash_iternew_p(&kfvs, &hiter, (uintptr_t *)&v); val_p;
+ val_p = BLI_smallhash_iternext_p(&hiter, (uintptr_t *)&v))
{
+ KnifeEdge *kfe_hit = NULL;
+
knife_project_v2(kcd, v->cageco, s);
d = dist_squared_to_line_segment_v2(s, s1, s2);
- if (d <= vert_tol_sq) {
- if (point_is_visible(kcd, v->cageco, s, &mats)) {
- memset(&hit, 0, sizeof(hit));
- hit.v = v;
+ if ((d <= vert_tol_sq) &&
+ (point_is_visible(kcd, v->cageco, s, &mats, bm_elem_from_knife_vert(v, &kfe_hit))))
+ {
+ memset(&hit, 0, sizeof(hit));
+ hit.v = v;
- /* If this isn't from an existing BMVert, it may have been added to a BMEdge originally.
+ /* If this isn't from an existing BMVert, it may have been added to a BMEdge originally.
* knowing if the hit comes from an edge is important for edge-in-face checks later on
* see: #knife_add_single_cut -> #knife_verts_edge_in_face, T42611 */
- if (v->v == NULL) {
- for (ref = v->edges.first; ref; ref = ref->next) {
- kfe = ref->ref;
- if (kfe->e) {
- hit.kfe = kfe;
- break;
- }
- }
- }
-
- 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);
- BLI_array_append(linehits, hit);
+ if (kfe_hit) {
+ hit.kfe = kfe_hit;
}
+
+ 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);
+ BLI_array_append(linehits, hit);
+ }
+ else {
+ /* note that these vertes aren't used */
+ *val_p = NULL;
}
}
+
/* now edge hits; don't add if a vertex at end of edge should have hit */
for (val = BLI_smallhash_iternew(&kfes, &hiter, (uintptr_t *)&kfe); val;
val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&kfe))
{
+ int kfe_verts_in_cut;
+ /* if we intersect both verts, don't attempt to intersect the edge */
+
+ kfe_verts_in_cut = (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v1) != NULL) +
+ (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v2) != NULL);
+
+ if (kfe_verts_in_cut == 2) {
+ continue;
+ }
+
knife_project_v2(kcd, kfe->v1->cageco, se1);
knife_project_v2(kcd, kfe->v2->cageco, se2);
- isect_kind = isect_seg_seg_v2_point(s1, s2, se1, se2, sint);
+ isect_kind = (kfe_verts_in_cut) ? -1 : isect_seg_seg_v2_point(s1, s2, se1, se2, sint);
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);
@@ -1486,7 +1597,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
* 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_cage, p_cage_tmp);
- if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, &mats)) {
+ if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, &mats, bm_elem_from_knife_edge(kfe))) {
memset(&hit, 0, sizeof(hit));
if (kcd->snap_midpoints) {
/* choose intermediate point snap too */
@@ -1515,7 +1626,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
float p[3], p_cage[3];
if (use_hit_prev && knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) {
- if (point_is_visible(kcd, p_cage, s1, &mats)) {
+ if (point_is_visible(kcd, p_cage, s1, &mats, (BMElem *)f)) {
memset(&hit, 0, sizeof(hit));
hit.f = f;
copy_v3_v3(hit.hit, p);
@@ -1527,7 +1638,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
}
if (use_hit_curr && knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) {
- if (point_is_visible(kcd, p_cage, s2, &mats)) {
+ if (point_is_visible(kcd, p_cage, s2, &mats, (BMElem *)f)) {
memset(&hit, 0, sizeof(hit));
hit.f = f;
copy_v3_v3(hit.hit, p);
@@ -1589,6 +1700,10 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float
f = BKE_bmbvh_ray_cast(kcd->bmbvh, origin, ray, 0.0f, NULL, co, cageco);
+ if (f && kcd->only_select && BM_elem_flag_test(f, BM_ELEM_SELECT) == 0) {
+ f = NULL;
+ }
+
if (is_space)
*is_space = !f;
@@ -1983,34 +2098,17 @@ static int knife_update_active(KnifeTool_OpData *kcd)
return 1;
}
-/* sort list of kverts by fraction along edge e */
-static void sort_by_frac_along(ListBase *lst, BMEdge *e)
+static int sort_verts_by_dist_cb(void *co_p, const void *cur_a_p, const void *cur_b_p)
{
- /* note, since we know the point is along the edge, sort from distance to v1co */
- const float *v1co = e->v1->co;
- Ref *cur = NULL, *prev = NULL, *next = NULL;
-
- if (lst->first == lst->last)
- return;
-
- for (cur = ((Ref *)lst->first)->next; cur; cur = next) {
- KnifeVert *vcur = cur->ref;
- const float vcur_fac_sq = len_squared_v3v3(v1co, vcur->co);
+ const KnifeVert *cur_a = ((const Ref *)cur_a_p)->ref;
+ const KnifeVert *cur_b = ((const Ref *)cur_b_p)->ref;
+ const float *co = co_p;
+ const float a_sq = len_squared_v3v3(co, cur_a->co);
+ const float b_sq = len_squared_v3v3(co, cur_b->co);
- next = cur->next;
- prev = cur->prev;
-
- BLI_remlink(lst, cur);
-
- while (prev) {
- KnifeVert *vprev = prev->ref;
- if (len_squared_v3v3(v1co, vprev->co) <= vcur_fac_sq)
- break;
- prev = prev->prev;
- }
-
- BLI_insertlinkafter(lst, prev, cur);
- }
+ if (a_sq < b_sq) return -1;
+ else if (a_sq > b_sq) return 1;
+ else return 0;
}
/* The chain so far goes from an instantiated vertex to kfv (some may be reversed).
@@ -2341,13 +2439,22 @@ static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f)
{
bool v1_inside, v2_inside;
bool v1_inface, v2_inface;
+ BMLoop *l1, *l2;
if (!f || !v1 || !v2)
return false;
+ l1 = v1->v ? BM_face_vert_share_loop(f, v1->v) : NULL;
+ l2 = v2->v ? BM_face_vert_share_loop(f, v2->v) : NULL;
+
+ if ((l1 && l2) && BM_loop_is_adjacent(l1, l2)) {
+ /* boundary-case, always false to avoid edge-in-face checks below */
+ return false;
+ }
+
/* find out if v1 and v2, if set, are part of the face */
- v1_inface = v1->v ? BM_vert_in_face(f, v1->v) : false;
- v2_inface = v2->v ? BM_vert_in_face(f, v2->v) : false;
+ v1_inface = (l1 != NULL);
+ v2_inface = (l2 != NULL);
/* BM_face_point_inside_test uses best-axis projection so this isn't most accurate test... */
v1_inside = v1_inface ? false : BM_face_point_inside_test(f, v1->co);
@@ -2591,6 +2698,14 @@ static void knife_make_cuts(KnifeTool_OpData *kcd)
/* put list of cutting edges for a face into fhash, keyed by face */
BLI_mempool_iternew(kcd->kedges, &iter);
for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
+
+ /* select edges that lie directly on the cut */
+ if (kcd->select_result) {
+ if (kfe->e && kfe->is_cut) {
+ BM_edge_select_set(bm, kfe->e, true);
+ }
+ }
+
f = kfe->basef;
if (!f || kfe->e)
continue;
@@ -2627,7 +2742,8 @@ static void knife_make_cuts(KnifeTool_OpData *kcd)
for (lst = BLI_smallhash_iternew(ehash, &hiter, (uintptr_t *)&e); lst;
lst = BLI_smallhash_iternext(&hiter, (uintptr_t *)&e))
{
- sort_by_frac_along(lst, e);
+ BLI_listbase_sort_r(lst, e->v1->co, sort_verts_by_dist_cb);
+
for (ref = lst->first; ref; ref = ref->next) {
kfv = ref->ref;
pct = line_point_factor_v3(kfv->co, e->v1->co, e->v2->co);
@@ -2759,10 +2875,11 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(kcd->em, scene, NULL);
- kcd->bmbvh = BKE_bmbvh_new_from_editmesh(kcd->em,
- BMBVH_RETURN_ORIG |
- (only_select ? BMBVH_RESPECT_SELECT : BMBVH_RESPECT_HIDDEN),
- kcd->cagecos, false);
+ kcd->bmbvh = BKE_bmbvh_new_from_editmesh(
+ kcd->em,
+ BMBVH_RETURN_ORIG |
+ ((only_select && cut_through) ? BMBVH_RESPECT_SELECT : BMBVH_RESPECT_HIDDEN),
+ kcd->cagecos, false);
kcd->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 15), "knife");
kcd->vthresh = KMAXDIST - 1;
@@ -3120,16 +3237,14 @@ void MESH_OT_knife_tool(wmOperatorType *ot)
* tessellation here seems way overkill,
* but without this its very hard to know of a point is inside the face
*/
-static void edvm_mesh_knife_face_point(BMFace *f, float r_cent[3])
+static void edbm_mesh_knife_face_point(BMFace *f, float r_cent[3])
{
const int tottri = f->len - 2;
BMLoop **loops = BLI_array_alloca(loops, f->len);
unsigned int (*index)[3] = BLI_array_alloca(index, tottri);
int j;
-
- const float *best_co[3] = {NULL};
- float best_area = -1.0f;
- bool ok = false;
+ int j_best = 0; /* use as fallback when unset */
+ float area_best = -1.0f;
BM_face_calc_tessellation(f, loops, index);
@@ -3142,49 +3257,34 @@ static void edvm_mesh_knife_face_point(BMFace *f, float r_cent[3])
float cross[3];
cross_v3_v3v3(cross, p2, p3);
area = fabsf(dot_v3v3(p1, cross));
- if (area > best_area) {
- best_co[0] = p1;
- best_co[1] = p2;
- best_co[2] = p3;
- best_area = area;
- ok = true;
+ if (area > area_best) {
+ j_best = j;
+ area_best = area;
}
}
- if (ok) {
- mid_v3_v3v3v3(r_cent, best_co[0], best_co[1], best_co[2]);
- }
- else {
- mid_v3_v3v3v3(r_cent, loops[0]->v->co, loops[1]->v->co, loops[2]->v->co);
- }
+ mid_v3_v3v3v3(
+ r_cent,
+ loops[index[j_best][0]]->v->co,
+ loops[index[j_best][1]]->v->co,
+ loops[index[j_best][2]]->v->co);
}
-static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f, float projmat[4][4])
+static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2])
{
- float cent_ss[2];
- float cent[3];
-
- edvm_mesh_knife_face_point(f, cent);
-
- ED_view3d_project_float_v2_m4(ar, cent, cent_ss, projmat);
-
- /* check */
- {
- LinkNode *p = polys;
- int isect = 0;
-
- while (p) {
- const float (*mval_fl)[2] = p->link;
- const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
- isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1, false);
- p = p->next;
- }
+ LinkNode *p = polys;
+ int isect = 0;
- if (isect % 2) {
- return true;
- }
+ while (p) {
+ const float (*mval_fl)[2] = p->link;
+ const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
+ isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1, false);
+ p = p->next;
}
+ if (isect % 2) {
+ return true;
+ }
return false;
}
@@ -3194,6 +3294,7 @@ static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f,
void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_through)
{
KnifeTool_OpData *kcd;
+ bglMats mats;
view3d_operator_needs_opengl(C);
@@ -3212,6 +3313,10 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
if (use_tag) {
BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false);
}
+
+ if (kcd->cut_through == false) {
+ bgl_get_mats(&mats);
+ }
}
/* execute */
@@ -3276,7 +3381,10 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
BMFace *f;
BMIter fiter;
BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
- if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat)) {
+ float cent[3], cent_ss[2];
+ edbm_mesh_knife_face_point(f, cent);
+ knife_project_v2(kcd, cent, cent_ss);
+ if (edbm_mesh_knife_point_isect(polys, cent_ss)) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
}
}
@@ -3309,7 +3417,12 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
} while ((l_iter = l_iter->next) != l_first && (found == false));
if (found) {
- if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat)) {
+ float cent[3], cent_ss[2];
+ edbm_mesh_knife_face_point(f, cent);
+ knife_project_v2(kcd, cent, cent_ss);
+ if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, &mats, (BMElem *)f)) &&
+ edbm_mesh_knife_point_isect(polys, cent_ss))
+ {
BM_elem_flag_enable(f, BM_ELEM_TAG);
keep_search = true;
}
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index e1ef74cbaf8..4eaac6cc1d3 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -32,9 +32,12 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_windowmanager_types.h"
+#ifdef WITH_FREESTYLE
+# include "DNA_meshdata_types.h"
+#endif
+
#include "BLI_math.h"
#include "BLI_linklist.h"
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 4f149bf2c52..ead243d6de8 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -626,7 +626,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
* split off vertex if...
* - we cant find an edge - this means we are ripping a faces vert that is connected to other
* geometry only at the vertex.
- * - the boundary edge total is greater then 2,
+ * - the boundary edge total is greater than 2,
* in this case edge split _can_ work but we get far nicer results if we use this special case.
* - there are only 2 edges but we are a wire vert. */
if ((is_wire == false && totboundary_edge > 2) ||
diff --git a/source/blender/editors/mesh/editmesh_rip_edge.c b/source/blender/editors/mesh/editmesh_rip_edge.c
index 5daf33fae3b..a501dfc8c2c 100644
--- a/source/blender/editors/mesh/editmesh_rip_edge.c
+++ b/source/blender/editors/mesh/editmesh_rip_edge.c
@@ -24,8 +24,6 @@
* based on mouse cursor position, split of vertices along the closest edge.
*/
-#include "MEM_guardedalloc.h"
-
#include "DNA_object_types.h"
#include "BLI_math.h"
@@ -34,9 +32,6 @@
#include "BKE_report.h"
#include "BKE_editmesh.h"
-#include "RNA_define.h"
-#include "RNA_access.h"
-
#include "WM_types.h"
#include "ED_mesh.h"
@@ -177,7 +172,7 @@ static int edbm_rip_edge_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve
ED_view3d_project_float_v2_m4(ar, v_other->co, v_other_sco, projectMat);
- /* avoid comparing with view-axis aligned edges (less then a pixel) */
+ /* avoid comparing with view-axis aligned edges (less than a pixel) */
if (len_squared_v2v2(v_sco, v_other_sco) > 1.0f) {
float v_dir[2];
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 5f3f7cb242c..d3073d519f6 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -38,7 +38,6 @@
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_array.h"
-#include "BLI_smallhash.h"
#include "BKE_context.h"
#include "BKE_report.h"
@@ -62,8 +61,6 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "GPU_extensions.h"
-
#include "UI_resources.h"
#include "bmesh_tools.h"
@@ -386,8 +383,6 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float
}
-
-
static bool findnearestvert__backbufIndextest(void *handle, unsigned int index)
{
BMEditMesh *em = (BMEditMesh *)handle;
@@ -711,6 +706,7 @@ static EnumPropertyItem prop_similar_types[] = {
{SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
{SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
{SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
+ {SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""},
#ifdef WITH_FREESTYLE
{SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""},
#endif
@@ -888,7 +884,7 @@ static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *UNUS
#ifdef WITH_FREESTYLE
const int a_end = SIMFACE_FREESTYLE;
#else
- const int a_end = SIMFACE_COPLANAR;
+ const int a_end = SIMFACE_SMOOTH;
#endif
for (a = SIMFACE_MATERIAL; a <= a_end; a++) {
RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
@@ -994,6 +990,7 @@ static int edbm_select_similar_region_exec(bContext *C, wmOperator *op)
}
MEM_freeN(groups_array);
+ MEM_freeN(group_index);
if (changed) {
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
@@ -3365,8 +3362,8 @@ static int loop_find_region(BMLoop *l, int flag,
static int verg_radial(const void *va, const void *vb)
{
- BMEdge *e_a = *((BMEdge **)va);
- BMEdge *e_b = *((BMEdge **)vb);
+ const BMEdge *e_a = *((const BMEdge **)va);
+ const BMEdge *e_b = *((const BMEdge **)vb);
int a, b;
a = BM_edge_face_count(e_a);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index a136bc5e0c5..a480b2051cc 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -878,7 +878,7 @@ static int edbm_vert_connect_exec(bContext *C, wmOperator *op)
BMesh *bm = em->bm;
BMOperator bmop;
bool is_pair = (bm->totvertsel == 2);
- int len;
+ int len = 0;
bool check_degenerate = true;
const int verts_len = bm->totvertsel;
BMVert **verts;
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index c6571058040..86cd75eed7a 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -232,7 +232,7 @@ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool
else {
em->emcopyusers--;
if (em->emcopyusers < 0) {
- printf("warning: em->emcopyusers was less then zero.\n");
+ printf("warning: em->emcopyusers was less than zero.\n");
}
if (em->emcopyusers <= 0) {
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index e2ce97a3bdf..152d055d239 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -43,7 +43,6 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
-#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
@@ -51,7 +50,6 @@
#include "BKE_report.h"
#include "BKE_editmesh.h"
-#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
@@ -571,24 +569,13 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e
return OPERATOR_CANCELLED;
}
- /* check input variables */
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- char path[FILE_MAX];
-
- RNA_string_get(op->ptr, "filepath", path);
- ima = BKE_image_load_exists(path);
- }
- else {
- char name[MAX_ID_NAME - 2];
- RNA_string_get(op->ptr, "name", name);
- ima = (Image *)BKE_libblock_find_name(ID_IM, name);
- }
-
+ ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
if (!ima) {
- BKE_report(op->reports, RPT_ERROR, "Not an image");
return OPERATOR_CANCELLED;
}
-
+ /* handled below */
+ id_us_min((ID *)ima);
+
/* put mesh in editmode */
obedit = base->object;
@@ -639,6 +626,7 @@ void MESH_OT_drop_named_image(wmOperatorType *ot)
/* properties */
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Image name to assign");
RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path to image file");
+ RNA_def_boolean(ot->srna, "relative_path", true, "Relative Path", "Select the file relative to the blend file");
}
static int mesh_uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index f6a54beb8c8..57daec49465 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -47,7 +47,6 @@
#include "RNA_define.h"
#include "RNA_access.h"
-#include "RNA_enum_types.h"
#include "BKE_depsgraph.h"
#include "BKE_context.h"
diff --git a/source/blender/editors/metaball/mball_ops.c b/source/blender/editors/metaball/mball_ops.c
index b7822200d98..3af85c33bcc 100644
--- a/source/blender/editors/metaball/mball_ops.c
+++ b/source/blender/editors/metaball/mball_ops.c
@@ -30,8 +30,6 @@
#include "DNA_scene_types.h"
-#include "BLI_utildefines.h"
-
#include "RNA_access.h"
#include "WM_api.h"
@@ -62,7 +60,7 @@ void ED_operatormacros_metaball(void)
wmOperatorTypeMacro *otmacro;
ot = WM_operatortype_append_macro("MBALL_OT_duplicate_move", "Duplicate",
- "Make copies of the selected bones within the same armature and move them",
+ "Make copies of the selected metaelements and move them",
OPTYPE_UNDO | OPTYPE_REGISTER);
WM_operatortype_macro_define(ot, "MBALL_OT_duplicate_metaelems");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 9b380ff8d48..79437bb05b9 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -56,6 +56,7 @@ set(SRC
object_relations.c
object_select.c
object_shapekey.c
+ object_data_transfer.c
object_transform.c
object_warp.c
object_vgroup.c
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 24dcf85cec8..c3edd63b2d4 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -69,7 +69,6 @@
#include "BKE_effect.h"
#include "BKE_font.h"
#include "BKE_group.h"
-#include "BKE_image.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
@@ -97,7 +96,6 @@
#include "ED_armature.h"
#include "ED_curve.h"
-#include "ED_lattice.h"
#include "ED_mball.h"
#include "ED_mesh.h"
#include "ED_node.h"
@@ -108,7 +106,6 @@
#include "ED_transform.h"
#include "ED_view3d.h"
-#include "UI_interface.h"
#include "UI_resources.h"
#include "GPU_material.h"
@@ -833,24 +830,12 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
Image *ima = NULL;
Object *ob = NULL;
- /* check image input variables */
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- char path[FILE_MAX];
-
- RNA_string_get(op->ptr, "filepath", path);
- ima = BKE_image_load_exists(path);
- }
- else if (RNA_struct_property_is_set(op->ptr, "name")) {
- char name[MAX_ID_NAME - 2];
-
- RNA_string_get(op->ptr, "name", name);
- ima = (Image *)BKE_libblock_find_name(ID_IM, name);
- }
-
- if (ima == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Not an image");
+ ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
+ if (!ima) {
return OPERATOR_CANCELLED;
}
+ /* handled below */
+ id_us_min((ID *)ima);
base = ED_view3d_give_base_under_cursor(C, event->mval);
@@ -902,6 +887,8 @@ void OBJECT_OT_drop_named_image(wmOperatorType *ot)
/* properties */
prop = RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "Filepath", "Path to image file");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ RNA_def_boolean(ot->srna, "relative_path", true, "Relative Path", "Select the file relative to the blend file");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Image name to assign");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
ED_object_add_generic_props(ot, false);
@@ -990,8 +977,11 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
if (0 == RNA_struct_property_is_set(op->ptr, "location")) {
wmEvent *event = CTX_wm_window(C)->eventstate;
+ ARegion *ar = CTX_wm_region(C);
+ const int mval[2] = {event->x - ar->winrct.xmin,
+ event->y - ar->winrct.ymin};
ED_object_location_from_view(C, loc);
- ED_view3d_cursor3d_position(C, loc, event->mval);
+ ED_view3d_cursor3d_position(C, loc, mval);
RNA_float_set_array(op->ptr, "location", loc);
}
}
@@ -1299,6 +1289,44 @@ static void copy_object_set_idnew(bContext *C, int dupflag)
/********************* Make Duplicates Real ************************/
+/**
+ * \note regarding hashing dupli-objects, skip the first member of #DupliObject.persistent_id
+ * since its a unique index and we only want to know if the group objects are from the same dupli-group instance.
+ */
+static unsigned int dupliobject_hash(const void *ptr)
+{
+ const DupliObject *dob = ptr;
+ unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
+ unsigned int i;
+ for (i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
+ hash ^= (dob->persistent_id[i] ^ i);
+ }
+ return hash;
+}
+
+static bool dupliobject_cmp(const void *a_, const void *b_)
+{
+ const DupliObject *a = a_;
+ const DupliObject *b = b_;
+ unsigned int i;
+
+ if (a->ob != b->ob) {
+ return true;
+ }
+
+ for (i = 1; (i < MAX_DUPLI_RECUR); i++) {
+ if (a->persistent_id[i] != b->persistent_id[i]) {
+ return true;
+ }
+ else if (a->persistent_id[i] == INT_MAX) {
+ break;
+ }
+ }
+
+ /* matching */
+ return false;
+}
+
static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
const bool use_base_parent,
const bool use_hierarchy)
@@ -1315,8 +1343,8 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
lb = object_duplilist(bmain->eval_ctx, scene, base->object);
if (use_hierarchy || use_base_parent) {
- dupli_gh = BLI_ghash_ptr_new("make_object_duplilist_real dupli_gh");
- parent_gh = BLI_ghash_pair_new("make_object_duplilist_real parent_gh");
+ dupli_gh = BLI_ghash_ptr_new(__func__);
+ parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
}
for (dob = lb->first; dob; dob = dob->next) {
@@ -1356,7 +1384,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (dupli_gh)
BLI_ghash_insert(dupli_gh, dob, ob);
if (parent_gh)
- BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->persistent_id[0])), ob);
+ BLI_ghash_insert(parent_gh, dob, ob);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
@@ -1372,9 +1400,14 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
/* find parent that was also made real */
if (ob_src_par) {
- GHashPair *pair = BLI_ghashutil_pairalloc(ob_src_par, SET_INT_IN_POINTER(dob->persistent_id[0]));
- ob_dst_par = BLI_ghash_lookup(parent_gh, pair);
- BLI_ghashutil_pairfree(pair);
+ /* OK to keep most of the members uninitialized,
+ * they won't be read, this is simply for a hash lookup. */
+ DupliObject dob_key;
+ dob_key.ob = ob_src_par;
+ memcpy(&dob_key.persistent_id[1],
+ &dob->persistent_id[1],
+ sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
+ ob_dst_par = BLI_ghash_lookup(parent_gh, &dob_key);
}
if (ob_dst_par) {
@@ -1437,7 +1470,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (dupli_gh)
BLI_ghash_free(dupli_gh, NULL, NULL);
if (parent_gh)
- BLI_ghash_free(parent_gh, BLI_ghashutil_pairfree, NULL);
+ BLI_ghash_free(parent_gh, NULL, NULL);
copy_object_set_idnew(C, 0);
@@ -2279,7 +2312,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
MEM_freeN(base);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index 1f1bdbe55e5..758f4d180b9 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -45,8 +45,6 @@
#include "BLI_blenlib.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLI_math.h"
-#include "BLI_math_geom.h"
#include "BKE_blender.h"
#include "BKE_screen.h"
@@ -71,7 +69,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_colormanagement.h"
#include "GPU_draw.h" /* GPU_free_image */
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 57fabcb06cf..83eeedfef52 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -1081,8 +1081,9 @@ static int bake_exec(bContext *C, wmOperator *op)
/* 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;
+ if (!bake_objects_check(bkr.main, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) {
+ goto finally;
+ }
if (bkr.is_clear) {
const bool is_tangent = ((bkr.pass_type == SCE_PASS_NORMAL) && (bkr.normal_space == R_BAKE_SPACE_TANGENT));
@@ -1117,6 +1118,8 @@ static int bake_exec(bContext *C, wmOperator *op)
RE_SetReports(re, NULL);
+
+finally:
BLI_freelistN(&bkr.selected_objects);
return result;
}
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
new file mode 100644
index 00000000000..f6cf0312e2d
--- /dev/null
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -0,0 +1,675 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Bastien Montagne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/object/object_data_transfer.c
+ * \ingroup edobj
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_data_transfer.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "object_intern.h"
+
+/* All possible data to transfer.
+ * Note some are 'fake' ones, i.e. they are not hold by real CDLayers. */
+/* Not shared with modifier, since we use a usual enum here, not a multi-choice one. */
+static EnumPropertyItem DT_layer_items[] = {
+ {0, "", 0, "Vertex Data", ""},
+ {DT_TYPE_MDEFORMVERT, "VGROUP_WEIGHTS", 0, "Vertex Group(s)", "Transfer active or all vertex groups"},
+#if 0 /* XXX For now, would like to finish/merge work from 2014 gsoc first. */
+ {DT_TYPE_SHAPEKEY, "SHAPEKEYS", 0, "Shapekey(s)", "Transfer active or all shape keys"},
+#endif
+#if 0 /* XXX When SkinModifier is enabled, it seems to erase its own CD_MVERT_SKIN layer from final DM :( */
+ {DT_TYPE_SKIN, "SKIN", 0, "Skin Weight", "Transfer skin weights"},
+#endif
+ {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"},
+ {0, "", 0, "Edge Data", ""},
+ {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"},
+ {DT_TYPE_SEAM, "SEAM", 0, "UV Seam", "Transfer UV seam mark"},
+ {DT_TYPE_CREASE, "CREASE", 0, "Subsurf Crease", "Transfer crease values"},
+ {DT_TYPE_BWEIGHT_EDGE, "BEVEL_WEIGHT_EDGE", 0, "Bevel Weight", "Transfer bevel weights"},
+ {DT_TYPE_FREESTYLE_EDGE, "FREESTYLE_EDGE", 0, "Freestyle Mark", "Transfer Freestyle edge mark"},
+ {0, "", 0, "Face Corner Data", ""},
+ {DT_TYPE_VCOL, "VCOL", 0, "VCol", "Vertex (face corners) colors"},
+ {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"},
+ {0, "", 0, "Face Data", ""},
+ {DT_TYPE_SHARP_FACE, "SMOOTH", 0, "Smooth", "Transfer flat/smooth mark"},
+ {DT_TYPE_FREESTYLE_FACE, "FREESTYLE_FACE", 0, "Freestyle Mark", "Transfer Freestyle face mark"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+/* Note: DT_layers_select_src_items enum is from rna_modifier.c */
+static EnumPropertyItem *dt_layers_select_src_itemf(
+ bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ EnumPropertyItem *item = NULL, tmp_item = {0};
+ int totitem = 0;
+
+ const int data_type = RNA_enum_get(ptr, "data_type");
+
+ if (!C) { /* needed for docs and i18n tools */
+ return DT_layers_select_src_items;
+ }
+
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_ACTIVE_SRC);
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_ALL_SRC);
+
+ if (data_type == DT_TYPE_MDEFORMVERT) {
+ Object *ob_src = CTX_data_active_object(C);
+
+ if (BKE_object_pose_armature_get(ob_src)) {
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT);
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM);
+ }
+
+ if (ob_src) {
+ bDeformGroup *dg;
+ int i;
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = dg->name;
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ else if (data_type == DT_TYPE_SHAPEKEY) {
+ /* TODO */
+ }
+ else if (data_type == DT_TYPE_UV) {
+ Object *ob_src = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (ob_src) {
+ DerivedMesh *dm_src;
+ CustomData *pdata;
+ int num_data, i;
+
+ /* XXX Is this OK? */
+ dm_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MTEXPOLY);
+ pdata = dm_src->getPolyDataLayout(dm_src);
+ num_data = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(pdata, CD_MTEXPOLY, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ else if (data_type == DT_TYPE_VCOL) {
+ Object *ob_src = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (ob_src) {
+ DerivedMesh *dm_src;
+ CustomData *ldata;
+ int num_data, i;
+
+ /* XXX Is this OK? */
+ dm_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL);
+ ldata = dm_src->getLoopDataLayout(dm_src);
+ num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPCOL, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+/* Note: DT_layers_select_dst_items enum is from rna_modifier.c */
+static EnumPropertyItem *dt_layers_select_dst_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+ const int layers_select_src = RNA_enum_get(ptr, "layers_select_src");
+
+ if (!C) { /* needed for docs and i18n tools */
+ return DT_layers_select_dst_items;
+ }
+
+ if (layers_select_src == DT_LAYERS_ACTIVE_SRC || layers_select_src >= 0) {
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_dst_items, DT_LAYERS_ACTIVE_DST);
+ }
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_dst_items, DT_LAYERS_NAME_DST);
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_dst_items, DT_LAYERS_INDEX_DST);
+
+ /* No 'specific' to-layers here, since we may transfer to several objects at once! */
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+/* Note: DT_mix_mode_items enum is from rna_modifier.c */
+static EnumPropertyItem *dt_mix_mode_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+ const int dtdata_type = RNA_enum_get(ptr, "data_type");
+ bool support_advanced_mixing, support_threshold;
+
+ if (!C) { /* needed for docs and i18n tools */
+ return DT_mix_mode_items;
+ }
+
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_TRANSFER);
+
+ BKE_object_data_transfer_get_dttypes_capacity(dtdata_type, &support_advanced_mixing, &support_threshold);
+
+ if (support_threshold) {
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_REPLACE_ABOVE_THRESHOLD);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_REPLACE_BELOW_THRESHOLD);
+ }
+
+ if (support_advanced_mixing) {
+ RNA_enum_item_add_separator(&item, &totitem);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_MIX);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_ADD);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_SUB);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_MUL);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static bool data_transfer_check(bContext *UNUSED(C), wmOperator *op)
+{
+ const int layers_select_src = RNA_enum_get(op->ptr, "layers_select_src");
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "layers_select_dst");
+ const int layers_select_dst = RNA_property_enum_get(op->ptr, prop);
+
+ /* TODO: check for invalid layers_src select modes too! */
+
+ if ((layers_select_src != DT_LAYERS_ACTIVE_SRC) && (layers_select_dst == DT_LAYERS_ACTIVE_DST)) {
+ RNA_property_enum_set(op->ptr, prop, DT_LAYERS_NAME_DST);
+ return true;
+ }
+
+ return false;
+}
+
+/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
+static void data_transfer_exec_preprocess_objects(
+ bContext *C, wmOperator *op, Object *ob_src, ListBase *ctx_objects, const bool reverse_transfer)
+{
+ CollectionPointerLink *ctx_ob;
+ CTX_data_selected_editable_objects(C, ctx_objects);
+
+ if (reverse_transfer) {
+ return; /* Nothing else to do in this case... */
+ }
+
+ for (ctx_ob = ctx_objects->first; ctx_ob; ctx_ob = ctx_ob->next) {
+ Object *ob = ctx_ob->ptr.data;
+ Mesh *me;
+ if ((ob == ob_src) || (ob->type != OB_MESH)) {
+ continue;
+ }
+
+ me = ob->data;
+ if (me->id.lib) {
+ /* Do not transfer to linked data, not supported. */
+ BKE_reportf(op->reports, RPT_WARNING, "Skipping object '%s', linked data '%s' cannot be modified",
+ ob->id.name + 2, me->id.name + 2);
+ me->id.flag &= ~LIB_DOIT;
+ continue;
+ }
+
+ me->id.flag |= LIB_DOIT;
+ }
+}
+
+/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
+static bool data_transfer_exec_is_object_valid(
+ wmOperator *op, Object *ob_src, Object *ob_dst, const bool reverse_transfer)
+{
+ Mesh *me;
+ if ((ob_dst == ob_src) || !ELEM(OB_MESH, ob_src->type, ob_dst->type)) {
+ return false;
+ }
+
+ if (reverse_transfer) {
+ return true;
+ }
+
+ me = ob_dst->data;
+ if (me->id.flag & LIB_DOIT) {
+ me->id.flag &= ~LIB_DOIT;
+ return true;
+ }
+ else if (me->id.lib == NULL) {
+ /* Do not transfer apply operation more than once. */
+ /* XXX This is not nice regarding vgroups, which are half-Object data... :/ */
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Skipping object '%s', data '%s' has already been processed with a previous object",
+ ob_dst->id.name + 2, me->id.name + 2);
+ }
+ return false;
+}
+
+static int data_transfer_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob_src = CTX_data_active_object(C);
+
+ ListBase ctx_objects;
+ CollectionPointerLink *ctx_ob_dst;
+
+ bool changed = false;
+
+ const bool reverse_transfer = RNA_boolean_get(op->ptr, "use_reverse_transfer");
+
+ const int data_type = RNA_enum_get(op->ptr, "data_type");
+ const bool use_create = RNA_boolean_get(op->ptr, "use_create");
+
+ const int map_vert_mode = RNA_enum_get(op->ptr, "vert_mapping");
+ const int map_edge_mode = RNA_enum_get(op->ptr, "edge_mapping");
+ const int map_loop_mode = RNA_enum_get(op->ptr, "loop_mapping");
+ const int map_poly_mode = RNA_enum_get(op->ptr, "poly_mapping");
+
+ const bool use_object_transform = RNA_boolean_get(op->ptr, "use_object_transform");
+ const bool use_max_distance = RNA_boolean_get(op->ptr, "use_max_distance");
+ const float max_distance = use_max_distance ? RNA_float_get(op->ptr, "max_distance") : FLT_MAX;
+ const float ray_radius = RNA_float_get(op->ptr, "ray_radius");
+ const float islands_precision = RNA_float_get(op->ptr, "islands_precision");
+
+ const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
+ const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
+ int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
+ int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
+ const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
+
+ const int mix_mode = RNA_enum_get(op->ptr, "mix_mode");
+ const float mix_factor = RNA_float_get(op->ptr, "mix_factor");
+
+ SpaceTransform space_transform_data;
+ SpaceTransform *space_transform = use_object_transform ? &space_transform_data : NULL;
+
+ if (reverse_transfer && ((ID *)(ob_src->data))->lib) {
+ /* Do not transfer to linked data, not supported. */
+ return OPERATOR_CANCELLED;
+ }
+
+ if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
+ layers_select_src[fromto_idx] = layers_src;
+ layers_select_dst[fromto_idx] = layers_dst;
+ }
+
+ data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, reverse_transfer);
+
+ for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
+ Object *ob_dst = ctx_ob_dst->ptr.data;
+
+ if (reverse_transfer) {
+ SWAP(Object *, ob_src, ob_dst);
+ }
+
+ if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, reverse_transfer)) {
+ if (space_transform) {
+ BLI_SPACE_TRANSFORM_SETUP(space_transform, ob_dst, ob_src);
+ }
+
+ if (BKE_object_data_transfer_mesh(
+ scene, ob_src, ob_dst, data_type, use_create,
+ map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode,
+ space_transform, max_distance, ray_radius, islands_precision,
+ layers_select_src, layers_select_dst,
+ mix_mode, mix_factor, NULL, false, op->reports))
+ {
+ changed = true;
+ }
+ }
+
+ if (reverse_transfer) {
+ SWAP(Object *, ob_src, ob_dst);
+ }
+ }
+
+ BLI_freelistN(&ctx_objects);
+
+#if 0 /* TODO */
+ /* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
+ return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+#else
+ (void)changed;
+ return OPERATOR_FINISHED;
+#endif
+}
+
+/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
+/* Note this context poll is only really partial, it cannot check for all possible invalid cases. */
+static int data_transfer_poll(bContext *C)
+{
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && ob->type == OB_MESH && data);
+}
+
+/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
+static bool data_transfer_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
+{
+ PropertyRNA *prop_other;
+
+ const char *prop_id = RNA_property_identifier(prop);
+ const int data_type = RNA_enum_get(ptr, "data_type");
+ bool use_max_distance = false;
+ bool use_modifier = false;
+
+ if ((prop_other = RNA_struct_find_property(ptr, "use_max_distance"))) {
+ use_max_distance = RNA_property_boolean_get(ptr, prop_other);
+ }
+ if ((prop_other = RNA_struct_find_property(ptr, "modifier"))) {
+ use_modifier = RNA_property_is_set(ptr, prop_other);
+ }
+
+ if (STREQ(prop_id, "modifier")) {
+ return use_modifier;
+ }
+
+ if (use_modifier) {
+ /* Hide everything but 'modifier' property, if set. */
+ return false;
+ }
+
+ if (STREQ(prop_id, "max_distance") && !use_max_distance) {
+ return false;
+ }
+ if (STREQ(prop_id, "islands_precision") && !DT_DATATYPE_IS_LOOP(data_type)) {
+ return false;
+ }
+
+ if (STREQ(prop_id, "vert_mapping") && !DT_DATATYPE_IS_VERT(data_type)) {
+ return false;
+ }
+ if (STREQ(prop_id, "edge_mapping") && !DT_DATATYPE_IS_EDGE(data_type)) {
+ return false;
+ }
+ if (STREQ(prop_id, "loop_mapping") && !DT_DATATYPE_IS_LOOP(data_type)) {
+ return false;
+ }
+ if (STREQ(prop_id, "poly_mapping") && !DT_DATATYPE_IS_POLY(data_type)) {
+ return false;
+ }
+
+ if ((STREQ(prop_id, "layers_select_src") || STREQ(prop_id, "layers_select_dst")) &&
+ !DT_DATATYPE_IS_MULTILAYERS(data_type))
+ {
+ return false;
+ }
+
+ /* Else, show it! */
+ return true;
+}
+
+/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
+static void data_transfer_ui(bContext *C, wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ /* Main auto-draw call */
+ uiDefAutoButsRNA(layout, &ptr, data_transfer_draw_check_prop, '\0');
+}
+
+/* transfers weight from active to selected */
+void OBJECT_OT_data_transfer(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* Identifiers.*/
+ ot->name = "Transfer Mesh Data";
+ ot->idname = "OBJECT_OT_data_transfer";
+ ot->description = "Transfer data layer(s) (weights, edge sharp, ...) from active to selected meshes";
+
+ /* API callbacks.*/
+ ot->poll = data_transfer_poll;
+ ot->invoke = WM_menu_invoke;
+ ot->exec = data_transfer_exec;
+ ot->check = data_transfer_check;
+ ot->ui = data_transfer_ui;
+
+ /* Flags.*/
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties.*/
+ prop = RNA_def_boolean(ot->srna, "use_reverse_transfer", false, "Reverse Transfer",
+ "Transfer from selected objects to active one");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ /* Data type to transfer. */
+ ot->prop = RNA_def_enum(ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
+ RNA_def_boolean(ot->srna, "use_create", true, "Create Data", "Add data layers on destination meshes if needed");
+
+ /* Mapping methods. */
+ RNA_def_enum(ot->srna, "vert_mapping", DT_method_vertex_items, MREMAP_MODE_VERT_NEAREST, "Vertex Mapping",
+ "Method used to map source vertices to destination ones");
+ RNA_def_enum(ot->srna, "edge_mapping", DT_method_edge_items, MREMAP_MODE_EDGE_NEAREST, "Edge Mapping",
+ "Method used to map source edges to destination ones");
+ RNA_def_enum(ot->srna, "loop_mapping", DT_method_loop_items, MREMAP_MODE_LOOP_NEAREST_POLYNOR,
+ "Face Corner Mapping", "Method used to map source faces' corners to destination ones");
+ RNA_def_enum(ot->srna, "poly_mapping", DT_method_poly_items, MREMAP_MODE_POLY_NEAREST, "Face Mapping",
+ "Method used to map source faces to destination ones");
+
+ /* Mapping options and filtering. */
+ RNA_def_boolean(ot->srna, "use_object_transform", true, "Object Transform",
+ "Evaluate source and destination meshes in their respective object spaces");
+ RNA_def_boolean(ot->srna, "use_max_distance", false, "Only Neighbor Geometry",
+ "Source elements must be closer than given distance from destination one");
+ prop = RNA_def_float(ot->srna, "max_distance", 1.0f, 0.0f, FLT_MAX, "Max Distance",
+ "Maximum allowed distance between source and destination element, for non-topology mappings",
+ 0.0f, 100.0f);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ prop = RNA_def_float(ot->srna, "ray_radius", 0.0f, 0.0f, FLT_MAX, "Ray Radius",
+ "'Width' of rays (especially useful when raycasting against vertices or edges)",
+ 0.0f, 10.0f);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ prop = RNA_def_float(ot->srna, "islands_precision", 0.1f, 0.0f, 10.0f, "Islands Precision",
+ "Factor controlling precision of islands handling (the higher, the better the results)",
+ 0.0f, 1.0f);
+ RNA_def_property_subtype(prop, PROP_FACTOR);
+
+ /* How to handle multi-layers types of data. */
+ prop = RNA_def_enum(ot->srna, "layers_select_src", DT_layers_select_src_items, DT_LAYERS_ACTIVE_SRC,
+ "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_src_itemf);
+
+ prop = RNA_def_enum(ot->srna, "layers_select_dst", DT_layers_select_dst_items, DT_LAYERS_ACTIVE_DST,
+ "Destination Layers Matching", "How to match source and destination layers");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_dst_itemf);
+
+ prop = RNA_def_enum(ot->srna, "mix_mode", DT_mix_mode_items, CDT_MIX_TRANSFER, "Mix Mode",
+ "How to affect destination elements with source values");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_mix_mode_itemf);
+ RNA_def_float(ot->srna, "mix_factor", 1.0f, 0.0f, 1.0f, "Mix Factor",
+ "Factor to use when applying data to destination (exact behavior depends on mix mode)", 0.0f, 1.0f);
+}
+
+/******************************************************************************/
+/* Note: This operator is hybrid, it can work as a usual standalone Object operator,
+ * or as a DataTransfer modifier tool.
+ */
+
+static int datalayout_transfer_poll(bContext *C)
+{
+ return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH)) || data_transfer_poll(C));
+}
+
+static int datalayout_transfer_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob_act = ED_object_active_context(C);
+ DataTransferModifierData *dtmd;
+
+ dtmd = (DataTransferModifierData *)edit_modifier_property_get(op, ob_act, eModifierType_DataTransfer);
+
+ /* If we have a modifier, we transfer data layout from this modifier's source object to active one.
+ * Else, we transfer data layout from active object to all selected ones. */
+ if (dtmd) {
+ Object *ob_src = dtmd->ob_source;
+ Object *ob_dst = ob_act;
+
+ const bool use_delete = false; /* Never when used from modifier, for now. */
+
+ if (!ob_src) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_object_data_transfer_layout(scene, ob_src, ob_dst, dtmd->data_types, use_delete,
+ dtmd->layers_select_src, dtmd->layers_select_dst);
+ }
+ else {
+ Object *ob_src = ob_act;
+
+ ListBase ctx_objects;
+ CollectionPointerLink *ctx_ob_dst;
+
+ const int data_type = RNA_enum_get(op->ptr, "data_type");
+ const bool use_delete = RNA_boolean_get(op->ptr, "use_delete");
+
+ const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
+ const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
+ int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
+ int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
+ const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
+
+ if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
+ layers_select_src[fromto_idx] = layers_src;
+ layers_select_dst[fromto_idx] = layers_dst;
+ }
+
+ data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, false);
+
+ for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
+ Object *ob_dst = ctx_ob_dst->ptr.data;
+ if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) {
+ BKE_object_data_transfer_layout(scene, ob_src, ob_dst, data_type, use_delete,
+ layers_select_src, layers_select_dst);
+ }
+ }
+
+ BLI_freelistN(&ctx_objects);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int datalayout_transfer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (edit_modifier_invoke_properties(C, op)) {
+ return datalayout_transfer_exec(C, op);
+ }
+ else {
+ return WM_menu_invoke(C, op, event);
+ }
+}
+
+void OBJECT_OT_datalayout_transfer(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ ot->name = "Transfer Mesh Data Layout";
+ ot->description = "Transfer layout of data layer(s) from active to selected meshes";
+ ot->idname = "OBJECT_OT_datalayout_transfer";
+
+ ot->poll = datalayout_transfer_poll;
+ ot->invoke = datalayout_transfer_invoke;
+ ot->exec = datalayout_transfer_exec;
+ ot->check = data_transfer_check;
+ ot->ui = data_transfer_ui;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties.*/
+ edit_modifier_properties(ot);
+
+ /* Data type to transfer. */
+ ot->prop = RNA_def_enum(ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
+ RNA_def_boolean(ot->srna, "use_delete", false, "Exact Match",
+ "Also delete some data layers from destination if necessary, so that it matches exactly source");
+
+ /* How to handle multi-layers types of data. */
+ prop = RNA_def_enum(ot->srna, "layers_select_src", DT_layers_select_src_items, DT_LAYERS_ACTIVE_SRC,
+ "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_src_itemf);
+
+ prop = RNA_def_enum(ot->srna, "layers_select_dst", DT_layers_select_dst_items, DT_LAYERS_ACTIVE_DST,
+ "Destination Layers Matching", "How to match source and destination layers");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_dst_itemf);
+}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 6fa3caa6172..64fddf1b6a1 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -37,6 +37,11 @@ struct Lattice;
struct Curve;
struct Object;
struct Mesh;
+struct bContext;
+struct StructRNA;
+struct wmOperator;
+
+struct ModifierData;
struct HookModifierData;
/* add hook menu */
@@ -155,6 +160,12 @@ void GROUP_OT_objects_add_active(struct wmOperatorType *ot);
void GROUP_OT_objects_remove_active(struct wmOperatorType *ot);
/* object_modifier.c */
+int edit_modifier_poll_generic(struct bContext *C, struct StructRNA *rna_type, int obtype_flag);
+int edit_modifier_poll(struct bContext *C);
+void edit_modifier_properties(struct wmOperatorType *ot);
+int edit_modifier_invoke_properties(struct bContext *C, struct wmOperator *op);
+struct ModifierData *edit_modifier_property_get(struct wmOperator *op, struct Object *ob, int type);
+
void OBJECT_OT_modifier_add(struct wmOperatorType *ot);
void OBJECT_OT_modifier_remove(struct wmOperatorType *ot);
void OBJECT_OT_modifier_move_up(struct wmOperatorType *ot);
@@ -214,7 +225,6 @@ void OBJECT_OT_vertex_group_remove_from(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_select(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_deselect(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_copy_to_linked(struct wmOperatorType *ot);
-void OBJECT_OT_vertex_group_transfer_weight(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_copy_to_selected(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_normalize(struct wmOperatorType *ot);
@@ -266,5 +276,9 @@ void OBJECT_OT_lod_remove(struct wmOperatorType *ot);
/* object_random.c */
void OBJECT_OT_vertex_random(struct wmOperatorType *ot);
+/* object_transfer_data.c */
+void OBJECT_OT_data_transfer(struct wmOperatorType *ot);
+void OBJECT_OT_datalayout_transfer(struct wmOperatorType *ot);
+
#endif /* __OBJECT_INTERN_H__ */
diff --git a/source/blender/editors/object/object_lod.c b/source/blender/editors/object/object_lod.c
index 48e980015a7..ced306178b8 100644
--- a/source/blender/editors/object/object_lod.c
+++ b/source/blender/editors/object/object_lod.c
@@ -32,18 +32,22 @@
#include "DNA_object_types.h"
#include "BKE_context.h"
-#include "BKE_object.h"
#include "WM_api.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "ED_screen.h"
#include "ED_object.h"
+#ifdef WITH_GAMEENGINE
+# include "BKE_object.h"
+
+# include "RNA_enum_types.h"
+#endif
+
#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 cec5c683221..5a479af83b5 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -68,6 +68,7 @@
#include "BKE_multires.h"
#include "BKE_report.h"
#include "BKE_object.h"
+#include "BKE_object_deform.h"
#include "BKE_ocean.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
@@ -807,7 +808,7 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot)
/************************ generic functions for operators using mod names and data context *********************/
-static int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
+int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
@@ -819,17 +820,17 @@ static int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obty
return 1;
}
-static int edit_modifier_poll(bContext *C)
+int edit_modifier_poll(bContext *C)
{
return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
}
-static void edit_modifier_properties(wmOperatorType *ot)
+void edit_modifier_properties(wmOperatorType *ot)
{
RNA_def_string(ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
}
-static int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
+int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
{
ModifierData *md;
@@ -848,7 +849,7 @@ static int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
return false;
}
-static ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
+ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
{
char modifier_name[MAX_NAME];
ModifierData *md;
@@ -1353,7 +1354,7 @@ void OBJECT_OT_multires_external_save(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- WM_operator_properties_filesel(ot, FOLDERFILE | BTXFILE, FILE_SPECIAL, FILE_SAVE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_BTX, FILE_SPECIAL, FILE_SAVE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
edit_modifier_properties(ot);
}
@@ -1667,7 +1668,7 @@ static void skin_armature_bone_create(Object *skin_ob,
BLI_snprintf(bone->name, sizeof(bone->name), "Bone.%.2d", endx);
/* add bDeformGroup */
- if ((dg = ED_vgroup_add_name(skin_ob, bone->name))) {
+ if ((dg = BKE_object_defgroup_add_name(skin_ob, bone->name))) {
ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE);
ED_vgroup_vert_add(skin_ob, dg, v, 1, WEIGHT_REPLACE);
}
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index bef64fec8d0..15eb9090ce5 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -40,7 +40,6 @@
#include "BKE_context.h"
#include "RNA_access.h"
-#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -178,7 +177,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_vertex_group_select);
WM_operatortype_append(OBJECT_OT_vertex_group_deselect);
WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked);
- WM_operatortype_append(OBJECT_OT_vertex_group_transfer_weight);
WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected);
WM_operatortype_append(OBJECT_OT_vertex_group_copy);
WM_operatortype_append(OBJECT_OT_vertex_group_normalize);
@@ -250,6 +248,9 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_lod_remove);
WM_operatortype_append(OBJECT_OT_vertex_random);
+
+ WM_operatortype_append(OBJECT_OT_data_transfer);
+ WM_operatortype_append(OBJECT_OT_datalayout_transfer);
}
void ED_operatormacros_object(void)
@@ -421,6 +422,10 @@ void ED_keymap_object(wmKeyConfig *keyconf)
WM_keymap_add_menu(keymap, "VIEW3D_MT_object_specials", WKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OBJECT_OT_data_transfer", TKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ /* XXX No more available 'T' shortcuts... :/ */
+ /* WM_keymap_verify_item(keymap, "OBJECT_OT_datalayout_transfer", TKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); */
+
for (i = 0; i <= 5; i++) {
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_subdivision_set", ZEROKEY + i, KM_PRESS, KM_CTRL, 0);
RNA_int_set(kmi->ptr, "level", i);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 48e617eda11..67b5c8061cd 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -803,6 +803,7 @@ static void parent_set_vert_find(KDTree *tree, Object *child, int vert_par[3], b
tot = BLI_kdtree_find_nearest_n(tree, co_find, nearest, 3);
BLI_assert(tot == 3);
+ UNUSED_VARS(tot);
vert_par[0] = nearest[0].index;
vert_par[1] = nearest[1].index;
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index 6bb23a4a7f0..3fe8c86ef5c 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -75,10 +75,10 @@
/*********************** add shape key ***********************/
-static void ED_object_shape_key_add(bContext *C, Scene *scene, Object *ob, const bool from_mix)
+static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix)
{
KeyBlock *kb;
- if ((kb = BKE_object_insert_shape_key(scene, ob, NULL, from_mix))) {
+ if ((kb = BKE_object_insert_shape_key(ob, NULL, from_mix))) {
Key *key = BKE_key_from_object(ob);
/* for absolute shape keys, new keys may not be added last */
ob->shapenr = BLI_findindex(&key->block, kb) + 1;
@@ -320,11 +320,10 @@ static int shape_key_poll(bContext *C)
static int shape_key_add_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
const bool from_mix = RNA_boolean_get(op->ptr, "from_mix");
- ED_object_shape_key_add(C, scene, ob, from_mix);
+ ED_object_shape_key_add(C, ob, from_mix);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index f19765a5344..92fe5ded4dd 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -33,9 +33,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
-#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -69,7 +67,6 @@
#include "ED_armature.h"
#include "ED_keyframing.h"
-#include "ED_mball.h"
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_view3d.h"
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 49c77770467..e70281c502b 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -36,16 +36,13 @@
#include "MEM_guardedalloc.h"
-#include "DNA_cloth_types.h"
#include "DNA_curve_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
#include "DNA_scene_types.h"
-#include "DNA_particle_types.h"
#include "BLI_alloca.h"
#include "BLI_array.h"
@@ -54,7 +51,6 @@
#include "BLI_utildefines.h"
#include "BLI_linklist_stack.h"
-#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
@@ -85,11 +81,6 @@
#include "object_intern.h"
/************************ Exported Functions **********************/
-static void vgroup_remap_update_users(Object *ob, int *map);
-static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *defgroup);
-static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg);
-static void vgroup_delete_all(Object *ob);
-
static bool vertex_group_use_vert_sel(Object *ob)
{
if (ob->mode == OB_MODE_EDIT) {
@@ -126,81 +117,6 @@ bool ED_vgroup_sync_from_pose(Object *ob)
return false;
}
-bool ED_vgroup_object_is_edit_mode(Object *ob)
-{
- if (ob->type == OB_MESH)
- return (BKE_editmesh_from_object(ob) != NULL);
- else if (ob->type == OB_LATTICE)
- return (((Lattice *)ob->data)->editlatt != NULL);
-
- return false;
-}
-
-bDeformGroup *ED_vgroup_add_name(Object *ob, const char *name)
-{
- bDeformGroup *defgroup;
-
- if (!ob || !OB_TYPE_SUPPORT_VGROUP(ob->type))
- return NULL;
-
- defgroup = BKE_defgroup_new(ob, name);
-
- ob->actdef = BLI_listbase_count(&ob->defbase);
-
- return defgroup;
-}
-
-bDeformGroup *ED_vgroup_add(Object *ob)
-{
- return ED_vgroup_add_name(ob, DATA_("Group"));
-}
-
-void ED_vgroup_delete(Object *ob, bDeformGroup *defgroup)
-{
- BLI_assert(BLI_findindex(&ob->defbase, defgroup) != -1);
-
- if (ED_vgroup_object_is_edit_mode(ob))
- vgroup_delete_edit_mode(ob, defgroup);
- else
- vgroup_delete_object_mode(ob, defgroup);
-}
-
-void ED_vgroup_clear(Object *ob)
-{
- bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
- int edit_mode = ED_vgroup_object_is_edit_mode(ob);
-
- while (dg) {
- bDeformGroup *next_dg = dg->next;
-
- if (edit_mode)
- vgroup_delete_edit_mode(ob, dg);
- else
- vgroup_delete_object_mode(ob, dg);
-
- dg = next_dg;
- }
-}
-
-bool ED_vgroup_data_create(ID *id)
-{
- /* create deform verts */
-
- if (GS(id->name) == ID_ME) {
- Mesh *me = (Mesh *)id;
- me->dvert = CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
- return true;
- }
- else if (GS(id->name) == ID_LT) {
- Lattice *lt = (Lattice *)id;
- lt->dvert = MEM_callocN(sizeof(MDeformVert) * lt->pntsu * lt->pntsv * lt->pntsw, "lattice deformVert");
- return true;
- }
- else {
- return false;
- }
-}
-
/**
* Removes out of range MDeformWeights
*/
@@ -327,31 +243,6 @@ bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, co
return false;
}
-static bool ed_vgroup_dm_parray_alloc(DerivedMesh *dm, MDeformVert ***dvert_arr, int *dvert_tot)
-{
- *dvert_tot = 0;
- *dvert_arr = NULL;
-
- if (dm) {
- MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
- if (dvert) {
- int i, totvert = dm->getNumVerts(dm);
-
- *dvert_tot = totvert;
- *dvert_arr = MEM_mallocN(sizeof(void *) * totvert, "vgroup parray from me");
-
- for (i = 0; i < totvert; i++) {
- (*dvert_arr)[i] = dvert + i;
- }
-
- return true;
- }
- }
-
- return false;
-}
-
/**
* For use with tools that use ED_vgroup_parray_alloc with \a use_vert_sel == true.
* This finds the unselected mirror deform verts and copys the weights to them from the selected.
@@ -465,34 +356,6 @@ void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array, const int dvert_tot
}
}
-/* returns true if the id type supports weights */
-bool ED_vgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
-{
- if (id) {
- switch (GS(id->name)) {
- case ID_ME:
- {
- Mesh *me = (Mesh *)id;
- *dvert_arr = me->dvert;
- *dvert_tot = me->totvert;
- return true;
- }
- case ID_LT:
- {
- Lattice *lt = (Lattice *)id;
- lt = (lt->editlatt) ? lt->editlatt->latt : lt;
- *dvert_arr = lt->dvert;
- *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
- return true;
- }
- }
- }
-
- *dvert_arr = NULL;
- *dvert_tot = 0;
- return false;
-}
-
/* matching index only */
bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
{
@@ -511,7 +374,7 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
- if ((dvert_array == NULL) && (dvert_array_from != NULL) && ED_vgroup_data_create(ob->data)) {
+ if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) {
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
new_vgroup = true;
}
@@ -523,7 +386,7 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
if (new_vgroup == true) {
/* free the newly added vgroup since it wasn't compatible */
- vgroup_delete_all(ob);
+ BKE_object_defgroup_remove_all(ob);
}
/* if true: both are 0 and nothing needs changing, consider this a success */
@@ -541,7 +404,7 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
for (i = 0; i <= defbase_tot_from; i++) remap[i] = i;
for (; i <= defbase_tot; i++) remap[i] = 0; /* can't use these, so disable */
- vgroup_remap_update_users(ob, remap);
+ BKE_object_defgroup_remap_update_users(ob, remap);
MEM_freeN(remap);
}
@@ -682,7 +545,7 @@ static void vgroup_normalize_active(Object *ob, eVGroupSelect subset_type)
return;
}
- vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
defvert_normalize_subset(dvert_act, vgroup_validmap, vgroup_tot);
MEM_freeN((void *)vgroup_validmap);
@@ -703,7 +566,7 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
BMEditMesh *em = me->edit_btmesh;
MDeformVert *dvert_act;
int i, vgroup_tot, subset_count;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
if (em) {
@@ -747,51 +610,6 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
/***********************Start weight transfer (WT)*********************************/
-typedef enum WT_VertexGroupMode {
- WT_REPLACE_ACTIVE_VERTEX_GROUP = 1,
- WT_REPLACE_ALL_VERTEX_GROUPS = 2
-} WT_VertexGroupMode;
-
-typedef enum WT_Method {
- WT_BY_INDEX = 1,
- WT_BY_NEAREST_VERTEX = 2,
- WT_BY_NEAREST_FACE = 3,
- WT_BY_NEAREST_VERTEX_IN_FACE = 4
-} WT_Method;
-
-typedef enum WT_ReplaceMode {
- WT_REPLACE_ALL_WEIGHTS = 1,
- WT_REPLACE_EMPTY_WEIGHTS = 2
-} WT_ReplaceMode;
-
-static EnumPropertyItem WT_vertex_group_mode_item[] = {
- {WT_REPLACE_ACTIVE_VERTEX_GROUP,
- "WT_REPLACE_ACTIVE_VERTEX_GROUP", 0, "Active", "Transfer active vertex group from selected to active mesh"},
- {WT_REPLACE_ALL_VERTEX_GROUPS,
- "WT_REPLACE_ALL_VERTEX_GROUPS", 0, "All", "Transfer all vertex groups from selected to active mesh"},
- {0, NULL, 0, NULL, NULL}
-};
-
-static EnumPropertyItem WT_method_item[] = {
- {WT_BY_INDEX,
- "WT_BY_INDEX", 0, "Vertex index", "Copy for identical meshes"},
- {WT_BY_NEAREST_VERTEX,
- "WT_BY_NEAREST_VERTEX", 0, "Nearest vertex", "Copy weight from closest vertex"},
- {WT_BY_NEAREST_FACE,
- "WT_BY_NEAREST_FACE", 0, "Nearest face", "Barycentric interpolation from nearest face"},
- {WT_BY_NEAREST_VERTEX_IN_FACE,
- "WT_BY_NEAREST_VERTEX_IN_FACE", 0, "Nearest vertex in face", "Copy weight from closest vertex in nearest face"},
- {0, NULL, 0, NULL, NULL}
-};
-
-static EnumPropertyItem WT_replace_mode_item[] = {
- {WT_REPLACE_ALL_WEIGHTS,
- "WT_REPLACE_ALL_WEIGHTS", 0, "All", "Overwrite all weights"},
- {WT_REPLACE_EMPTY_WEIGHTS,
- "WT_REPLACE_EMPTY_WEIGHTS", 0, "Empty", "Add weights to vertices with no weight"},
- {0, NULL, 0, NULL, NULL}
-};
-
static EnumPropertyItem WT_vertex_group_select_item[] = {
{WT_VGROUP_ACTIVE,
"ACTIVE", 0, "Active Group", "The active Vertex Group"},
@@ -867,298 +685,6 @@ static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_act
ot->prop = prop;
}
-/* Copy weight.*/
-static void vgroup_transfer_weight(float *r_weight_dst, const float weight_src, const WT_ReplaceMode replace_mode)
-{
- switch (replace_mode) {
- case WT_REPLACE_ALL_WEIGHTS:
- *r_weight_dst = weight_src;
- break;
-
- case WT_REPLACE_EMPTY_WEIGHTS:
- if (*r_weight_dst == 0.0f) {
- *r_weight_dst = weight_src;
- }
- break;
-
- default:
- BLI_assert(0);
- break;
- }
-}
-
-/* Could be exposed externally by implementing it in header with the rest.
- * Simple refactoring will break something.
- * For now, naming is ed_ instead of ED_*/
-static bool ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGroup *dg_src, Scene *scene,
- WT_Method method, WT_ReplaceMode replace_mode, wmOperator *op)
-{
- bDeformGroup *dg_dst;
- Mesh *me_dst;
- DerivedMesh *dmesh_src;
- BVHTreeFromMesh tree_mesh_vertices_src, tree_mesh_faces_src = {NULL};
- MDeformVert **dv_array_src, **dv_array_dst, **dv_src, **dv_dst;
- MVert *mv_dst, *mv_src;
- MFace *mface_src, *mf;
- BVHTreeNearest nearest;
- MDeformWeight *dw_dst, *dw_src;
- int dv_tot_src, dv_tot_dst, i, v_index, index_dst, index_src, index_nearest, index_nearest_vertex;
- unsigned int f_index;
- float weight, tmp_weight[4], tmp_co[3], normal[3], tmp_mat[4][4], dist_v1, dist_v2, dist_v3, dist_v4;
- const int use_vert_sel = vertex_group_use_vert_sel(ob_dst);
- bool is_dg_dst_new = false;
-
- /* Ensure vertex group on target.*/
- if ((dg_dst = defgroup_find_name(ob_dst, dg_src->name)) == NULL) {
- dg_dst = BKE_defgroup_new(ob_dst, dg_src->name);
- is_dg_dst_new = true;
- }
-
- /* Get meshes.*/
- dmesh_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MASK_MDEFORMVERT);
- me_dst = ob_dst->data;
-
- /* Get vertex group array from source mesh */
- if (!ed_vgroup_dm_parray_alloc(dmesh_src, &dv_array_src, &dv_tot_src)) {
- BKE_report(op->reports, RPT_ERROR, "Transfer failed (source mesh does not have any vertex groups)");
- return false;
- }
-
- /* Create data in memory when nothing there.*/
- if (!me_dst->dvert) ED_vgroup_data_create(&me_dst->id);
-
- /* Get vertex group for destination mesh */
- ED_vgroup_parray_alloc(&me_dst->id, &dv_array_dst, &dv_tot_dst, use_vert_sel);
-
- /* Get indexes of vertex groups.*/
- index_src = BLI_findindex(&ob_src->defbase, dg_src);
- index_dst = BLI_findindex(&ob_dst->defbase, dg_dst);
-
- /* Get vertices.*/
- mv_dst = me_dst->mvert;
- mv_src = dmesh_src->getVertArray(dmesh_src);
-
- /* Prepare transformation matrix.*/
- invert_m4_m4(ob_src->imat, ob_src->obmat);
- mul_m4_m4m4(tmp_mat, ob_src->imat, ob_dst->obmat);
-
- /* Clear weights.*/
- if (replace_mode == WT_REPLACE_ALL_WEIGHTS) {
- for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++) {
-
- if (*dv_dst == NULL) continue;
-
- dw_dst = defvert_find_index(*dv_dst, index_dst);
- /* Remove vertex from group.*/
- if (dw_dst) defvert_remove_group(*dv_dst, dw_dst);
- }
- }
-
- switch (method) {
-
- case WT_BY_INDEX:
- /* Check if indices are matching, delete and return if not.*/
- if (ob_dst == ob_src || dv_tot_dst == 0 || dv_tot_dst != dv_tot_src ||
- dv_array_src == NULL || dv_array_dst == NULL)
- {
- if (is_dg_dst_new) {
- ED_vgroup_delete(ob_dst, dg_dst);
- }
-
- if (dv_array_src) MEM_freeN(dv_array_src);
- if (dv_array_dst) MEM_freeN(dv_array_dst);
- dmesh_src->release(dmesh_src);
- BKE_report(op->reports, RPT_ERROR, "Transfer failed (indices are not matching)");
- return false;
- }
-
- /* Loop through the vertices.*/
- for (i = 0, dv_src = dv_array_src, dv_dst = dv_array_dst;
- i < me_dst->totvert;
- i++, dv_dst++, dv_src++, mv_src++, mv_dst++)
- {
-
- if (*dv_dst == NULL) {
- continue;
- }
-
- /* Copy weight.*/
- dw_src = defvert_find_index(*dv_src, index_src);
- if (dw_src && dw_src->weight) {
- dw_dst = defvert_verify_index(*dv_dst, index_dst);
- vgroup_transfer_weight(&dw_dst->weight, dw_src->weight, replace_mode);
- }
- }
- break;
-
- case WT_BY_NEAREST_VERTEX:
- /* Make node tree.*/
- bvhtree_from_mesh_verts(&tree_mesh_vertices_src, dmesh_src, FLT_EPSILON, 2, 6);
-
- /* Loop trough vertices.*/
- for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) {
-
- if (*dv_dst == NULL) {
- continue;
- }
-
- /* Reset nearest.*/
- nearest.dist_sq = FLT_MAX;
- /* It is faster to start searching at the top of the tree instead of previous search result.*/
- nearest.index = -1;
-
- /* Transform into target space.*/
- mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co);
-
- /* Node tree accelerated search for closest vetex.*/
- BLI_bvhtree_find_nearest(tree_mesh_vertices_src.tree, tmp_co,
- &nearest, tree_mesh_vertices_src.nearest_callback, &tree_mesh_vertices_src);
-
- /* Copy weight that are not NULL including weight value 0. In relevant cases, existing weights are
- * overwritten prior to this. See the "Clear weights." step above.*/
- dw_src = defvert_find_index(dv_array_src[nearest.index], index_src);
- if (dw_src && dw_src->weight) {
- dw_dst = defvert_verify_index(*dv_dst, index_dst);
- vgroup_transfer_weight(&dw_dst->weight, dw_src->weight, replace_mode);
- }
- }
-
- /* Free memory.*/
- free_bvhtree_from_mesh(&tree_mesh_vertices_src);
- break;
-
- case WT_BY_NEAREST_FACE:
- /* Get faces.*/
- DM_ensure_tessface(dmesh_src);
- mface_src = dmesh_src->getTessFaceArray(dmesh_src);
-
- /* Make node tree.*/
- bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, FLT_EPSILON, 2, 6);
-
- /* Loop through the vertices.*/
- for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) {
-
- if (*dv_dst == NULL) {
- continue;
- }
-
- /* Reset nearest.*/
- nearest.dist_sq = FLT_MAX;
- /* It is faster to start searching at the top of the tree instead of previous search result.*/
- nearest.index = -1;
-
- /* Transform into target space.*/
- mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co);
-
- /* Node tree accelerated search for closest face.*/
- BLI_bvhtree_find_nearest(tree_mesh_faces_src.tree, tmp_co,
- &nearest, tree_mesh_faces_src.nearest_callback, &tree_mesh_faces_src);
- index_nearest = nearest.index;
-
- /* Project onto face.*/
- mf = &mface_src[index_nearest];
- normal_tri_v3(normal, mv_src[mf->v1].co, mv_src[mf->v2].co, mv_src[mf->v3].co);
- project_v3_plane(tmp_co, normal, mv_src[mf->v1].co);
-
- /* Interpolate weights over face.*/
- interp_weights_face_v3(tmp_weight,
- mv_src[mf->v1].co,
- mv_src[mf->v2].co,
- mv_src[mf->v3].co,
- mf->v4 ? mv_src[mf->v4].co : NULL,
- tmp_co);
-
- /* Get weights from face.*/
- f_index = mf->v4 ? 3 : 2;
- weight = 0.0f;
- do {
- v_index = (&mf->v1)[f_index];
- weight += tmp_weight[f_index] * defvert_find_weight(dv_array_src[v_index], index_src);
- } while (f_index--);
-
- /* Copy weight that are not NULL including weight value 0. In relevant cases, existing weights are
- * overwritten prior to this. See the "Clear weights." step above.*/
- if (weight > 0.0f) {
- dw_dst = defvert_verify_index(*dv_dst, index_dst);
- vgroup_transfer_weight(&dw_dst->weight, weight, replace_mode);
- }
- }
-
- /* Free memory.*/
- free_bvhtree_from_mesh(&tree_mesh_faces_src);
- break;
-
- case WT_BY_NEAREST_VERTEX_IN_FACE:
- /* Get faces.*/
- DM_ensure_tessface(dmesh_src);
- mface_src = dmesh_src->getTessFaceArray(dmesh_src);
-
- /* Make node tree.*/
- bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, FLT_EPSILON, 2, 6);
-
- /* Loop through the vertices.*/
- for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) {
-
- if (*dv_dst == NULL) {
- continue;
- }
-
- /* Reset nearest.*/
- nearest.dist_sq = FLT_MAX;
- /* It is faster to start searching at the top of the tree instead of previous search result.*/
- nearest.index = -1;
-
- /* Transform into target space.*/
- mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co);
-
- /* Node tree accelerated search for closest face.*/
- BLI_bvhtree_find_nearest(tree_mesh_faces_src.tree, tmp_co,
- &nearest, tree_mesh_faces_src.nearest_callback, &tree_mesh_faces_src);
- index_nearest = nearest.index;
-
- /* Get distances.*/
- mf = &mface_src[index_nearest];
- dist_v1 = len_squared_v3v3(tmp_co, mv_src[mf->v1].co);
- dist_v2 = len_squared_v3v3(tmp_co, mv_src[mf->v2].co);
- dist_v3 = len_squared_v3v3(tmp_co, mv_src[mf->v3].co);
-
- /* Get closest vertex.*/
- f_index = mf->v4 ? 3 : 2;
- if (dist_v1 < dist_v2 && dist_v1 < dist_v3) index_nearest_vertex = mf->v1;
- else if (dist_v2 < dist_v3) index_nearest_vertex = mf->v2;
- else index_nearest_vertex = mf->v3;
- if (f_index == 3) {
- dist_v4 = len_squared_v3v3(tmp_co, mv_src[mf->v4].co);
- if (dist_v4 < dist_v1 && dist_v4 < dist_v2 && dist_v4 < dist_v3) {
- index_nearest_vertex = mf->v4;
- }
- }
-
- /* Copy weight that are not NULL including weight value 0. In relevant cases, existing weights are
- * overwritten prior to this. See the "Clear weights." step above.*/
- dw_src = defvert_find_index(dv_array_src[index_nearest_vertex], index_src);
- if (dw_src && dw_src->weight) {
- dw_dst = defvert_verify_index(*dv_dst, index_dst);
- vgroup_transfer_weight(&dw_dst->weight, dw_src->weight, replace_mode);
- }
- }
-
- /* Free memory.*/
- free_bvhtree_from_mesh(&tree_mesh_faces_src);
- break;
-
- default:
- BLI_assert(0);
- break;
- }
-
- /* Free memory.*/
- if (dv_array_src) MEM_freeN(dv_array_src);
- if (dv_array_dst) MEM_freeN(dv_array_dst);
- dmesh_src->release(dmesh_src);
-
- return true;
-}
/***********************End weight transfer (WT)***********************************/
@@ -1175,7 +701,7 @@ static void ED_vgroup_nr_vert_add(Object *ob,
int tot;
/* get the vert */
- ED_vgroup_array_get(ob->data, &dvert, &tot);
+ BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
if (dvert == NULL)
return;
@@ -1208,7 +734,7 @@ static void ED_vgroup_nr_vert_add(Object *ob,
break;
case WEIGHT_SUBTRACT:
dw->weight -= weight;
- /* if the weight is zero or less then
+ /* if the weight is zero or less than
* remove the vert from the deform group
*/
if (dw->weight <= 0.0f) {
@@ -1261,8 +787,8 @@ void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight,
/* if there's no deform verts then create some,
*/
- if (ED_vgroup_array_get(ob->data, &dv, &tot) && dv == NULL)
- ED_vgroup_data_create(ob->data);
+ if (BKE_object_defgroup_array_get(ob->data, &dv, &tot) && dv == NULL)
+ BKE_object_defgroup_data_create(ob->data);
/* call another function to do the work
*/
@@ -1287,7 +813,7 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
/* get the deform vertices corresponding to the
* vertnum
*/
- ED_vgroup_array_get(ob->data, &dvert, &tot);
+ BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
if (dvert) {
MDeformVert *dv = &dvert[vertnum];
@@ -1498,86 +1024,6 @@ static void vgroup_duplicate(Object *ob)
}
}
-/**
- * Return the subset type of the Vertex Group Selection
- */
-bool *ED_vgroup_subset_from_select_type(Object *ob, eVGroupSelect subset_type, int *r_vgroup_tot, int *r_subset_count)
-{
- bool *vgroup_validmap = NULL;
- *r_vgroup_tot = BLI_listbase_count(&ob->defbase);
-
- switch (subset_type) {
- case WT_VGROUP_ACTIVE:
- {
- const int def_nr_active = ob->actdef - 1;
- vgroup_validmap = MEM_mallocN(*r_vgroup_tot * sizeof(*vgroup_validmap), __func__);
- memset(vgroup_validmap, false, *r_vgroup_tot * sizeof(*vgroup_validmap));
- if ((def_nr_active >= 0) && (def_nr_active < *r_vgroup_tot)) {
- *r_subset_count = 1;
- vgroup_validmap[def_nr_active] = true;
- }
- else {
- *r_subset_count = 0;
- }
- break;
- }
- case WT_VGROUP_BONE_SELECT:
- {
- vgroup_validmap = BKE_objdef_selected_get(ob, *r_vgroup_tot, r_subset_count);
- break;
- }
- case WT_VGROUP_BONE_DEFORM:
- {
- int i;
- vgroup_validmap = BKE_objdef_validmap_get(ob, *r_vgroup_tot);
- *r_subset_count = 0;
- for (i = 0; i < *r_vgroup_tot; i++) {
- if (vgroup_validmap[i] == true) {
- *r_subset_count += 1;
- }
- }
- break;
- }
- case WT_VGROUP_BONE_DEFORM_OFF:
- {
- int i;
- vgroup_validmap = BKE_objdef_validmap_get(ob, *r_vgroup_tot);
- *r_subset_count = 0;
- for (i = 0; i < *r_vgroup_tot; i++) {
- vgroup_validmap[i] = !vgroup_validmap[i];
- if (vgroup_validmap[i] == true) {
- *r_subset_count += 1;
- }
- }
- break;
- }
- case WT_VGROUP_ALL:
- default:
- {
- vgroup_validmap = MEM_mallocN(*r_vgroup_tot * sizeof(*vgroup_validmap), __func__);
- memset(vgroup_validmap, true, *r_vgroup_tot * sizeof(*vgroup_validmap));
- *r_subset_count = *r_vgroup_tot;
- break;
- }
- }
-
- return vgroup_validmap;
-}
-
-/**
- * store indices from the vgroup_validmap (faster lookups in some cases)
- */
-void ED_vgroup_subset_to_index_array(const bool *vgroup_validmap, const int vgroup_tot,
- int *r_vgroup_subset_map)
-{
- int i, j = 0;
- for (i = 0; i < vgroup_tot; i++) {
- if (vgroup_validmap[i]) {
- r_vgroup_subset_map[j++] = i;
- }
- }
-}
-
static void vgroup_normalize(Object *ob)
{
MDeformWeight *dw;
@@ -2052,7 +1498,7 @@ static void vgroup_normalize_all(Object *ob,
if (dvert_array) {
const int defbase_tot = BLI_listbase_count(&ob->defbase);
- bool *lock_flags = BKE_objdef_lock_flags_get(ob, defbase_tot);
+ bool *lock_flags = BKE_object_defgroup_lock_flags_get(ob, defbase_tot);
if ((lock_active == true) &&
(lock_flags != NULL) &&
@@ -2205,7 +1651,7 @@ static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const i
BLI_SMALLSTACK_DECLARE(dv_stack, MDeformVert *);
- ED_vgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
+ BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count);
@@ -2725,298 +2171,13 @@ cleanup:
}
-static void vgroup_remap_update_users(Object *ob, int *map)
-{
- ExplodeModifierData *emd;
- ModifierData *md;
- ParticleSystem *psys;
- ClothModifierData *clmd;
- ClothSimSettings *clsim;
- int a;
-
- /* these cases don't use names to refer to vertex groups, so when
- * they get deleted the numbers get out of sync, this corrects that */
-
- if (ob->soft)
- ob->soft->vertgroup = map[ob->soft->vertgroup];
-
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Explode) {
- emd = (ExplodeModifierData *)md;
- emd->vgroup = map[emd->vgroup];
- }
- else if (md->type == eModifierType_Cloth) {
- clmd = (ClothModifierData *)md;
- clsim = clmd->sim_parms;
-
- if (clsim) {
- clsim->vgroup_mass = map[clsim->vgroup_mass];
- clsim->vgroup_bend = map[clsim->vgroup_bend];
- clsim->vgroup_struct = map[clsim->vgroup_struct];
- }
- }
- }
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- for (a = 0; a < PSYS_TOT_VG; a++)
- psys->vgroup[a] = map[psys->vgroup[a]];
- }
-}
-
-
-static void vgroup_delete_update_users(Object *ob, int id)
-{
- int i, defbase_tot = BLI_listbase_count(&ob->defbase) + 1;
- int *map = MEM_mallocN(sizeof(int) * defbase_tot, "vgroup del");
-
- map[id] = map[0] = 0;
- for (i = 1; i < id; i++) map[i] = i;
- for (i = id + 1; i < defbase_tot; i++) map[i] = i - 1;
-
- vgroup_remap_update_users(ob, map);
- MEM_freeN(map);
-}
-
-
-static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg)
-{
- MDeformVert *dvert_array = NULL;
- int dvert_tot = 0;
- const int def_nr = BLI_findindex(&ob->defbase, dg);
-
- BLI_assert(def_nr != -1);
-
- ED_vgroup_array_get(ob->data, &dvert_array, &dvert_tot);
-
- if (dvert_array) {
- int i, j;
- MDeformVert *dv;
- for (i = 0, dv = dvert_array; i < dvert_tot; i++, dv++) {
- MDeformWeight *dw;
-
- dw = defvert_find_index(dv, def_nr);
- defvert_remove_group(dv, dw); /* dw can be NULL */
-
- /* inline, make into a function if anything else needs to do this */
- for (j = 0; j < dv->totweight; j++) {
- if (dv->dw[j].def_nr > def_nr) {
- dv->dw[j].def_nr--;
- }
- }
- /* done */
- }
- }
-
- vgroup_delete_update_users(ob, def_nr + 1);
-
- /* Remove the group */
- BLI_freelinkN(&ob->defbase, dg);
-
- /* Update the active deform index if necessary */
- if (ob->actdef > def_nr)
- ob->actdef--;
- if (ob->actdef < 1 && ob->defbase.first)
- ob->actdef = 1;
-
- /* remove all dverts */
- if (BLI_listbase_is_empty(&ob->defbase)) {
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
- me->dvert = NULL;
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = ob->data;
- if (lt->dvert) {
- MEM_freeN(lt->dvert);
- lt->dvert = NULL;
- }
- }
- }
-}
-
-/* only in editmode */
-/* removes from active defgroup, if allverts==0 only selected vertices */
-static bool vgroup_active_remove_verts(Object *ob, const bool allverts, bDeformGroup *dg)
-{
- MDeformVert *dv;
- const int def_nr = BLI_findindex(&ob->defbase, dg);
- bool changed = false;
-
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (me->edit_btmesh) {
- BMEditMesh *em = me->edit_btmesh;
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- if (cd_dvert_offset != -1) {
- BMVert *eve;
- BMIter iter;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
-
- if (dv && dv->dw && (allverts || BM_elem_flag_test(eve, BM_ELEM_SELECT))) {
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
- defvert_remove_group(dv, dw); /* dw can be NULL */
- changed = true;
- }
- }
- }
- }
- else {
- if (me->dvert) {
- MVert *mv;
- int i;
-
- mv = me->mvert;
- dv = me->dvert;
-
- for (i = 0; i < me->totvert; i++, mv++, dv++) {
- if (mv->flag & SELECT) {
- if (dv->dw && (allverts || (mv->flag & SELECT))) {
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
- defvert_remove_group(dv, dw); /* dw can be NULL */
- changed = true;
- }
- }
- }
- }
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
-
- if (lt->dvert) {
- BPoint *bp;
- int i, tot = lt->pntsu * lt->pntsv * lt->pntsw;
-
- for (i = 0, bp = lt->def; i < tot; i++, bp++) {
- if (allverts || (bp->f1 & SELECT)) {
- MDeformWeight *dw;
-
- dv = &lt->dvert[i];
-
- dw = defvert_find_index(dv, def_nr);
- defvert_remove_group(dv, dw); /* dw can be NULL */
- changed = true;
- }
- }
- }
- }
-
- return changed;
-}
-
-static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg)
-{
- int i;
- const int dg_index = BLI_findindex(&ob->defbase, dg);
-
- BLI_assert(dg_index != -1);
-
- /* Make sure that no verts are using this group */
- if (vgroup_active_remove_verts(ob, true, dg) == false) {
- /* do nothing */
- }
- /* Make sure that any verts with higher indices are adjusted accordingly */
- else if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_btmesh;
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- BMIter iter;
- BMVert *eve;
- MDeformVert *dvert;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
-
- if (dvert)
- for (i = 0; i < dvert->totweight; i++)
- if (dvert->dw[i].def_nr > dg_index)
- dvert->dw[i].def_nr--;
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
- BPoint *bp;
- MDeformVert *dvert = lt->dvert;
- int a, tot;
-
- if (dvert) {
- tot = lt->pntsu * lt->pntsv * lt->pntsw;
- for (a = 0, bp = lt->def; a < tot; a++, bp++, dvert++) {
- for (i = 0; i < dvert->totweight; i++) {
- if (dvert->dw[i].def_nr > dg_index)
- dvert->dw[i].def_nr--;
- }
- }
- }
- }
-
- vgroup_delete_update_users(ob, dg_index + 1);
-
- /* Remove the group */
- BLI_freelinkN(&ob->defbase, dg);
-
- /* Update the active deform index if necessary */
- if (ob->actdef > dg_index)
- ob->actdef--;
- if (ob->actdef < 1 && ob->defbase.first)
- ob->actdef = 1;
-
- /* remove all dverts */
- if (BLI_listbase_is_empty(&ob->defbase)) {
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
- me->dvert = NULL;
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
- if (lt->dvert) {
- MEM_freeN(lt->dvert);
- lt->dvert = NULL;
- }
- }
- }
-}
-
-static void vgroup_delete(Object *ob)
+static void vgroup_delete_active(Object *ob)
{
bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
if (!dg)
return;
- if (BKE_object_is_in_editmode_vgroup(ob))
- vgroup_delete_edit_mode(ob, dg);
- else
- vgroup_delete_object_mode(ob, dg);
-}
-
-static void vgroup_delete_all(Object *ob)
-{
- /* Remove all DVerts */
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
- me->dvert = NULL;
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
- if (lt->dvert) {
- MEM_freeN(lt->dvert);
- lt->dvert = NULL;
- }
- }
-
- /* Remove all DefGroups */
- BLI_freelistN(&ob->defbase);
-
- /* Fix counters/indices */
- ob->actdef = 0;
+ BKE_object_defgroup_remove(ob, dg);
}
/* only in editmode */
@@ -3061,7 +2222,7 @@ static void vgroup_assign_verts(Object *ob, const float weight)
int i;
if (!me->dvert) {
- ED_vgroup_data_create(&me->id);
+ BKE_object_defgroup_data_create(&me->id);
}
mv = me->mvert;
@@ -3085,7 +2246,7 @@ static void vgroup_assign_verts(Object *ob, const float weight)
int a, tot;
if (lt->dvert == NULL)
- ED_vgroup_data_create(&lt->id);
+ BKE_object_defgroup_data_create(&lt->id);
dv = lt->dvert;
@@ -3103,22 +2264,6 @@ static void vgroup_assign_verts(Object *ob, const float weight)
}
}
-/* only in editmode */
-/* removes from all defgroup, if allverts==0 only selected vertices */
-static bool vgroup_remove_verts(Object *ob, int allverts)
-{
- bool changed = false;
- /* To prevent code redundancy, we just use vgroup_active_remove_verts, but that
- * only operates on the active vgroup. So we iterate through all groups, by changing
- * active group index
- */
- bDeformGroup *dg;
- for (dg = ob->defbase.first; dg; dg = dg->next) {
- changed |= vgroup_active_remove_verts(ob, allverts, dg);
- }
- return changed;
-}
-
/********************** vertex group operators *********************/
static int vertex_group_poll(bContext *C)
@@ -3150,7 +2295,7 @@ static int vertex_group_mesh_poll(bContext *C)
ob->defbase.first);
}
-static int vertex_group_mesh_supported_poll(bContext *C)
+static int UNUSED_FUNCTION(vertex_group_mesh_supported_poll)(bContext *C)
{
Object *ob = ED_object_context(C);
ID *data = (ob) ? ob->data : NULL;
@@ -3226,7 +2371,7 @@ static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
- ED_vgroup_add(ob);
+ BKE_object_defgroup_add(ob);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -3254,9 +2399,9 @@ static int vertex_group_remove_exec(bContext *C, wmOperator *op)
Object *ob = ED_object_context(C);
if (RNA_boolean_get(op->ptr, "all"))
- vgroup_delete_all(ob);
+ BKE_object_defgroup_remove_all(ob);
else
- vgroup_delete(ob);
+ vgroup_delete_active(ob);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
@@ -3321,7 +2466,7 @@ static int vertex_group_assign_new_exec(bContext *C, wmOperator *op)
{
/* create new group... */
Object *ob = ED_object_context(C);
- ED_vgroup_add(ob);
+ BKE_object_defgroup_add(ob);
/* assign selection to new group */
return vertex_group_assign_exec(C, op);
@@ -3353,14 +2498,14 @@ static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
Object *ob = ED_object_context(C);
if (use_all_groups) {
- if (vgroup_remove_verts(ob, 0) == false) {
+ if (BKE_object_defgroup_clear_all(ob, true) == false) {
return OPERATOR_CANCELLED;
}
}
else {
bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
- if ((dg == NULL) || (vgroup_active_remove_verts(ob, use_all_verts, dg) == false)) {
+ if ((dg == NULL) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) {
return OPERATOR_CANCELLED;
}
}
@@ -3486,7 +2631,7 @@ static int vertex_group_levels_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
vgroup_levels_subset(ob, vgroup_validmap, vgroup_tot, subset_count, offset, gain);
MEM_freeN((void *)vgroup_validmap);
@@ -3552,7 +2697,7 @@ static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
vgroup_normalize_all(ob, vgroup_validmap, vgroup_tot, subset_count, lock_active);
MEM_freeN((void *)vgroup_validmap);
@@ -3674,7 +2819,7 @@ static int vertex_group_invert_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
vgroup_invert_subset(ob, vgroup_validmap, vgroup_tot, subset_count, auto_assign, auto_remove);
MEM_freeN((void *)vgroup_validmap);
@@ -3715,7 +2860,7 @@ static int vertex_group_blend_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
vgroup_blend_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac);
MEM_freeN((void *)vgroup_validmap);
@@ -3791,7 +2936,7 @@ static int vertex_group_clean_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single);
MEM_freeN((void *)vgroup_validmap);
@@ -3832,7 +2977,7 @@ static int vertex_group_quantize_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
vgroup_quantize_subset(ob, vgroup_validmap, vgroup_tot, subset_count, steps);
MEM_freeN((void *)vgroup_validmap);
@@ -3870,7 +3015,7 @@ static int vertex_group_limit_total_exec(bContext *C, wmOperator *op)
int subset_count, vgroup_tot;
- const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
int remove_tot = vgroup_limit_total_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit);
MEM_freeN((void *)vgroup_validmap);
@@ -3934,7 +3079,7 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
/* identifiers */
ot->name = "Mirror Vertex Group";
ot->idname = "OBJECT_OT_vertex_group_mirror";
- ot->description = "Mirror all vertex groups, flip weights and/or names, editing only selected vertices, "
+ ot->description = "Mirror vertex group, flip weights and/or names, editing only selected vertices, "
"flipping when both sides are selected otherwise copy from unselected";
/* api callbacks */
@@ -4032,143 +3177,6 @@ void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob_act = CTX_data_active_object(C);
-
- bDeformGroup *dg_act = BLI_findlink(&ob_act->defbase, (ob_act->actdef - 1));
- char dg_act_name[MAX_VGROUP_NAME]; /* may be freed so copy */
-
- int fail = 0;
- bool changed = false;
-
- WT_VertexGroupMode vertex_group_mode = RNA_enum_get(op->ptr, "group_select_mode");
- WT_Method method = RNA_enum_get(op->ptr, "method");
- WT_ReplaceMode replace_mode = RNA_enum_get(op->ptr, "replace_mode");
-
- if (vertex_group_mode == WT_REPLACE_ACTIVE_VERTEX_GROUP) {
- if (!dg_act) {
- BKE_report(op->reports, RPT_WARNING, "Failed, active object has no active groups");
- return OPERATOR_FINISHED; /* to get the chance to make changes in the redo panel*/
- }
- }
-
- if (dg_act) {
- BLI_strncpy(dg_act_name, dg_act->name, sizeof(dg_act_name));
- }
-
- /* Macro to loop through selected objects and perform operation depending on function, option and method.*/
- CTX_DATA_BEGIN (C, Object *, ob_src, selected_editable_objects)
- {
- if (ob_act != ob_src) {
-
- if (BLI_listbase_is_empty(&ob_src->defbase)) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Skipping object '%s' it has no vertex groups", ob_src->id.name + 2);
- continue;
- }
- else if (ob_src->type != OB_MESH) {
- /* armatures can be in pose mode so ignore them */
- if (ob_src->type != OB_ARMATURE) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Skipping object '%s' only copying from meshes is supported", ob_src->id.name + 2);
- }
- continue;
- }
-
- switch (vertex_group_mode) {
-
- case WT_REPLACE_ACTIVE_VERTEX_GROUP:
- {
- bDeformGroup *dg_src;
- dg_src = defgroup_find_name(ob_src, dg_act_name);
-
- if (dg_src == NULL) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Skipping object '%s' no group '%s' found", ob_src->id.name + 2, dg_act_name);
- continue;
- }
-
- if (ed_vgroup_transfer_weight(ob_act, ob_src, dg_src, scene, method, replace_mode, op)) {
- changed = true;
- }
- else {
- fail++;
- }
- break;
- }
- case WT_REPLACE_ALL_VERTEX_GROUPS:
- {
- bDeformGroup *dg_src;
- for (dg_src = ob_src->defbase.first; dg_src; dg_src = dg_src->next) {
- if (ed_vgroup_transfer_weight(ob_act, ob_src, dg_src, scene, method, replace_mode, op)) {
- changed = true;
- }
- else {
- fail++;
- }
- }
- break;
- }
- default:
- BLI_assert(0);
- break;
- }
- }
- }
- CTX_DATA_END;
-
- if (changed) {
-
- /* possible the active vertex group changed because of adding/removing */
- /* note!, dg_act may be realloc'd, only check its not NULL */
- if (dg_act) {
- ED_vgroup_select_by_name(ob_act, dg_act_name);
- }
- else {
- ED_vgroup_sync_from_pose(ob_act);
- }
-
- /* Event notifiers for correct display of data.*/
-
-
- DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_act); /* for buttons */
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_act);
- return OPERATOR_FINISHED;
- }
- else {
- if (BLI_listbase_is_empty(&op->reports->list)) {
- BKE_report(op->reports, RPT_WARNING, "Failed, no other selected objects with vertex groups found");
- }
-
- return OPERATOR_FINISHED; /* to get the chance to make changes in the redo panel */
- }
-}
-
-/* transfers weight from active to selected */
-void OBJECT_OT_vertex_group_transfer_weight(wmOperatorType *ot)
-{
- /* Identifiers.*/
- ot->name = "Transfer Weights";
- ot->idname = "OBJECT_OT_vertex_group_transfer_weight";
- ot->description = "Transfer weight paint to active from selected mesh";
-
- /* API callbacks.*/
- ot->poll = vertex_group_mesh_supported_poll;
- ot->exec = vertex_group_transfer_weight_exec;
-
- /* Flags.*/
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* Properties.*/
- /* TODO, use vgroup_operator_subset_select_props for group_select_mode */
- ot->prop = RNA_def_enum(ot->srna, "group_select_mode", WT_vertex_group_mode_item, WT_REPLACE_ALL_VERTEX_GROUPS, "Group", "");
- ot->prop = RNA_def_enum(ot->srna, "method", WT_method_item, WT_BY_NEAREST_FACE, "Method", "");
- ot->prop = RNA_def_enum(ot->srna, "replace_mode", WT_replace_mode_item, WT_REPLACE_ALL_WEIGHTS, "Replace", "");
-}
-
static int set_active_group_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
@@ -4297,7 +3305,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
else {
int dvert_tot = 0;
- ED_vgroup_array_get(ob->data, &dvert, &dvert_tot);
+ BKE_object_defgroup_array_get(ob->data, &dvert, &dvert_tot);
/*create as necessary*/
if (dvert) {
@@ -4314,7 +3322,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
sort_map[i]++;
sort_map_update[0] = 0;
- vgroup_remap_update_users(ob, sort_map_update);
+ BKE_object_defgroup_remap_update_users(ob, sort_map_update);
BLI_assert(sort_map_update[ob->actdef] >= 0);
ob->actdef = sort_map_update[ob->actdef];
diff --git a/source/blender/editors/object/object_warp.c b/source/blender/editors/object/object_warp.c
index 8016dabf3a3..7413bb07c4c 100644
--- a/source/blender/editors/object/object_warp.c
+++ b/source/blender/editors/object/object_warp.c
@@ -31,7 +31,6 @@
#include "BLI_math.h"
-#include "BKE_utildefines.h"
#include "BKE_context.h"
#include "RNA_access.h"
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index 637af5d6536..d864934171b 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -40,6 +40,7 @@
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_deform.h"
+#include "BKE_object_deform.h"
#include "BKE_depsgraph.h"
#include "BKE_dynamicpaint.h"
#include "BKE_global.h"
@@ -235,11 +236,11 @@ static int output_toggle_exec(bContext *C, wmOperator *op)
/* Vertex Weight Layer */
else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
if (!exists) {
- ED_vgroup_add_name(ob, name);
+ BKE_object_defgroup_add_name(ob, name);
}
else {
bDeformGroup *defgroup = defgroup_find_name(ob, name);
- if (defgroup) ED_vgroup_delete(ob, defgroup);
+ if (defgroup) BKE_object_defgroup_remove(ob, defgroup);
}
}
}
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index b53891f4880..b5adf38527b 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -72,8 +72,6 @@
#include "DNA_scene_types.h"
#include "DNA_mesh_types.h"
-#include "PIL_time.h"
-
static float get_fluid_viscosity(FluidsimSettings *settings)
{
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index 2a8718b3ef5..37cf95e5c2d 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -29,10 +29,6 @@
#include <stdlib.h>
-#include "DNA_scene_types.h"
-
-#include "BLI_utildefines.h"
-
#include "RNA_access.h"
#include "WM_api.h"
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index dd0816e509d..85b059d5574 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -37,8 +37,6 @@
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
-#include "BLI_math.h"
-
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 13a3d7a523f..9b4f128ef86 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -33,16 +33,12 @@
#include <stdlib.h>
#include <string.h>
-#include "MEM_guardedalloc.h"
-#include "DNA_group_types.h"
#include "DNA_object_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
#include "BLF_translation.h"
@@ -50,7 +46,6 @@
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_group.h"
-#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
diff --git a/source/blender/editors/physics/rigidbody_world.c b/source/blender/editors/physics/rigidbody_world.c
index 1c893992cf2..7bb189bd71b 100644
--- a/source/blender/editors/physics/rigidbody_world.c
+++ b/source/blender/editors/physics/rigidbody_world.c
@@ -37,8 +37,6 @@
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
-#include "BLI_math.h"
-
#ifdef WITH_BULLET
# include "RBI_api.h"
#endif
@@ -48,8 +46,6 @@
#include "BKE_rigidbody.h"
#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -199,5 +195,5 @@ void RIGIDBODY_OT_world_export(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE, FILE_SPECIAL, FILE_SAVE, FILE_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER, FILE_SPECIAL, FILE_SAVE, FILE_RELPATH, FILE_DEFAULTDISPLAY);
}
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index baf25a49f7c..b04f1d3e738 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -75,10 +75,8 @@
#include "RE_engine.h"
#include "IMB_colormanagement.h"
-#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#include "GPU_extensions.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -86,7 +84,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "wm_window.h"
#include "render_intern.h"
@@ -343,7 +340,11 @@ static void render_freejob(void *rjv)
}
/* str is IMA_MAX_RENDER_TEXT in size */
-static void make_renderinfo_string(RenderStats *rs, Scene *scene, bool v3d_override, char *str)
+static void make_renderinfo_string(const RenderStats *rs,
+ const Scene *scene,
+ const bool v3d_override,
+ const char *error,
+ char *str)
{
char info_time_str[32]; // used to be extern to header_info.c
uintptr_t mem_in_use, mmap_in_use, peak_memory;
@@ -416,8 +417,12 @@ static void make_renderinfo_string(RenderStats *rs, Scene *scene, bool v3d_overr
spos += sprintf(spos, IFACE_("| Full Sample %d "), rs->curfsa);
/* extra info */
- if (rs->infostr && rs->infostr[0])
+ if (rs->infostr && rs->infostr[0]) {
spos += sprintf(spos, "| %s ", rs->infostr);
+ }
+ else if (error && error[0]) {
+ spos += sprintf(spos, "| %s ", error);
+ }
/* very weak... but 512 characters is quite safe */
if (spos >= str + IMA_MAX_RENDER_TEXT)
@@ -438,7 +443,8 @@ static void image_renderinfo_cb(void *rjv, RenderStats *rs)
if (rr->text == NULL)
rr->text = MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext");
- make_renderinfo_string(rs, rj->scene, rj->v3d_override, rr->text);
+ make_renderinfo_string(rs, rj->scene, rj->v3d_override,
+ rr->error, rr->text);
}
RE_ReleaseResult(rj->re);
@@ -1121,7 +1127,7 @@ static void render_view3d_renderinfo_cb(void *rjp, RenderStats *rs)
*rp->stop = 1;
}
else {
- make_renderinfo_string(rs, rp->scene, false, rp->engine->text);
+ make_renderinfo_string(rs, rp->scene, false, NULL, rp->engine->text);
/* make jobs timer to send notifier */
*(rp->do_update) = true;
@@ -1439,7 +1445,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;
+ rp->has_freestyle = (scene->r.mode & R_EDGE_FRS) != 0;
copy_m4_m4(rp->viewmat, rp->rv3d->viewmat);
/* clear info text */
@@ -1551,10 +1557,10 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
RE_ReleaseResultImage(re);
}
-void ED_viewport_render_kill_jobs(const bContext *C, bool free_database)
+void ED_viewport_render_kill_jobs(wmWindowManager *wm,
+ Main *bmain,
+ bool free_database)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- Main *bmain = CTX_data_main(C);
bScreen *sc;
ScrArea *sa;
ARegion *ar;
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 559c86bf48c..8024add41cf 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -69,7 +69,6 @@
#include "GPU_extensions.h"
#include "GPU_glew.h"
-#include "wm_window.h"
#include "render_intern.h"
@@ -144,8 +143,10 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
int chanshown = sseq ? sseq->chanshown : 0;
struct bGPdata *gpd = (sseq && (sseq->flag & SEQ_SHOW_GPENCIL)) ? sseq->gpd : NULL;
- context = BKE_sequencer_new_render_data(oglrender->bmain->eval_ctx, oglrender->bmain,
- scene, oglrender->sizex, oglrender->sizey, 100.0f);
+ BKE_sequencer_new_render_data(
+ oglrender->bmain->eval_ctx, oglrender->bmain, scene,
+ oglrender->sizex, oglrender->sizey, 100.0f,
+ &context);
ibuf = BKE_sequencer_give_ibuf(&context, CFRA, chanshown);
@@ -187,7 +188,9 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
wmOrtho2(0, sizex, 0, sizey);
glTranslatef(sizex / 2, sizey / 2, 0.0f);
- ED_gpencil_draw_ex(gpd, sizex, sizey, scene->r.cfra);
+ G.f |= G_RENDER_OGL;
+ ED_gpencil_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ);
+ G.f &= ~G_RENDER_OGL;
gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect);
@@ -271,7 +274,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
/* shouldnt suddenly give errors mid-render but possible */
char err_out[256] = "unknown";
ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey,
- IB_rect, OB_SOLID, false, true,
+ IB_rect, OB_SOLID, false, true, true,
(draw_sky) ? R_ADDSKY : R_ALPHAPREMUL, err_out);
camera = scene->camera;
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 2a0ec853079..ea80a07fdd4 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -60,6 +60,7 @@
#include "DNA_brush_types.h"
#include "DNA_screen_types.h"
+#include "BKE_appdir.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_colortools.h"
@@ -78,14 +79,11 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#include "IMB_colormanagement.h"
-#include "GPU_extensions.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "PIL_time.h"
#include "RE_pipeline.h"
#include "RE_engine.h"
@@ -96,9 +94,7 @@
#include "ED_datafiles.h"
#include "ED_render.h"
-#include "UI_interface.h"
-#include "render_intern.h"
ImBuf *get_brush_icon(Brush *brush)
{
@@ -121,7 +117,7 @@ ImBuf *get_brush_icon(Brush *brush)
// otherwise lets try to find it in other directories
if (!(brush->icon_imbuf)) {
- folder = BLI_get_folder(BLENDER_DATAFILES, "brushicons");
+ folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons");
BLI_make_file_string(G.main->name, path, folder, brush->icon_filepath);
@@ -565,8 +561,9 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");
float fx = rect->xmin + offx;
float fy = rect->ymin;
+ if (re)
+ RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte);
- RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte);
glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte);
MEM_freeN(rect_byte);
@@ -1101,6 +1098,25 @@ static void icon_preview_free(void *customdata)
MEM_freeN(ip);
}
+void ED_preview_icon_render(Scene *scene, ID *id, unsigned int *rect, int sizex, int sizey)
+{
+ IconPreview ip = {0};
+ short stop = false, update = false;
+ float progress = 0.0f;
+
+ ip.scene = scene;
+ ip.owner = id;
+ ip.id = id;
+
+ icon_preview_add_size(&ip, rect, sizex, sizey);
+
+ icon_preview_startjob_all_sizes(&ip, &stop, &update, &progress);
+
+ icon_preview_endjob(&ip);
+
+ BLI_freelistN(&ip.sizes);
+}
+
void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey)
{
wmJob *wm_job;
@@ -1180,12 +1196,11 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
-void ED_preview_kill_jobs(const struct bContext *C)
+void ED_preview_kill_jobs(wmWindowManager *wm, Main *bmain)
{
- wmWindowManager *wm = CTX_wm_manager(C);
if (wm)
WM_jobs_kill(wm, NULL, common_preview_startjob);
-
- ED_viewport_render_kill_jobs(C, false);
+
+ ED_viewport_render_kill_jobs(wm, bmain, false);
}
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index eaa7cf40aca..91c689373be 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -51,7 +51,6 @@
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
#include "BKE_font.h"
-#include "BKE_freestyle.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_library.h"
@@ -65,17 +64,15 @@
#include "BKE_world.h"
#include "BKE_editmesh.h"
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-#include "GPU_material.h"
#ifdef WITH_FREESTYLE
+# include "BKE_freestyle.h"
# include "FRS_freestyle.h"
+# include "RNA_enum_types.h"
#endif
#include "RNA_access.h"
-#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -1481,7 +1478,7 @@ void TEXTURE_OT_envmap_save(wmOperatorType *ot)
"(use -1 to skip a face)", 0.0f, 0.0f);
RNA_def_property_flag(prop, PROP_HIDDEN);
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_SAVE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
}
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index 6118db703b4..be42e2ed518 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -41,11 +41,11 @@
#include "DNA_world_types.h"
#include "DNA_windowmanager_types.h"
+#include "BLI_listbase.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_icons.h"
#include "BKE_main.h"
@@ -85,7 +85,11 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
/* don't call this recursively for frame updates */
if (recursive_check)
return;
-
+
+ /* Do not call if no WM available, see T42688. */
+ if (BLI_listbase_is_empty(&bmain->wm))
+ return;
+
recursive_check = true;
C = CTX_create();
@@ -276,7 +280,7 @@ static void material_changed(Main *bmain, Material *ma)
/* glsl */
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
/* find node materials using this */
for (parent = bmain->mat.first; parent; parent = parent->id.next) {
@@ -290,7 +294,7 @@ static void material_changed(Main *bmain, Material *ma)
BKE_icon_changed(BKE_icon_getid(&parent->id));
if (parent->gpumaterial.first)
- GPU_material_free(parent);
+ GPU_material_free(&parent->gpumaterial);
}
/* find if we have a scene with textured display */
@@ -336,10 +340,10 @@ static void lamp_changed(Main *bmain, Lamp *la)
for (ma = bmain->mat.first; ma; ma = ma->id.next)
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
if (defmaterial.gpumaterial.first)
- GPU_material_free(&defmaterial);
+ GPU_material_free(&defmaterial.gpumaterial);
}
static int material_uses_texture(Material *ma, Tex *tex)
@@ -377,7 +381,7 @@ static void texture_changed(Main *bmain, Tex *tex)
BKE_icon_changed(BKE_icon_getid(&ma->id));
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
}
/* find lamps */
@@ -406,6 +410,9 @@ static void texture_changed(Main *bmain, Tex *tex)
}
BKE_icon_changed(BKE_icon_getid(&wo->id));
+
+ if (wo->gpumaterial.first)
+ GPU_material_free(&wo->gpumaterial);
}
/* find compositing nodes */
@@ -451,14 +458,17 @@ static void world_changed(Main *bmain, World *wo)
/* icons */
BKE_icon_changed(BKE_icon_getid(&wo->id));
-
+
/* glsl */
for (ma = bmain->mat.first; ma; ma = ma->id.next)
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
if (defmaterial.gpumaterial.first)
- GPU_material_free(&defmaterial);
+ GPU_material_free(&defmaterial.gpumaterial);
+
+ if (wo->gpumaterial.first)
+ GPU_material_free(&wo->gpumaterial);
}
static void image_changed(Main *bmain, Image *ima)
@@ -478,6 +488,7 @@ static void scene_changed(Main *bmain, Scene *scene)
{
Object *ob;
Material *ma;
+ World *wo;
/* glsl */
for (ob = bmain->object.first; ob; ob = ob->id.next) {
@@ -487,16 +498,20 @@ static void scene_changed(Main *bmain, Scene *scene)
if (ob->mode & OB_MODE_TEXTURE_PAINT) {
BKE_texpaint_slots_refresh_object(scene, ob);
BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- GPU_drawobject_free(ob->derivedFinal);
+ GPU_drawobject_free(ob->derivedFinal);
}
}
for (ma = bmain->mat.first; ma; ma = ma->id.next)
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
+ for (wo = bmain->world.first; wo; wo = wo->id.next)
+ if (wo->gpumaterial.first)
+ GPU_material_free(&wo->gpumaterial);
+
if (defmaterial.gpumaterial.first)
- GPU_material_free(&defmaterial);
+ GPU_material_free(&defmaterial.gpumaterial);
}
void ED_render_id_flush_update(Main *bmain, ID *id)
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 630ff8fecf6..71714bdcda9 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -41,7 +41,6 @@
#include "BLI_utildefines.h"
#include "BLI_linklist_stack.h"
-#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -896,7 +895,7 @@ static void region_azone_tria(ScrArea *sa, AZone *az, ARegion *ar)
static void region_azone_initialize(ScrArea *sa, ARegion *ar, AZEdge edge, const bool is_fullscreen)
{
- AZone *az;
+ AZone *az = NULL;
const bool is_hidden = (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) == 0;
if (is_hidden || !is_fullscreen) {
@@ -907,7 +906,7 @@ static void region_azone_initialize(ScrArea *sa, ARegion *ar, AZEdge edge, const
az->edge = edge;
}
- if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
+ if (!is_hidden) {
if (!is_fullscreen) {
if (G.debug_value == 3)
region_azone_icon(sa, az, ar);
@@ -1352,8 +1351,18 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand
}
if (flag & ED_KEYMAP_GPENCIL) {
/* grease pencil */
- wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Grease Pencil", 0, 0);
- WM_event_add_keymap_handler(handlers, keymap);
+ /* NOTE: This is now 2 keymaps - One for basic functionality,
+ * and one that only applies when "Edit Mode" is enabled
+ * for strokes.
+ *
+ * For now, it's easier to just include both,
+ * since you hardly want one without the other.
+ */
+ wmKeyMap *keymap_general = WM_keymap_find(wm->defaultconf, "Grease Pencil", 0, 0);
+ wmKeyMap *keymap_edit = WM_keymap_find(wm->defaultconf, "Grease Pencil Stroke Edit Mode", 0, 0);
+
+ WM_event_add_keymap_handler(handlers, keymap_general);
+ WM_event_add_keymap_handler(handlers, keymap_edit);
}
if (flag & ED_KEYMAP_HEADER) {
/* standard keymap for headers regions */
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index c095dfe7792..134feb59d55 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -45,7 +45,6 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "GPU_extensions.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index 18c9a94e46f..ce9c608247b 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -26,12 +26,13 @@
* \ingroup edscr
*/
-
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DNA_object_types.h"
#include "DNA_armature_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_sequence_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -45,11 +46,13 @@
#include "BKE_object.h"
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_gpencil.h"
#include "BKE_sequencer.h"
#include "RNA_access.h"
#include "ED_armature.h"
+#include "ED_gpencil.h"
#include "WM_api.h"
#include "UI_interface.h"
@@ -66,12 +69,16 @@ const char *screen_context_dir[] = {
"sculpt_object", "vertex_paint_object", "weight_paint_object",
"image_paint_object", "particle_edit_object",
"sequences", "selected_sequences", "selected_editable_sequences", /* sequencer */
+ "gpencil_data", "gpencil_data_owner", /* grease pencil data */
+ "visible_gpencil_layers", "editable_gpencil_layers", "editable_gpencil_strokes",
+ "active_gpencil_layer", "active_gpencil_frame",
"active_operator",
NULL};
int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result)
{
bScreen *sc = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
Scene *scene = sc->scene;
Base *base;
unsigned int lay = scene->lay;
@@ -392,6 +399,112 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
}
+ else if (CTX_data_equals(member, "gpencil_data")) {
+ /* FIXME: for some reason, CTX_data_active_object(C) returns NULL when called from these situations
+ * (as outlined above - see Campbell's #ifdefs). That causes the get_active function to fail when
+ * called from context. For that reason, we end up using an alternative where we pass everything in!
+ */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+
+ if (gpd) {
+ CTX_data_id_pointer_set(result, &gpd->id);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "gpencil_data_owner")) {
+ /* pointer to which data/datablock owns the reference to the Grease Pencil data being used (as gpencil_data)
+ * XXX: see comment for gpencil_data case...
+ */
+ bGPdata **gpd_ptr = NULL;
+ PointerRNA ptr;
+
+ /* get pointer to Grease Pencil Data */
+ gpd_ptr = ED_gpencil_data_get_pointers_direct((ID *)sc, scene, sa, obact, &ptr);
+
+ if (gpd_ptr) {
+ CTX_data_pointer_set(result, ptr.id.data, ptr.type, ptr.data);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "active_gpencil_layer")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ if (gpl) {
+ CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl);
+ return 1;
+ }
+ }
+ }
+ else if (CTX_data_equals(member, "active_gpencil_frame")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ if (gpl) {
+ CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl->actframe);
+ return 1;
+ }
+ }
+ }
+ else if (CTX_data_equals(member, "visible_gpencil_layers")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl;
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if ((gpl->flag & GP_LAYER_HIDE) == 0) {
+ CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "editable_gpencil_layers")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl;
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0) {
+ CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
+ else if (CTX_data_equals(member, "editable_gpencil_strokes")) {
+ /* XXX: see comment for gpencil_data case... */
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+
+ if (gpd) {
+ bGPDlayer *gpl;
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0 && (gpl->actframe)) {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ CTX_data_list_add(result, &gpd->id, &RNA_GPencilStroke, gps);
+ }
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
else if (CTX_data_equals(member, "active_operator")) {
wmOperator *op = NULL;
@@ -400,7 +513,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
op = sfile->op;
}
else if ((op = UI_context_active_operator_get(C))) {
- /* do nothign */
+ /* do nothing */
}
else {
/* note, this checks poll, could be a problem, but this also
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index c179cfc464c..3972d00293c 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1748,6 +1748,13 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
}
}
+ if (sa && (sa->spacetype != type)) {
+ newsa->flag |= AREA_FLAG_TEMP_TYPE;
+ }
+ else {
+ newsa->flag &= ~AREA_FLAG_TEMP_TYPE;
+ }
+
ED_area_newspace(C, newsa, type);
return newsa;
@@ -1763,6 +1770,21 @@ void ED_screen_full_prevspace(bContext *C, ScrArea *sa)
ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
}
+void ED_screen_retore_temp_type(bContext *C, ScrArea *sa, bool is_screen_change)
+{
+ /* incase nether functions below run */
+ ED_area_tag_redraw(sa);
+
+ if (sa->flag & AREA_FLAG_TEMP_TYPE) {
+ ED_area_prevspace(C, sa);
+ sa->flag &= ~AREA_FLAG_TEMP_TYPE;
+ }
+
+ if (is_screen_change && sa->full) {
+ ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
+ }
+}
+
/* restore a screen / area back to default operation, after temp fullscreen modes */
void ED_screen_full_restore(bContext *C, ScrArea *sa)
{
@@ -1789,12 +1811,14 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa)
else
ED_screen_state_toggle(C, win, sa, state);
}
- else if (sl->spacetype == SPACE_FILE) {
+ else if (sa->flag & AREA_FLAG_TEMP_TYPE) {
ED_screen_full_prevspace(C, sa);
}
else {
ED_screen_state_toggle(C, win, sa, state);
}
+
+ sa->flag &= ~AREA_FLAG_TEMP_TYPE;
}
/* otherwise just tile the area again */
else {
@@ -1857,6 +1881,11 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
BKE_screen_free(oldscreen);
BKE_libblock_free(CTX_data_main(C), oldscreen);
+ /* After we've restored back to SCREENNORMAL, we have to wait with
+ * screen handling as it uses the area coords which aren't updated yet.
+ * Without doing so, the screen handling gets wrong area coords,
+ * which in worst case can lead to crashes (see T43139) */
+ sc->skip_handling = true;
}
else {
/* change from SCREENNORMAL to new state */
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 454bb3b7ca3..39321ec0770 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -43,6 +43,7 @@
#include "DNA_lattice_types.h"
#include "DNA_object_types.h"
#include "DNA_curve_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
#include "DNA_meta_types.h"
#include "DNA_mask_types.h"
@@ -81,8 +82,6 @@
#include "UI_interface.h"
#include "UI_resources.h"
-#include "wm_window.h"
-
#include "screen_intern.h" /* own module include */
#define KM_MODAL_CANCEL 1
@@ -2150,6 +2149,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
bDopeSheet ads = {NULL};
DLRBT_Tree keys;
ActKeyColumn *ak;
@@ -2177,7 +2177,9 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
if (ob)
ob_to_keylist(&ads, ob, &keys, NULL);
-
+
+ gpencil_to_keylist(&ads, gpd, &keys);
+
{
Mask *mask = CTX_data_edit_mask(C);
if (mask) {
@@ -3523,12 +3525,14 @@ static void SCREEN_OT_animation_step(wmOperatorType *ot)
/* find window that owns the animation timer */
bScreen *ED_screen_animation_playing(const wmWindowManager *wm)
{
- wmWindow *window;
+ wmWindow *win;
+
+ for (win = wm->windows.first; win; win = win->next) {
+ if (win->screen->animtimer) {
+ return win->screen;
+ }
+ }
- for (window = wm->windows.first; window; window = window->next)
- if (window->screen->animtimer)
- return window->screen;
-
return NULL;
}
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index be5fd48b41a..e7f256e414a 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -65,7 +65,6 @@
#include "PIL_time.h"
-#include "ED_screen_types.h"
#include "screen_intern.h"
@@ -287,7 +286,7 @@ void SCREEN_OT_screenshot(wmOperatorType *ot)
ot->flag = 0;
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE, FILE_SPECIAL, FILE_SAVE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE, FILE_SPECIAL, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
RNA_def_boolean(ot->srna, "full", 1, "Full Screen",
"Capture the whole window (otherwise only capture the active area)");
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index e27ef705fad..430ea1cc11d 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -341,8 +341,8 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
BKE_paint_reset_overlay_invalid(invalid);
@@ -426,7 +426,7 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
len = sqrtf(x * x + y * y);
if (len <= 1) {
- float avg = BKE_brush_curve_strength_clamp(br, len, 1.0f); /* Falloff curve */
+ float avg = BKE_brush_curve_strength(br, len, 1.0f); /* Falloff curve */
buffer[index] = 255 - (GLubyte)(255 * avg);
@@ -464,8 +464,8 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
BKE_paint_reset_overlay_invalid(PAINT_INVALID_OVERLAY_CURVE);
@@ -595,7 +595,7 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
/* brush rotation */
glTranslatef(0.5, 0.5, 0);
- glRotatef((double)RAD2DEGF(ups->brush_rotation),
+ glRotatef((double)RAD2DEGF((primary) ? ups->brush_rotation : ups->brush_rotation_sec),
0.0, 0.0, 1.0);
glTranslatef(-0.5f, -0.5f, 0);
@@ -1000,9 +1000,7 @@ 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) {
- if (brush->flag & BRUSH_RAKE)
- /* here, translation contains the mouse coordinates. */
- paint_calculate_rake_rotation(ups, translation);
+ paint_calculate_rake_rotation(ups, brush, translation);
}
/* draw overlay */
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index 8c7c3b102e3..1f5ee708ad0 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -329,7 +329,7 @@ void PAINTCURVE_OT_add_point(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add New Paint Curve Point";
- ot->description = "Add new paint curve point";
+ ot->description = ot->name;
ot->idname = "PAINTCURVE_OT_add_point";
/* api callbacks */
@@ -410,8 +410,8 @@ static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
void PAINTCURVE_OT_delete_point(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add New Paint Curve Point";
- ot->description = "Add new paint curve point";
+ ot->name = "Remove Paint Curve Point";
+ ot->description = ot->name;
ot->idname = "PAINTCURVE_OT_delete_point";
/* api callbacks */
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 021822793ff..d52b17372f7 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -45,13 +45,11 @@
#include "BLI_utildefines.h"
#include "BLI_threads.h"
-#include "PIL_time.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "DNA_brush_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
@@ -62,15 +60,9 @@
#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"
#include "UI_view2d.h"
@@ -85,7 +77,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "GPU_draw.h"
#include "GPU_buffers.h"
@@ -671,22 +662,24 @@ void paint_brush_color_get(struct Scene *scene, struct Brush *br, bool color_cor
copy_v3_v3(color, BKE_brush_secondary_color_get(scene, br));
else {
if (br->flag & BRUSH_USE_GRADIENT) {
+ float color_gr[4];
switch (br->gradient_stroke_mode) {
case BRUSH_GRADIENT_PRESSURE:
- do_colorband(br->gradient, pressure, color);
+ do_colorband(br->gradient, pressure, color_gr);
break;
case BRUSH_GRADIENT_SPACING_REPEAT:
{
float coord = fmod(distance / br->gradient_spacing, 1.0);
- do_colorband(br->gradient, coord, color);
+ do_colorband(br->gradient, coord, color_gr);
break;
}
case BRUSH_GRADIENT_SPACING_CLAMP:
{
- do_colorband(br->gradient, distance / br->gradient_spacing, color);
+ do_colorband(br->gradient, distance / br->gradient_spacing, color_gr);
break;
}
}
+ copy_v3_v3(color, color_gr);
}
else
copy_v3_v3(color, BKE_brush_color_get(scene, br));
@@ -1065,7 +1058,7 @@ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings)
enabled = true;
if (enabled) {
- BKE_paint_init(&imapaint->paint, PAINT_CURSOR_TEXTURE_PAINT);
+ BKE_paint_init(&settings->unified_paint_settings, &imapaint->paint, PAINT_CURSOR_TEXTURE_PAINT);
paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll);
}
@@ -1422,7 +1415,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
ob->mode |= mode_flag;
- BKE_paint_init(&scene->toolsettings->imapaint.paint, PAINT_CURSOR_TEXTURE_PAINT);
+ BKE_paint_init(&scene->toolsettings->unified_paint_settings, &imapaint->paint, PAINT_CURSOR_TEXTURE_PAINT);
if (U.glreslimit != 0)
GPU_free_images();
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index ea0e30a6635..95940d89694 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -38,9 +38,7 @@
#include "DNA_space_types.h"
#include "DNA_object_types.h"
-#include "BLI_math.h"
-#include "BLI_rect.h"
#include "BLI_math_color_blend.h"
#include "BLI_stack.h"
#include "BLI_bitmap.h"
@@ -65,7 +63,6 @@
#include "UI_view2d.h"
-#include "RE_shader_ext.h"
#include "GPU_draw.h"
@@ -362,7 +359,7 @@ static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter, int d
float xy[2] = {x + xoff, y + yoff};
float len = len_v2(xy);
- *m = (unsigned short)(65535.0f * BKE_brush_curve_strength_clamp(brush, len, radius));
+ *m = (unsigned short)(65535.0f * BKE_brush_curve_strength(brush, len, radius));
}
}
@@ -689,7 +686,7 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *pai
bool do_partial_update_mask = false;
/* invalidate case for all mapping modes */
if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
- mask_rotation += ups->brush_rotation;
+ mask_rotation += ups->brush_rotation_sec;
}
else if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) {
renew_maxmask = true;
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 9cc1906596f..3e675012d05 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -50,7 +50,6 @@
#include "BLF_translation.h"
-#include "PIL_time.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -62,7 +61,6 @@
#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"
@@ -80,10 +78,8 @@
#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_node.h"
#include "ED_paint.h"
@@ -101,7 +97,6 @@
#include "RNA_enum_types.h"
#include "GPU_draw.h"
-#include "GPU_buffers.h"
#include "IMB_colormanagement.h"
@@ -192,7 +187,7 @@ typedef struct ProjPaintImage {
ImagePaintPartialRedraw *partRedrawRect;
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 */
+ * Here we store the mask rectangle */
bool **valid; /* store flag to enforce validation of undo rectangle */
int touch;
} ProjPaintImage;
@@ -1339,7 +1334,7 @@ static float project_paint_uvpixel_mask(
/* now we can use the normal as a mask */
if (ps->is_ortho) {
- angle = angle_normalized_v3v3((float *)ps->viewDir, no);
+ angle = angle_normalized_v3v3(ps->viewDir, no);
}
else {
/* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */
@@ -1967,25 +1962,63 @@ static int float_z_sort(const void *p1, const void *p2)
return (((float *)p1)[2] < ((float *)p2)[2] ? -1 : 1);
}
+/* assumes one point is within the rectangle */
+static void line_rect_clip(
+ rctf *rect,
+ const float l1[4], const float l2[4],
+ const float uv1[2], const float uv2[2],
+ float uv[2], bool is_ortho)
+{
+ float min = FLT_MAX, tmp;
+ if ((l1[0] - rect->xmin) * (l2[0] - rect->xmin) < 0) {
+ tmp = rect->xmin;
+ min = min_ff((tmp - l1[0]) / (l2[0] - l1[0]), min);
+ }
+ else if ((l1[0] - rect->xmax) * (l2[0] - rect->xmax) < 0) {
+ tmp = rect->xmax;
+ min = min_ff((tmp - l1[0]) / (l2[0] - l1[0]), min);
+ }
+ if ((l1[1] - rect->ymin) * (l2[1] - rect->ymin) < 0) {
+ tmp = rect->ymin;
+ min = min_ff((tmp - l1[1]) / (l2[1] - l1[1]), min);
+ }
+ else if ((l1[1] - rect->ymax) * (l2[1] - rect->ymax) < 0) {
+ tmp = rect->ymax;
+ min = min_ff((tmp - l1[1]) / (l2[1] - l1[1]), min);
+ }
+
+ tmp = (is_ortho) ? 1.0f : (l1[3] + min * (l2[3] - l1[3]));
+
+ uv[0] = (uv1[0] + min * (uv2[0] - uv1[0])) / tmp;
+ uv[1] = (uv1[1] + min * (uv2[1] - uv1[1])) / tmp;
+}
+
+
static void project_bucket_clip_face(
const bool is_ortho,
rctf *bucket_bounds,
float *v1coSS, float *v2coSS, float *v3coSS,
const float *uv1co, const float *uv2co, const float *uv3co,
float bucket_bounds_uv[8][2],
- int *tot)
+ int *tot, bool cull)
{
int inside_bucket_flag = 0;
int inside_face_flag = 0;
const int flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
-
+ bool colinear = false;
+
float bucket_bounds_ss[4][2];
+ /* detect pathological case where face the three vertices are almost colinear in screen space.
+ * mostly those will be culled but when flood filling or with smooth shading */
+ if (dist_squared_to_line_v2(v1coSS, v2coSS, v3coSS) < PROJ_PIXEL_TOLERANCE)
+ colinear = true;
+
/* get the UV space bounding box */
inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v1coSS);
inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v2coSS) << 1;
inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2;
-
+
if (inside_bucket_flag == ISECT_ALL3) {
/* all screenspace points are inside the bucket bounding box, this means we don't need to clip and can simply return the UVs */
if (flip) { /* facing the back? */
@@ -1997,9 +2030,59 @@ static void project_bucket_clip_face(
copy_v2_v2(bucket_bounds_uv[0], uv1co);
copy_v2_v2(bucket_bounds_uv[1], uv2co);
copy_v2_v2(bucket_bounds_uv[2], uv3co);
+ }
+
+ *tot = 3;
+ return;
+ }
+ /* handle pathological case here, no need for further intersections below since tringle area is almost zero */
+ if (colinear) {
+ int flag;
+
+ (*tot) = 0;
+
+ if (cull)
+ return;
+
+ if (inside_bucket_flag & ISECT_1) { copy_v2_v2(bucket_bounds_uv[*tot], uv1co); (*tot)++; }
+
+ flag = inside_bucket_flag & (ISECT_1 | ISECT_2);
+ if (flag && flag != (ISECT_1 | ISECT_2)) {
+ line_rect_clip(bucket_bounds, v1coSS, v2coSS, uv1co, uv2co, bucket_bounds_uv[*tot], is_ortho);
+ (*tot)++;
+ }
+
+ if (inside_bucket_flag & ISECT_2) { copy_v2_v2(bucket_bounds_uv[*tot], uv2co); (*tot)++; }
+
+ flag = inside_bucket_flag & (ISECT_2 | ISECT_3);
+ if (flag && flag != (ISECT_2 | ISECT_3)) {
+ line_rect_clip(bucket_bounds, v2coSS, v3coSS, uv2co, uv3co, bucket_bounds_uv[*tot], is_ortho);
+ (*tot)++;
}
- *tot = 3;
+ if (inside_bucket_flag & ISECT_3) { copy_v2_v2(bucket_bounds_uv[*tot], uv3co); (*tot)++; }
+
+ flag = inside_bucket_flag & (ISECT_3 | ISECT_1);
+ if (flag && flag != (ISECT_3 | ISECT_1)) {
+ line_rect_clip(bucket_bounds, v3coSS, v1coSS, uv3co, uv1co, bucket_bounds_uv[*tot], is_ortho);
+ (*tot)++;
+ }
+
+ if ((*tot) < 3) { /* no intersections to speak of */
+ *tot = 0;
+ return;
+ }
+
+ /* at this point we have all uv points needed in a row. all that's needed is to invert them if necessary */
+ if (flip) {
+ /* flip only to the middle of the array */
+ int i, max = *tot / 2;
+ for (i = 0; i < max; i++) {
+ SWAP(float, bucket_bounds_uv[i][0], bucket_bounds_uv[max - i][0]);
+ SWAP(float, bucket_bounds_uv[i][1], bucket_bounds_uv[max - i][1]);
+ }
+ }
+
return;
}
@@ -2128,47 +2211,32 @@ static void project_bucket_clip_face(
if (flip) qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort_flip);
else qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort);
- /* remove doubles */
- /* first/last check */
- if (fabsf(isectVCosSS[0][0] - isectVCosSS[(*tot) - 1][0]) < PROJ_PIXEL_TOLERANCE &&
- fabsf(isectVCosSS[0][1] - isectVCosSS[(*tot) - 1][1]) < PROJ_PIXEL_TOLERANCE)
- {
- (*tot)--;
- }
-
- /* its possible there is only a few left after remove doubles */
- if ((*tot) < 3) {
- // printf("removed too many doubles A\n");
- *tot = 0;
- return;
- }
-
doubles = true;
while (doubles == true) {
doubles = false;
- for (i = 1; i < (*tot); i++) {
- if (fabsf(isectVCosSS[i - 1][0] - isectVCosSS[i][0]) < PROJ_PIXEL_TOLERANCE &&
- fabsf(isectVCosSS[i - 1][1] - isectVCosSS[i][1]) < PROJ_PIXEL_TOLERANCE)
+
+ for (i = 0; i < (*tot); i++) {
+ if (fabsf(isectVCosSS[(i + 1) % *tot][0] - isectVCosSS[i][0]) < PROJ_PIXEL_TOLERANCE &&
+ fabsf(isectVCosSS[(i + 1) % *tot][1] - isectVCosSS[i][1]) < PROJ_PIXEL_TOLERANCE)
{
int j;
- for (j = i + 1; j < (*tot); j++) {
- isectVCosSS[j - 1][0] = isectVCosSS[j][0];
- isectVCosSS[j - 1][1] = isectVCosSS[j][1];
+ for (j = i; j < (*tot) - 1; j++) {
+ isectVCosSS[j][0] = isectVCosSS[j + 1][0];
+ isectVCosSS[j][1] = isectVCosSS[j + 1][1];
}
doubles = true; /* keep looking for more doubles */
(*tot)--;
}
}
+
+ /* its possible there is only a few left after remove doubles */
+ if ((*tot) < 3) {
+ // printf("removed too many doubles B\n");
+ *tot = 0;
+ return;
+ }
}
- /* its possible there is only a few left after remove doubles */
- if ((*tot) < 3) {
- // printf("removed too many doubles B\n");
- *tot = 0;
- return;
- }
-
-
if (is_ortho) {
for (i = 0; i < (*tot); i++) {
barycentric_weights_v2(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
@@ -2406,8 +2474,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
is_ortho, bucket_bounds,
v1coSS, v2coSS, v3coSS,
uv1co, uv2co, uv3co,
- uv_clip, &uv_clip_tot
- );
+ uv_clip, &uv_clip_tot,
+ ps->do_backfacecull || ps->do_occlude);
/* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */
#if 0
@@ -2428,10 +2496,10 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
CLAMP(bounds_px.ymax, 0, ibuf->y);
}
- /*
+#if 0
project_paint_undo_tiles_init(&bounds_px, ps->projImages + image_index, tmpibuf,
tile_width, threaded, ps->do_masking);
- */
+#endif
/* clip face and */
has_isect = 0;
@@ -2821,7 +2889,7 @@ static bool project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int buck
int fidx;
project_bucket_bounds(ps, bucket_x, bucket_y, &bucket_bounds);
-
+
/* Is one of the faces verts in the bucket bounds? */
fidx = mf->v4 ? 3 : 2;
@@ -3092,7 +3160,7 @@ static void project_paint_begin(ProjPaintState *ps)
invert_m4_m4(ps->ob->imat, ps->ob->obmat);
- if (ps->source == PROJ_SRC_VIEW) {
+ if (ELEM(ps->source, PROJ_SRC_VIEW, PROJ_SRC_VIEW_FILL)) {
/* normal drawing */
ps->winx = ps->ar->winx;
ps->winy = ps->ar->winy;
@@ -3230,7 +3298,7 @@ static void project_paint_begin(ProjPaintState *ps)
CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter));
#endif
}
- else { /* re-projection, use bounds */
+ else if (ps->source != PROJ_SRC_VIEW_FILL) { /* re-projection, use bounds */
ps->screenMin[0] = 0;
ps->screenMax[0] = (float)(ps->winx);
@@ -3426,8 +3494,8 @@ static void project_paint_begin(ProjPaintState *ps)
#ifdef PROJ_DEBUG_WINCLIP
/* ignore faces outside the view */
- if (
- (v1coSS[0] < ps->screenMin[0] &&
+ if ((ps->source != PROJ_SRC_VIEW_FILL) &&
+ ((v1coSS[0] < ps->screenMin[0] &&
v2coSS[0] < ps->screenMin[0] &&
v3coSS[0] < ps->screenMin[0] &&
(mf->v4 && v4coSS[0] < ps->screenMin[0])) ||
@@ -3445,7 +3513,7 @@ static void project_paint_begin(ProjPaintState *ps)
(v1coSS[1] > ps->screenMax[1] &&
v2coSS[1] > ps->screenMax[1] &&
v3coSS[1] > ps->screenMax[1] &&
- (mf->v4 && v4coSS[1] > ps->screenMax[1]))
+ (mf->v4 && v4coSS[1] > ps->screenMax[1])))
)
{
continue;
@@ -3795,10 +3863,9 @@ static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, fl
}
}
-/* do_projectpaint_smear*
- *
- * note, mask is used to modify the alpha here, this is not correct since it allows
- * accumulation of color greater then 'projPixel->mask' however in the case of smear its not
+/**
+ * \note mask is used to modify the alpha here, this is not correct since it allows
+ * accumulation of color greater than 'projPixel->mask' however in the case of smear its not
* really that important to be correct as it is with clone and painting
*/
static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, float mask,
@@ -4219,7 +4286,7 @@ static void *do_projectpaint_thread(void *ph_v)
if (dist_sq <= brush_radius_sq) {
dist = sqrtf(dist_sq);
- falloff = BKE_brush_curve_strength_clamp(ps->brush, dist, brush_radius);
+ falloff = BKE_brush_curve_strength(ps->brush, dist, brush_radius);
if (falloff > 0.0f) {
float texrgb[3];
@@ -4454,7 +4521,35 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
touch_any = 1;
}
}
+
+ /* calculate pivot for rotation around seletion if needed */
+ if (U.uiflag & USER_ORBIT_SELECTION) {
+ float w[3];
+ int side, index;
+
+ index = project_paint_PickFace(ps, pos, w, &side);
+
+ if (index != -1) {
+ MFace *mf;
+ float world[3];
+ UnifiedPaintSettings *ups = &ps->scene->toolsettings->unified_paint_settings;
+ mf = ps->dm_mface + index;
+
+ if (side == 0) {
+ interp_v3_v3v3v3(world, ps->dm_mvert[(*(&mf->v1))].co, ps->dm_mvert[(*(&mf->v2))].co, ps->dm_mvert[(*(&mf->v3))].co, w);
+ }
+ else {
+ interp_v3_v3v3v3(world, ps->dm_mvert[(*(&mf->v1))].co, ps->dm_mvert[(*(&mf->v3))].co, ps->dm_mvert[(*(&mf->v4))].co, w);
+ }
+
+ ups->average_stroke_counter++;
+ mul_m4_v3(ps->ob->obmat, world);
+ add_v3_v3(ups->average_stroke_accum, world);
+ ups->last_stroke_valid = true;
+ }
+ }
+
return touch_any;
}
@@ -4626,7 +4721,7 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
paint_brush_init_tex(ps->brush);
- ps->source = PROJ_SRC_VIEW;
+ ps->source = (ps->tool == PAINT_TOOL_FILL) ? PROJ_SRC_VIEW_FILL : PROJ_SRC_VIEW;
if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) {
MEM_freeN(ps);
@@ -4649,10 +4744,6 @@ 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;
}
@@ -5130,6 +5221,8 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
DAG_id_tag_update(&ma->id, 0);
ED_area_tag_redraw(CTX_wm_area(C));
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+
return true;
}
}
@@ -5288,6 +5381,8 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
if (synch_selection)
scene->toolsettings->uv_flag |= UV_SYNC_SELECTION;
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+
DAG_id_tag_update(ob->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 9c4701d0a01..bb875d2ef00 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -207,6 +207,7 @@ static bool paint_brush_update(bContext *C,
UnifiedPaintSettings *ups = stroke->ups;
bool location_sampled = false;
bool location_success = false;
+ bool do_random = 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.
@@ -256,17 +257,13 @@ static bool paint_brush_update(bContext *C,
if (paint_supports_dynamic_tex_coords(brush, mode)) {
if (((brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) ||
(brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) ||
- (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)) &&
- !(brush->flag & BRUSH_RAKE))
+ (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)))
{
- if (brush->flag & BRUSH_RANDOM_ROTATION)
- ups->brush_rotation = 2.0f * (float)M_PI * BLI_frand();
- else
- ups->brush_rotation = 0.0f;
+ do_random = true;
}
if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
- BKE_brush_randomize_texture_coordinates(ups, false);
+ BKE_brush_randomize_texture_coords(ups, false);
else {
copy_v2_v2(ups->tex_mouse, mouse);
}
@@ -274,7 +271,7 @@ static bool paint_brush_update(bContext *C,
/* 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);
+ BKE_brush_randomize_texture_coords(ups, true);
else {
copy_v2_v2(ups->mask_tex_mouse, mouse);
}
@@ -291,7 +288,7 @@ static bool paint_brush_update(bContext *C,
ups->anchored_size = ups->pixel_radius = sqrtf(dx * dx + dy * dy);
- ups->brush_rotation = atan2f(dx, dy) + M_PI;
+ ups->brush_rotation = ups->brush_rotation_sec = atan2f(dx, dy) + M_PI;
if (brush->flag & BRUSH_EDGE_TO_EDGE) {
halfway[0] = dx * 0.5f + stroke->initial_mouse[0];
@@ -328,13 +325,27 @@ static bool paint_brush_update(bContext *C,
ups->pixel_radius /= stroke->zoom_2d;
ups->draw_anchored = true;
}
- else if (brush->flag & BRUSH_RAKE) {
+ else {
/* here we are using the initial mouse coordinate because we do not want the rake
* result to depend on jittering */
- if (!stroke->brush_init)
+ if (!stroke->brush_init) {
copy_v2_v2(ups->last_rake, mouse_init);
- else
- paint_calculate_rake_rotation(ups, mouse_init);
+ }
+ else {
+ paint_calculate_rake_rotation(ups, brush, mouse_init);
+ }
+ }
+
+ if (do_random) {
+ if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
+ ups->brush_rotation += -brush->mtex.random_angle / 2.0f +
+ brush->mtex.random_angle * BLI_frand();
+ }
+
+ if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
+ ups->brush_rotation_sec += -brush->mask_mtex.random_angle / 2.0f +
+ brush->mask_mtex.random_angle * BLI_frand();
+ }
}
if (!location_sampled) {
@@ -651,6 +662,10 @@ PaintStroke *paint_stroke_new(bContext *C,
/* initialize here */
ups->overlap_factor = 1.0;
ups->stroke_active = true;
+
+ zero_v3(ups->average_stroke_accum);
+ ups->average_stroke_counter = 0;
+
/* initialize here to avoid initialization conflict with threaded strokes */
curvemapping_initialize(br->curve);
@@ -675,9 +690,12 @@ static void stroke_done(struct bContext *C, struct wmOperator *op)
ups->stroke_active = false;
/* reset rotation here to avoid doing so in cursor display */
- if (!(stroke->brush->flag & BRUSH_RAKE))
+ if (!(stroke->brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
ups->brush_rotation = 0.0f;
+ if (!(stroke->brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
+ ups->brush_rotation_sec = 0.0f;
+
if (stroke->stroke_started) {
if (stroke->redraw)
stroke->redraw(C, stroke, true);
@@ -1064,10 +1082,10 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
else if ((br->flag & BRUSH_LINE) && stroke->stroke_started &&
(first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))))
{
- if (br->flag & BRUSH_RAKE) {
+ if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
- paint_calculate_rake_rotation(stroke->ups, sample_average.mouse);
}
+ paint_calculate_rake_rotation(stroke->ups, br, sample_average.mouse);
}
else if (first_modal ||
/* regular dabs */
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index d41af26a4d1..9c2c13f9a2d 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -48,15 +48,13 @@
#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_material.h"
#include "BKE_paint.h"
#include "BKE_report.h"
-#include "BKE_image.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -66,16 +64,12 @@
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
-#include "RE_shader_ext.h"
#include "RE_render_ext.h"
#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 */
@@ -397,12 +391,12 @@ static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *
}
-static Image *imapaint_face_image(DerivedMesh *dm, int face_index)
+static Image *imapaint_face_image(Object *ob, Mesh *me, int face_index)
{
Image *ima;
- MFace *mf = dm->getTessFaceArray(dm) + face_index;
- Material *ma = dm->mat[mf->mat_nr];
- ima = ma ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
+ MPoly *mp = me->mpoly + face_index;
+ Material *ma = give_current_material(ob, mp->mat_nr + 1);;
+ ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
return ima;
}
@@ -456,16 +450,15 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
if (ob) {
+ Mesh *me = (Mesh *)ob->data;
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);
+ unsigned int totface = me->totface;
MTFace *dm_mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
- DM_update_materials(dm, ob);
-
if (dm_mtface) {
view3d_set_viewcontext(C, &vc);
@@ -475,7 +468,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
Image *image;
if (use_material)
- image = imapaint_face_image(dm, faceindex);
+ image = imapaint_face_image(ob, me, faceindex);
else
image = imapaint->canvas;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 75bef040d2e..7324cebbf49 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -66,8 +66,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "GPU_buffers.h"
-
#include "ED_armature.h"
#include "ED_object.h"
#include "ED_mesh.h"
@@ -387,7 +385,7 @@ static int wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
}
/* curdef should never be NULL unless this is
- * a lamp and ED_vgroup_add_name fails */
+ * a lamp and BKE_object_defgroup_add_name fails */
return mirrdef;
}
@@ -937,7 +935,7 @@ static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co
else {
factor = 1.0f;
}
- return factor * BKE_brush_curve_strength_clamp(brush, dist, brush_size_pressure);
+ return factor * BKE_brush_curve_strength(brush, dist, brush_size_pressure);
}
}
if (rgba)
@@ -2074,7 +2072,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
paint_cursor_start(C, weight_paint_poll);
- BKE_paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
+ BKE_paint_init(&scene->toolsettings->unified_paint_settings, &wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
/* weight paint specific */
ED_mesh_mirror_spatial_table(ob, NULL, NULL, 's');
@@ -2159,7 +2157,7 @@ static bool wpaint_ensure_data(bContext *C, wmOperator *op)
/* if nothing was added yet, we make dverts and a vertex deform group */
if (!me->dvert) {
- ED_vgroup_data_create(&me->id);
+ BKE_object_defgroup_data_create(&me->id);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
}
@@ -2174,7 +2172,7 @@ static bool wpaint_ensure_data(bContext *C, wmOperator *op)
if (pchan) {
bDeformGroup *dg = defgroup_find_name(ob, pchan->name);
if (dg == NULL) {
- dg = ED_vgroup_add_name(ob, pchan->name); /* sets actdef */
+ dg = BKE_object_defgroup_add_name(ob, pchan->name); /* sets actdef */
}
else {
int actdef = 1 + BLI_findindex(&ob->defbase, dg);
@@ -2186,7 +2184,7 @@ static bool wpaint_ensure_data(bContext *C, wmOperator *op)
}
}
if (BLI_listbase_is_empty(&ob->defbase)) {
- ED_vgroup_add(ob);
+ BKE_object_defgroup_add(ob);
}
/* ensure we don't try paint onto an invalid group */
@@ -2236,9 +2234,9 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UN
/* set up auto-normalize, and generate map for detecting which
* vgroups affect deform bones */
wpd->defbase_tot = BLI_listbase_count(&ob->defbase);
- wpd->lock_flags = BKE_objdef_lock_flags_get(ob, wpd->defbase_tot);
+ wpd->lock_flags = BKE_object_defgroup_lock_flags_get(ob, wpd->defbase_tot);
if (ts->auto_normalize || ts->multipaint || wpd->lock_flags) {
- wpd->vgroup_validmap = BKE_objdef_validmap_get(ob, wpd->defbase_tot);
+ wpd->vgroup_validmap = BKE_object_defgroup_validmap_get(ob, wpd->defbase_tot);
}
/* painting on subsurfs should give correct points too, this returns me->totvert amount */
@@ -2318,7 +2316,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
/* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */
wpi.defbase_tot = wpd->defbase_tot;
- wpi.defbase_sel = BKE_objdef_selected_get(ob, wpi.defbase_tot, &wpi.defbase_tot_sel);
+ wpi.defbase_sel = BKE_object_defgroup_selected_get(ob, wpi.defbase_tot, &wpi.defbase_tot_sel);
if (wpi.defbase_tot_sel == 0 && ob->actdef > 0) {
wpi.defbase_tot_sel = 1;
}
@@ -2682,7 +2680,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
paint_cursor_start(C, vertex_paint_poll);
- BKE_paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT);
+ BKE_paint_init(&scene->toolsettings->unified_paint_settings, &vp->paint, PAINT_CURSOR_VERTEX_PAINT);
}
/* update modifier stack for mapping requirements */
@@ -3024,7 +3022,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
* avoid this if we can! */
DAG_id_tag_update(ob->data, 0);
}
- else if (!GPU_buffer_legacy(ob->derivedFinal)) {
+ else {
/* If using new VBO drawing, mark mcol as dirty to force colors gpu buffer refresh! */
ob->derivedFinal->dirty |= DM_DIRTY_MCOL_UPDATE_DRAW;
}
@@ -3217,7 +3215,7 @@ static void gradientVert_update(DMGradient_userData *grad_data, int index)
/* no need to clamp 'alpha' yet */
/* adjust weight */
- alpha = BKE_brush_curve_strength_clamp(grad_data->brush, alpha, 1.0f);
+ alpha = BKE_brush_curve_strength(grad_data->brush, alpha, 1.0f);
if (alpha != 0.0f) {
MDeformVert *dv = &me->dvert[index];
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 1e4931ac792..dbb29997102 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -40,7 +40,6 @@
#include "BLI_dial.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
-#include "BLI_threads.h"
#include "BLF_translation.h"
@@ -56,7 +55,6 @@
#include "BKE_brush.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
-#include "BKE_crazyspace.h"
#include "BKE_depsgraph.h"
#include "BKE_image.h"
#include "BKE_key.h"
@@ -85,7 +83,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RE_render_ext.h"
#include "GPU_buffers.h"
@@ -106,6 +103,8 @@
#if defined(__APPLE__) && defined _OPENMP
#include <sys/sysctl.h>
+#include "BLI_threads.h"
+
/* Query how many cores not counting HT aka physical cores we've got. */
static int system_physical_thread_count(void)
{
@@ -116,33 +115,6 @@ static int system_physical_thread_count(void)
}
#endif /* __APPLE__ */
-void ED_sculpt_stroke_get_average(Object *ob, float stroke[3])
-{
- if (ob->sculpt->last_stroke_valid && ob->sculpt->average_stroke_counter > 0) {
- float fac = 1.0f / ob->sculpt->average_stroke_counter;
- mul_v3_v3fl(stroke, ob->sculpt->average_stroke_accum, fac);
- }
- else {
- copy_v3_v3(stroke, ob->obmat[3]);
- }
-}
-
-bool ED_sculpt_minmax(bContext *C, float min[3], float max[3])
-{
- Object *ob = CTX_data_active_object(C);
-
- if (ob && ob->sculpt && ob->sculpt->last_stroke_valid) {
- copy_v3_v3(min, ob->sculpt->last_stroke);
- copy_v3_v3(max, ob->sculpt->last_stroke);
-
- return 1;
- }
- else {
- return 0;
- }
-}
-
-
/* Check if there are any active modifiers in stack (used for flushing updates at enter/exit sculpt mode) */
static bool sculpt_has_active_modifiers(Scene *scene, Object *ob)
{
@@ -2957,7 +2929,7 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
/* Note: we do the topology update before any brush actions to avoid
* issues with the proxies. The size of the proxy can't change, so
* topology must be updated first. */
-static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
+static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *UNUSED(ups))
{
SculptSession *ss = ob->sculpt;
SculptSearchSphereData data;
@@ -3018,13 +2990,10 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
/* update average stroke position */
copy_v3_v3(location, ss->cache->true_location);
mul_m4_v3(ob->obmat, location);
-
- add_v3_v3(ob->sculpt->average_stroke_accum, location);
- ob->sculpt->average_stroke_counter++;
}
}
-static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
+static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups)
{
SculptSession *ss = ob->sculpt;
SculptSearchSphereData data;
@@ -3138,8 +3107,10 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
copy_v3_v3(location, ss->cache->true_location);
mul_m4_v3(ob->obmat, location);
- add_v3_v3(ob->sculpt->average_stroke_accum, location);
- ob->sculpt->average_stroke_counter++;
+ add_v3_v3(ups->average_stroke_accum, location);
+ ups->average_stroke_counter++;
+ /* update last stroke position */
+ ups->last_stroke_valid = true;
}
}
@@ -3348,9 +3319,9 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm,
}
}
-typedef void (*BrushActionFunc)(Sculpt *sd, Object *ob, Brush *brush);
+typedef void (*BrushActionFunc)(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups);
-static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush,
+static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups,
BrushActionFunc action,
const char symm, const int axis,
const float feather)
@@ -3362,7 +3333,7 @@ static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush,
const float angle = 2 * M_PI * i / sd->radial_symm[axis - 'X'];
ss->cache->radial_symmetry_pass = i;
calc_brushdata_symm(sd, ss->cache, symm, axis, angle, feather);
- action(sd, ob, brush);
+ action(sd, ob, brush, ups);
}
}
@@ -3400,11 +3371,11 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob,
cache->radial_symmetry_pass = 0;
calc_brushdata_symm(sd, cache, i, 0, 0, feather);
- action(sd, ob, brush);
+ action(sd, ob, brush, ups);
- do_radial_symmetry(sd, ob, brush, action, i, 'X', feather);
- do_radial_symmetry(sd, ob, brush, action, i, 'Y', feather);
- do_radial_symmetry(sd, ob, brush, action, i, 'Z', feather);
+ do_radial_symmetry(sd, ob, brush, ups, action, i, 'X', feather);
+ do_radial_symmetry(sd, ob, brush, ups, action, i, 'Y', feather);
+ do_radial_symmetry(sd, ob, brush, ups, action, i, 'Z', feather);
}
}
}
@@ -4156,9 +4127,6 @@ static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op)
is_smooth = sculpt_any_smooth_mode(brush, NULL, mode);
BKE_sculpt_update_mesh_elements(scene, sd, ob, is_smooth, need_mask);
- zero_v3(ob->sculpt->average_stroke_accum);
- ob->sculpt->average_stroke_counter = 0;
-
return 1;
}
@@ -4365,10 +4333,6 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
}
}
- /* update last stroke position */
- ob->sculpt->last_stroke_valid = 1;
- ED_sculpt_stroke_get_average(ob, ob->sculpt->last_stroke);
-
sculpt_cache_free(ss->cache);
ss->cache = NULL;
@@ -4985,7 +4949,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
"Object has negative scale, sculpting may be unpredictable");
}
- BKE_paint_init(&ts->sculpt->paint, PAINT_CURSOR_SCULPT);
+ BKE_paint_init(&ts->unified_paint_settings, &ts->sculpt->paint, PAINT_CURSOR_SCULPT);
paint_cursor_start(C, sculpt_poll_view3d);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index d90eaafa379..23bc4a483d3 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -60,7 +60,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "paint_intern.h"
#include "uvedit_intern.h"
@@ -237,7 +236,7 @@ void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings
settings->uvsculpt->paint.flags |= PAINT_SHOW_BRUSH;
}
- BKE_paint_init(&settings->uvsculpt->paint, PAINT_CURSOR_SCULPT);
+ BKE_paint_init(&settings->unified_paint_settings, &settings->uvsculpt->paint, PAINT_CURSOR_SCULPT);
settings->uvsculpt->paint.paint_cursor = WM_paint_cursor_activate(wm, uv_sculpt_brush_poll,
brush_drawcursor_uvsculpt, NULL);
@@ -558,15 +557,15 @@ static int uv_element_offset_from_face_get(UvElementMap *map, BMFace *efa, BMLoo
static unsigned int uv_edge_hash(const void *key)
{
- UvEdge *edge = (UvEdge *)key;
+ const UvEdge *edge = key;
return (BLI_ghashutil_uinthash(edge->uv2) +
BLI_ghashutil_uinthash(edge->uv1));
}
static bool uv_edge_compare(const void *a, const void *b)
{
- UvEdge *edge1 = (UvEdge *)a;
- UvEdge *edge2 = (UvEdge *)b;
+ const UvEdge *edge1 = a;
+ const UvEdge *edge2 = b;
if ((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)) {
return 0;
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 7ede6c95b9d..d9f4b97fe09 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -72,7 +72,6 @@
#include "ED_sound.h"
#include "ED_util.h"
-#include "sound_intern.h"
/******************** open sound operator ********************/
@@ -143,7 +142,7 @@ static int sound_open_exec(bContext *C, wmOperator *op)
RNA_property_update(C, &pprop->ptr, pprop->prop);
}
- if (op->customdata) MEM_freeN(op->customdata);
+ MEM_freeN(op->customdata);
return OPERATOR_FINISHED;
}
@@ -184,7 +183,7 @@ static void SOUND_OT_open(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | SOUNDFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
RNA_def_boolean(ot->srna, "mono", false, "Mono", "Mixdown the sound to mono");
@@ -206,7 +205,7 @@ static void SOUND_OT_open_mono(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | SOUNDFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
RNA_def_boolean(ot->srna, "mono", true, "Mono", "Mixdown the sound to mono");
@@ -651,7 +650,7 @@ static void SOUND_OT_mixdown(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | SOUNDFILE, FILE_SPECIAL, FILE_SAVE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND, FILE_SPECIAL, FILE_SAVE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
#ifdef WITH_AUDASPACE
RNA_def_int(ot->srna, "accuracy", 1024, 1, 16777216, "Accuracy", "Sample accuracy, important for animation data (the lower the value, the more accurate)", 1, 16777216);
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index e55ce3ea8eb..bc9c578b558 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -545,7 +545,7 @@ static short copy_action_keys(bAnimContext *ac)
static short paste_action_keys(bAnimContext *ac,
- const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode)
+ const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
{
ListBase anim_data = {NULL, NULL};
int filter, ok = 0;
@@ -562,7 +562,7 @@ static short paste_action_keys(bAnimContext *ac,
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* paste keyframes */
- ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode);
+ ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
/* clean up */
ANIM_animdata_freelist(&anim_data);
@@ -622,6 +622,7 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset");
const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge");
+ const bool flipped = RNA_boolean_get(op->ptr, "flipped");
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -638,7 +639,7 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
}
else {
/* non-zero return means an error occurred while trying to paste */
- if (paste_action_keys(&ac, offset_mode, merge_mode)) {
+ if (paste_action_keys(&ac, offset_mode, merge_mode, flipped)) {
return OPERATOR_CANCELLED;
}
}
@@ -651,6 +652,7 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
void ACTION_OT_paste(wmOperatorType *ot)
{
+ PropertyRNA *prop;
/* identifiers */
ot->name = "Paste Keyframes";
ot->idname = "ACTION_OT_paste";
@@ -667,6 +669,8 @@ void ACTION_OT_paste(wmOperatorType *ot)
/* props */
RNA_def_enum(ot->srna, "offset", keyframe_paste_offset_items, KEYFRAME_PASTE_OFFSET_CFRA_START, "Offset", "Paste time offset of keys");
RNA_def_enum(ot->srna, "merge", keyframe_paste_merge_items, KEYFRAME_PASTE_MERGE_MIX, "Type", "Method of merging pasted keys and existing");
+ prop = RNA_def_boolean(ot->srna, "flipped", false, "Flipped", "Paste keyframes from mirrored bones if they exist");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ******************** Insert Keyframes Operator ************************* */
@@ -965,8 +969,11 @@ static int actkeys_clean_exec(bContext *C, wmOperator *op)
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
return OPERATOR_PASS_THROUGH;
+ }
/* get cleaning threshold */
thresh = RNA_float_get(op->ptr, "threshold");
@@ -1025,15 +1032,18 @@ static void sample_action_keys(bAnimContext *ac)
/* ------------------- */
-static int actkeys_sample_exec(bContext *C, wmOperator *UNUSED(op))
+static int actkeys_sample_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
return OPERATOR_PASS_THROUGH;
+ }
/* sample keyframes */
sample_action_keys(&ac);
@@ -1138,8 +1148,11 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op)
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
return OPERATOR_PASS_THROUGH;
+ }
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
@@ -1209,8 +1222,11 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op)
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
return OPERATOR_PASS_THROUGH;
+ }
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
@@ -1288,8 +1304,11 @@ static int actkeys_handletype_exec(bContext *C, wmOperator *op)
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented");
return OPERATOR_PASS_THROUGH;
+ }
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
@@ -1324,7 +1343,7 @@ void ACTION_OT_handle_type(wmOperatorType *ot)
/* ******************** Set Keyframe-Type Operator *********************** */
-/* this function is responsible for setting interpolation mode for keyframes */
+/* this function is responsible for setting keyframe type for keyframes */
static void setkeytype_action_keys(bAnimContext *ac, short mode)
{
ListBase anim_data = {NULL, NULL};
@@ -1349,6 +1368,29 @@ static void setkeytype_action_keys(bAnimContext *ac, short mode)
ANIM_animdata_freelist(&anim_data);
}
+/* this function is responsible for setting the keyframe type for Grease Pencil frames */
+static void setkeytype_gpencil_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through each layer */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gplayer_frames_keytype_set(ale->data, mode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+}
+
/* ------------------- */
static int actkeys_keytype_exec(bContext *C, wmOperator *op)
@@ -1359,14 +1401,22 @@ static int actkeys_keytype_exec(bContext *C, wmOperator *op)
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+
+ if (ac.datatype == ANIMCONT_MASK) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented for Masks");
return OPERATOR_PASS_THROUGH;
+ }
/* get handle setting mode */
mode = RNA_enum_get(op->ptr, "type");
/* set handle type */
- setkeytype_action_keys(&ac, mode);
+ if (ac.datatype == ANIMCONT_GPENCIL) {
+ setkeytype_gpencil_keys(&ac, mode);
+ }
+ else {
+ setkeytype_action_keys(&ac, mode);
+ }
/* set notifier that keyframe properties have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c
index b99419dec20..0fbacefa8e3 100644
--- a/source/blender/editors/space_action/action_ops.c
+++ b/source/blender/editors/space_action/action_ops.c
@@ -35,7 +35,6 @@
#include "DNA_space_types.h"
-#include "BLI_utildefines.h"
#include "ED_anim_api.h"
#include "ED_markers.h"
@@ -44,7 +43,6 @@
#include "action_intern.h"
#include "RNA_access.h"
-#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -207,9 +205,13 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
/* copy/paste */
WM_keymap_add_item(keymap, "ACTION_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
+ kmi = WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "flipped", true);
#ifdef __APPLE__
WM_keymap_add_item(keymap, "ACTION_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
+ kmi = WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_OSKEY | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "flipped", true);
#endif
/* auto-set range */
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 77c6cce6cda..01f0d1ae54f 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -32,7 +32,6 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
@@ -61,7 +60,6 @@
#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"
@@ -155,6 +153,7 @@ void ED_spacemacros_init(void)
ED_operatormacros_mask();
ED_operatormacros_sequencer();
ED_operatormacros_paint();
+ ED_operatormacros_gpencil();
/* register dropboxes (can use macros) */
spacetypes = BKE_spacetypes_list();
@@ -318,7 +317,3 @@ void ED_spacetype_xxx(void)
}
/* ****************************** end template *********************** */
-
-
-
-
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 3b939702c58..a67af289f59 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -61,7 +61,9 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_scene.h"
-#include "BKE_freestyle.h"
+#ifdef WITH_FREESTYLE
+# include "BKE_freestyle.h"
+#endif
#include "RNA_access.h"
@@ -468,7 +470,7 @@ void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts)
}
else {
/* set one user as active based on active index */
- if (ct->index == BLI_listbase_count_ex(&ct->users, ct->index))
+ if (ct->index == BLI_listbase_count_ex(&ct->users, ct->index + 1))
ct->index = 0;
ct->user = BLI_findlink(&ct->users, ct->index);
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 4d62f528915..a778df4b783 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -28,7 +28,6 @@
* \ingroup spbuttons
*/
-
#include <string.h>
#include <stdio.h>
@@ -46,10 +45,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "UI_resources.h"
-#include "UI_view2d.h"
-
-
#include "buttons_intern.h" /* own include */
/* ******************** default callbacks for buttons space ***************** */
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index fe36d9a9685..f8299a8d335 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -69,26 +69,9 @@
/* Panels */
-static int clip_grease_pencil_panel_poll(const bContext *C, PanelType *UNUSED(pt))
+void ED_clip_buttons_register(ARegionType *UNUSED(art))
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- return sc->view == SC_VIEW_CLIP;
-}
-
-void ED_clip_buttons_register(ARegionType *art)
-{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype clip panel gpencil");
- strcpy(pt->idname, "CLIP_PT_gpencil");
- strcpy(pt->label, N_("Grease Pencil"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw_header = ED_gpencil_panel_standard_header;
- pt->draw = ED_gpencil_panel_standard;
- pt->flag |= PNL_DEFAULT_CLOSED;
- pt->poll = clip_grease_pencil_panel_poll;
- BLI_addtail(&art->paneltypes, pt);
}
/********************* MovieClip Template ************************/
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index fe5b332aeb1..4bf4c1e7baa 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -30,7 +30,6 @@
*/
#include "DNA_movieclip_types.h"
-#include "DNA_object_types.h" /* SELECT */
#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c
index 7ae5eda7139..d2f2fdd0b46 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_ops.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c
@@ -29,7 +29,6 @@
* \ingroup spclip
*/
-#include "DNA_object_types.h" /* SELECT */
#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index a35251e71ef..6c55d8d034e 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -63,7 +63,6 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "RNA_access.h"
#include "BLF_api.h"
@@ -1123,7 +1122,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
bool draw_outline, int width, int height)
{
bool tiny = (sc->flag & SC_SHOW_TINY_MARKER) != 0;
- bool is_selected_track = plane_track->flag & SELECT;
+ bool is_selected_track = (plane_track->flag & SELECT) != 0;
bool draw_plane_quad = plane_track->image == NULL || plane_track->image_opacity == 0.0f;
float px[2];
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index f25f035db32..89693a403fe 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -57,7 +57,6 @@
#include "BKE_tracking.h"
#include "BKE_library.h"
-#include "GPU_extensions.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c
index 723c8bd144a..2c3b8acf672 100644
--- a/source/blender/editors/space_clip/clip_graph_draw.c
+++ b/source/blender/editors/space_clip/clip_graph_draw.c
@@ -50,7 +50,6 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "BLF_api.h"
#include "clip_intern.h" // own include
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index d1e2c770ade..2a2f15c94bb 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -45,8 +45,6 @@
#include "ED_screen.h"
#include "ED_clip.h"
-#include "UI_interface.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 787a7fca273..e3d45a297a7 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -299,7 +299,7 @@ void CLIP_OT_open(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_RELPATH | WM_FILESEL_FILES | WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY);
}
@@ -1307,7 +1307,14 @@ static void proxy_endjob(void *pjv)
if (pj->index_context)
IMB_anim_index_rebuild_finish(pj->index_context, pj->stop);
- BKE_movieclip_reload(pj->clip);
+ if (pj->clip->source == MCLIP_SRC_MOVIE) {
+ /* Timecode might have changed, so do a full reload to deal with this. */
+ BKE_movieclip_reload(pj->clip);
+ }
+ else {
+ /* For image sequences we'll preserve original cache. */
+ BKE_movieclip_clear_proxy_cache(pj->clip);
+ }
WM_main_add_notifier(NC_MOVIECLIP | ND_DISPLAY, pj->clip);
}
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index a79ac1f7b82..5f919c9b51d 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -30,12 +30,10 @@
*/
#include "DNA_scene_types.h"
-#include "DNA_object_types.h" /* SELECT */
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
@@ -54,8 +52,6 @@
#include "ED_screen.h"
#include "ED_clip.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
#include "UI_interface.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index bf9b55ba3dd..fc2c0d3d45c 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -420,6 +420,9 @@ static void clip_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
clip_scopes_check_gpencil_change(sa);
ED_area_tag_redraw(sa);
}
+ else if (wmn->data & ND_GPENCIL_EDITMODE) {
+ ED_area_tag_redraw(sa);
+ }
break;
}
}
@@ -1245,6 +1248,8 @@ static void clip_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), AR
case NC_GPENCIL:
if (wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
+ else if (wmn->data & ND_GPENCIL_EDITMODE)
+ ED_region_tag_redraw(ar);
break;
}
}
@@ -1495,7 +1500,7 @@ static void clip_properties_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(s
/* context changes */
switch (wmn->category) {
case NC_GPENCIL:
- if (wmn->data == ND_DATA)
+ if (ELEM(wmn->data, ND_DATA, ND_GPENCIL_EDITMODE))
ED_region_tag_redraw(ar);
break;
case NC_BRUSH:
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index bdb57cca81e..742e58d80dd 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -41,7 +41,6 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
-#include "BLI_rect.h"
#include "BLI_blenlib.h"
#include "BKE_main.h"
@@ -65,7 +64,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "UI_interface.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -74,7 +72,6 @@
#include "PIL_time.h"
-#include "UI_view2d.h"
#include "clip_intern.h" // own include
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index 860d9dc6b3c..bc6ac507f03 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -36,7 +36,6 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BLI_listbase.h"
#include "BLI_rect.h"
#include "BLI_lasso.h"
@@ -49,16 +48,9 @@
#include "ED_screen.h"
#include "ED_clip.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-
-#include "UI_interface.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
-#include "PIL_time.h"
-
#include "UI_view2d.h"
#include "clip_intern.h" // own include
diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c
index 635d5ea07fd..d206ce4699e 100644
--- a/source/blender/editors/space_console/console_draw.c
+++ b/source/blender/editors/space_console/console_draw.c
@@ -30,7 +30,6 @@
#include <sys/stat.h>
#include <limits.h>
-#include "BLF_api.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 6f63f315f74..3f3c14d3a7d 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -47,7 +47,6 @@
#include "BKE_global.h"
#include "BKE_main.h"
-#include "BLF_api.h"
#include "BLF_translation.h"
#include "IMB_imbuf_types.h"
@@ -67,7 +66,6 @@
#include "WM_types.h"
-#include "fsmenu.h"
#include "filelist.h"
#include "file_intern.h" // own include
@@ -113,6 +111,7 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
ARegion *artmp;
+ const bool is_browse_only = (sfile->op == NULL);
/* Initialize UI block. */
BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar);
@@ -126,15 +125,22 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
available_w -= chan_offs;
}
}
-
+
/* Is there enough space for the execute / cancel buttons? */
- loadbutton = UI_fontstyle_string_width(params->title) + btn_margin;
- CLAMP_MIN(loadbutton, btn_minw);
- if (available_w <= loadbutton + separator + input_minw || params->title[0] == 0) {
+
+ if (is_browse_only) {
loadbutton = 0;
}
else {
+ loadbutton = UI_fontstyle_string_width(params->title) + btn_margin;
+ CLAMP_MIN(loadbutton, btn_minw);
+ if (available_w <= loadbutton + separator + input_minw) {
+ loadbutton = 0;
+ }
+ }
+
+ if (loadbutton) {
line1_w -= (loadbutton + separator);
line2_w = line1_w;
}
@@ -147,7 +153,7 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
else {
line2_w -= (fnumbuttons + separator);
}
-
+
/* Text input fields for directory and file. */
if (available_w > 0) {
int overwrite_alert = file_draw_check_exists(sfile);
@@ -235,33 +241,33 @@ static int get_file_icon(struct direntry *file)
if (strcmp(file->relname, "..") == 0) {
return ICON_FILE_PARENT;
}
- if (file->flags & APPLICATIONBUNDLE) {
+ if (file->flags & FILE_TYPE_APPLICATIONBUNDLE) {
return ICON_UGLYPACKAGE;
}
- if (file->flags & BLENDERFILE) {
+ if (file->flags & FILE_TYPE_BLENDER) {
return ICON_FILE_BLEND;
}
return ICON_FILE_FOLDER;
}
- else if (file->flags & BLENDERFILE)
+ else if (file->flags & FILE_TYPE_BLENDER)
return ICON_FILE_BLEND;
- else if (file->flags & BLENDERFILE_BACKUP)
+ else if (file->flags & FILE_TYPE_BLENDER_BACKUP)
return ICON_FILE_BACKUP;
- else if (file->flags & IMAGEFILE)
+ else if (file->flags & FILE_TYPE_IMAGE)
return ICON_FILE_IMAGE;
- else if (file->flags & MOVIEFILE)
+ else if (file->flags & FILE_TYPE_MOVIE)
return ICON_FILE_MOVIE;
- else if (file->flags & PYSCRIPTFILE)
+ else if (file->flags & FILE_TYPE_PYSCRIPT)
return ICON_FILE_SCRIPT;
- else if (file->flags & SOUNDFILE)
+ else if (file->flags & FILE_TYPE_SOUND)
return ICON_FILE_SOUND;
- else if (file->flags & FTFONTFILE)
+ else if (file->flags & FILE_TYPE_FTFONT)
return ICON_FILE_FONT;
- else if (file->flags & BTXFILE)
+ else if (file->flags & FILE_TYPE_BTX)
return ICON_FILE_BLANK;
- else if (file->flags & COLLADAFILE)
+ else if (file->flags & FILE_TYPE_COLLADA)
return ICON_FILE_BLANK;
- else if (file->flags & TEXTFILE)
+ else if (file->flags & FILE_TYPE_TEXT)
return ICON_FILE_TEXT;
else
return ICON_FILE_BLANK;
@@ -516,10 +522,15 @@ void file_draw_list(const bContext *C, ARegion *ar)
UI_ThemeColor4(TH_TEXT);
- if (!(file->selflag & EDITING_FILE)) {
- if ((params->active_file == i) || (file->selflag & HILITED_FILE) || (file->selflag & SELECTED_FILE)) {
- int colorid = (file->selflag & SELECTED_FILE) ? TH_HILITE : TH_BACK;
- int shade = (params->active_file == i) || (file->selflag & HILITED_FILE) ? 20 : 0;
+ if (!(file->selflag & FILE_SEL_EDITING)) {
+ if ((params->active_file == i) || (file->selflag & FILE_SEL_HIGHLIGHTED) || (file->selflag & FILE_SEL_SELECTED)) {
+ int colorid = (file->selflag & FILE_SEL_SELECTED) ? TH_HILITE : TH_BACK;
+ int shade = (params->active_file == i) || (file->selflag & FILE_SEL_HIGHLIGHTED) ? 20 : 0;
+
+ /* readonly files (".." and ".") must not be drawn as selected - set color back to normal */
+ if (STREQ(file->relname, "..") || STREQ(file->relname, ".")) {
+ colorid = TH_BACK;
+ }
draw_tile(sx, sy - 1, layout->tile_w + 4, sfile->layout->tile_h + layout->tile_border_y, colorid, shade);
}
}
@@ -536,7 +547,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
is_icon = 1;
}
- file_draw_preview(block, file, sx, sy, imb, layout, !is_icon && (file->flags & IMAGEFILE), do_drag);
+ file_draw_preview(block, file, sx, sy, imb, layout, !is_icon && (file->flags & FILE_TYPE_IMAGE), do_drag);
}
else {
file_draw_icon(block, file->path, sx, sy - (UI_UNIT_Y / 6), get_file_icon(file), ICON_DEFAULT_WIDTH_SCALE, ICON_DEFAULT_HEIGHT_SCALE, do_drag);
@@ -545,7 +556,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
UI_ThemeColor4(TH_TEXT);
- if (file->selflag & EDITING_FILE) {
+ if (file->selflag & FILE_SEL_EDITING) {
uiBut *but;
short width;
@@ -568,11 +579,11 @@ void file_draw_list(const bContext *C, ARegion *ar)
UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* allow non utf8 names */
UI_but_flag_disable(but, UI_BUT_UNDO);
if (false == UI_but_active_only(C, ar, block, but)) {
- file->selflag &= ~EDITING_FILE;
+ file->selflag &= ~FILE_SEL_EDITING;
}
}
- if (!(file->selflag & EDITING_FILE)) {
+ if (!(file->selflag & FILE_SEL_EDITING)) {
int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight : sy;
file_draw_string(sx + 1, tpos, file->relname, (float)textwidth, textheight, align);
}
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 13beba3fff8..3a579820106 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -34,6 +34,7 @@
#include "BLO_readfile.h"
+#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_global.h"
@@ -219,7 +220,7 @@ static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select,
const FileCheckType check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_ALL;
/* flag the files as selected in the filelist */
- filelist_select(sfile->files, &sel, select, SELECTED_FILE, check_type);
+ filelist_select(sfile->files, &sel, select, FILE_SEL_SELECTED, check_type);
/* Don't act on multiple selected files */
if (sel.first != sel.last) select = 0;
@@ -258,9 +259,25 @@ static int file_border_select_modal(bContext *C, wmOperator *op, const wmEvent *
sel = file_selection_get(C, &rect, 0);
if ( (sel.first != params->sel_first) || (sel.last != params->sel_last) ) {
- file_deselect_all(sfile, HILITED_FILE);
- filelist_select(sfile->files, &sel, FILE_SEL_ADD, HILITED_FILE, CHECK_ALL);
+ int idx;
+
+ file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
+ filelist_select(sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+
+ /* dont highlight readonly file (".." or ".") on border select */
+ for (idx = sel.last; idx >= 0; idx--) {
+ struct direntry *file = filelist_file(sfile->files, idx);
+
+ if (STREQ(file->relname, "..") || STREQ(file->relname, ".")) {
+ file->selflag &= ~FILE_SEL_HIGHLIGHTED;
+ }
+
+ /* active_file gets highlighted as well - make sure it is no readonly file */
+ if (sel.last == idx) {
+ params->active_file = idx;
+ }
+ }
}
params->sel_first = sel.first; params->sel_last = sel.last;
@@ -268,7 +285,7 @@ static int file_border_select_modal(bContext *C, wmOperator *op, const wmEvent *
else {
params->active_file = -1;
params->sel_first = params->sel_last = -1;
- file_deselect_all(sfile, HILITED_FILE);
+ file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
}
@@ -288,7 +305,7 @@ static int file_border_select_exec(bContext *C, wmOperator *op)
if (!extend) {
SpaceFile *sfile = CTX_wm_space_file(C);
- file_deselect_all(sfile, SELECTED_FILE);
+ file_deselect_all(sfile, FILE_SEL_SELECTED);
}
BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect);
@@ -340,8 +357,20 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (!BLI_rcti_isect_pt(&ar->v2d.mask, rect.xmin, rect.ymin))
return OPERATOR_CANCELLED;
- /* single select, deselect all selected first */
- if (!extend) file_deselect_all(sfile, SELECTED_FILE);
+ if (sfile && sfile->params) {
+ int idx = sfile->params->active_file;
+
+ if (idx >= 0) {
+ struct direntry *file = filelist_file(sfile->files, idx);
+ if (STREQ(file->relname, "..") || STREQ(file->relname, ".")) {
+ /* skip - If a readonly file (".." or ".") is selected, skip deselect all! */
+ }
+ else {
+ /* single select, deselect all selected first */
+ if (!extend) file_deselect_all(sfile, FILE_SEL_SELECTED);
+ }
+ }
+ }
ret = file_select(C, &rect, extend ? FILE_SEL_TOGGLE : FILE_SEL_ADD, fill, do_diropen);
if (FILE_SELECT_DIR == ret)
@@ -398,11 +427,11 @@ static int file_select_all_exec(bContext *C, wmOperator *UNUSED(op))
}
/* select all only if previously no file was selected */
if (is_selected) {
- filelist_select(sfile->files, &sel, FILE_SEL_REMOVE, SELECTED_FILE, CHECK_ALL);
+ filelist_select(sfile->files, &sel, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
}
else {
const FileCheckType check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_FILES;
- filelist_select(sfile->files, &sel, FILE_SEL_ADD, SELECTED_FILE, check_type);
+ filelist_select(sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_SELECTED, check_type);
}
ED_area_tag_redraw(sa);
return OPERATOR_FINISHED;
@@ -472,7 +501,7 @@ static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op))
char name[FILE_MAX];
fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, FS_INSERT_SAVE);
- BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ BLI_make_file_string("/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
}
@@ -504,7 +533,7 @@ static int bookmark_delete_exec(bContext *C, wmOperator *op)
char name[FILE_MAX];
fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index);
- BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ BLI_make_file_string("/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
ED_area_tag_redraw(sa);
}
@@ -540,7 +569,7 @@ static int reset_recent_exec(bContext *C, wmOperator *UNUSED(op))
while (fsmenu_get_entry(fsmenu, FS_CATEGORY_RECENT, 0) != NULL) {
fsmenu_remove_entry(fsmenu, FS_CATEGORY_RECENT, 0);
}
- BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ BLI_make_file_string("/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
ED_area_tag_redraw(sa);
@@ -821,7 +850,7 @@ int file_exec(bContext *C, wmOperator *exec_op)
fsmenu_insert_entry(fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir, FS_INSERT_SAVE | FS_INSERT_FIRST);
}
- BLI_make_file_string(G.main->name, filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ BLI_make_file_string(G.main->name, filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu_get(), filepath);
WM_event_fileselect_event(wm, op, EVT_FILESELECT_EXEC);
@@ -1197,7 +1226,7 @@ static void file_expand_directory(bContext *C)
else if (sfile->params->dir[0] == '~') {
char tmpstr[sizeof(sfile->params->dir) - 1];
BLI_strncpy(tmpstr, sfile->params->dir + 1, sizeof(tmpstr));
- BLI_join_dirfile(sfile->params->dir, sizeof(sfile->params->dir), BLI_getDefaultDocumentFolder(), tmpstr);
+ BLI_join_dirfile(sfile->params->dir, sizeof(sfile->params->dir), BKE_appdir_folder_default(), tmpstr);
}
else if (sfile->params->dir[0] == '\0')
@@ -1481,7 +1510,7 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
int numfiles = filelist_numfiles(sfile->files);
if ( (0 <= idx) && (idx < numfiles) ) {
struct direntry *file = filelist_file(sfile->files, idx);
- filelist_select_file(sfile->files, idx, FILE_SEL_ADD, EDITING_FILE, CHECK_ALL);
+ filelist_select_file(sfile->files, idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
BLI_strncpy(sfile->params->renameedit, file->relname, FILE_MAXFILE);
sfile->params->renamefile[0] = '\0';
}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 871abbda48a..bcef0817ffe 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -45,9 +45,10 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_fileops_types.h"
+#include "BLI_fnmatch.h"
#include "BLI_linklist.h"
#include "BLI_utildefines.h"
-#include "BLI_fileops_types.h"
#ifdef WIN32
# include "BLI_winstuff.h"
@@ -64,8 +65,8 @@
#include "DNA_space_types.h"
-#include "ED_fileselect.h"
#include "ED_datafiles.h"
+#include "ED_fileselect.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -80,6 +81,119 @@
#include "filelist.h"
+
+/* ----------------- FOLDERLIST (previous/next) -------------- */
+
+typedef struct FolderList {
+ struct FolderList *next, *prev;
+ char *foldername;
+} FolderList;
+
+ListBase *folderlist_new(void)
+{
+ ListBase *p = MEM_callocN(sizeof(ListBase), "folderlist");
+ return p;
+}
+
+void folderlist_popdir(struct ListBase *folderlist, char *dir)
+{
+ const char *prev_dir;
+ struct FolderList *folder;
+ folder = folderlist->last;
+
+ if (folder) {
+ /* remove the current directory */
+ MEM_freeN(folder->foldername);
+ BLI_freelinkN(folderlist, folder);
+
+ folder = folderlist->last;
+ if (folder) {
+ prev_dir = folder->foldername;
+ BLI_strncpy(dir, prev_dir, FILE_MAXDIR);
+ }
+ }
+ /* delete the folder next or use setdir directly before PREVIOUS OP */
+}
+
+void folderlist_pushdir(ListBase *folderlist, const char *dir)
+{
+ struct FolderList *folder, *previous_folder;
+ previous_folder = folderlist->last;
+
+ /* check if already exists */
+ if (previous_folder && previous_folder->foldername) {
+ if (BLI_path_cmp(previous_folder->foldername, dir) == 0) {
+ return;
+ }
+ }
+
+ /* create next folder element */
+ folder = (FolderList *)MEM_mallocN(sizeof(FolderList), "FolderList");
+ folder->foldername = BLI_strdup(dir);
+
+ /* add it to the end of the list */
+ BLI_addtail(folderlist, folder);
+}
+
+const char *folderlist_peeklastdir(ListBase *folderlist)
+{
+ struct FolderList *folder;
+
+ if (!folderlist->last)
+ return NULL;
+
+ folder = folderlist->last;
+ return folder->foldername;
+}
+
+int folderlist_clear_next(struct SpaceFile *sfile)
+{
+ struct FolderList *folder;
+
+ /* if there is no folder_next there is nothing we can clear */
+ if (!sfile->folders_next)
+ return 0;
+
+ /* if previous_folder, next_folder or refresh_folder operators are executed it doesn't clear folder_next */
+ folder = sfile->folders_prev->last;
+ if ((!folder) || (BLI_path_cmp(folder->foldername, sfile->params->dir) == 0))
+ return 0;
+
+ /* eventually clear flist->folders_next */
+ return 1;
+}
+
+/* not listbase itself */
+void folderlist_free(ListBase *folderlist)
+{
+ if (folderlist) {
+ FolderList *folder;
+ for (folder = folderlist->first; folder; folder = folder->next)
+ MEM_freeN(folder->foldername);
+ BLI_freelistN(folderlist);
+ }
+}
+
+ListBase *folderlist_duplicate(ListBase *folderlist)
+{
+
+ if (folderlist) {
+ ListBase *folderlistn = MEM_callocN(sizeof(ListBase), "copy folderlist");
+ FolderList *folder;
+
+ BLI_duplicatelist(folderlistn, folderlist);
+
+ for (folder = folderlistn->first; folder; folder = folder->next) {
+ folder->foldername = MEM_dupallocN(folder->foldername);
+ }
+ return folderlistn;
+ }
+ return NULL;
+}
+
+
+/* ------------------FILELIST------------------------ */
+
struct FileList;
typedef struct FileImage {
@@ -91,77 +205,87 @@ typedef struct FileImage {
ImBuf *img;
} FileImage;
-typedef struct ThumbnailJob {
- ListBase loadimages;
- const short *stop;
- const short *do_update;
- struct FileList *filelist;
- ReportList reports;
-} ThumbnailJob;
+typedef struct FileListFilter {
+ bool hide_dot;
+ bool hide_parent;
+ unsigned int filter;
+ char filter_glob[64];
+ char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */
+} FileListFilter;
typedef struct FileList {
struct direntry *filelist;
- int *fidx;
int numfiles;
- int numfiltered;
char dir[FILE_MAX];
short prv_w;
short prv_h;
- short hide_dot;
- unsigned int filter;
- char filter_glob[64];
- short changed;
+
+ bool changed;
+
+ short sort;
+ bool need_sorting;
+
+ FileListFilter filter_data;
+ int *fidx; /* Also used to detect when we need to filter! */
+ int numfiltered;
+
+ bool need_thumbnails;
struct BlendHandle *libfiledata;
- short hide_parent;
void (*readf)(struct FileList *);
- bool (*filterf)(struct direntry *file, const char *dir, unsigned int filter, short hide_dot);
-
+ bool (*filterf)(struct direntry *, const char *, FileListFilter *);
} FileList;
-typedef struct FolderList {
- struct FolderList *next, *prev;
- char *foldername;
-} FolderList;
+#define FILENAME_IS_BREADCRUMBS(_n) \
+ ((_n)[0] == '.' && ((_n)[1] == '\0' || ((_n)[1] == '.' && (_n)[2] == '\0')))
#define SPECIAL_IMG_SIZE 48
#define SPECIAL_IMG_ROWS 4
#define SPECIAL_IMG_COLS 4
-#define SPECIAL_IMG_FOLDER 0
-#define SPECIAL_IMG_PARENT 1
-#define SPECIAL_IMG_REFRESH 2
-#define SPECIAL_IMG_BLENDFILE 3
-#define SPECIAL_IMG_SOUNDFILE 4
-#define SPECIAL_IMG_MOVIEFILE 5
-#define SPECIAL_IMG_PYTHONFILE 6
-#define SPECIAL_IMG_TEXTFILE 7
-#define SPECIAL_IMG_FONTFILE 8
-#define SPECIAL_IMG_UNKNOWNFILE 9
-#define SPECIAL_IMG_LOADING 10
-#define SPECIAL_IMG_BACKUP 11
-#define SPECIAL_IMG_MAX SPECIAL_IMG_BACKUP + 1
+enum {
+ SPECIAL_IMG_FOLDER = 0,
+ SPECIAL_IMG_PARENT = 1,
+ SPECIAL_IMG_REFRESH = 2,
+ SPECIAL_IMG_BLENDFILE = 3,
+ SPECIAL_IMG_SOUNDFILE = 4,
+ SPECIAL_IMG_MOVIEFILE = 5,
+ SPECIAL_IMG_PYTHONFILE = 6,
+ SPECIAL_IMG_TEXTFILE = 7,
+ SPECIAL_IMG_FONTFILE = 8,
+ SPECIAL_IMG_UNKNOWNFILE = 9,
+ SPECIAL_IMG_LOADING = 10,
+ SPECIAL_IMG_BACKUP = 11,
+ SPECIAL_IMG_MAX
+};
static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX];
-/* ******************* SORT ******************* */
+static void filelist_from_main(struct FileList *filelist);
+static void filelist_from_library(struct FileList *filelist);
+
+static void filelist_read_main(struct FileList *filelist);
+static void filelist_read_library(struct FileList *filelist);
+static void filelist_read_dir(struct FileList *filelist);
+
+static void filelist_filter_clear(FileList *filelist);
+
+/* ********** Sort helpers ********** */
static bool compare_is_directory(const struct direntry *entry)
{
/* for library browse .blend files may be treated as directories, but
* for sorting purposes they should be considered regular files */
if (S_ISDIR(entry->type))
- return !(entry->flags & (BLENDERFILE | BLENDERFILE_BACKUP));
+ return !(entry->flags & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP));
return false;
}
-static int compare_name(const void *a1, const void *a2)
+static int compare_direntry_generic(const struct direntry *entry1, const struct direntry *entry2)
{
- const struct direntry *entry1 = a1, *entry2 = a2;
-
/* type is equal to stat.st_mode */
if (compare_is_directory(entry1)) {
@@ -185,35 +309,29 @@ static int compare_name(const void *a1, const void *a2)
if (strcmp(entry1->relname, "..") == 0) return (-1);
if (strcmp(entry2->relname, "..") == 0) return (1);
+ return 0;
+}
+
+static int compare_name(const void *a1, const void *a2)
+{
+ const struct direntry *entry1 = a1, *entry2 = a2;
+ int ret;
+
+ if ((ret = compare_direntry_generic(entry1, entry2))) {
+ return ret;
+ }
+
return (BLI_natstrcmp(entry1->relname, entry2->relname));
}
static int compare_date(const void *a1, const void *a2)
{
const struct direntry *entry1 = a1, *entry2 = a2;
+ int ret;
- /* type is equal to stat.st_mode */
-
- if (compare_is_directory(entry1)) {
- if (compare_is_directory(entry2) == 0) return (-1);
+ if ((ret = compare_direntry_generic(entry1, entry2))) {
+ return ret;
}
- else {
- if (compare_is_directory(entry2)) return (1);
- }
- if (S_ISREG(entry1->type)) {
- if (S_ISREG(entry2->type) == 0) return (-1);
- }
- else {
- if (S_ISREG(entry2->type)) return (1);
- }
- if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
- if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
-
- /* make sure "." and ".." are always first */
- if (strcmp(entry1->relname, ".") == 0) return (-1);
- if (strcmp(entry2->relname, ".") == 0) return (1);
- if (strcmp(entry1->relname, "..") == 0) return (-1);
- if (strcmp(entry2->relname, "..") == 0) return (1);
if (entry1->s.st_mtime < entry2->s.st_mtime) return 1;
if (entry1->s.st_mtime > entry2->s.st_mtime) return -1;
@@ -224,29 +342,11 @@ static int compare_date(const void *a1, const void *a2)
static int compare_size(const void *a1, const void *a2)
{
const struct direntry *entry1 = a1, *entry2 = a2;
+ int ret;
- /* type is equal to stat.st_mode */
-
- if (compare_is_directory(entry1)) {
- if (compare_is_directory(entry2) == 0) return (-1);
- }
- else {
- if (compare_is_directory(entry2)) return (1);
- }
- if (S_ISREG(entry1->type)) {
- if (S_ISREG(entry2->type) == 0) return (-1);
+ if ((ret = compare_direntry_generic(entry1, entry2))) {
+ return ret;
}
- else {
- if (S_ISREG(entry2->type)) return (1);
- }
- if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
- if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
-
- /* make sure "." and ".." are always first */
- if (strcmp(entry1->relname, ".") == 0) return (-1);
- if (strcmp(entry2->relname, ".") == 0) return (1);
- if (strcmp(entry1->relname, "..") == 0) return (-1);
- if (strcmp(entry2->relname, "..") == 0) return (1);
if (entry1->s.st_size < entry2->s.st_size) return 1;
if (entry1->s.st_size > entry2->s.st_size) return -1;
@@ -258,6 +358,11 @@ static int compare_extension(const void *a1, const void *a2)
const struct direntry *entry1 = a1, *entry2 = a2;
const char *sufix1, *sufix2;
const char *nil = "";
+ int ret;
+
+ if ((ret = compare_direntry_generic(entry1, entry2))) {
+ return ret;
+ }
if (!(sufix1 = strstr(entry1->relname, ".blend.gz")))
sufix1 = strrchr(entry1->relname, '.');
@@ -266,126 +371,191 @@ static int compare_extension(const void *a1, const void *a2)
if (!sufix1) sufix1 = nil;
if (!sufix2) sufix2 = nil;
- /* type is equal to stat.st_mode */
+ return (BLI_strcasecmp(sufix1, sufix2));
+}
- if (compare_is_directory(entry1)) {
- if (compare_is_directory(entry2) == 0) return (-1);
- }
- else {
- if (compare_is_directory(entry2)) return (1);
- }
- if (S_ISREG(entry1->type)) {
- if (S_ISREG(entry2->type) == 0) return (-1);
+bool filelist_need_sorting(struct FileList *filelist)
+{
+ return filelist->need_sorting && (filelist->sort != FILE_SORT_NONE);
+}
+
+void filelist_sort(struct FileList *filelist)
+{
+ if (filelist_need_sorting(filelist)) {
+ filelist->need_sorting = false;
+
+ switch (filelist->sort) {
+ case FILE_SORT_ALPHA:
+ qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name);
+ break;
+ case FILE_SORT_TIME:
+ qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date);
+ break;
+ case FILE_SORT_SIZE:
+ qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size);
+ break;
+ case FILE_SORT_EXTENSION:
+ qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension);
+ break;
+ case FILE_SORT_NONE: /* Should never reach this point! */
+ default:
+ BLI_assert(0);
+ return;
+ }
+
+ filelist_filter_clear(filelist);
}
- else {
- if (S_ISREG(entry2->type)) return (1);
+}
+
+void filelist_setsorting(struct FileList *filelist, const short sort)
+{
+ if (filelist->sort != sort) {
+ filelist->sort = sort;
+ filelist->need_sorting = true;
}
- if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
- if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
-
- /* make sure "." and ".." are always first */
- if (strcmp(entry1->relname, ".") == 0) return (-1);
- if (strcmp(entry2->relname, ".") == 0) return (1);
- if (strcmp(entry1->relname, "..") == 0) return (-1);
- if (strcmp(entry2->relname, "..") == 0) return (1);
-
- return (BLI_strcasecmp(sufix1, sufix2));
}
-static bool is_hidden_file(const char *filename, short hide_dot)
+/* ********** Filter helpers ********** */
+
+static bool is_hidden_file(const char *filename, FileListFilter *filter)
{
bool is_hidden = false;
- if (hide_dot) {
- if (filename[0] == '.' && filename[1] != '.' && filename[1] != 0) {
- is_hidden = 1; /* ignore .file */
- }
- else if (((filename[0] == '.') && (filename[1] == 0))) {
- is_hidden = 1; /* ignore . */
+ if (filter->hide_dot) {
+ if (filename[0] == '.' && filename[1] != '.' && filename[1] != '\0') {
+ is_hidden = true; /* ignore .file */
}
else {
int len = strlen(filename);
if ((len > 0) && (filename[len - 1] == '~')) {
- is_hidden = 1; /* ignore file~ */
+ is_hidden = true; /* ignore file~ */
}
}
}
- else {
- if (((filename[0] == '.') && (filename[1] == 0))) {
- is_hidden = 1; /* ignore . */
+ if (!is_hidden && filter->hide_parent) {
+ if (filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') {
+ is_hidden = true; /* ignore .. */
}
}
+ if (!is_hidden && ((filename[0] == '.') && (filename[1] == '\0'))) {
+ is_hidden = true; /* ignore . */
+ }
return is_hidden;
}
-static bool is_filtered_file(struct direntry *file, const char *UNUSED(dir), unsigned int filter, short hide_dot)
+static bool is_filtered_file(struct direntry *file, const char *UNUSED(root), FileListFilter *filter)
{
- bool is_filtered = false;
- if (filter) {
- if (file->flags & filter) {
- is_filtered = 1;
+ bool is_filtered = !is_hidden_file(file->relname, filter);
+
+ if (is_filtered && filter->filter && !FILENAME_IS_BREADCRUMBS(file->relname)) {
+ if ((file->type & S_IFDIR) && !(filter->filter & FILE_TYPE_FOLDER)) {
+ is_filtered = false;
}
- else if (file->type & S_IFDIR) {
- if (filter & FOLDERFILE) {
- is_filtered = 1;
+ if (!(file->type & S_IFDIR) && !(file->flags & filter->filter)) {
+ is_filtered = false;
+ }
+ if (is_filtered && (filter->filter_search[0] != '\0')) {
+ if (fnmatch(filter->filter_search, file->relname, FNM_CASEFOLD) != 0) {
+ is_filtered = false;
}
}
}
- else {
- is_filtered = 1;
- }
- return is_filtered && !is_hidden_file(file->relname, hide_dot);
+
+ return is_filtered;
}
-static bool is_filtered_lib(struct direntry *file, const char *dir, unsigned int filter, short hide_dot)
+static bool is_filtered_lib(struct direntry *file, const char *root, FileListFilter *filter)
{
- bool is_filtered = false;
- char tdir[FILE_MAX], tgroup[BLO_GROUP_MAX];
- if (BLO_is_a_library(dir, tdir, tgroup)) {
- is_filtered = !is_hidden_file(file->relname, hide_dot);
+ bool is_filtered = !is_hidden_file(file->relname, filter);
+ char dir[FILE_MAXDIR], group[BLO_GROUP_MAX];
+
+ if (BLO_is_a_library(root, dir, group)) {
+ is_filtered = !is_hidden_file(file->relname, filter);
+ if (is_filtered && filter->filter && !FILENAME_IS_BREADCRUMBS(file->relname)) {
+ if (is_filtered && (filter->filter_search[0] != '\0')) {
+ if (fnmatch(filter->filter_search, file->relname, FNM_CASEFOLD) != 0) {
+ is_filtered = false;
+ }
+ }
+ }
}
else {
- is_filtered = is_filtered_file(file, dir, filter, hide_dot);
+ is_filtered = is_filtered_file(file, root, filter);
}
+
return is_filtered;
}
-static bool is_filtered_main(struct direntry *file, const char *UNUSED(dir), unsigned int UNUSED(filter), short hide_dot)
+static bool is_filtered_main(struct direntry *file, const char *UNUSED(dir), FileListFilter *filter)
+{
+ return !is_hidden_file(file->relname, filter);
+}
+
+static void filelist_filter_clear(FileList *filelist)
{
- return !is_hidden_file(file->relname, hide_dot);
+ MEM_SAFE_FREE(filelist->fidx);
+ filelist->numfiltered = 0;
}
void filelist_filter(FileList *filelist)
{
int num_filtered = 0;
- int i, j;
+ int *fidx_tmp;
+ int i;
- if (!filelist->filelist)
+ if (!filelist->filelist) {
return;
+ }
- /* How many files are left after filter ? */
+ if (filelist->fidx) {
+ /* Assume it has already been filtered, nothing else to do! */
+ return;
+ }
+
+ fidx_tmp = MEM_mallocN(sizeof(*fidx_tmp) * (size_t)filelist->numfiles, __func__);
+
+ /* Filter remap & count how many files are left after filter in a single loop. */
for (i = 0; i < filelist->numfiles; ++i) {
struct direntry *file = &filelist->filelist[i];
- if (filelist->filterf(file, filelist->dir, filelist->filter, filelist->hide_dot)) {
- num_filtered++;
+
+ if (filelist->filterf(file, filelist->dir, &filelist->filter_data)) {
+ fidx_tmp[num_filtered++] = i;
}
}
-
- if (filelist->fidx) {
- MEM_freeN(filelist->fidx);
- filelist->fidx = NULL;
- }
- filelist->fidx = (int *)MEM_callocN(num_filtered * sizeof(int), "filteridx");
+
+ /* Note: maybe we could even accept filelist->fidx to be filelist->numfiles -len allocated? */
+ filelist->fidx = (int *)MEM_mallocN(sizeof(*filelist->fidx) * (size_t)num_filtered, __func__);
+ memcpy(filelist->fidx, fidx_tmp, sizeof(*filelist->fidx) * (size_t)num_filtered);
filelist->numfiltered = num_filtered;
- for (i = 0, j = 0; i < filelist->numfiles; ++i) {
- struct direntry *file = &filelist->filelist[i];
- if (filelist->filterf(file, filelist->dir, filelist->filter, filelist->hide_dot)) {
- filelist->fidx[j++] = i;
- }
+ MEM_freeN(fidx_tmp);
+}
+
+void filelist_setfilter_options(FileList *filelist, const bool hide_dot, const bool hide_parent,
+ const unsigned int filter,
+ const char *filter_glob, const char *filter_search)
+{
+ if ((filelist->filter_data.hide_dot != hide_dot) ||
+ (filelist->filter_data.hide_parent != hide_parent) ||
+ (filelist->filter_data.filter != filter) ||
+ !STREQ(filelist->filter_data.filter_glob, filter_glob) ||
+ (BLI_strcmp_ignore_pad(filelist->filter_data.filter_search, filter_search, '*') != 0))
+ {
+ filelist->filter_data.hide_dot = hide_dot;
+ filelist->filter_data.hide_parent = hide_parent;
+
+ filelist->filter_data.filter = filter;
+ BLI_strncpy(filelist->filter_data.filter_glob, filter_glob, sizeof(filelist->filter_data.filter_glob));
+ BLI_strncpy_ensure_pad(filelist->filter_data.filter_search, filter_search, '*',
+ sizeof(filelist->filter_data.filter_search));
+
+ /* And now, free filtered data so that we now we have to filter again. */
+ filelist_filter_clear(filelist);
}
}
+/* ********** Icon/image helpers ********** */
+
void filelist_init_icons(void)
{
short x, y, k;
@@ -428,115 +598,86 @@ void filelist_free_icons(void)
}
}
-/* -----------------FOLDERLIST (previous/next) -------------- */
-ListBase *folderlist_new(void)
-{
- ListBase *p = MEM_callocN(sizeof(ListBase), "folderlist");
- return p;
-}
-
-void folderlist_popdir(struct ListBase *folderlist, char *dir)
+void filelist_imgsize(struct FileList *filelist, short w, short h)
{
- const char *prev_dir;
- struct FolderList *folder;
- folder = folderlist->last;
-
- if (folder) {
- /* remove the current directory */
- MEM_freeN(folder->foldername);
- BLI_freelinkN(folderlist, folder);
-
- folder = folderlist->last;
- if (folder) {
- prev_dir = folder->foldername;
- BLI_strncpy(dir, prev_dir, FILE_MAXDIR);
- }
- }
- /* delete the folder next or use setdir directly before PREVIOUS OP */
+ filelist->prv_w = w;
+ filelist->prv_h = h;
}
-void folderlist_pushdir(ListBase *folderlist, const char *dir)
+ImBuf *filelist_getimage(struct FileList *filelist, const int index)
{
- struct FolderList *folder, *previous_folder;
- previous_folder = folderlist->last;
-
- /* check if already exists */
- if (previous_folder && previous_folder->foldername) {
- if (BLI_path_cmp(previous_folder->foldername, dir) == 0) {
- return;
- }
- }
-
- /* create next folder element */
- folder = (FolderList *)MEM_mallocN(sizeof(FolderList), "FolderList");
- folder->foldername = BLI_strdup(dir);
-
- /* add it to the end of the list */
- BLI_addtail(folderlist, folder);
-}
+ ImBuf *ibuf = NULL;
+ int fidx = 0;
-const char *folderlist_peeklastdir(ListBase *folderlist)
-{
- struct FolderList *folder;
+ BLI_assert(G.background == false);
- if (!folderlist->last)
+ if ((index < 0) || (index >= filelist->numfiltered)) {
return NULL;
+ }
+ fidx = filelist->fidx[index];
+ ibuf = filelist->filelist[fidx].image;
- folder = folderlist->last;
- return folder->foldername;
+ return ibuf;
}
-int folderlist_clear_next(struct SpaceFile *sfile)
+ImBuf *filelist_geticon(struct FileList *filelist, const int index)
{
- struct FolderList *folder;
-
- /* if there is no folder_next there is nothing we can clear */
- if (!sfile->folders_next)
- return 0;
-
- /* if previous_folder, next_folder or refresh_folder operators are executed it doesn't clear folder_next */
- folder = sfile->folders_prev->last;
- if ((!folder) || (BLI_path_cmp(folder->foldername, sfile->params->dir) == 0))
- return 0;
+ ImBuf *ibuf = NULL;
+ struct direntry *file = NULL;
+ int fidx = 0;
- /* eventually clear flist->folders_next */
- return 1;
-}
+ BLI_assert(G.background == false);
-/* not listbase itself */
-void folderlist_free(ListBase *folderlist)
-{
- if (folderlist) {
- FolderList *folder;
- for (folder = folderlist->first; folder; folder = folder->next)
- MEM_freeN(folder->foldername);
- BLI_freelistN(folderlist);
+ if ((index < 0) || (index >= filelist->numfiltered)) {
+ return NULL;
}
-}
-
-ListBase *folderlist_duplicate(ListBase *folderlist)
-{
-
- if (folderlist) {
- ListBase *folderlistn = MEM_callocN(sizeof(ListBase), "copy folderlist");
- FolderList *folder;
-
- BLI_duplicatelist(folderlistn, folderlist);
-
- for (folder = folderlistn->first; folder; folder = folder->next) {
- folder->foldername = MEM_dupallocN(folder->foldername);
+ fidx = filelist->fidx[index];
+ file = &filelist->filelist[fidx];
+ if (file->type & S_IFDIR) {
+ if (strcmp(filelist->filelist[fidx].relname, "..") == 0) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
+ }
+ else if (strcmp(filelist->filelist[fidx].relname, ".") == 0) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
+ }
+ else {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
}
- return folderlistn;
}
- return NULL;
-}
+ else {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
+ }
+ if (file->flags & FILE_TYPE_BLENDER) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
+ }
+ else if ((file->flags & FILE_TYPE_MOVIE) || (file->flags & FILE_TYPE_MOVIE_ICON)) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
+ }
+ else if (file->flags & FILE_TYPE_SOUND) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
+ }
+ else if (file->flags & FILE_TYPE_PYSCRIPT) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
+ }
+ else if (file->flags & FILE_TYPE_FTFONT) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
+ }
+ else if (file->flags & FILE_TYPE_TEXT) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
+ }
+ else if (file->flags & FILE_TYPE_IMAGE) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING];
+ }
+ else if (file->flags & FILE_TYPE_BLENDER_BACKUP) {
+ ibuf = gSpecialFileImages[SPECIAL_IMG_BACKUP];
+ }
-static void filelist_read_main(struct FileList *filelist);
-static void filelist_read_library(struct FileList *filelist);
-static void filelist_read_dir(struct FileList *filelist);
+ return ibuf;
+}
+
+/* ********** Main ********** */
-/* ------------------FILELIST------------------------ */
FileList *filelist_new(short type)
{
FileList *p = MEM_callocN(sizeof(FileList), "filelist");
@@ -558,7 +699,6 @@ FileList *filelist_new(short type)
return p;
}
-
void filelist_free(struct FileList *filelist)
{
if (!filelist) {
@@ -566,18 +706,16 @@ void filelist_free(struct FileList *filelist)
return;
}
- if (filelist->fidx) {
- MEM_freeN(filelist->fidx);
- filelist->fidx = NULL;
- }
+ MEM_SAFE_FREE(filelist->fidx);
+ filelist->numfiltered = 0;
+ memset(&filelist->filter_data, 0, sizeof(filelist->filter_data));
+
+ filelist->need_sorting = false;
+ filelist->sort = FILE_SORT_NONE;
- BLI_free_filelist(filelist->filelist, filelist->numfiles);
+ BLI_filelist_free(filelist->filelist, filelist->numfiles, NULL);
filelist->numfiles = 0;
filelist->filelist = NULL;
- filelist->filter = 0;
- filelist->filter_glob[0] = '\0';
- filelist->numfiltered = 0;
- filelist->hide_dot = 0;
}
void filelist_freelib(struct FileList *filelist)
@@ -607,89 +745,11 @@ void filelist_setdir(struct FileList *filelist, const char *dir)
BLI_strncpy(filelist->dir, dir, sizeof(filelist->dir));
}
-void filelist_imgsize(struct FileList *filelist, short w, short h)
-{
- filelist->prv_w = w;
- filelist->prv_h = h;
-}
-
short filelist_changed(struct FileList *filelist)
{
return filelist->changed;
}
-ImBuf *filelist_getimage(struct FileList *filelist, int index)
-{
- ImBuf *ibuf = NULL;
- int fidx = 0;
-
- BLI_assert(G.background == false);
-
- if ((index < 0) || (index >= filelist->numfiltered)) {
- return NULL;
- }
- fidx = filelist->fidx[index];
- ibuf = filelist->filelist[fidx].image;
-
- return ibuf;
-}
-
-ImBuf *filelist_geticon(struct FileList *filelist, int index)
-{
- ImBuf *ibuf = NULL;
- struct direntry *file = NULL;
- int fidx = 0;
-
- BLI_assert(G.background == false);
-
- if ((index < 0) || (index >= filelist->numfiltered)) {
- return NULL;
- }
- fidx = filelist->fidx[index];
- file = &filelist->filelist[fidx];
- if (file->type & S_IFDIR) {
- if (strcmp(filelist->filelist[fidx].relname, "..") == 0) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
- }
- else if (strcmp(filelist->filelist[fidx].relname, ".") == 0) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
- }
- else {
- ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
- }
- }
- else {
- ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
- }
-
- if (file->flags & BLENDERFILE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
- }
- else if ((file->flags & MOVIEFILE) || (file->flags & MOVIEFILE_ICON)) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
- }
- else if (file->flags & SOUNDFILE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
- }
- else if (file->flags & PYSCRIPTFILE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
- }
- else if (file->flags & FTFONTFILE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
- }
- else if (file->flags & TEXTFILE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
- }
- else if (file->flags & IMAGEFILE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING];
- }
- else if (file->flags & BLENDERFILE_BACKUP) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_BACKUP];
- }
-
- return ibuf;
-}
-
struct direntry *filelist_file(struct FileList *filelist, int index)
{
int fidx = 0;
@@ -728,21 +788,6 @@ int filelist_find(struct FileList *filelist, const char *filename)
return fidx;
}
-void filelist_hidedot(struct FileList *filelist, short hide)
-{
- filelist->hide_dot = hide;
-}
-
-void filelist_setfilter(struct FileList *filelist, unsigned int filter)
-{
- filelist->filter = filter;
-}
-
-void filelist_setfilter_types(struct FileList *filelist, const char *filter_glob)
-{
- BLI_strncpy(filelist->filter_glob, filter_glob, sizeof(filelist->filter_glob));
-}
-
/* would recognize .blend as well */
static bool file_is_blend_backup(const char *str)
{
@@ -772,47 +817,47 @@ static bool file_is_blend_backup(const char *str)
static int path_extension_type(const char *path)
{
if (BLO_has_bfile_extension(path)) {
- return BLENDERFILE;
+ return FILE_TYPE_BLENDER;
}
else if (file_is_blend_backup(path)) {
- return BLENDERFILE_BACKUP;
+ return FILE_TYPE_BLENDER_BACKUP;
}
else if (BLI_testextensie(path, ".app")) {
- return APPLICATIONBUNDLE;
+ return FILE_TYPE_APPLICATIONBUNDLE;
}
else if (BLI_testextensie(path, ".py")) {
- return PYSCRIPTFILE;
+ return FILE_TYPE_PYSCRIPT;
}
else if (BLI_testextensie_n(path, ".txt", ".glsl", ".osl", ".data", NULL)) {
- return TEXTFILE;
+ return FILE_TYPE_TEXT;
}
else if (BLI_testextensie_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) {
- return FTFONTFILE;
+ return FILE_TYPE_FTFONT;
}
else if (BLI_testextensie(path, ".btx")) {
- return BTXFILE;
+ return FILE_TYPE_BTX;
}
else if (BLI_testextensie(path, ".dae")) {
- return COLLADAFILE;
+ return FILE_TYPE_COLLADA;
}
else if (BLI_testextensie_array(path, imb_ext_image) ||
(G.have_quicktime && BLI_testextensie_array(path, imb_ext_image_qt)))
{
- return IMAGEFILE;
+ return FILE_TYPE_IMAGE;
}
else if (BLI_testextensie(path, ".ogg")) {
if (IMB_isanim(path)) {
- return MOVIEFILE;
+ return FILE_TYPE_MOVIE;
}
else {
- return SOUNDFILE;
+ return FILE_TYPE_SOUND;
}
}
else if (BLI_testextensie_array(path, imb_ext_movie)) {
- return MOVIEFILE;
+ return FILE_TYPE_MOVIE;
}
else if (BLI_testextensie_array(path, imb_ext_audio)) {
- return SOUNDFILE;
+ return FILE_TYPE_SOUND;
}
return 0;
}
@@ -828,25 +873,25 @@ int ED_file_extension_icon(const char *path)
{
int type = path_extension_type(path);
- if (type == BLENDERFILE)
+ if (type == FILE_TYPE_BLENDER)
return ICON_FILE_BLEND;
- else if (type == BLENDERFILE_BACKUP)
+ else if (type == FILE_TYPE_BLENDER_BACKUP)
return ICON_FILE_BACKUP;
- else if (type == IMAGEFILE)
+ else if (type == FILE_TYPE_IMAGE)
return ICON_FILE_IMAGE;
- else if (type == MOVIEFILE)
+ else if (type == FILE_TYPE_MOVIE)
return ICON_FILE_MOVIE;
- else if (type == PYSCRIPTFILE)
+ else if (type == FILE_TYPE_PYSCRIPT)
return ICON_FILE_SCRIPT;
- else if (type == SOUNDFILE)
+ else if (type == FILE_TYPE_SOUND)
return ICON_FILE_SOUND;
- else if (type == FTFONTFILE)
+ else if (type == FILE_TYPE_FTFONT)
return ICON_FILE_FONT;
- else if (type == BTXFILE)
+ else if (type == FILE_TYPE_BTX)
return ICON_FILE_BLANK;
- else if (type == COLLADAFILE)
+ else if (type == FILE_TYPE_COLLADA)
return ICON_FILE_BLANK;
- else if (type == TEXTFILE)
+ else if (type == FILE_TYPE_TEXT)
return ICON_FILE_TEXT;
return ICON_FILE_BLANK;
@@ -869,12 +914,11 @@ static void filelist_setfiletypes(struct FileList *filelist)
#endif
file->flags = file_extension_type(filelist->dir, file->relname);
- if (filelist->filter_glob[0] &&
- BLI_testextensie_glob(file->relname, filelist->filter_glob))
+ if (filelist->filter_data.filter_glob[0] &&
+ BLI_testextensie_glob(file->relname, filelist->filter_data.filter_glob))
{
- file->flags = OPERATORFILE;
+ file->flags = FILE_TYPE_OPERATOR;
}
-
}
}
@@ -885,11 +929,15 @@ static void filelist_read_dir(struct FileList *filelist)
filelist->fidx = NULL;
filelist->filelist = NULL;
+ BLI_make_exist(filelist->dir);
BLI_cleanup_dir(G.main->name, filelist->dir);
- filelist->numfiles = BLI_dir_contents(filelist->dir, &(filelist->filelist));
+ filelist->numfiles = BLI_filelist_dir_contents(filelist->dir, &(filelist->filelist));
+
+ /* We shall *never* get an empty list here, since we now the dir exists and is readable
+ * (ensured by BLI_make_exist()). So we expect at the very least the parent '..' entry. */
+ BLI_assert(filelist->numfiles != 0);
filelist_setfiletypes(filelist);
- filelist_filter(filelist);
}
static void filelist_read_main(struct FileList *filelist)
@@ -907,7 +955,6 @@ static void filelist_read_library(struct FileList *filelist)
int num;
struct direntry *file;
- BLI_make_exist(filelist->dir);
filelist_read_dir(filelist);
file = filelist->filelist;
for (num = 0; num < filelist->numfiles; num++, file++) {
@@ -929,18 +976,15 @@ static void filelist_read_library(struct FileList *filelist)
void filelist_readdir(struct FileList *filelist)
{
filelist->readf(filelist);
-}
-int filelist_empty(struct FileList *filelist)
-{
- return filelist->filelist == NULL;
+ filelist->need_sorting = true;
+ filelist->need_thumbnails = true;
+ filelist_filter_clear(filelist);
}
-void filelist_parent(struct FileList *filelist)
+int filelist_empty(struct FileList *filelist)
{
- BLI_parent_dir(filelist->dir);
- BLI_make_exist(filelist->dir);
- filelist_readdir(filelist);
+ return filelist->filelist == NULL;
}
void filelist_select_file(struct FileList *filelist, int index, FileSelType select, unsigned int flag, FileCheckType check)
@@ -995,35 +1039,15 @@ bool filelist_is_selected(struct FileList *filelist, int index, FileCheckType ch
}
switch (check) {
case CHECK_DIRS:
- return S_ISDIR(file->type) && (file->selflag & SELECTED_FILE);
+ return S_ISDIR(file->type) && (file->selflag & FILE_SEL_SELECTED);
case CHECK_FILES:
- return S_ISREG(file->type) && (file->selflag & SELECTED_FILE);
+ return S_ISREG(file->type) && (file->selflag & FILE_SEL_SELECTED);
case CHECK_ALL:
default:
- return (file->selflag & SELECTED_FILE) != 0;
+ return (file->selflag & FILE_SEL_SELECTED) != 0;
}
}
-void filelist_sort(struct FileList *filelist, short sort)
-{
- switch (sort) {
- case FILE_SORT_ALPHA:
- qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name);
- break;
- case FILE_SORT_TIME:
- qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date);
- break;
- case FILE_SORT_SIZE:
- qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size);
- break;
- case FILE_SORT_EXTENSION:
- qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension);
- break;
- }
-
- filelist_filter(filelist);
-}
-
bool filelist_islibrary(struct FileList *filelist, char *dir, char *group)
{
@@ -1042,8 +1066,8 @@ static int groupname_to_code(const char *group)
return buf[0] ? BKE_idcode_from_name(buf) : 0;
}
-
-void filelist_from_library(struct FileList *filelist)
+
+static void filelist_from_library(struct FileList *filelist)
{
LinkNode *l, *names, *previews;
struct ImBuf *ima;
@@ -1124,7 +1148,7 @@ void filelist_from_library(struct FileList *filelist)
ima = IMB_allocImBuf(w, h, 32, IB_rect);
memcpy(ima->rect, rect, w * h * sizeof(unsigned int));
filelist->filelist[i + 1].image = ima;
- filelist->filelist[i + 1].flags = IMAGEFILE;
+ filelist->filelist[i + 1].flags = FILE_TYPE_IMAGE;
}
}
}
@@ -1133,20 +1157,10 @@ void filelist_from_library(struct FileList *filelist)
BLI_linklist_free(names, free);
if (previews) BLI_linklist_free(previews, BKE_previewimg_freefunc);
- filelist_sort(filelist, FILE_SORT_ALPHA);
-
BLI_strncpy(G.main->name, filename, sizeof(filename)); /* prevent G.main->name to change */
-
- filelist->filter = 0;
- filelist_filter(filelist);
-}
-
-void filelist_hideparent(struct FileList *filelist, short hide)
-{
- filelist->hide_parent = hide;
}
-void filelist_from_main(struct FileList *filelist)
+static void filelist_from_main(struct FileList *filelist)
{
ID *id;
struct direntry *files, *firstlib = NULL;
@@ -1166,9 +1180,9 @@ void filelist_from_main(struct FileList *filelist)
/* make directories */
#ifdef WITH_FREESTYLE
- filelist->numfiles = 25;
-#else
filelist->numfiles = 24;
+#else
+ filelist->numfiles = 23;
#endif
filelist->filelist = (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry));
@@ -1178,32 +1192,31 @@ void filelist_from_main(struct FileList *filelist)
}
filelist->filelist[0].relname = BLI_strdup("..");
- filelist->filelist[2].relname = BLI_strdup("Scene");
- filelist->filelist[3].relname = BLI_strdup("Object");
- filelist->filelist[4].relname = BLI_strdup("Mesh");
- filelist->filelist[5].relname = BLI_strdup("Curve");
- filelist->filelist[6].relname = BLI_strdup("Metaball");
- filelist->filelist[7].relname = BLI_strdup("Material");
- filelist->filelist[8].relname = BLI_strdup("Texture");
- filelist->filelist[9].relname = BLI_strdup("Image");
- filelist->filelist[10].relname = BLI_strdup("Ika");
- filelist->filelist[11].relname = BLI_strdup("Wave");
- filelist->filelist[12].relname = BLI_strdup("Lattice");
- filelist->filelist[13].relname = BLI_strdup("Lamp");
- filelist->filelist[14].relname = BLI_strdup("Camera");
- filelist->filelist[15].relname = BLI_strdup("Ipo");
- filelist->filelist[16].relname = BLI_strdup("World");
- filelist->filelist[17].relname = BLI_strdup("Screen");
- filelist->filelist[18].relname = BLI_strdup("VFont");
- filelist->filelist[19].relname = BLI_strdup("Text");
- filelist->filelist[20].relname = BLI_strdup("Armature");
- filelist->filelist[21].relname = BLI_strdup("Action");
- filelist->filelist[22].relname = BLI_strdup("NodeTree");
- filelist->filelist[23].relname = BLI_strdup("Speaker");
+ filelist->filelist[1].relname = BLI_strdup("Scene");
+ filelist->filelist[2].relname = BLI_strdup("Object");
+ filelist->filelist[3].relname = BLI_strdup("Mesh");
+ filelist->filelist[4].relname = BLI_strdup("Curve");
+ filelist->filelist[5].relname = BLI_strdup("Metaball");
+ filelist->filelist[6].relname = BLI_strdup("Material");
+ filelist->filelist[7].relname = BLI_strdup("Texture");
+ filelist->filelist[8].relname = BLI_strdup("Image");
+ filelist->filelist[9].relname = BLI_strdup("Ika");
+ filelist->filelist[10].relname = BLI_strdup("Wave");
+ filelist->filelist[11].relname = BLI_strdup("Lattice");
+ filelist->filelist[12].relname = BLI_strdup("Lamp");
+ filelist->filelist[13].relname = BLI_strdup("Camera");
+ filelist->filelist[14].relname = BLI_strdup("Ipo");
+ filelist->filelist[15].relname = BLI_strdup("World");
+ filelist->filelist[16].relname = BLI_strdup("Screen");
+ filelist->filelist[17].relname = BLI_strdup("VFont");
+ filelist->filelist[18].relname = BLI_strdup("Text");
+ filelist->filelist[19].relname = BLI_strdup("Armature");
+ filelist->filelist[20].relname = BLI_strdup("Action");
+ filelist->filelist[21].relname = BLI_strdup("NodeTree");
+ filelist->filelist[22].relname = BLI_strdup("Speaker");
#ifdef WITH_FREESTYLE
- filelist->filelist[24].relname = BLI_strdup("FreestyleLineStyle");
+ filelist->filelist[23].relname = BLI_strdup("FreestyleLineStyle");
#endif
- filelist_sort(filelist, FILE_SORT_ALPHA);
}
else {
@@ -1216,7 +1229,7 @@ void filelist_from_main(struct FileList *filelist)
id = lb->first;
filelist->numfiles = 0;
while (id) {
- if (!filelist->hide_dot || id->name[2] != '.') {
+ if (!filelist->filter_data.hide_dot || id->name[2] != '.') {
filelist->numfiles++;
}
@@ -1224,12 +1237,12 @@ void filelist_from_main(struct FileList *filelist)
}
/* XXXXX TODO: if databrowse F4 or append/link filelist->hide_parent has to be set */
- if (!filelist->hide_parent) filelist->numfiles += 1;
+ if (!filelist->filter_data.hide_parent) filelist->numfiles += 1;
filelist->filelist = filelist->numfiles > 0 ? (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry)) : NULL;
files = filelist->filelist;
- if (!filelist->hide_parent) {
+ if (!filelist->filter_data.hide_parent) {
memset(&(filelist->filelist[0]), 0, sizeof(struct direntry));
filelist->filelist[0].relname = BLI_strdup("..");
filelist->filelist[0].type |= S_IFDIR;
@@ -1243,7 +1256,7 @@ void filelist_from_main(struct FileList *filelist)
while (id) {
ok = 1;
if (ok) {
- if (!filelist->hide_dot || id->name[2] != '.') {
+ if (!filelist->filter_data.hide_dot || id->name[2] != '.') {
memset(files, 0, sizeof(struct direntry));
if (id->lib == NULL) {
files->relname = BLI_strdup(id->name + 2);
@@ -1256,10 +1269,10 @@ void filelist_from_main(struct FileList *filelist)
#if 0 /* XXXXX TODO show the selection status of the objects */
if (!filelist->has_func) { /* F4 DATA BROWSE */
if (idcode == ID_OB) {
- if ( ((Object *)id)->flag & SELECT) files->selflag |= SELECTED_FILE;
+ if ( ((Object *)id)->flag & SELECT) files->selflag |= FILE_SEL_SELECTED;
}
else if (idcode == ID_SCE) {
- if ( ((Scene *)id)->r.scemode & R_BG_RENDER) files->selflag |= SELECTED_FILE;
+ if ( ((Scene *)id)->r.scemode & R_BG_RENDER) files->selflag |= FILE_SEL_SELECTED;
}
}
#endif
@@ -1267,7 +1280,7 @@ void filelist_from_main(struct FileList *filelist)
files->poin = id;
fake = id->flag & LIB_FAKEUSER;
if (idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) {
- files->flags |= IMAGEFILE;
+ files->flags |= FILE_TYPE_IMAGE;
}
if (id->lib && fake) BLI_snprintf(files->extra, sizeof(files->extra), "LF %d", id->us);
else if (id->lib) BLI_snprintf(files->extra, sizeof(files->extra), "L %d", id->us);
@@ -1292,8 +1305,22 @@ void filelist_from_main(struct FileList *filelist)
qsort(firstlib, totlib, sizeof(struct direntry), compare_name);
}
}
- filelist->filter = 0;
- filelist_filter(filelist);
+}
+
+/* ********** Thumbnails job ********** */
+
+typedef struct ThumbnailJob {
+ ListBase loadimages;
+ ImBuf *static_icons_buffers[BIFICONID_LAST];
+ const short *stop;
+ const short *do_update;
+ struct FileList *filelist;
+ ReportList reports;
+} ThumbnailJob;
+
+bool filelist_need_thumbnails(FileList *filelist)
+{
+ return filelist->need_thumbnails;
}
static void thumbnail_joblist_free(ThumbnailJob *tj)
@@ -1318,18 +1345,18 @@ static void thumbnails_startjob(void *tjv, short *stop, short *do_update, float
tj->do_update = do_update;
while ((*stop == 0) && (limg)) {
- if (limg->flags & IMAGEFILE) {
+ if (limg->flags & FILE_TYPE_IMAGE) {
limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_IMAGE);
}
- else if (limg->flags & (BLENDERFILE | BLENDERFILE_BACKUP)) {
+ else if (limg->flags & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_BLEND);
}
- else if (limg->flags & MOVIEFILE) {
+ else if (limg->flags & FILE_TYPE_MOVIE) {
limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_MOVIE);
if (!limg->img) {
/* remember that file can't be loaded via IMB_open_anim */
- limg->flags &= ~MOVIEFILE;
- limg->flags |= MOVIEFILE_ICON;
+ limg->flags &= ~FILE_TYPE_MOVIE;
+ limg->flags |= FILE_TYPE_MOVIE_ICON;
}
}
*do_update = true;
@@ -1348,9 +1375,9 @@ static void thumbnails_update(void *tjv)
if (!limg->done && limg->img) {
tj->filelist->filelist[limg->index].image = limg->img;
/* update flag for movie files where thumbnail can't be created */
- if (limg->flags & MOVIEFILE_ICON) {
- tj->filelist->filelist[limg->index].flags &= ~MOVIEFILE;
- tj->filelist->filelist[limg->index].flags |= MOVIEFILE_ICON;
+ if (limg->flags & FILE_TYPE_MOVIE_ICON) {
+ tj->filelist->filelist[limg->index].flags &= ~FILE_TYPE_MOVIE;
+ tj->filelist->filelist[limg->index].flags |= FILE_TYPE_MOVIE_ICON;
}
limg->done = true;
}
@@ -1359,6 +1386,15 @@ static void thumbnails_update(void *tjv)
}
}
+static void thumbnails_endjob(void *tjv)
+{
+ ThumbnailJob *tj = tjv;
+
+ if (!*tj->stop) {
+ tj->filelist->need_thumbnails = false;
+ }
+}
+
static void thumbnails_free(void *tjv)
{
ThumbnailJob *tj = tjv;
@@ -1378,7 +1414,9 @@ void thumbnails_start(FileList *filelist, const bContext *C)
tj->filelist = filelist;
for (idx = 0; idx < filelist->numfiles; idx++) {
if (!filelist->filelist[idx].image) {
- if ((filelist->filelist[idx].flags & (IMAGEFILE | MOVIEFILE | BLENDERFILE | BLENDERFILE_BACKUP))) {
+ if (filelist->filelist[idx].flags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE |
+ FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))
+ {
FileImage *limg = MEM_callocN(sizeof(FileImage), "loadimage");
BLI_strncpy(limg->path, filelist->filelist[idx].path, FILE_MAX);
limg->index = idx;
@@ -1395,7 +1433,7 @@ void thumbnails_start(FileList *filelist, const bContext *C)
0, WM_JOB_TYPE_FILESEL_THUMBNAIL);
WM_jobs_customdata_set(wm_job, tj, thumbnails_free);
WM_jobs_timer(wm_job, 0.5, NC_WINDOW, NC_WINDOW);
- WM_jobs_callbacks(wm_job, thumbnails_startjob, NULL, thumbnails_update, NULL);
+ WM_jobs_callbacks(wm_job, thumbnails_startjob, NULL, thumbnails_update, thumbnails_endjob);
/* start the job */
WM_jobs_start(CTX_wm_manager(C), wm_job);
@@ -1403,7 +1441,7 @@ void thumbnails_start(FileList *filelist, const bContext *C)
void thumbnails_stop(wmWindowManager *wm, FileList *filelist)
{
- WM_jobs_kill(wm, filelist, NULL);
+ WM_jobs_kill_type(wm, filelist, WM_JOB_TYPE_FILESEL_THUMBNAIL);
}
int thumbnails_running(wmWindowManager *wm, FileList *filelist)
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index c37bb882168..797d54a89b1 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -60,47 +60,53 @@ typedef enum FileCheckType {
CHECK_ALL = 3
} FileCheckType;
-struct FileList * filelist_new(short type);
+struct ListBase * folderlist_new(void);
+void folderlist_free(struct ListBase *folderlist);
+struct ListBase * folderlist_duplicate(ListBase *folderlist);
+void folderlist_popdir(struct ListBase *folderlist, char *dir);
+void folderlist_pushdir(struct ListBase *folderlist, const char *dir);
+const char * folderlist_peeklastdir(struct ListBase *folderdist);
+int folderlist_clear_next(struct SpaceFile *sfile);
+
+
+void filelist_setsorting(struct FileList *filelist, const short sort);
+bool filelist_need_sorting(struct FileList *filelist);
+void filelist_sort(struct FileList *filelist);
+
+void filelist_setfilter_options(struct FileList *filelist, const bool hide_dot, const bool hide_parent,
+ const unsigned int filter,
+ const char *filter_glob, const char *filter_search);
+void filelist_filter(struct FileList *filelist);
+
void filelist_init_icons(void);
void filelist_free_icons(void);
-int filelist_find(struct FileList *filelist, const char *file);
+void filelist_imgsize(struct FileList *filelist, short w, short h);
+struct ImBuf * filelist_getimage(struct FileList *filelist, const int index);
+struct ImBuf * filelist_geticon(struct FileList *filelist, const int index);
+
+struct FileList * filelist_new(short type);
void filelist_free(struct FileList *filelist);
-void filelist_sort(struct FileList *filelist, short sort);
-int filelist_numfiles(struct FileList *filelist);
+
const char * filelist_dir(struct FileList *filelist);
+void filelist_readdir(struct FileList *filelist);
void filelist_setdir(struct FileList *filelist, const char *dir);
+
+int filelist_empty(struct FileList *filelist);
+int filelist_numfiles(struct FileList *filelist);
struct direntry * filelist_file(struct FileList *filelist, int index);
+int filelist_find(struct FileList *filelist, const char *file);
+
+short filelist_changed(struct FileList *filelist);
+
void filelist_select(struct FileList *filelist, FileSelection *sel, FileSelType select, unsigned int flag, FileCheckType check);
void filelist_select_file(struct FileList *filelist, int index, FileSelType select, unsigned int flag, FileCheckType check);
bool filelist_is_selected(struct FileList *filelist, int index, FileCheckType check);
-void filelist_hidedot(struct FileList *filelist, short hide);
-void filelist_setfilter(struct FileList *filelist, unsigned int filter);
-void filelist_setfilter_types(struct FileList *filelist, const char *filter_glob);
-void filelist_filter(struct FileList *filelist);
-void filelist_imgsize(struct FileList *filelist, short w, short h);
-struct ImBuf * filelist_getimage(struct FileList *filelist, int index);
-struct ImBuf * filelist_geticon(struct FileList *filelist, int index);
-short filelist_changed(struct FileList *filelist);
-void filelist_readdir(struct FileList *filelist);
-
-int filelist_empty(struct FileList *filelist);
-void filelist_parent(struct FileList *filelist);
struct BlendHandle *filelist_lib(struct FileList *filelist);
bool filelist_islibrary(struct FileList *filelist, char *dir, char *group);
-void filelist_from_main(struct FileList *filelist);
-void filelist_from_library(struct FileList *filelist);
void filelist_freelib(struct FileList *filelist);
-void filelist_hideparent(struct FileList *filelist, short hide);
-
-struct ListBase * folderlist_new(void);
-void folderlist_free(struct ListBase *folderlist);
-struct ListBase * folderlist_duplicate(ListBase *folderlist);
-void folderlist_popdir(struct ListBase *folderlist, char *dir);
-void folderlist_pushdir(struct ListBase *folderlist, const char *dir);
-const char * folderlist_peeklastdir(struct ListBase *folderdist);
-int folderlist_clear_next(struct SpaceFile *sfile);
+bool filelist_need_thumbnails(struct FileList *filelist);
void thumbnails_start(struct FileList *filelist, const struct bContext *C);
void thumbnails_stop(struct wmWindowManager *wm, struct FileList *filelist);
int thumbnails_running(struct wmWindowManager *wm, struct FileList *filelist);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 8b90cf6cc29..3e663275dcd 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -58,6 +58,7 @@
#include "BLI_fileops_types.h"
#include "BLI_fnmatch.h"
+#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -157,30 +158,30 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->filter = 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_blender")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BLENDERFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_backup")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BLENDERFILE_BACKUP : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER_BACKUP : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_image")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? IMAGEFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_IMAGE : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_movie")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? MOVIEFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_MOVIE : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_python")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? PYSCRIPTFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_PYSCRIPT : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_font")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FTFONTFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_FTFONT : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_sound")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? SOUNDFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_SOUND : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_text")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? TEXTFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_TEXT : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_folder")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FOLDERFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_FOLDER : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_btx")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BTXFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BTX : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_collada")))
- params->filter |= RNA_property_boolean_get(op->ptr, prop) ? COLLADAFILE : 0;
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_COLLADA : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) {
RNA_property_string_get(op->ptr, prop, params->filter_glob);
- params->filter |= (OPERATORFILE | FOLDERFILE);
+ params->filter |= (FILE_TYPE_OPERATOR | FILE_TYPE_FOLDER);
}
else {
params->filter_glob[0] = '\0';
@@ -214,7 +215,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
if (params->display == FILE_DEFAULTDISPLAY) {
if (U.uiflag & USER_SHOW_THUMBNAILS) {
- if (params->filter & (IMAGEFILE | MOVIEFILE))
+ if (params->filter & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE))
params->display = FILE_IMGDISPLAY;
else
params->display = FILE_SHORTDISPLAY;
@@ -253,7 +254,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
BLI_split_dir_part(G.main->name, sfile->params->dir, sizeof(sfile->params->dir));
}
else {
- const char *doc_path = BLI_getDefaultDocumentFolder();
+ const char *doc_path = BKE_appdir_folder_default();
if (doc_path) {
BLI_strncpy(sfile->params->dir, doc_path, sizeof(sfile->params->dir));
}
@@ -602,9 +603,12 @@ void file_change_dir(bContext *C, int checkdir)
SpaceFile *sfile = CTX_wm_space_file(C);
if (sfile->params) {
-
ED_fileselect_clear(wm, sfile);
+ /* Clear search string, it is very rare to want to keep that filter while changing dir,
+ * and usually very annoying to keep it actually! */
+ sfile->params->filter_search[0] = '\0';
+
if (checkdir && !BLI_is_dir(sfile->params->dir)) {
BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir));
/* could return but just refresh the current dir */
@@ -634,7 +638,7 @@ int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matche
for (i = 0; i < n; i++) {
file = filelist_file(sfile->files, i);
if (fnmatch(pattern, file->relname, 0) == 0) {
- file->selflag |= SELECTED_FILE;
+ file->selflag |= FILE_SEL_SELECTED;
if (!match) {
BLI_strncpy(matched_file, file->relname, FILE_MAX);
}
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index f046ac7cdb3..4ab9bc6a849 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -367,7 +367,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
/* As 10.4 doesn't provide proper API to retrieve the favorite places,
* assume they are the standard ones
- * TODO : replace hardcoded paths with proper BLI_get_folder calls */
+ * TODO : replace hardcoded paths with proper BKE_appdir_folder_id calls */
home = getenv("HOME");
if (read_bookmarks && home) {
BLI_snprintf(line, sizeof(line), "%s/", home);
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index d5be04cff20..f0555933146 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -39,8 +39,8 @@
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
-#include "BLO_readfile.h"
+#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_global.h"
@@ -193,64 +193,59 @@ static void file_refresh(const bContext *C, ScrArea *UNUSED(sa))
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
- if (!sfile->folders_prev)
+ if (!sfile->folders_prev) {
sfile->folders_prev = folderlist_new();
+ }
if (!sfile->files) {
sfile->files = filelist_new(params->type);
filelist_setdir(sfile->files, params->dir);
- params->active_file = -1; // added this so it opens nicer (ton)
+ params->active_file = -1; /* added this so it opens nicer (ton) */
}
- filelist_hidedot(sfile->files, params->flag & FILE_HIDE_DOT);
- filelist_setfilter(sfile->files, params->flag & FILE_FILTER ? params->filter : 0);
- filelist_setfilter_types(sfile->files, params->filter_glob);
+ filelist_setsorting(sfile->files, params->sort);
+ filelist_setfilter_options(sfile->files, params->flag & FILE_HIDE_DOT,
+ false, /* TODO hide_parent, should be controllable? */
+ params->flag & FILE_FILTER ? params->filter : 0,
+ params->filter_glob,
+ params->filter_search);
if (filelist_empty(sfile->files)) {
thumbnails_stop(wm, sfile->files);
filelist_readdir(sfile->files);
- if (params->sort != FILE_SORT_NONE) {
- filelist_sort(sfile->files, params->sort);
- }
+ filelist_sort(sfile->files);
BLI_strncpy(params->dir, filelist_dir(sfile->files), FILE_MAX);
- if (params->display == FILE_IMGDISPLAY) {
+ }
+ else if (filelist_need_sorting(sfile->files)) {
+ thumbnails_stop(wm, sfile->files);
+ filelist_sort(sfile->files);
+ }
+
+ if ((params->display == FILE_IMGDISPLAY) && filelist_need_thumbnails(sfile->files)) {
+ if (!thumbnails_running(wm, sfile->files)) {
thumbnails_start(sfile->files, C);
}
}
else {
- if (params->sort != FILE_SORT_NONE) {
- thumbnails_stop(wm, sfile->files);
- filelist_sort(sfile->files, params->sort);
- if (params->display == FILE_IMGDISPLAY) {
- thumbnails_start(sfile->files, C);
- }
- }
- else {
- if (params->display == FILE_IMGDISPLAY) {
- if (!thumbnails_running(wm, sfile->files)) {
- thumbnails_start(sfile->files, C);
- }
- }
- else {
- /* stop any running thumbnail jobs if we're not
- * displaying them - speedup for NFS */
- thumbnails_stop(wm, sfile->files);
- }
- filelist_filter(sfile->files);
- }
+ /* stop any running thumbnail jobs if we're not displaying them - speedup for NFS */
+ thumbnails_stop(wm, sfile->files);
}
-
+
+ filelist_filter(sfile->files);
+
if (params->renamefile[0] != '\0') {
int idx = filelist_find(sfile->files, params->renamefile);
if (idx >= 0) {
struct direntry *file = filelist_file(sfile->files, idx);
if (file) {
- file->selflag |= EDITING_FILE;
+ file->selflag |= FILE_SEL_EDITING;
}
}
BLI_strncpy(sfile->params->renameedit, sfile->params->renamefile, sizeof(sfile->params->renameedit));
params->renamefile[0] = '\0';
}
- if (sfile->layout) sfile->layout->dirty = true;
+ if (sfile->layout) {
+ sfile->layout->dirty = true;
+ }
}
static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
@@ -656,7 +651,7 @@ void ED_file_exit(void)
void ED_file_read_bookmarks(void)
{
- const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
+ const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
fsmenu_free();
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 53beb5e0659..b87f80c4e62 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -60,8 +60,6 @@
#include "BKE_context.h"
#include "BKE_report.h"
-#include "UI_interface.h"
-#include "UI_resources.h"
#include "UI_view2d.h"
#include "ED_anim_api.h"
@@ -699,7 +697,7 @@ static short copy_graph_keys(bAnimContext *ac)
}
static short paste_graph_keys(bAnimContext *ac,
- const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode)
+ const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
{
ListBase anim_data = {NULL, NULL};
int filter, ok = 0;
@@ -716,7 +714,7 @@ static short paste_graph_keys(bAnimContext *ac,
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* paste keyframes */
- ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode);
+ ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
/* clean up */
ANIM_animdata_freelist(&anim_data);
@@ -767,6 +765,7 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op)
const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset");
const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge");
+ const bool flipped = RNA_boolean_get(op->ptr, "flipped");
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -776,7 +775,7 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op)
ac.reports = op->reports;
/* paste keyframes - non-zero return means an error occurred while trying to paste */
- if (paste_graph_keys(&ac, offset_mode, merge_mode)) {
+ if (paste_graph_keys(&ac, offset_mode, merge_mode, flipped)) {
return OPERATOR_CANCELLED;
}
@@ -788,6 +787,8 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op)
void GRAPH_OT_paste(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Paste Keyframes";
ot->idname = "GRAPH_OT_paste";
@@ -804,6 +805,8 @@ void GRAPH_OT_paste(wmOperatorType *ot)
/* props */
RNA_def_enum(ot->srna, "offset", keyframe_paste_offset_items, KEYFRAME_PASTE_OFFSET_CFRA_START, "Offset", "Paste time offset of keys");
RNA_def_enum(ot->srna, "merge", keyframe_paste_merge_items, KEYFRAME_PASTE_MERGE_MIX, "Type", "Method of merging pasted keys and existing");
+ prop = RNA_def_boolean(ot->srna, "flipped", false, "Flipped", "Paste keyframes from mirrored bones if they exist");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ******************** Duplicate Keyframes Operator ************************* */
@@ -1241,7 +1244,7 @@ void GRAPH_OT_sound_bake(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | SOUNDFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
RNA_def_float(ot->srna, "low", 0.0f, 0.0, 100000.0, "Lowest frequency",
"Cutoff frequency of a high-pass filter that is applied to the audio data", 0.1, 1000.00);
diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h
index 408c78d194e..50412952139 100644
--- a/source/blender/editors/space_graph/graph_intern.h
+++ b/source/blender/editors/space_graph/graph_intern.h
@@ -62,6 +62,7 @@ void graph_draw_ghost_curves(struct bAnimContext *ac, struct SpaceIpo *sipo, str
void GRAPH_OT_select_all_toggle(struct wmOperatorType *ot);
void GRAPH_OT_select_border(struct wmOperatorType *ot);
void GRAPH_OT_select_lasso(struct wmOperatorType *ot);
+void GRAPH_OT_select_circle(struct wmOperatorType *ot);
void GRAPH_OT_select_column(struct wmOperatorType *ot);
void GRAPH_OT_select_linked(struct wmOperatorType *ot);
void GRAPH_OT_select_more(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 62b6b59df29..da308d0b1f1 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -34,6 +34,7 @@
#include "DNA_scene_types.h"
+#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math_base.h"
@@ -200,6 +201,174 @@ static void GRAPH_OT_cursor_set(wmOperatorType *ot)
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Value", "", -100.0f, 100.0f);
}
+/* Hide/Reveal ------------------------------------------------------------ */
+
+static int graphview_curves_hide_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ ListBase all_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ const bool unselected = RNA_boolean_get(op->ptr, "unselected");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get list of all channels that selection may need to be flushed to
+ * - hierarchy must not affect what we have access to here...
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
+
+ /* filter data
+ * - of the remaining visible curves, we want to hide the ones that are
+ * selected/unselected (depending on "unselected" prop)
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ if (unselected)
+ filter |= ANIMFILTER_UNSEL;
+ else
+ filter |= ANIMFILTER_SEL;
+
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
+ /* TODO: find out why this is the case, and fix that */
+ if (ale->type == ANIMTYPE_OBJECT)
+ continue;
+
+ /* change the hide setting, and unselect it... */
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_CLEAR);
+
+ /* now, also flush selection status up/down as appropriate */
+ ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
+ BLI_freelistN(&all_data);
+
+ /* unhide selected */
+ if (unselected) {
+ /* turn off requirement for visible */
+ filter = ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_LIST_CHANNELS;
+
+ /* flushing has been done */
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
+ /* TODO: find out why this is the case, and fix that */
+ if (ale->type == ANIMTYPE_OBJECT)
+ continue;
+
+ /* change the hide setting, and unselect it... */
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD);
+
+ /* now, also flush selection status up/down as appropriate */
+ ANIM_flush_setting_anim_channels(&ac, &anim_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
+ }
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void GRAPH_OT_hide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Hide Curves";
+ ot->idname = "GRAPH_OT_hide";
+ ot->description = "Hide selected curves from Graph Editor view";
+
+ /* api callbacks */
+ ot->exec = graphview_curves_hide_exec;
+ ot->poll = ED_operator_graphedit_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected curves");
+}
+
+/* ........ */
+
+static int graphview_curves_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ ListBase all_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get list of all channels that selection may need to be flushed to
+ * - hierarchy must not affect what we have access to here...
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
+
+ /* filter data
+ * - just go through all visible channels, ensuring that everything is set to be curve-visible
+ */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
+ /* TODO: find out why this is the case, and fix that */
+ if (ale->type == ANIMTYPE_OBJECT)
+ continue;
+
+ /* select if it is not visible */
+ if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0)
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD);
+
+ /* change the visibility setting */
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
+
+ /* now, also flush selection status up/down as appropriate */
+ ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, true);
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
+ BLI_freelistN(&all_data);
+
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void GRAPH_OT_reveal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Reveal Curves";
+ ot->idname = "GRAPH_OT_reveal";
+ ot->description = "Make previously hidden curves visible again in Graph Editor view";
+
+ /* api callbacks */
+ ot->exec = graphview_curves_reveal_exec;
+ ot->poll = ED_operator_graphedit_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* ************************** registration - operator types **********************************/
void graphedit_operatortypes(void)
@@ -215,12 +384,16 @@ void graphedit_operatortypes(void)
WM_operatortype_append(GRAPH_OT_ghost_curves_create);
WM_operatortype_append(GRAPH_OT_ghost_curves_clear);
+ WM_operatortype_append(GRAPH_OT_hide);
+ WM_operatortype_append(GRAPH_OT_reveal);
+
/* keyframes */
/* selection */
WM_operatortype_append(GRAPH_OT_clickselect);
WM_operatortype_append(GRAPH_OT_select_all_toggle);
WM_operatortype_append(GRAPH_OT_select_border);
WM_operatortype_append(GRAPH_OT_select_lasso);
+ WM_operatortype_append(GRAPH_OT_select_circle);
WM_operatortype_append(GRAPH_OT_select_column);
WM_operatortype_append(GRAPH_OT_select_linked);
WM_operatortype_append(GRAPH_OT_select_more);
@@ -359,6 +532,8 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "deselect", true);
+ WM_keymap_add_item(keymap, "GRAPH_OT_select_circle", CKEY, KM_PRESS, 0, 0);
+
/* column select */
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_KEYS);
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_CFRA);
@@ -405,9 +580,13 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
/* copy/paste */
WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
+ kmi = WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "flipped", true);
#ifdef __APPLE__
WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
+ kmi = WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_OSKEY | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "flipped", true);
#endif
/* auto-set range */
@@ -429,6 +608,19 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
/* transform system */
transform_keymap_for_space(keyconf, keymap, SPACE_IPO);
+ /* pivot point settings */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "value", "BOUNDING_BOX_CENTER");
+
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "value", "CURSOR");
+
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "value", "INDIVIDUAL_ORIGINS");
+
/* special markers hotkeys for anim editors: see note in definition of this function */
ED_marker_keymap_animedit_conflictfree(keymap);
}
@@ -438,6 +630,7 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
void graphedit_keymap(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
+ wmKeyMapItem *kmi;
/* keymap for all regions */
keymap = WM_keymap_find(keyconf, "Graph Editor Generic", SPACE_IPO, 0);
@@ -448,7 +641,17 @@ void graphedit_keymap(wmKeyConfig *keyconf)
/* find (i.e. a shortcut for setting the name filter) */
WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
-
+
+ /* hide/reveal selected curves */
+ kmi = WM_keymap_add_item(keymap, "GRAPH_OT_hide", HKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", false);
+
+ kmi = WM_keymap_add_item(keymap, "GRAPH_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", true);
+
+ WM_keymap_add_item(keymap, "GRAPH_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
+
+
/* channels */
/* Channels are not directly handled by the Graph Editor module, but are inherited from the Animation module.
* All the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as these
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 378139accbc..78dbae7618b 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -219,7 +219,7 @@ void GRAPH_OT_select_all_toggle(wmOperatorType *ot)
*/
static void borderselect_graphkeys(
bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, bool incl_handles,
- struct KeyframeEdit_LassoData *data_lasso)
+ void *data)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@@ -244,10 +244,16 @@ static void borderselect_graphkeys(
/* init editing data */
memset(&ked, 0, sizeof(KeyframeEditData));
- if (data_lasso) {
+ if (mode == BEZT_OK_REGION_LASSO) {
+ struct KeyframeEdit_LassoData *data_lasso = data;
data_lasso->rectf_scaled = &scaled_rectf;
ked.data = data_lasso;
}
+ else if (mode == BEZT_OK_REGION_CIRCLE) {
+ struct KeyframeEdit_CircleData *data_circle = data;
+ data_circle->rectf_scaled = &scaled_rectf;
+ ked.data = data;
+ }
else {
ked.data = &scaled_rectf;
}
@@ -485,6 +491,81 @@ void GRAPH_OT_select_lasso(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first");
}
+static int graph_circle_select_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ const int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
+ short selectmode;
+ bool incl_handles;
+ rctf rect_fl;
+ struct KeyframeEdit_CircleData data;
+ float x = RNA_int_get(op->ptr, "x");
+ float y = RNA_int_get(op->ptr, "y");
+ float radius = RNA_int_get(op->ptr, "radius");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ data.mval[0] = x;
+ data.mval[1] = y;
+ data.radius_squared = radius * radius;
+ data.rectf_view = &rect_fl;
+
+ if (gesture_mode == GESTURE_MODAL_SELECT)
+ selectmode = SELECT_ADD;
+ else
+ selectmode = SELECT_SUBTRACT;
+
+ rect_fl.xmin = x - radius;
+ rect_fl.xmax = x + radius;
+ rect_fl.ymin = y - radius;
+ rect_fl.ymax = y + radius;
+
+ if (ac.spacetype == SPACE_IPO) {
+ SpaceIpo *sipo = (SpaceIpo *)ac.sl;
+ if (selectmode == SELECT_ADD) {
+ incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) ||
+ (sipo->flag & SIPO_NOHANDLES)) == 0;
+ }
+ else {
+ incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
+ }
+ }
+ else {
+ incl_handles = false;
+ }
+
+ /* apply borderselect action */
+ borderselect_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data);
+
+ /* send notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GRAPH_OT_select_circle(wmOperatorType *ot)
+{
+ ot->name = "Circle Select";
+ ot->description = "Select keyframe points using circle selection";
+ ot->idname = "GRAPH_OT_select_circle";
+
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->exec = graph_circle_select_exec;
+ ot->poll = graphop_visible_keyframes_poll;
+ ot->cancel = WM_gesture_circle_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "radius", 1, 1, INT_MAX, "Radius", "", 1, INT_MAX);
+ RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+}
+
/* ******************** Column Select Operator **************************** */
/* This operator works in one of four ways:
* - 1) select all keyframes in the same frame as a selected one (KKEY)
diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c
index e9c8ae95acd..eea360ced45 100644
--- a/source/blender/editors/space_graph/graph_utils.c
+++ b/source/blender/editors/space_graph/graph_utils.c
@@ -40,7 +40,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BKE_context.h"
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index be65cdb2d4f..05868283b2e 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -977,19 +977,9 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser
}
}
-void image_buttons_register(ARegionType *art)
+void image_buttons_register(ARegionType *UNUSED(art))
{
- PanelType *pt;
- const char *category = "Grease Pencil";
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil");
- strcpy(pt->idname, "IMAGE_PT_gpencil");
- strcpy(pt->label, N_("Grease Pencil"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw_header = ED_gpencil_panel_standard_header;
- pt->draw = ED_gpencil_panel_standard;
- BLI_strncpy(pt->category, category, BLI_strlen_utf8(category));
- BLI_addtail(&art->paneltypes, pt);
+
}
static int image_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index f41e237beb4..7c5aa349fa0 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -854,8 +854,13 @@ void draw_image_main(const bContext *C, ARegion *ar)
draw_render_info(sima->iuser.scene, ima, ar, zoomx, zoomy);
}
-static bool show_image_cache(Image *image, Mask *mask)
+bool ED_space_image_show_cache(SpaceImage *sima)
{
+ Image *image = ED_space_image(sima);
+ Mask *mask = NULL;
+ if (sima->mode == SI_MODE_MASK) {
+ mask = ED_space_image_get_mask(sima);
+ }
if (image == NULL && mask == NULL) {
return false;
}
@@ -873,12 +878,12 @@ void draw_image_cache(const bContext *C, ARegion *ar)
float x, cfra = CFRA, sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1);
Mask *mask = NULL;
- if (sima->mode == SI_MODE_MASK) {
- mask = ED_space_image_get_mask(sima);
+ if (!ED_space_image_show_cache(sima)) {
+ return;
}
- if (!show_image_cache(image, mask)) {
- return;
+ if (sima->mode == SI_MODE_MASK) {
+ mask = ED_space_image_get_mask(sima);
}
glEnable(GL_BLEND);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 836ff25bddc..9d816853e8e 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -92,6 +92,8 @@
#include "PIL_time.h"
+#include "RE_engine.h"
+
#include "image_intern.h"
/******************** view navigation utilities *********************/
@@ -1052,6 +1054,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
char path[FILE_MAX];
int frame_seq_len = 0;
int frame_ofs = 1;
+ bool exists = false;
const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
@@ -1070,7 +1073,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
errno = 0;
- ima = BKE_image_load_exists(path);
+ ima = BKE_image_load_exists_ex(path, &exists);
if (!ima) {
if (op->customdata) MEM_freeN(op->customdata);
@@ -1084,8 +1087,9 @@ static int image_open_exec(bContext *C, wmOperator *op)
/* only image path after save, never ibuf */
if (is_relative_path) {
- const char *relbase = ID_BLEND_PATH(bmain, &ima->id);
- BLI_path_rel(ima->name, relbase);
+ if (!exists) {
+ BLI_path_rel(ima->name, bmain->name);
+ }
}
/* hook into UI */
@@ -1127,7 +1131,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
}
/* XXX unpackImage frees image buffers */
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
BKE_image_signal(ima, iuser, IMA_SIGNAL_RELOAD);
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
@@ -1203,7 +1207,7 @@ void IMAGE_OT_open(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
}
@@ -1279,7 +1283,7 @@ static int image_replace_exec(bContext *C, wmOperator *op)
sima->image->source = IMA_SRC_FILE;
/* XXX unpackImage frees image buffers */
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
BKE_icon_changed(BKE_icon_getid(&sima->image->id));
BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_RELOAD);
@@ -1322,7 +1326,7 @@ void IMAGE_OT_replace(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
}
@@ -1732,7 +1736,7 @@ void IMAGE_OT_save_as(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "save_as_render", 0, "Save As Render", "Apply render part of display transform when saving byte image");
RNA_def_boolean(ot->srna, "copy", 0, "Copy", "Create a new image file without modifying the current image in blender");
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_SAVE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_SAVE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
}
@@ -1880,7 +1884,7 @@ static int image_reload_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* XXX unpackImage frees image buffers */
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
// XXX other users?
BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_RELOAD);
@@ -2309,7 +2313,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save");
/* XXX unpackImage frees image buffers */
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
unpackImage(op->reports, ima, method);
@@ -2580,8 +2584,9 @@ static int image_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event
ImageSampleInfo *info;
if (ar->regiontype == RGN_TYPE_WINDOW) {
- if (event->mval[1] <= 16)
+ if (event->mval[1] <= 16 && ED_space_image_show_cache(sima)) {
return OPERATOR_PASS_THROUGH;
+ }
}
if (!ED_space_image_has_buffer(sima))
@@ -3015,8 +3020,10 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
ARegion *ar = CTX_wm_region(C);
if (ar->regiontype == RGN_TYPE_WINDOW) {
- if (event->mval[1] > 16)
+ SpaceImage *sima = CTX_wm_space_image(C);
+ if (event->mval[1] > 16 || !ED_space_image_show_cache(sima)) {
return OPERATOR_PASS_THROUGH;
+ }
}
RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
@@ -3108,8 +3115,21 @@ static int render_border_exec(bContext *C, wmOperator *op)
{
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
+ Render *re = RE_GetRender(scene->id.name);
+ RenderData *rd;
rctf border;
+ if (re == NULL) {
+ /* Shouldn't happen, but better be safe close to the release. */
+ return OPERATOR_CANCELLED;
+ }
+
+ rd = RE_engine_get_render_data(re);
+ if ((rd->mode & (R_BORDER | R_CROP)) == (R_BORDER | R_CROP)) {
+ BKE_report(op->reports, RPT_INFO, "Can not set border from a cropped render");
+ return OPERATOR_CANCELLED;
+ }
+
/* get rectangle from operator */
WM_operator_properties_border_to_rctf(op, &border);
UI_view2d_region_to_view_rctf(&ar->v2d, &border, &border);
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 5dc9af2de84..6cf53533618 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -356,7 +356,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 (ELEM(drag->icon, 0, ICON_FILE_IMAGE, 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 1;
return 0;
}
@@ -797,7 +797,9 @@ static void image_main_area_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion *
/* context changes */
switch (wmn->category) {
case NC_GPENCIL:
- if (wmn->action == NA_EDITED)
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
+ ED_region_tag_redraw(ar);
+ else if (wmn->data & ND_GPENCIL_EDITMODE)
ED_region_tag_redraw(ar);
break;
case NC_IMAGE:
@@ -860,6 +862,10 @@ static void image_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
case NC_NODE:
ED_region_tag_redraw(ar);
break;
+ case NC_GPENCIL:
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
+ ED_region_tag_redraw(ar);
+ break;
}
}
@@ -908,7 +914,7 @@ static void image_tools_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa),
/* context changes */
switch (wmn->category) {
case NC_GPENCIL:
- if (wmn->data == ND_DATA)
+ if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED))
ED_region_tag_redraw(ar);
break;
case NC_BRUSH:
diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c
index 86af89bd6a9..e2895109b48 100644
--- a/source/blender/editors/space_info/info_draw.c
+++ b/source/blender/editors/space_info/info_draw.c
@@ -33,7 +33,6 @@
#include <sys/stat.h>
#include <limits.h>
-#include "BLF_api.h"
#include "BLI_utildefines.h"
@@ -45,8 +44,6 @@
#include "BIF_gl.h"
-#include "ED_datafiles.h"
-#include "ED_types.h"
#include "UI_resources.h"
#include "UI_interface.h"
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index 33333e4c992..ebce13389c9 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -155,7 +155,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
MEM_freeN(offsets);
return 1;
}
- else if (y_next - cdc->lheight < cdc->ymin) {
+ else if (y_next < cdc->ymin) {
/* have not reached the drawable area so don't break */
cdc->xy[1] = y_next;
diff --git a/source/blender/editors/space_logic/logic_buttons.c b/source/blender/editors/space_logic/logic_buttons.c
index 085fe68df92..e0cbc1c9539 100644
--- a/source/blender/editors/space_logic/logic_buttons.c
+++ b/source/blender/editors/space_logic/logic_buttons.c
@@ -34,7 +34,6 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
#include "ED_screen.h"
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 5464449a94e..21a9246d7e6 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -96,11 +96,7 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf
static int vergname(const void *v1, const void *v2)
{
- char **x1, **x2;
-
- x1 = (char **)v1;
- x2 = (char **)v2;
-
+ const char * const *x1 = v1, * const *x2 = v2;
return BLI_natstrcmp(*x1, *x2);
}
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 89cfd389a9d..66023ce1243 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -143,6 +143,7 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
case ANIMTYPE_DSLAT:
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
{
/* for these channels, we only do AnimData */
if (ale->adt && adt_ptr) {
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index fbb4d273626..0abe5e42c3e 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -182,6 +182,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
case ANIMTYPE_DSLAT:
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
+ case ANIMTYPE_DSGPENCIL:
{
/* sanity checking... */
if (ale->adt) {
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 4cae820de89..ef3c3504a85 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -59,7 +59,6 @@
#include "WM_types.h"
#include "UI_interface.h"
-#include "UI_interface_icons.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -619,7 +618,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* *********************************************** */
/* Channel List */
-void draw_nla_channel_list(bContext *C, bAnimContext *ac, ARegion *ar)
+void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index f43982fac8b..a883f350f1c 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -1372,11 +1372,15 @@ static int nlaedit_toggle_mute_exec(bContext *C, wmOperator *UNUSED(op))
/* just flip the mute flag for now */
// TODO: have a pre-pass to check if mute all or unmute all?
strip->flag ^= NLASTRIP_FLAG_MUTED;
+
+ /* tag AnimData to get recalculated */
+ ale->update |= ANIM_UPDATE_DEPS;
}
}
}
- /* free temp data */
+ /* cleanup */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* set notifier that things have changed */
@@ -2130,9 +2134,13 @@ static int nlaedit_snap_exec(bContext *C, wmOperator *op)
/* remove the meta-strips now that we're done */
BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
+
+ /* tag for recalculating the animation */
+ ale->update |= ANIM_UPDATE_DEPS;
}
- /* free temp data */
+ /* cleanup */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* refresh auto strip properties */
@@ -2246,6 +2254,7 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
if (fcm) {
set_active_fmodifier(&strip->modifiers, fcm);
+ ale->update |= ANIM_UPDATE_DEPS;
}
else {
BKE_reportf(op->reports, RPT_ERROR,
@@ -2256,6 +2265,7 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
}
/* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* set notifier that things have changed */
@@ -2321,6 +2331,9 @@ static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op)
}
}
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
+
/* successful or not? */
if (ok == 0) {
BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
@@ -2375,10 +2388,12 @@ static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op)
for (strip = nlt->strips.first; strip; strip = strip->next) {
// TODO: do we want to replace existing modifiers? add user pref for that!
ok += ANIM_fmodifiers_paste_from_buf(&strip->modifiers, 0);
+ ale->update |= ANIM_UPDATE_DEPS;
}
}
/* clean up */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* successful or not? */
diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h
index 766ae28da6f..bd96b5a4de5 100644
--- a/source/blender/editors/space_nla/nla_intern.h
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -50,7 +50,7 @@ void NLA_OT_properties(wmOperatorType *ot);
/* nla_draw.c */
void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar);
-void draw_nla_channel_list(bContext *C, bAnimContext *ac, ARegion *ar);
+void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar);
/* **************************************** */
/* nla_select.c */
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
index 5e1381db696..b3a875047db 100644
--- a/source/blender/editors/space_nla/nla_ops.c
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -28,15 +28,11 @@
* \ingroup spnla
*/
-
#include <string.h>
#include <stdio.h>
#include "DNA_scene_types.h"
-
-#include "BLI_blenlib.h"
-
#include "BKE_context.h"
#include "BKE_screen.h"
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index cc1d6002134..ec584525aeb 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -236,7 +236,7 @@ static void nla_channel_area_draw(const bContext *C, ARegion *ar)
/* data */
if (ANIM_animdata_get_context(C, &ac)) {
- draw_nla_channel_list((bContext *)C, &ac, ar);
+ draw_nla_channel_list(C, &ac, ar);
}
/* reset view matrix */
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index e0fe622d98d..c45626e4284 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -54,7 +54,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "ED_node.h"
@@ -64,7 +63,6 @@
#include "UI_resources.h"
#include "IMB_colormanagement.h"
-#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
@@ -781,8 +779,8 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
if (RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) {
uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE);
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index 5805c11a438..b6fa4518ed6 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -29,8 +29,6 @@
* \ingroup spnode
*/
-#include <errno.h>
-
#include "MEM_guardedalloc.h"
#include "DNA_node_types.h"
@@ -227,7 +225,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
float insert_point[2];
/* always first */
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
node_deselect_all(snode);
@@ -304,33 +302,12 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
- Image *ima = NULL;
+ Image *ima;
int type = 0;
- /* check input variables */
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- char path[FILE_MAX];
- RNA_string_get(op->ptr, "filepath", path);
-
- errno = 0;
-
- ima = BKE_image_load_exists(path);
-
- if (!ima) {
- BKE_reportf(op->reports, RPT_ERROR, "Cannot read image '%s': %s",
- path, errno ? strerror(errno) : TIP_("unsupported format"));
- return OPERATOR_CANCELLED;
- }
- }
- else if (RNA_struct_property_is_set(op->ptr, "name")) {
- char name[MAX_ID_NAME - 2];
- RNA_string_get(op->ptr, "name", name);
- ima = (Image *)BKE_libblock_find_name(ID_IM, name);
-
- if (!ima) {
- BKE_reportf(op->reports, RPT_ERROR, "Image '%s' not found", name);
- return OPERATOR_CANCELLED;
- }
+ ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
+ if (!ima) {
+ return OPERATOR_CANCELLED;
}
switch (snode->nodetree->type) {
@@ -347,7 +324,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
node = node_add_node(C, NULL, type, snode->cursor[0], snode->cursor[1]);
@@ -357,9 +334,14 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
}
node->id = (ID *)ima;
-
- BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+
+ /* When adding new image file via drag-drop we need to load imbuf in order
+ * to get proper image source.
+ */
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+ }
snode_notify(C, snode);
snode_dag_update(C, snode);
@@ -397,8 +379,8 @@ void NODE_OT_add_file(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); //XXX TODO, relative_path
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Datablock name to assign");
}
@@ -426,7 +408,7 @@ static int node_add_mask_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
node = node_add_node(C, NULL, CMP_NODE_MASK, snode->cursor[0], snode->cursor[1]);
@@ -471,8 +453,8 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
PointerRNA ptr, idptr;
PropertyRNA *prop;
const char *idname;
- char _treename[MAX_ID_NAME - 2];
- char *treename = _treename;
+ char treename_buf[MAX_ID_NAME - 2];
+ const char *treename;
if (RNA_struct_property_is_set(op->ptr, "type")) {
prop = RNA_struct_find_property(op->ptr, "type");
@@ -484,10 +466,11 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
if (RNA_struct_property_is_set(op->ptr, "name")) {
- RNA_string_get(op->ptr, "name", treename);
+ RNA_string_get(op->ptr, "name", treename_buf);
+ treename = treename_buf;
}
else {
- treename = (char *)DATA_("NodeTree");
+ treename = DATA_("NodeTree");
}
if (!ntreeTypeFind(idname)) {
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index 58d94a28226..76a096b8471 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -57,6 +57,7 @@
/* ******************* node space & buttons ************** */
+#if 0
/* poll for active nodetree */
static int active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt))
{
@@ -64,6 +65,7 @@ static int active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt))
return (snode && snode->nodetree);
}
+#endif
static int node_sockets_poll(const bContext *C, PanelType *UNUSED(pt))
{
@@ -197,15 +199,6 @@ void node_buttons_register(ARegionType *art)
pt->draw = node_tree_interface_panel;
pt->poll = node_tree_interface_poll;
BLI_addtail(&art->paneltypes, pt);
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype node panel gpencil");
- strcpy(pt->idname, "NODE_PT_gpencil");
- strcpy(pt->label, N_("Grease Pencil"));
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw_header = ED_gpencil_panel_standard_header;
- pt->draw = ED_gpencil_panel_standard;
- pt->poll = active_nodetree_poll;
- BLI_addtail(&art->paneltypes, pt);
}
static int node_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 42259a37f45..16ad63bcafa 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -66,7 +66,10 @@
#include "RNA_access.h"
#include "node_intern.h" /* own include */
-#include "COM_compositor.h"
+
+#ifdef WITH_COMPOSITOR
+# include "COM_compositor.h"
+#endif
/* XXX interface.h */
extern void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
@@ -1130,6 +1133,9 @@ void node_update_nodetree(const bContext *C, bNodeTree *ntree)
{
bNode *node;
+ /* make sure socket "used" tags are correct, for displaying value buttons */
+ ntreeTagUsedSockets(ntree);
+
/* update nodes front to back, so children sizes get updated before parents */
for (node = ntree->nodes.last; node; node = node->prev) {
node_update(C, ntree, node);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index a16adb09b4f..1e258368b8b 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -31,7 +31,6 @@
#include "MEM_guardedalloc.h"
-#include "DNA_action_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
@@ -73,8 +72,6 @@
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
-#include "NOD_common.h"
-#include "NOD_socket.h"
#include "NOD_composite.h"
#include "NOD_shader.h"
#include "NOD_texture.h"
@@ -342,14 +339,22 @@ void snode_dag_update(bContext *C, SpaceNode *snode)
void snode_notify(bContext *C, SpaceNode *snode)
{
+ ID *id = snode->id;
+
WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL);
- if (ED_node_is_shader(snode))
- WM_event_add_notifier(C, NC_MATERIAL | ND_NODES, snode->id);
+ if (ED_node_is_shader(snode)) {
+ if (GS(id->name) == ID_MA)
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
+ else if (GS(id->name) == ID_LA)
+ WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id);
+ else if (GS(id->name) == ID_WO)
+ WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
+ }
else if (ED_node_is_compositor(snode))
- WM_event_add_notifier(C, NC_SCENE | ND_NODES, snode->id);
+ WM_event_add_notifier(C, NC_SCENE | ND_NODES, id);
else if (ED_node_is_texture(snode))
- WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, snode->id);
+ WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, id);
}
void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo)
@@ -662,11 +667,16 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
/* if active texture changed, free glsl materials */
if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
Material *ma;
+ World *wo;
for (ma = bmain->mat.first; ma; ma = ma->id.next)
if (ma->nodetree && ma->use_nodes && ntreeHasTree(ma->nodetree, ntree))
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
+ for (wo = bmain->world.first; wo; wo = wo->id.next)
+ if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree))
+ GPU_material_free(&wo->gpumaterial);
+
WM_main_add_notifier(NC_IMAGE, NULL);
}
@@ -1142,7 +1152,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
bNodeLink *link, *newlink, *lastlink;
const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
lastnode = ntree->nodes.last;
for (node = ntree->nodes.first; node; node = node->next) {
@@ -1277,7 +1287,7 @@ static int node_read_renderlayers_exec(bContext *C, wmOperator *UNUSED(op))
Scene *curscene = CTX_data_scene(C), *scene;
bNode *node;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
/* first tag scenes unread */
for (scene = bmain->scene.first; scene; scene = scene->id.next)
@@ -1476,7 +1486,7 @@ static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op))
if ((snode == NULL) || (snode->edittree == NULL))
return OPERATOR_CANCELLED;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
node_flag_toggle_exec(snode, NODE_PREVIEW);
@@ -1540,7 +1550,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
if ((snode == NULL) || (snode->edittree == NULL))
return OPERATOR_CANCELLED;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
/* Toggle for all selected nodes */
hidden = 0;
@@ -1588,7 +1598,7 @@ static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
for (node = snode->edittree->nodes.first; node; node = node->next) {
/* Only allow muting of nodes having a mute func! */
@@ -1626,7 +1636,7 @@ static int node_delete_exec(bContext *C, wmOperator *UNUSED(op))
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node, *next;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
for (node = snode->edittree->nodes.first; node; node = next) {
next = node->next;
@@ -1667,7 +1677,7 @@ static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node, *next;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
for (node = snode->edittree->nodes.first; node; node = next) {
next = node->next;
@@ -1924,7 +1934,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
bNode *node;
bNodeLink *link, *newlink;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
/* clear current clipboard */
BKE_node_clipboard_clear();
@@ -2037,7 +2047,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
if (!all_nodes_valid)
return OPERATOR_CANCELLED;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
/* deselect old nodes */
node_deselect_all(snode);
@@ -2445,7 +2455,7 @@ static int viewer_border_exec(bContext *C, wmOperator *op)
void *lock;
ImBuf *ibuf;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index de119cf04fb..b69808d4e81 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -55,7 +55,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -64,7 +63,6 @@
#include "node_intern.h" /* own include */
#include "NOD_common.h"
-#include "NOD_socket.h"
static int node_group_operator_active(bContext *C)
{
@@ -144,7 +142,7 @@ static int node_group_edit_exec(bContext *C, wmOperator *op)
bNode *gnode;
const bool exit = RNA_boolean_get(op->ptr, "exit");
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
gnode = node_group_get_active(C, node_idname);
@@ -352,7 +350,7 @@ static int node_group_ungroup_exec(bContext *C, wmOperator *op)
const char *node_idname = group_node_idname(C);
bNode *gnode;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
gnode = node_group_get_active(C, node_idname);
if (!gnode)
@@ -522,7 +520,7 @@ static int node_group_separate_exec(bContext *C, wmOperator *op)
int type = RNA_enum_get(op->ptr, "type");
float offx, offy;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
/* are we inside of a group? */
ngroup = snode->edittree;
@@ -915,7 +913,7 @@ static int node_group_make_exec(bContext *C, wmOperator *op)
bNode *gnode;
Main *bmain = CTX_data_main(C);
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
if (!node_group_make_test_selected(ntree, NULL, ntree_idname, op->reports))
return OPERATOR_CANCELLED;
@@ -966,7 +964,7 @@ static int node_group_insert_exec(bContext *C, wmOperator *op)
bNode *gnode;
Main *bmain = CTX_data_main(C);
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
gnode = node_group_get_active(C, node_idname);
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 8dfc2ac8e83..c8951a1172e 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -57,7 +57,6 @@
#include "BLF_translation.h"
#include "node_intern.h" /* own include */
-#include "NOD_common.h"
/* ****************** Add *********************** */
@@ -368,7 +367,7 @@ static int node_active_link_viewer_exec(bContext *C, wmOperator *UNUSED(op))
if (!node)
return OPERATOR_CANCELLED;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
if (node_link_viewer(C, node) == OPERATOR_CANCELLED)
return OPERATOR_CANCELLED;
@@ -747,7 +746,7 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
&cursor[0], &cursor[1]);
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
nldrag = node_link_init(snode, cursor, detach);
@@ -803,7 +802,7 @@ static int node_make_link_exec(bContext *C, wmOperator *op)
SpaceNode *snode = CTX_wm_space_node(C);
const bool replace = RNA_boolean_get(op->ptr, "replace");
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
snode_autoconnect(snode, 1, replace);
@@ -874,7 +873,7 @@ static int cut_links_exec(bContext *C, wmOperator *op)
bool found = false;
bNodeLink *link, *next;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
for (link = snode->edittree->links.first; link; link = next) {
next = link->next;
@@ -884,7 +883,8 @@ static int cut_links_exec(bContext *C, wmOperator *op)
if (cut_links_intersect(link, mcoords, i)) {
if (found == false) {
- ED_preview_kill_jobs(C);
+ /* TODO(sergey): Why did we kill jobs twice? */
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
found = true;
}
@@ -941,7 +941,7 @@ static int detach_links_exec(bContext *C, wmOperator *UNUSED(op))
bNodeTree *ntree = snode->edittree;
bNode *node;
- ED_preview_kill_jobs(C);
+ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
for (node = ntree->nodes.first; node; node = node->next) {
if (node->flag & SELECT) {
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index ab0619604a9..8b68ac013c2 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -30,7 +30,6 @@
#include "DNA_node_types.h"
#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
@@ -54,7 +53,6 @@
#include "ED_util.h"
-#include "node_intern.h"
/************************* Node Socket Manipulation **************************/
diff --git a/source/blender/editors/space_node/node_toolbar.c b/source/blender/editors/space_node/node_toolbar.c
index dd5bad3f8ad..e3e263f2e44 100644
--- a/source/blender/editors/space_node/node_toolbar.c
+++ b/source/blender/editors/space_node/node_toolbar.c
@@ -28,27 +28,18 @@
* \ingroup nodes
*/
-
-#include "MEM_guardedalloc.h"
-
#include "BLI_utildefines.h"
#include "DNA_node_types.h"
#include "BKE_context.h"
-#include "BKE_node.h"
#include "BKE_screen.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "RNA_access.h"
-
#include "ED_screen.h"
-#include "UI_interface.h"
-#include "UI_resources.h"
-
#include "node_intern.h" /* own include */
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index e28c775ad88..e3baddef158 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -28,8 +28,6 @@
* \ingroup spnode
*/
-
-
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
@@ -515,6 +513,11 @@ static void node_area_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn)
ED_area_tag_refresh(sa);
}
break;
+ case NC_GPENCIL:
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ ED_area_tag_redraw(sa);
+ }
+ break;
}
}
@@ -670,7 +673,7 @@ static int node_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *
return 1;
}
else if (drag->type == WM_DRAG_PATH) {
- if (ELEM(drag->icon, 0, ICON_FILE_IMAGE)) /* rule might not work? */
+ if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)) /* rule might not work? */
return 1;
}
return 0;
@@ -699,9 +702,11 @@ static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
if (id) {
RNA_string_set(drop->ptr, "name", id->name + 2);
+ RNA_struct_property_unset(drop->ptr, "filepath");
}
- if (drag->path[0]) {
+ else if (drag->path[0]) {
RNA_string_set(drop->ptr, "filepath", drag->path);
+ RNA_struct_property_unset(drop->ptr, "name");
}
}
@@ -768,6 +773,8 @@ static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegi
case NC_GPENCIL:
if (wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
+ else if (wmn->data & ND_GPENCIL_EDITMODE)
+ ED_region_tag_redraw(ar);
break;
}
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 61c4fe3cd02..9bc043b384e 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1018,6 +1018,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
UI_icon_draw(x, y, ICON_MOD_WIREFRAME); break;
case eModifierType_LaplacianDeform:
UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
+ case eModifierType_DataTransfer:
+ UI_icon_draw(x, y, ICON_MOD_DATA_TRANSFER); break;
case eModifierType_PointCache:
UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
/* Default */
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index d735b5e75cf..4f13454ef34 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -30,7 +30,6 @@
#include "DNA_space_types.h"
-#include "BLI_utildefines.h"
#include "RNA_access.h"
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 6f5bf712d55..23586a6a509 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -290,6 +290,10 @@ static eOLDrawState tree_element_active_material(
}
}
if (set != OL_SETSEL_NONE) {
+ /* Tagging object for update seems a bit stupid here, but looks like we have to do it
+ * for render views to update. See T42973.
+ * Note that RNA material update does it too, see e.g. rna_MaterialSlot_update(). */
+ DAG_id_tag_update((ID *)ob, OB_RECALC_OB);
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
}
return OL_DRAWSEL_NONE;
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index f8a90c942bc..4aa36da594b 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -1371,59 +1371,42 @@ static void outliner_sort(SpaceOops *soops, ListBase *lb)
/* Filtering ----------------------------------------------- */
-static int outliner_filter_has_name(TreeElement *te, const char *name, int flags)
+static bool outliner_filter_has_name(TreeElement *te, const char *name, int flags)
{
-#if 0
- int found = 0;
-
- /* determine if match */
- if (flags & SO_FIND_CASE_SENSITIVE) {
- if (flags & SO_FIND_COMPLETE)
- found = strcmp(te->name, name) == 0;
- else
- found = strstr(te->name, name) != NULL;
- }
- else {
- if (flags & SO_FIND_COMPLETE)
- found = BLI_strcasecmp(te->name, name) == 0;
- else
- found = BLI_strcasestr(te->name, name) != NULL;
- }
-#else
-
int fn_flag = 0;
- int found = 0;
-
+
if ((flags & SO_FIND_CASE_SENSITIVE) == 0)
fn_flag |= FNM_CASEFOLD;
- if (flags & SO_FIND_COMPLETE) {
- found = fnmatch(name, te->name, fn_flag) == 0;
- }
- else {
- char fn_name[sizeof(((struct SpaceOops *)NULL)->search_string) + 2];
- BLI_snprintf(fn_name, sizeof(fn_name), "*%s*", name);
- found = fnmatch(fn_name, te->name, fn_flag) == 0;
- }
- return found;
-#endif
+ return fnmatch(name, te->name, fn_flag) == 0;
}
static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
{
TreeElement *te, *ten;
TreeStoreElem *tselem;
-
+ char search_buff[sizeof(((struct SpaceOops *)NULL)->search_string) + 2];
+ char *search_string;
+
/* although we don't have any search string, we return true
* since the entire tree is ok then...
*/
if (soops->search_string[0] == 0)
return 1;
+ if (soops->search_flags & SO_FIND_COMPLETE) {
+ search_string = soops->search_string;
+ }
+ else {
+ /* Implicitly add heading/trailing wildcards if needed. */
+ BLI_strncpy_ensure_pad(search_buff, soops->search_string, '*', sizeof(search_buff));
+ search_string = search_buff;
+ }
+
for (te = lb->first; te; te = ten) {
ten = te->next;
- if (0 == outliner_filter_has_name(te, soops->search_string, soops->search_flags)) {
+ if (!outliner_filter_has_name(te, search_string, soops->search_flags)) {
/* item isn't something we're looking for, but...
* - if the subtree is expanded, check if there are any matches that can be easily found
* so that searching for "cu" in the default scene will still match the Cube
@@ -1553,10 +1536,19 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
tselem = TREESTORE(ten);
lib = (Library *)tselem->id;
if (lib && lib->parent) {
- BLI_remlink(&soops->tree, ten);
par = (TreeElement *)lib->parent->id.newid;
- BLI_addtail(&par->subtree, ten);
- ten->parent = par;
+ if (tselem->id->flag & LIB_INDIRECT) {
+ /* Only remove from 'first level' if lib is not also directly used. */
+ BLI_remlink(&soops->tree, ten);
+ BLI_addtail(&par->subtree, ten);
+ ten->parent = par;
+ }
+ else {
+ /* Else, make a new copy of the libtree for our parent. */
+ TreeElement *dupten = outliner_add_element(soops, &par->subtree, lib, NULL, 0, 0);
+ outliner_add_library_contents(mainvar, soops, dupten, lib);
+ dupten->parent = par;
+ }
}
ten = nten;
}
diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c
index 9077d0cf8ed..d265ae62db6 100644
--- a/source/blender/editors/space_script/script_edit.c
+++ b/source/blender/editors/space_script/script_edit.c
@@ -32,7 +32,6 @@
#include <string.h>
#include <stdio.h>
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -131,7 +130,7 @@ static int script_reload_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
#else
- (void)C, (void)op; /* unused */
+ UNUSED_VARS(C, op);
return OPERATOR_CANCELLED;
#endif
}
diff --git a/source/blender/editors/space_script/script_ops.c b/source/blender/editors/space_script/script_ops.c
index 045df87d8db..41c07596a3b 100644
--- a/source/blender/editors/space_script/script_ops.c
+++ b/source/blender/editors/space_script/script_ops.c
@@ -32,19 +32,7 @@
#include <stdlib.h>
#include <math.h>
-
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-
-#include "BKE_context.h"
-
-#include "RNA_access.h"
-
#include "WM_api.h"
-#include "WM_types.h"
#include "script_intern.h"
@@ -63,4 +51,3 @@ void script_keymap(wmKeyConfig *UNUSED(keyconf))
{
/* Script space is deprecated, and doesn't need a keymap */
}
-
diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c
index fd2cd268a27..759dcd3d0a4 100644
--- a/source/blender/editors/space_script/space_script.c
+++ b/source/blender/editors/space_script/space_script.c
@@ -35,7 +35,6 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -53,7 +52,6 @@
#include "UI_view2d.h"
#ifdef WITH_PYTHON
-#include "BPY_extern.h"
#endif
#include "script_intern.h" // own include
diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt
index 4cf9c0c95c2..d9aff2781f0 100644
--- a/source/blender/editors/space_sequencer/CMakeLists.txt
+++ b/source/blender/editors/space_sequencer/CMakeLists.txt
@@ -43,6 +43,7 @@ set(SRC
sequencer_edit.c
sequencer_modifier.c
sequencer_ops.c
+ sequencer_preview.c
sequencer_scopes.c
sequencer_select.c
sequencer_view.c
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index a94ce52aca5..38a01bcd78c 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -40,7 +40,6 @@
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
-#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -61,7 +60,6 @@
#include "ED_screen.h"
#include "ED_sequencer.h"
-#include "UI_view2d.h"
#include "BKE_sound.h"
@@ -626,7 +624,7 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(ot, FOLDERFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
RNA_def_boolean(ot->srna, "sound", true, "Sound", "Load sound with the movie");
@@ -675,7 +673,7 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(ot, FOLDERFILE | SOUNDFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
@@ -774,7 +772,7 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c
index d75eeca2c67..70c6da0bfb3 100644
--- a/source/blender/editors/space_sequencer/sequencer_buttons.c
+++ b/source/blender/editors/space_sequencer/sequencer_buttons.c
@@ -46,12 +46,12 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "UI_interface.h"
#include "sequencer_intern.h"
/* **************************** buttons ********************************* */
+#if 0
static int sequencer_grease_pencil_panel_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceSeq *sseq = CTX_wm_space_seq(C);
@@ -59,9 +59,11 @@ static int sequencer_grease_pencil_panel_poll(const bContext *C, PanelType *UNUS
/* don't show the gpencil if we are not showing the image */
return ED_space_sequencer_check_show_imbuf(sseq);
}
+#endif
-void sequencer_buttons_register(ARegionType *art)
+void sequencer_buttons_register(ARegionType *UNUSED(art))
{
+#if 0
PanelType *pt;
pt = MEM_callocN(sizeof(PanelType), "spacetype sequencer panel gpencil");
@@ -72,6 +74,7 @@ void sequencer_buttons_register(ARegionType *art)
pt->draw = ED_gpencil_panel_standard;
pt->poll = sequencer_grease_pencil_panel_poll;
BLI_addtail(&art->paneltypes, pt);
+#endif
}
/* **************** operator to open/close properties view ************* */
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 90ba1044677..afb650f8cfd 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -34,6 +34,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_threads.h"
#include "IMB_imbuf_types.h"
@@ -69,6 +70,7 @@
#include "WM_api.h"
+
/* own include */
#include "sequencer_intern.h"
@@ -86,9 +88,9 @@
#undef SEQP_BEGIN
#undef SEQ_END
-static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2);
+static Sequence *special_seq_update = NULL;
-static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[3])
+void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
{
unsigned char blendcol[3];
SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
@@ -179,14 +181,14 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[
}
}
-static void drawseqwave(Scene *scene, Sequence *seq, float x1, float y1, float x2, float y2, float stepsize)
+static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequence *seq, float x1, float y1, float x2, float y2, float stepsize)
{
/*
* x1 is the starting x value to draw the wave,
* x2 the end x value, same for y1 and y2
* stepsize is width of a pixel.
*/
- if (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM) {
+ if ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM)) {
int i, j, pos;
int length = floor((x2 - x1) / stepsize) + 1;
float ymid = (y1 + y2) / 2;
@@ -194,20 +196,30 @@ static void drawseqwave(Scene *scene, Sequence *seq, float x1, float y1, float x
float samplestep;
float startsample, endsample;
float value;
-
+ bSound *sound = seq->sound;
+
SoundWaveform *waveform;
-
- if (!seq->sound->waveform)
- sound_read_waveform(seq->sound);
-
- if (!seq->sound->waveform)
- return; /* zero length sound */
-
+
+ if (!sound->mutex)
+ sound->mutex = BLI_mutex_alloc();
+
+ BLI_mutex_lock(sound->mutex);
+ if (!seq->sound->waveform) {
+ if (!(sound->flags & SOUND_FLAGS_WAVEFORM_LOADING)) {
+ /* prevent sounds from reloading */
+ seq->sound->flags |= SOUND_FLAGS_WAVEFORM_LOADING;
+ BLI_mutex_unlock(sound->mutex);
+ sequencer_preview_add_sound(C, seq);
+ }
+ else {
+ BLI_mutex_unlock(sound->mutex);
+ }
+ return; /* nothing to draw */
+ }
+ BLI_mutex_unlock(sound->mutex);
+
waveform = seq->sound->waveform;
-
- if (!waveform)
- return;
-
+
startsample = floor((seq->startofs + seq->anim_startofs) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND);
endsample = ceil((seq->startofs + seq->anim_startofs + seq->enddisp - seq->startdisp) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND);
samplestep = (endsample - startsample) * stepsize / (x2 - x1);
@@ -303,7 +315,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
if ((seqm->flag & SEQ_MUTE) == 0 && (seq->flag & SEQ_MUTE))
drawmeta_stipple(1);
- get_seq_color3ubv(scene, seq, col);
+ color3ubv_from_seq(scene, seq, col);
glColor4ubv(col);
@@ -338,7 +350,7 @@ static float draw_seq_handle_size_get_clamped(Sequence *seq, const float pixelx)
const float maxhandle = pixelx * SEQ_HANDLE_SIZE_MAX;
float size = CLAMPIS(seq->handsize, minhandle, maxhandle);
- /* ensure we're not greater then half width */
+ /* ensure we're not greater than half width */
return min_ff(size, ((float)(seq->enddisp - seq->startdisp) / 2.0f) / pixelx);
}
@@ -422,112 +434,6 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
}
}
-static void draw_seq_extensions(Scene *scene, ARegion *ar, Sequence *seq)
-{
- float x1, x2, y1, y2, pixely, a;
- unsigned char col[3], blendcol[3];
- View2D *v2d = &ar->v2d;
-
- if (seq->type >= SEQ_TYPE_EFFECT) return;
-
- x1 = seq->startdisp;
- x2 = seq->enddisp;
-
- y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
- y2 = seq->machine + SEQ_STRIP_OFSTOP;
-
- pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
-
- if (pixely <= 0) return; /* can happen when the view is split/resized */
-
- blendcol[0] = blendcol[1] = blendcol[2] = 120;
-
- if (seq->startofs) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- get_seq_color3ubv(scene, seq, col);
-
- if (seq->flag & SELECT) {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
- glColor4ub(col[0], col[1], col[2], 170);
- }
- else {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
- glColor4ub(col[0], col[1], col[2], 110);
- }
-
- glRectf((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
-
- if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
- else glColor4ub(col[0], col[1], col[2], 160);
-
- fdrawbox((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1); //outline
-
- glDisable(GL_BLEND);
- }
- if (seq->endofs) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- get_seq_color3ubv(scene, seq, col);
-
- if (seq->flag & SELECT) {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
- glColor4ub(col[0], col[1], col[2], 170);
- }
- else {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
- glColor4ub(col[0], col[1], col[2], 110);
- }
-
- glRectf(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
-
- if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
- else glColor4ub(col[0], col[1], col[2], 160);
-
- fdrawbox(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); //outline
-
- glDisable(GL_BLEND);
- }
- if (seq->startstill) {
- get_seq_color3ubv(scene, seq, col);
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
- glColor3ubv((GLubyte *)col);
-
- draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
-
- /* feint pinstripes, helps see exactly which is extended and which isn't,
- * especially when the extension is very small */
- if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
- else UI_GetColorPtrShade3ubv(col, col, -16);
-
- glColor3ubv((GLubyte *)col);
-
- for (a = y1; a < y2; a += pixely * 2.0f) {
- fdrawline(x1, a, (float)(seq->start), a);
- }
- }
- if (seq->endstill) {
- get_seq_color3ubv(scene, seq, col);
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
- glColor3ubv((GLubyte *)col);
-
- draw_shadedstrip(seq, col, (float)(seq->start + seq->len), y1, x2, y2);
-
- /* feint pinstripes, helps see exactly which is extended and which isn't,
- * especially when the extension is very small */
- if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, 24);
- else UI_GetColorPtrShade3ubv(col, col, -16);
-
- glColor3ubv((GLubyte *)col);
-
- for (a = y1; a < y2; a += pixely * 2.0f) {
- fdrawline((float)(seq->start + seq->len), a, x2, a);
- }
- }
-}
-
/* draw info text on a sequence strip */
static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float y1, float y2, const unsigned char background_col[3])
{
@@ -634,7 +540,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
}
/* draws a shaded strip, made from gradient + flat color + gradient */
-static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2)
+void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2)
{
float ymid1, ymid2;
@@ -691,12 +597,117 @@ static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, floa
}
}
+void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq)
+{
+ float x1, x2, y1, y2, pixely, a;
+ unsigned char col[3], blendcol[3];
+ View2D *v2d = &ar->v2d;
+
+ x1 = seq->startdisp;
+ x2 = seq->enddisp;
+
+ y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
+ y2 = seq->machine + SEQ_STRIP_OFSTOP;
+
+ pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
+
+ if (pixely <= 0) return; /* can happen when the view is split/resized */
+
+ blendcol[0] = blendcol[1] = blendcol[2] = 120;
+
+ if (seq->startofs) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ color3ubv_from_seq(scene, seq, col);
+
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
+ glColor4ub(col[0], col[1], col[2], 170);
+ }
+ else {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
+ glColor4ub(col[0], col[1], col[2], 110);
+ }
+
+ glRectf((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
+
+ if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
+ else glColor4ub(col[0], col[1], col[2], 160);
+
+ fdrawbox((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1); //outline
+
+ glDisable(GL_BLEND);
+ }
+ if (seq->endofs) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ color3ubv_from_seq(scene, seq, col);
+
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
+ glColor4ub(col[0], col[1], col[2], 170);
+ }
+ else {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
+ glColor4ub(col[0], col[1], col[2], 110);
+ }
+
+ glRectf(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
+
+ if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
+ else glColor4ub(col[0], col[1], col[2], 160);
+
+ fdrawbox(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); //outline
+
+ glDisable(GL_BLEND);
+ }
+ if (seq->startstill) {
+ color3ubv_from_seq(scene, seq, col);
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
+ glColor3ubv((GLubyte *)col);
+
+ draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
+
+ /* feint pinstripes, helps see exactly which is extended and which isn't,
+ * especially when the extension is very small */
+ if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
+ else UI_GetColorPtrShade3ubv(col, col, -16);
+
+ glColor3ubv((GLubyte *)col);
+
+ for (a = y1; a < y2; a += pixely * 2.0f) {
+ fdrawline(x1, a, (float)(seq->start), a);
+ }
+ }
+ if (seq->endstill) {
+ color3ubv_from_seq(scene, seq, col);
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
+ glColor3ubv((GLubyte *)col);
+
+ draw_shadedstrip(seq, col, (float)(seq->start + seq->len), y1, x2, y2);
+
+ /* feint pinstripes, helps see exactly which is extended and which isn't,
+ * especially when the extension is very small */
+ if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, 24);
+ else UI_GetColorPtrShade3ubv(col, col, -16);
+
+ glColor3ubv((GLubyte *)col);
+
+ for (a = y1; a < y2; a += pixely * 2.0f) {
+ fdrawline((float)(seq->start + seq->len), a, x2, a);
+ }
+ }
+}
+
+
/*
* Draw a sequence strip, bounds check already made
* ARegion is currently only used to get the windows width in pixels
* so wave file sample drawing precision is zoom adjusted
*/
-static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline_tint, float pixelx)
+static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, ARegion *ar, Sequence *seq, int outline_tint, float pixelx)
{
View2D *v2d = &ar->v2d;
float x1, x2, y1, y2;
@@ -714,8 +725,8 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
/* get the correct color per strip type*/
- //get_seq_color3ubv(scene, seq, col);
- get_seq_color3ubv(scene, seq, background_col);
+ //color3ubv_from_seq(scene, seq, col);
+ color3ubv_from_seq(scene, seq, background_col);
/* draw the main strip body */
if (is_single_image) { /* single image */
@@ -726,11 +737,13 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
else { /* normal operation */
draw_shadedstrip(seq, background_col, x1, y1, x2, y2);
}
-
- /* draw additional info and controls */
- if (!is_single_image)
- draw_seq_extensions(scene, ar, seq);
-
+
+ if (!is_single_image) {
+ if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) {
+ draw_sequence_extensions(scene, ar, seq);
+ }
+ }
+
draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE);
draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE);
@@ -740,7 +753,9 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
/* draw sound wave */
if (seq->type == SEQ_TYPE_SOUND_RAM) {
- drawseqwave(scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx);
+ if (!(sseq->flag & SEQ_NO_WAVEFORMS)) {
+ drawseqwave(C, sseq, scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx);
+ }
}
/* draw lock */
@@ -773,7 +788,7 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
glDisable(GL_POLYGON_STIPPLE);
}
- get_seq_color3ubv(scene, seq, col);
+ color3ubv_from_seq(scene, seq, col);
if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT)) {
if (seq->flag & SEQ_OVERLAP) {
col[0] = 255; col[1] = col[2] = 40;
@@ -817,19 +832,29 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
}
}
-static Sequence *special_seq_update = NULL;
+void sequencer_special_update_set(Sequence *seq)
+{
+ special_seq_update = seq;
+}
-static void UNUSED_FUNCTION(set_special_seq_update) (int val)
+Sequence *ED_sequencer_special_preview_get(void)
{
-// int x;
+ return special_seq_update;
+}
- /* if mouse over a sequence && LEFTMOUSE */
- if (val) {
-// XXX special_seq_update = find_nearest_seq(&x);
- }
- else {
- special_seq_update = NULL;
- }
+void ED_sequencer_special_preview_set(bContext *C, const int mval[2])
+{
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ int hand;
+ Sequence *seq;
+ seq = find_nearest_seq(scene, &ar->v2d, &hand, mval);
+ sequencer_special_update_set(seq);
+}
+
+void ED_sequencer_special_preview_clear(void)
+{
+ sequencer_special_update_set(NULL);
}
ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int cfra, int frame_ofs)
@@ -842,9 +867,6 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int
short is_break = G.is_break;
render_size = sseq->render_size;
- if (render_size == 99) {
- render_size = 100;
- }
if (render_size == 0) {
render_size = scene->r.size;
}
@@ -859,7 +881,10 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int
rectx = (render_size * (float)scene->r.xsch) / 100.0f + 0.5f;
recty = (render_size * (float)scene->r.ysch) / 100.0f + 0.5f;
- context = BKE_sequencer_new_render_data(bmain->eval_ctx, bmain, scene, rectx, recty, proxy_size);
+ BKE_sequencer_new_render_data(
+ bmain->eval_ctx, bmain, scene,
+ rectx, recty, proxy_size,
+ &context);
/* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled
* by Esc pressed somewhere in the past
@@ -924,7 +949,7 @@ static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scop
return scope;
}
-void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay)
+void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay, bool draw_backdrop)
{
struct Main *bmain = CTX_data_main(C);
struct ImBuf *ibuf = NULL;
@@ -980,7 +1005,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
viewrecty /= proxy_size / 100.0f;
}
- if (!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
+ if ((!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) && !draw_backdrop) {
UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
glClearColor(col[0], col[1], col[2], 0.0);
glClear(GL_COLOR_BUFFER_BIT);
@@ -1055,23 +1080,25 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
/* without this colors can flicker from previous opengl state */
glColor4ub(255, 255, 255, 255);
- UI_view2d_totRect_set(v2d, viewrectx + 0.5f, viewrecty + 0.5f);
- UI_view2d_curRect_validate(v2d);
-
- /* setting up the view - actual drawing starts here */
- UI_view2d_view_ortho(v2d);
-
- /* only draw alpha for main buffer */
- if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
- if (sseq->flag & SEQ_USE_ALPHA) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
- glColor4f(1.0, 1.0, 1.0, 1.0);
+ if (!draw_backdrop) {
+ UI_view2d_totRect_set(v2d, viewrectx + 0.5f, viewrecty + 0.5f);
+ UI_view2d_curRect_validate(v2d);
+
+ /* setting up the view - actual drawing starts here */
+ UI_view2d_view_ortho(v2d);
+
+ /* only draw alpha for main buffer */
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ if (sseq->flag & SEQ_USE_ALPHA) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ }
}
}
-
+
if (scope) {
IMB_freeImBuf(ibuf);
ibuf = scope;
@@ -1161,6 +1188,14 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer);
+ if (draw_backdrop) {
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ }
glBegin(GL_QUADS);
if (draw_overlay) {
@@ -1183,6 +1218,25 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
}
}
+ else if (draw_backdrop) {
+ float aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct);
+ float image_aspect = viewrectx / viewrecty;
+ float imagex, imagey;
+
+ if (aspect >= image_aspect) {
+ imagex = image_aspect / aspect;
+ imagey = 1.0f;
+ }
+ else {
+ imagex = 1.0f;
+ imagey = aspect / image_aspect;
+ }
+
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey);
+ }
else {
glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
@@ -1190,6 +1244,15 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
}
glEnd();
+
+ if (draw_backdrop) {
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
+ }
+
glBindTexture(GL_TEXTURE_2D, last_texid);
glDisable(GL_TEXTURE_2D);
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA)
@@ -1199,6 +1262,16 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if (glsl_used)
IMB_colormanagement_finish_glsl_draw();
+ if (cache_handle)
+ IMB_display_buffer_release(cache_handle);
+
+ if (!scope)
+ IMB_freeImBuf(ibuf);
+
+ if (draw_backdrop) {
+ return;
+ }
+
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
float x1 = v2d->tot.xmin;
@@ -1248,9 +1321,6 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
ED_gpencil_draw_2dimage(C);
}
}
-
- if (!scope)
- IMB_freeImBuf(ibuf);
/* ortho at pixel level */
UI_view2d_view_restore(C);
@@ -1287,9 +1357,6 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
NULL, C);
}
}
-
- if (cache_handle)
- IMB_display_buffer_release(cache_handle);
}
#if 0
@@ -1366,6 +1433,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
View2D *v2d = &ar->v2d;
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
Sequence *last_seq = BKE_sequencer_active_get(scene);
int sel = 0, j;
float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
@@ -1386,7 +1454,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
else if (seq->machine > v2d->cur.ymax) continue;
/* strip passed all tests unscathed... so draw it now */
- draw_seq_strip(scene, ar, seq, outline_tint, pixelx);
+ draw_seq_strip(C, sseq, scene, ar, seq, outline_tint, pixelx);
}
/* draw selected next time round */
@@ -1395,7 +1463,16 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
/* draw the last selected last (i.e. 'active' in other parts of Blender), removes some overlapping error */
if (last_seq)
- draw_seq_strip(scene, ar, last_seq, 120, pixelx);
+ draw_seq_strip(C, sseq, scene, ar, last_seq, 120, pixelx);
+
+ /* draw highlight when previewing a single strip */
+ if (special_seq_update) {
+ const Sequence *seq = special_seq_update;
+ glEnable(GL_BLEND);
+ glColor4ub(255, 255, 255, 48);
+ glRectf(seq->startdisp, seq->machine + SEQ_STRIP_OFSBOTTOM, seq->enddisp, seq->machine + SEQ_STRIP_OFSTOP);
+ glDisable(GL_BLEND);
+ }
}
static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
@@ -1473,6 +1550,11 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
// NOTE: the gridlines are currently spaced every 25 frames, which is only fine for 25 fps, but maybe not for 30...
UI_view2d_constant_grid_draw(v2d);
+ if (sseq->draw_flag & SEQ_DRAW_BACKDROP) {
+ draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false, true);
+ UI_view2d_view_ortho(v2d);
+ }
+
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
seq_draw_sfra_efra(scene, v2d);
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 4ad521993be..81af6dccc70 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -49,7 +49,6 @@
#include "BKE_report.h"
#include "BKE_sound.h"
-#include "IMB_imbuf.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -62,9 +61,11 @@
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_sequencer.h"
+#include "ED_space_api.h"
#include "UI_view2d.h"
+
/* own include */
#include "sequencer_intern.h"
@@ -179,6 +180,10 @@ static void seq_proxy_build_job(const bContext *C)
LinkData *link;
Sequence *seq;
+ if (ed == NULL) {
+ return;
+ }
+
wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Building Proxies",
WM_JOB_PROGRESS, WM_JOB_TYPE_SEQ_BUILD_PROXY);
@@ -385,7 +390,7 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[
displen = (float)abs(seq->startdisp - seq->enddisp);
if (displen / pixelx > 16) { /* don't even try to grab the handles of small strips */
- /* Set the max value to handle to 1/3 of the total len when its less then 28.
+ /* Set the max value to handle to 1/3 of the total len when its less than 28.
* This is important because otherwise selecting handles happens even when you click in the middle */
if ((displen / 3) < 30 * pixelx) {
@@ -494,6 +499,13 @@ bool ED_space_sequencer_check_show_imbuf(SpaceSeq *sseq)
ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
}
+bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq)
+{
+ return (ELEM(sseq->view, SEQ_VIEW_SEQUENCE, SEQ_VIEW_SEQUENCE_PREVIEW) &&
+ ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
+}
+
+
int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3, const char **error_str)
{
Editing *ed = BKE_sequencer_editing_get(scene, false);
@@ -1129,7 +1141,7 @@ int sequencer_strip_has_path_poll(bContext *C)
return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && ((seq = ed->act_seq) != NULL) && (SEQ_HAS_PATH(seq)));
}
-int sequencer_view_poll(bContext *C)
+int sequencer_view_preview_poll(bContext *C)
{
SpaceSeq *sseq = CTX_wm_space_seq(C);
Editing *ed = BKE_sequencer_editing_get(CTX_data_scene(C), false);
@@ -1139,6 +1151,15 @@ int sequencer_view_poll(bContext *C)
return 0;
}
+int sequencer_view_strips_poll(bContext *C)
+{
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
+ if (sseq && ED_space_sequencer_check_show_strip(sseq))
+ return 1;
+
+ return 0;
+}
+
/* snap operator*/
static int sequencer_snap_exec(bContext *C, wmOperator *op)
{
@@ -1231,7 +1252,6 @@ void SEQUENCER_OT_snap(struct wmOperatorType *ot)
RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be snapped", INT_MIN, INT_MAX);
}
-
typedef struct SlipData {
int init_mouse[2];
float init_mouseloc[2];
@@ -1241,6 +1261,7 @@ typedef struct SlipData {
int num_seq;
bool slow;
int slow_offset; /* offset at the point where offset was turned on */
+ void *draw_handle;
} SlipData;
static void transseq_backup(TransSeq *ts, Sequence *seq)
@@ -1274,15 +1295,30 @@ static void transseq_restore(TransSeq *ts, Sequence *seq)
seq->len = ts->len;
}
-static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool first_level)
+static void draw_slip_extensions(const bContext *C, ARegion *ar, void *data)
+{
+ Scene *scene = CTX_data_scene(C);
+ SlipData *td = data;
+ int i;
+
+ for (i = 0; i < td->num_seq; i++) {
+ Sequence *seq = td->seq_array[i];
+
+ if ((seq->type != SEQ_TYPE_META) && td->trim[i]) {
+ draw_sequence_extensions(scene, ar, seq);
+ }
+ }
+}
+
+static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
{
Sequence *seq;
int num_items = 0;
for (seq = seqbasep->first; seq; seq = seq->next) {
- if (!first_level || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
+ if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
seq_array[offset + num_items] = seq;
- trim[offset + num_items] = first_level;
+ trim[offset + num_items] = do_trim;
num_items++;
if (seq->type == SEQ_TYPE_META) {
@@ -1322,6 +1358,7 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
SlipData *data;
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
+ ARegion *ar = CTX_wm_region(C);
float mouseloc[2];
int num_seq, i;
View2D *v2d = UI_view2d_fromcontext(C);
@@ -1344,6 +1381,8 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
transseq_backup(data->ts + i, data->seq_array[i]);
}
+ data->draw_handle = ED_region_draw_cb_activate(ar->type, draw_slip_extensions, data, REGION_DRAW_POST_VIEW);
+
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
copy_v2_v2_int(data->init_mouse, event->mval);
@@ -1353,6 +1392,9 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
WM_event_add_modal_handler(C, op);
+ /* notify so we draw extensions immediately */
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
return OPERATOR_RUNNING_MODAL;
}
@@ -1463,6 +1505,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
Scene *scene = CTX_data_scene(C);
SlipData *data = (SlipData *)op->customdata;
ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
switch (event->type) {
case MOUSEMOVE:
@@ -1504,6 +1547,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
case LEFTMOUSE:
{
+ ED_region_draw_cb_exit(ar->type, data->draw_handle);
MEM_freeN(data->seq_array);
MEM_freeN(data->trim);
MEM_freeN(data->ts);
@@ -1532,6 +1576,8 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
BKE_sequence_calc(scene, seq);
}
+ ED_region_draw_cb_exit(ar->type, data->draw_handle);
+
MEM_freeN(data->seq_array);
MEM_freeN(data->ts);
MEM_freeN(data->trim);
@@ -1587,7 +1633,6 @@ void SEQUENCER_OT_slip(struct wmOperatorType *ot)
INT32_MIN, INT32_MAX);
}
-
/* mute operator */
static int sequencer_mute_exec(bContext *C, wmOperator *op)
{
@@ -2810,74 +2855,13 @@ void SEQUENCER_OT_view_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
}
-
-static int find_next_prev_edit(Scene *scene, int cfra,
- const short side,
- const bool do_skip_mute, const bool do_center)
-{
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq;
-
- int dist, best_dist, best_frame = cfra;
- int seq_frames[2], seq_frames_tot;
-
- best_dist = MAXFRAME * 2;
-
- if (ed == NULL) return cfra;
-
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- int i;
-
- if (do_skip_mute && (seq->flag & SEQ_MUTE)) {
- continue;
- }
-
- if (do_center) {
- seq_frames[0] = (seq->startdisp + seq->enddisp) / 2;
- seq_frames_tot = 1;
- }
- else {
- seq_frames[0] = seq->startdisp;
- seq_frames[1] = seq->enddisp;
-
- seq_frames_tot = 2;
- }
-
- for (i = 0; i < seq_frames_tot; i++) {
- const int seq_frame = seq_frames[i];
-
- dist = MAXFRAME * 2;
-
- switch (side) {
- case SEQ_SIDE_LEFT:
- if (seq_frame < cfra) {
- dist = cfra - seq_frame;
- }
- break;
- case SEQ_SIDE_RIGHT:
- if (seq_frame > cfra) {
- dist = seq_frame - cfra;
- }
- break;
- }
-
- if (dist < best_dist) {
- best_frame = seq_frame;
- best_dist = dist;
- }
- }
- }
-
- return best_frame;
-}
-
static bool strip_jump_internal(Scene *scene,
const short side,
const bool do_skip_mute, const bool do_center)
{
bool changed = false;
int cfra = CFRA;
- int nfra = find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center);
+ int nfra = BKE_sequencer_find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center, false);
if (nfra != cfra) {
CFRA = nfra;
@@ -3350,7 +3334,7 @@ void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot)
ot->invoke = WM_border_select_invoke;
ot->exec = view_ghost_border_exec;
ot->modal = WM_border_select_modal;
- ot->poll = sequencer_view_poll;
+ ot->poll = sequencer_view_preview_poll;
ot->cancel = WM_border_select_cancel;
/* flags */
@@ -3361,13 +3345,43 @@ void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot)
}
/* rebuild_proxy operator */
-static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
+
+static int sequencer_rebuild_proxy_invoke(bContext *C, wmOperator *UNUSED(op),
+ const wmEvent *UNUSED(event))
{
seq_proxy_build_job(C);
return OPERATOR_FINISHED;
}
+static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+
+ if (ed == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ SEQP_BEGIN(ed, seq)
+ {
+ if ((seq->flag & SELECT)) {
+ struct SeqIndexBuildContext *context;
+ short stop = 0, do_update;
+ float progress;
+ context = BKE_sequencer_proxy_rebuild_context(bmain, scene, seq);
+ BKE_sequencer_proxy_rebuild(context, &stop, &do_update, &progress);
+ BKE_sequencer_proxy_rebuild_finish(context, 0);
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ }
+ }
+ SEQ_END
+
+ return OPERATOR_FINISHED;
+}
+
void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
{
/* identifiers */
@@ -3376,8 +3390,8 @@ void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
ot->description = "Rebuild all selected proxies and timecode indices using the job system";
/* api callbacks */
+ ot->invoke = sequencer_rebuild_proxy_invoke;
ot->exec = sequencer_rebuild_proxy_exec;
- ot->poll = ED_operator_sequencer_active;
/* flags */
ot->flag = OPTYPE_REGISTER;
@@ -3619,8 +3633,7 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILEPATH | WM_FILESEL_FILES,
FILE_DEFAULTDISPLAY);
}
-
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 438696d0327..5f1c9317fd9 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -45,6 +45,7 @@ struct ARegion;
struct ARegionType;
struct Scene;
struct Main;
+struct SequencePreview;
/* space_sequencer.c */
struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
@@ -52,7 +53,12 @@ struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
/* sequencer_draw.c */
void draw_timeline_seq(const struct bContext *C, struct ARegion *ar);
-void draw_image_seq(const struct bContext *C, struct Scene *scene, struct ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, bool draw_overlay);
+void draw_image_seq(const struct bContext *C, struct Scene *scene, struct ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, bool draw_overlay, bool draw_backdrop);
+void color3ubv_from_seq(struct Scene *curscene, struct Sequence *seq, unsigned char col[3]);
+void draw_shadedstrip(struct Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2);
+void draw_sequence_extensions(struct Scene *scene, struct ARegion *ar, struct Sequence *seq);
+
+void sequencer_special_update_set(Sequence *seq);
/* UNUSED */
// void seq_reset_imageofs(struct SpaceSeq *sseq);
@@ -73,7 +79,8 @@ int sequencer_edit_poll(struct bContext *C);
/* UNUSED */
//int sequencer_strip_poll(struct bContext *C);
int sequencer_strip_has_path_poll(struct bContext *C);
-int sequencer_view_poll(struct bContext *C);
+int sequencer_view_preview_poll(struct bContext *C);
+int sequencer_view_strips_poll(struct bContext *C);
/* externs */
extern EnumPropertyItem sequencer_prop_effect_types[];
@@ -150,13 +157,6 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot);
void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot);
void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot);
-/* RNA enums, just to be more readable */
-enum {
- SEQ_SIDE_NONE = 0,
- SEQ_SIDE_LEFT,
- SEQ_SIDE_RIGHT,
- SEQ_SIDE_BOTH
-};
enum {
SEQ_CUT_SOFT,
SEQ_CUT_HARD
@@ -199,5 +199,8 @@ void SEQUENCER_OT_strip_modifier_move(struct wmOperatorType *ot);
/* sequencer_view.c */
void SEQUENCER_OT_sample(struct wmOperatorType *ot);
+/* sequencer_preview.c */
+void sequencer_preview_add_sound(const struct bContext *C, struct Sequence *seq);
+
#endif /* __SEQUENCER_INTERN_H__ */
diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c
index ff40bf1e638..83f3f9bc961 100644
--- a/source/blender/editors/space_sequencer/sequencer_modifier.c
+++ b/source/blender/editors/space_sequencer/sequencer_modifier.c
@@ -29,24 +29,14 @@
* \ingroup spseq
*/
-#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "DNA_scene_types.h"
-#include "DNA_mask_types.h"
-#include "DNA_userdef_types.h"
#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_library.h"
-#include "BKE_main.h"
#include "BKE_sequencer.h"
-#include "BKE_movieclip.h"
-#include "BKE_mask.h"
-#include "BKE_report.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -54,8 +44,6 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-#include "UI_interface.h"
-#include "UI_resources.h"
/* own include */
#include "sequencer_intern.h"
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index 88646b55e23..9b5ef18f7cd 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -40,6 +40,8 @@
#include "ED_markers.h"
#include "ED_transform.h" /* transform keymap */
+#include "BKE_sequencer.h"
+
#include "sequencer_intern.h"
diff --git a/source/blender/editors/space_sequencer/sequencer_preview.c b/source/blender/editors/space_sequencer/sequencer_preview.c
new file mode 100644
index 00000000000..da00b0ff6e1
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_preview.c
@@ -0,0 +1,172 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009, Antony Riakiotakis
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_sequencer/sequencer_preview.c
+ * \ingroup spseq
+ */
+
+#include "DNA_sequence_types.h"
+#include "DNA_sound_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_threads.h"
+
+#include "BKE_sound.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "sequencer_intern.h"
+
+typedef struct PreviewJob {
+ ListBase previews;
+ ThreadMutex *mutex;
+ Scene *scene;
+ int total;
+ int processed;
+} PreviewJob;
+
+typedef struct PreviewJobAudio {
+ struct PreviewJobAudio *next, *prev;
+ bSound *sound;
+ int lr; /* sample left or right */
+ int startframe;
+ bool waveform; /* reload sound or waveform */
+} PreviewJobAudio;
+
+static void free_preview_job(void *data)
+{
+ PreviewJob *pj = (PreviewJob *)data;
+
+ BLI_mutex_free(pj->mutex);
+ BLI_freelistN(&pj->previews);
+ MEM_freeN(pj);
+}
+
+/* only this runs inside thread */
+static void preview_startjob(void *data, short *stop, short *do_update, float *progress)
+{
+ PreviewJob *pj = data;
+ PreviewJobAudio *previewjb;
+
+ BLI_mutex_lock(pj->mutex);
+ previewjb = pj->previews.first;
+ BLI_mutex_unlock(pj->mutex);
+
+ while (previewjb) {
+ PreviewJobAudio *preview_next;
+ bSound *sound = previewjb->sound;
+
+ sound_read_waveform(sound, stop);
+
+ if (*stop || G.is_break) {
+ BLI_mutex_lock(pj->mutex);
+ previewjb = previewjb->next;
+ BLI_mutex_unlock(pj->mutex);
+ while (previewjb) {
+ sound = previewjb->sound;
+
+ /* make sure we cleanup the loading flag! */
+ BLI_mutex_lock(sound->mutex);
+ sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+ BLI_mutex_unlock(sound->mutex);
+
+ BLI_mutex_lock(pj->mutex);
+ previewjb = previewjb->next;
+ BLI_mutex_unlock(pj->mutex);
+ }
+
+ BLI_mutex_lock(pj->mutex);
+ BLI_freelistN(&pj->previews);
+ pj->total = 0;
+ pj->processed = 0;
+ BLI_mutex_unlock(pj->mutex);
+ break;
+ }
+
+ BLI_mutex_lock(pj->mutex);
+ preview_next = previewjb->next;
+ BLI_freelinkN(&pj->previews, previewjb);
+ previewjb = preview_next;
+ pj->processed++;
+ *progress = (pj->total > 0) ? (float)pj->processed / (float)pj->total : 1.0;
+ *do_update = true;
+ BLI_mutex_unlock(pj->mutex);
+ }
+}
+
+static void preview_endjob(void *data)
+{
+ PreviewJob *pj = data;
+
+ WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
+}
+
+
+void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
+{
+ /* first, get the preview job, if it exists */
+ wmJob *wm_job;
+ PreviewJob *pj;
+ ScrArea *sa = CTX_wm_area(C);
+ PreviewJobAudio *audiojob = MEM_callocN(sizeof(PreviewJobAudio), "preview_audio");
+ wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Strip Previews",
+ WM_JOB_PROGRESS, WM_JOB_TYPE_SEQ_BUILD_PREVIEW);
+
+ pj = WM_jobs_customdata_get(wm_job);
+
+ if (!pj) {
+ pj = MEM_callocN(sizeof(PreviewJob), "preview rebuild job");
+
+ pj->mutex = BLI_mutex_alloc();
+ pj->scene = CTX_data_scene(C);
+
+ WM_jobs_customdata_set(wm_job, pj, free_preview_job);
+ WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
+ WM_jobs_callbacks(wm_job, preview_startjob, NULL, NULL, preview_endjob);
+ }
+
+ /* attempt to lock mutex of job here */
+
+ audiojob->sound = seq->sound;
+
+ BLI_mutex_lock(pj->mutex);
+ BLI_addtail(&pj->previews, audiojob);
+ pj->total++;
+ BLI_mutex_unlock(pj->mutex);
+
+ if (!WM_jobs_is_running(wm_job)) {
+ G.is_break = false;
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ }
+
+ ED_area_tag_redraw(sa);
+}
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
index 9b3b9f23036..24b3776da6d 100644
--- a/source/blender/editors/space_sequencer/sequencer_scopes.c
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -55,7 +55,7 @@ static void rgb_to_yuv_normalized(const float rgb[3], float yuv[3])
static void scope_put_pixel(unsigned char *table, unsigned char *pos)
{
- char newval = table[*pos];
+ unsigned char newval = table[*pos];
pos[0] = pos[1] = pos[2] = newval;
pos[3] = 255;
}
@@ -148,8 +148,8 @@ static ImBuf *make_waveform_view_from_ibuf_byte(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
int x, y;
- unsigned char *src = (unsigned char *) ibuf->rect;
- unsigned char *tgt = (unsigned char *) rval->rect;
+ const unsigned char *src = (unsigned char *)ibuf->rect;
+ unsigned char *tgt = (unsigned char *)rval->rect;
int w = ibuf->x + 3;
int h = 515;
float waveform_gamma = 0.2;
@@ -166,7 +166,7 @@ static ImBuf *make_waveform_view_from_ibuf_byte(ImBuf *ibuf)
unsigned char *last_p = NULL;
for (x = 0; x < ibuf->x; x++) {
- unsigned char *rgb = src + 4 * (ibuf->x * y + x);
+ const unsigned char *rgb = src + 4 * (ibuf->x * y + x);
float v = (float)rgb_to_luma_byte(rgb) / 255.0f;
unsigned char *p = tgt;
p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1);
@@ -189,7 +189,7 @@ static ImBuf *make_waveform_view_from_ibuf_float(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
int x, y;
- float *src = ibuf->rect_float;
+ const float *src = ibuf->rect_float;
unsigned char *tgt = (unsigned char *) rval->rect;
int w = ibuf->x + 3;
int h = 515;
@@ -245,8 +245,8 @@ static ImBuf *make_sep_waveform_view_from_ibuf_byte(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
int x, y;
- unsigned char *src = (unsigned char *) ibuf->rect;
- unsigned char *tgt = (unsigned char *) rval->rect;
+ const unsigned char *src = (const unsigned char *)ibuf->rect;
+ unsigned char *tgt = (unsigned char *)rval->rect;
int w = ibuf->x + 3;
int sw = ibuf->x / 3;
int h = 515;
@@ -264,7 +264,7 @@ static ImBuf *make_sep_waveform_view_from_ibuf_byte(ImBuf *ibuf)
for (x = 0; x < ibuf->x; x++) {
int c;
- unsigned char *rgb = src + 4 * (ibuf->x * y + x);
+ const unsigned char *rgb = src + 4 * (ibuf->x * y + x);
for (c = 0; c < 3; c++) {
unsigned char *p = tgt;
p += 4 * (w * ((rgb[c] * (h - 3)) / 255 + 1) + c * sw + x / 3 + 1);
@@ -290,8 +290,8 @@ static ImBuf *make_sep_waveform_view_from_ibuf_float(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
int x, y;
- float *src = ibuf->rect_float;
- unsigned char *tgt = (unsigned char *) rval->rect;
+ const float *src = ibuf->rect_float;
+ unsigned char *tgt = (unsigned char *)rval->rect;
int w = ibuf->x + 3;
int sw = ibuf->x / 3;
int h = 515;
@@ -455,7 +455,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
int x, y;
unsigned int nr, ng, nb;
- unsigned char *src = (unsigned char *) ibuf->rect;
+ const unsigned char *src = (unsigned char *)ibuf->rect;
unsigned int bins[3][HIS_STEPS];
@@ -468,7 +468,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
memset(cur_bins, 0, sizeof(cur_bins));
for (x = 0; x < ibuf->x; x++) {
- unsigned char *pixel = src + (y * ibuf->x + x) * 4;
+ const unsigned char *pixel = src + (y * ibuf->x + x) * 4;
cur_bins[0][pixel[0]]++;
cur_bins[1][pixel[1]]++;
@@ -532,7 +532,7 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
int nr, ng, nb, x, y;
- float *src = ibuf->rect_float;
+ const float *src = ibuf->rect_float;
unsigned int bins[3][HIS_STEPS];
@@ -635,7 +635,7 @@ static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect);
int x, y;
- char *src = (char *) ibuf->rect;
+ const char *src = (const char *) ibuf->rect;
char *tgt = (char *) rval->rect;
float rgb[3], yuv[3];
int w = 515;
@@ -659,7 +659,7 @@ static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf)
for (y = 0; y < ibuf->y; y++) {
for (x = 0; x < ibuf->x; x++) {
const char *src1 = src + 4 * (ibuf->x * y + x);
- const char *p;
+ char *p;
rgb[0] = (float)src1[0] / 255.0f;
rgb[1] = (float)src1[1] / 255.0f;
@@ -681,7 +681,7 @@ static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect);
int x, y;
- float *src = ibuf->rect_float;
+ const float *src = ibuf->rect_float;
char *tgt = (char *) rval->rect;
float rgb[3], yuv[3];
int w = 515;
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 933daf4adee..6792bbe0577 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -357,25 +357,22 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
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;
+ x = CFRA;
break;
}
SEQP_BEGIN (ed, seq)
{
if (x < CFRA) {
- if (seq->enddisp < CFRA) {
+ if (seq->enddisp <= CFRA) {
seq->flag |= SELECT;
recurs_sel_seq(seq);
}
}
else {
- if (seq->startdisp > CFRA) {
+ if (seq->startdisp >= CFRA) {
seq->flag |= SELECT;
recurs_sel_seq(seq);
}
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index c0cfaed7867..6231f02907a 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -328,7 +328,7 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl)
SpaceSeq *sseqn = MEM_dupallocN(sl);
/* clear or remove stuff from old */
-// XXX sseq->gpd = gpencil_data_duplicate(sseq->gpd);
+// XXX sseq->gpd = gpencil_data_duplicate(sseq->gpd, false);
memset(&sseqn->scopes, 0, sizeof(sseqn->scopes));
@@ -352,6 +352,10 @@ static void sequencer_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn
if (wmn->data == ND_SPACE_SEQUENCER)
sequencer_scopes_tag_refresh(sa);
break;
+ case NC_GPENCIL:
+ if (wmn->data & ND_GPENCIL_EDITMODE)
+ ED_area_tag_redraw(sa);
+ break;
}
}
@@ -559,7 +563,7 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
if (sseq->mainb == SEQ_DRAW_SEQUENCE) sseq->mainb = SEQ_DRAW_IMG_IMBUF;
if (!show_split || sseq->overlay_type != SEQ_DRAW_OVERLAY_REFERENCE)
- draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false);
+ draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false, false);
if (show_split && sseq->overlay_type != SEQ_DRAW_OVERLAY_CURRENT) {
int over_cfra;
@@ -570,7 +574,7 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
over_cfra = scene->r.cfra + scene->ed->over_ofs;
if (over_cfra != scene->r.cfra || sseq->overlay_type != SEQ_DRAW_OVERLAY_RECT)
- draw_image_seq(C, scene, ar, sseq, scene->r.cfra, over_cfra - scene->r.cfra, true);
+ draw_image_seq(C, scene, ar, sseq, scene->r.cfra, over_cfra - scene->r.cfra, true, false);
}
if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_playing(wm)) {
@@ -585,7 +589,7 @@ static void sequencer_preview_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED
/* context changes */
switch (wmn->category) {
case NC_GPENCIL:
- if (wmn->action == NA_EDITED) {
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
ED_region_tag_redraw(ar);
}
break;
@@ -641,7 +645,7 @@ static void sequencer_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED
/* context changes */
switch (wmn->category) {
case NC_GPENCIL:
- if (wmn->data == ND_DATA) {
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
ED_region_tag_redraw(ar);
}
break;
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index c8ca4e1a7da..31662c02966 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -44,6 +44,8 @@
#include "BKE_text.h"
#include "BKE_screen.h"
+#include "ED_text.h"
+
#include "BIF_gl.h"
#include "UI_interface.h"
@@ -380,7 +382,9 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
int a, fstart, fpos; /* utf8 chars */
int mi, ma, mstart, mend; /* mem */
char fmt_prev = 0xff;
-
+ /* don't draw lines below this */
+ const int clip_min_y = -(int)(st->lheight_dpi - 1);
+
flatten_string(st, &fs, str);
str = fs.buf;
max = w / st->cwidth;
@@ -423,7 +427,8 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
end = (wrap += max - padding);
- if (y <= 0) break;
+ if (y <= clip_min_y)
+ break;
}
else if (str[mi] == ' ' || str[mi] == '-') {
wrap = i + 1; mend = mi + 1;
@@ -431,7 +436,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
}
/* Draw the remaining text */
- for (a = fstart, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
+ for (a = fstart, ma = mstart; str[ma] && y > clip_min_y; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
if (use_syntax) {
if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
}
@@ -1322,6 +1327,8 @@ void draw_text_main(SpaceText *st, ARegion *ar)
int i, x, y, winx, linecount = 0, lineno = 0;
int wraplinecount = 0, wrap_skip = 0;
int margin_column_x;
+ /* don't draw lines below this */
+ const int clip_min_y = -(int)(st->lheight_dpi - 1);
/* if no text, nothing to do */
if (!text)
@@ -1329,7 +1336,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
/* dpi controlled line height and font size */
st->lheight_dpi = (U.widget_unit * st->lheight) / 20;
- st->viewlines = (st->lheight_dpi) ? (int)ar->winy / (st->lheight_dpi + TXT_LINE_SPACING) : 0;
+ st->viewlines = (st->lheight_dpi) ? (int)(ar->winy - clip_min_y) / (st->lheight_dpi + TXT_LINE_SPACING) : 0;
text_update_drawcache(st, ar);
@@ -1393,7 +1400,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
/* draw the text */
UI_ThemeColor(TH_TEXT);
- for (i = 0; y > 0 && i < st->viewlines && tmp; i++, tmp = tmp->next) {
+ for (i = 0; y > clip_min_y && i < st->viewlines && tmp; i++, tmp = tmp->next) {
if (st->showsyntax && !tmp->format)
tft->format_line(st, tmp, false);
@@ -1542,3 +1549,37 @@ void text_update_cursor_moved(bContext *C)
text_scroll_to_cursor__area(st, sa, true);
}
+
+/**
+ * Takes a cursor (row, character) and returns x,y pixel coords.
+ */
+bool ED_text_region_location_from_cursor(SpaceText *st, ARegion *ar, const int cursor_co[2], int r_pixel_co[2])
+{
+ TextLine *line = NULL;
+
+ if (!st->text) {
+ goto error;
+ }
+
+ line = BLI_findlink(&st->text->lines, cursor_co[0]);
+ if (!line || (cursor_co[1] < 0) || (cursor_co[1] > line->len)) {
+ goto error;
+ }
+ else {
+ int offl, offc;
+ int linenr_offset = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ /* handle tabs as well! */
+ int char_pos = text_get_char_pos(st, line->line, cursor_co[1]);
+
+ wrap_offset(st, ar, line, cursor_co[1], &offl, &offc);
+ r_pixel_co[0] = (char_pos + offc - st->left) * st->cwidth + linenr_offset;
+ r_pixel_co[1] = (cursor_co[0] + offl - st->top) * (st->lheight_dpi + TXT_LINE_SPACING);
+ r_pixel_co[1] = (ar->winy - (r_pixel_co[1] + TXT_OFFSET)) - st->lheight_dpi;
+ }
+ return true;
+
+
+error:
+ r_pixel_co[0] = r_pixel_co[1] = -1;
+ return false;
+}
diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c
index 02bac251065..92a3cce12e6 100644
--- a/source/blender/editors/space_text/text_header.c
+++ b/source/blender/editors/space_text/text_header.c
@@ -34,7 +34,6 @@
#include "BLI_blenlib.h"
-#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_screen.h"
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
index 5483cf04db7..f577714c480 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -50,8 +50,8 @@ void draw_text_main(struct SpaceText *st, struct ARegion *ar);
void text_update_line_edited(struct TextLine *line);
void text_update_edited(struct Text *text);
void text_update_character_width(struct SpaceText *st);
-void text_scroll_to_cursor(struct SpaceText *st, struct ARegion *ar, bool center);
-void text_scroll_to_cursor__area(struct SpaceText *st, struct ScrArea *sa, bool center);
+void text_scroll_to_cursor(struct SpaceText *st, struct ARegion *ar, const bool center);
+void text_scroll_to_cursor__area(struct SpaceText *st, struct ScrArea *sa, const bool center);
void text_update_cursor_moved(struct bContext *C);
#define TXT_OFFSET ((int)(0.5f * U.widget_unit))
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index ffabefdfb29..1cf0316aa06 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -300,7 +300,7 @@ void TEXT_OT_open(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE | PYSCRIPTFILE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); //XXX TODO, relative_path
RNA_def_boolean(ot->srna, "internal", 0, "Make internal", "Make text file internal after loading");
}
@@ -577,7 +577,7 @@ void TEXT_OT_save_as(wmOperatorType *ot)
ot->poll = text_edit_poll;
/* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE | PYSCRIPTFILE, FILE_SPECIAL, FILE_SAVE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT, FILE_SPECIAL, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); //XXX TODO, relative_path
}
@@ -714,88 +714,6 @@ void TEXT_OT_refresh_pyconstraints(wmOperatorType *ot)
/******************* paste operator *********************/
-static char *txt_copy_selected(Text *text)
-{
- TextLine *tmp, *linef, *linel;
- char *buf = NULL;
- int charf, charl, length = 0;
-
- if (!text) return NULL;
- if (!text->curl) return NULL;
- if (!text->sell) return NULL;
-
- if (!txt_has_sel(text)) return NULL;
-
- if (text->curl == text->sell) {
- linef = linel = text->curl;
-
- if (text->curc < text->selc) {
- charf = text->curc;
- charl = text->selc;
- }
- else {
- charf = text->selc;
- charl = text->curc;
- }
- }
- else if (txt_get_span(text->curl, text->sell) < 0) {
- linef = text->sell;
- linel = text->curl;
-
- charf = text->selc;
- charl = text->curc;
- }
- else {
- linef = text->curl;
- linel = text->sell;
-
- charf = text->curc;
- charl = text->selc;
- }
-
- if (linef == linel) {
- length = charl - charf;
-
- buf = MEM_callocN(length + 1, "cut buffera");
-
- BLI_strncpy(buf, linef->line + charf, length + 1);
- }
- else {
- length += linef->len - charf;
- length += charl;
- length++; /* For the '\n' */
-
- tmp = linef->next;
- while (tmp && tmp != linel) {
- length += tmp->len + 1;
- tmp = tmp->next;
- }
-
- buf = MEM_callocN(length + 1, "cut bufferb");
-
- strncpy(buf, linef->line + charf, linef->len - charf);
- length = linef->len - charf;
-
- buf[length++] = '\n';
-
- tmp = linef->next;
- while (tmp && tmp != linel) {
- strncpy(buf + length, tmp->line, tmp->len);
- length += tmp->len;
-
- buf[length++] = '\n';
-
- tmp = tmp->next;
- }
- strncpy(buf + length, linel->line, charl);
- length += charl;
-
- buf[length] = 0;
- }
-
- return buf;
-}
-
static int text_paste_exec(bContext *C, wmOperator *op)
{
const bool selection = RNA_boolean_get(op->ptr, "selection");
@@ -876,7 +794,10 @@ static void txt_copy_clipboard(Text *text)
{
char *buf;
- buf = txt_copy_selected(text);
+ if (!txt_has_sel(text))
+ return;
+
+ buf = txt_sel_to_buf(text);
if (buf) {
WM_clipboard_text_set(buf, 0);
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 09b4123a977..820d1d68f8d 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -32,6 +32,7 @@
#include <string.h>
#include <stdio.h>
+#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -307,6 +308,9 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
case ID_OB:
ob_to_keylist(&ads, (Object *)id, &keys, NULL);
break;
+ case ID_GD:
+ gpencil_to_keylist(&ads, (bGPdata *)id, &keys);
+ break;
}
/* build linked-list for searching */
@@ -336,16 +340,23 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
View2D *v2d = &ar->v2d;
bool onlysel = ((scene->flag & SCE_KEYS_NO_SELONLY) == 0);
+ /* draw grease pencil keyframes (if available) */
+ if (gpd) {
+ UI_ThemeColor(TH_TIME_GP_KEYFRAME);
+ time_draw_idblock_keyframes(v2d, (ID *)gpd, onlysel);
+ }
+
/* draw scene keyframes first
* - don't try to do this when only drawing active/selected data keyframes,
* since this can become quite slow
*/
if (onlysel == 0) {
/* set draw color */
- glColor3ub(0xDD, 0xA7, 0x00);
+ UI_ThemeColorShade(TH_TIME_KEYFRAME, -50);
time_draw_idblock_keyframes(v2d, (ID *)scene, onlysel);
}
@@ -354,7 +365,7 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
* OR the onlysel flag was set, which means that only active object's keyframes should
* be considered
*/
- glColor3ub(0xDD, 0xD7, 0x00);
+ UI_ThemeColor(TH_TIME_KEYFRAME);
if (ob && ((ob->mode == OB_MODE_POSE) || onlysel)) {
/* draw keyframes for active object only */
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index 0bd094b6a33..f986e909c7f 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -47,9 +47,7 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "UI_view2d.h"
-#include "userpref_intern.h" // own include
/* ******************** default callbacks for userpref space ***************** */
diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c
index 8dd6c3c0271..0783eacc65c 100644
--- a/source/blender/editors/space_userpref/userpref_ops.c
+++ b/source/blender/editors/space_userpref/userpref_ops.c
@@ -32,5 +32,4 @@
#include <string.h>
#include <stdio.h>
-#include "userpref_intern.h"
diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c
index 17f90fc54e3..d8b18140cde 100644
--- a/source/blender/editors/space_view3d/drawanimviz.c
+++ b/source/blender/editors/space_view3d/drawanimviz.c
@@ -54,7 +54,6 @@
#include "ED_armature.h"
#include "ED_keyframes_draw.h"
-#include "BLF_api.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index f25e4f143e6..691da78f26b 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -61,7 +61,6 @@
#include "ED_armature.h"
#include "ED_keyframes_draw.h"
-#include "BLF_api.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index fa9ba23e454..755c633531d 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -60,7 +60,6 @@
#include "UI_resources.h"
-#include "GPU_buffers.h"
#include "GPU_extensions.h"
#include "GPU_draw.h"
#include "GPU_material.h"
@@ -97,7 +96,7 @@ typedef struct drawTFace_userData {
BLI_INLINE int edge_vis_index(const int index) { return index * 2; }
BLI_INLINE int edge_sel_index(const int index) { return index * 2 + 1; }
-static BLI_bitmap *get_tface_mesh_marked_edge_info(Mesh *me)
+static BLI_bitmap *get_tface_mesh_marked_edge_info(Mesh *me, bool draw_select_edges)
{
BLI_bitmap *bitmap_edge_flags = BLI_BITMAP_NEW(me->totedge * 2, __func__);
MPoly *mp;
@@ -113,8 +112,17 @@ static BLI_bitmap *get_tface_mesh_marked_edge_info(Mesh *me)
ml = me->mloop + mp->loopstart;
for (j = 0; j < mp->totloop; j++, ml++) {
- BLI_BITMAP_ENABLE(bitmap_edge_flags, edge_vis_index(ml->e));
- if (select_set) BLI_BITMAP_ENABLE(bitmap_edge_flags, edge_sel_index(ml->e));
+ if ((draw_select_edges == false) &&
+ (select_set && BLI_BITMAP_TEST(bitmap_edge_flags, edge_sel_index(ml->e))))
+ {
+ BLI_BITMAP_DISABLE(bitmap_edge_flags, edge_vis_index(ml->e));
+ }
+ else {
+ BLI_BITMAP_ENABLE(bitmap_edge_flags, edge_vis_index(ml->e));
+ if (select_set) {
+ BLI_BITMAP_ENABLE(bitmap_edge_flags, edge_sel_index(ml->e));
+ }
+ }
}
}
}
@@ -129,21 +137,26 @@ static DMDrawOption draw_mesh_face_select__setHiddenOpts(void *userData, int ind
Mesh *me = data->me;
if (me->drawflag & ME_DRAWEDGES) {
- if ((me->drawflag & ME_HIDDENEDGES) || (BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index))))
+ if ((BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index))))
return DM_DRAW_OPTION_NORMAL;
else
return DM_DRAW_OPTION_SKIP;
}
- else if (BLI_BITMAP_TEST(data->edge_flags, edge_sel_index(index)))
+ else if (BLI_BITMAP_TEST(data->edge_flags, edge_sel_index(index)) &&
+ BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index)))
+ {
return DM_DRAW_OPTION_NORMAL;
- else
+ }
+ else {
return DM_DRAW_OPTION_SKIP;
+ }
}
static DMDrawOption draw_mesh_face_select__setSelectOpts(void *userData, int index)
{
drawMeshFaceSelect_userData *data = userData;
- return (BLI_BITMAP_TEST(data->edge_flags, edge_sel_index(index))) ? DM_DRAW_OPTION_NORMAL : DM_DRAW_OPTION_SKIP;
+ return (BLI_BITMAP_TEST(data->edge_flags, edge_sel_index(index)) &&
+ BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index))) ? DM_DRAW_OPTION_NORMAL : DM_DRAW_OPTION_SKIP;
}
/* draws unselected */
@@ -158,12 +171,12 @@ static DMDrawOption draw_mesh_face_select__drawFaceOptsInv(void *userData, int i
return DM_DRAW_OPTION_SKIP;
}
-void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm)
+void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm, bool draw_select_edges)
{
drawMeshFaceSelect_userData data;
data.me = me;
- data.edge_flags = get_tface_mesh_marked_edge_info(me);
+ data.edge_flags = get_tface_mesh_marked_edge_info(me, draw_select_edges);
glEnable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
@@ -562,14 +575,6 @@ static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, const bool has_mc
}
}
-static DMDrawOption draw_mcol__set_draw_legacy(MTFace *UNUSED(tface), const bool has_mcol, int UNUSED(matnr))
-{
- if (has_mcol)
- return DM_DRAW_OPTION_NORMAL;
- else
- return DM_DRAW_OPTION_NO_MCOL;
-}
-
static DMDrawOption draw_tface__set_draw(MTFace *tface, const bool UNUSED(has_mcol), int matnr)
{
Material *ma = give_current_material(Gtexdraw.ob, matnr + 1);
@@ -668,48 +673,48 @@ static void update_tface_color_layer(DerivedMesh *dm)
}
}
-static DMDrawOption draw_tface_mapped__set_draw(void *userData, int index)
+static DMDrawOption draw_tface_mapped__set_draw(void *userData, int origindex, int UNUSED(mat_nr))
{
Mesh *me = ((drawTFace_userData *)userData)->me;
/* array checked for NULL before calling */
- MPoly *mpoly = &me->mpoly[index];
+ MPoly *mpoly = &me->mpoly[origindex];
- BLI_assert(index >= 0 && index < me->totpoly);
+ BLI_assert(origindex >= 0 && origindex < me->totpoly);
if (mpoly->flag & ME_HIDE) {
return DM_DRAW_OPTION_SKIP;
}
else {
- MTexPoly *tpoly = (me->mtpoly) ? &me->mtpoly[index] : NULL;
+ MTexPoly *tpoly = (me->mtpoly) ? &me->mtpoly[origindex] : NULL;
MTFace mtf = {{{0}}};
int matnr = mpoly->mat_nr;
if (tpoly) {
ME_MTEXFACE_CPY(&mtf, tpoly);
}
-
+
return draw_tface__set_draw(&mtf, (me->mloopcol != NULL), matnr);
}
}
-static DMDrawOption draw_em_tf_mapped__set_draw(void *userData, int index)
+static DMDrawOption draw_em_tf_mapped__set_draw(void *userData, int origindex, int mat_nr)
{
drawEMTFMapped_userData *data = userData;
BMEditMesh *em = data->em;
BMFace *efa;
- if (UNLIKELY(index >= em->bm->totface))
+ if (UNLIKELY(origindex >= em->bm->totface))
return DM_DRAW_OPTION_NORMAL;
- efa = BM_face_at_index(em->bm, index);
+ efa = BM_face_at_index(em->bm, origindex);
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
return DM_DRAW_OPTION_SKIP;
}
else {
MTFace mtf = {{{0}}};
- int matnr = efa->mat_nr;
+ int matnr = (mat_nr != -1) ? mat_nr : efa->mat_nr;
if (data->has_mtface) {
MTexPoly *tpoly = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
@@ -929,24 +934,16 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
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, uvflag);
- else
- dm->drawFacesTex(dm, draw_tface__set_draw_legacy, NULL, NULL, uvflag);
- }
- else {
- drawTFace_userData userData;
-
- update_tface_color_layer(dm);
-
- userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
- userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
- userData.me = NULL;
-
- dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData, uvflag);
- }
+ else {
+ drawTFace_userData userData;
+
+ update_tface_color_layer(dm);
+
+ userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
+ userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ userData.me = NULL;
+
+ dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData, uvflag);
}
/* draw game engine text hack */
@@ -956,8 +953,10 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
draw_textured_end();
/* draw edges and selected faces over textured mesh */
- if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT))
- draw_mesh_face_select(rv3d, me, dm);
+ if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT)) {
+ bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0;
+ draw_mesh_face_select(rv3d, me, dm, draw_select_edges);
+ }
/* reset from negative scale correction */
glFrontFace(GL_CCW);
@@ -1153,8 +1152,10 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
glMatrixMode(GL_MODELVIEW);
/* faceselect mode drawing over textured mesh */
- if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT))
- draw_mesh_face_select(rv3d, ob->data, dm);
+ if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT)) {
+ bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0;
+ draw_mesh_face_select(rv3d, ob->data, dm, draw_select_edges);
+ }
}
/* Vertex Paint and Weight Paint */
@@ -1189,7 +1190,7 @@ void draw_mesh_paint_weight_faces(DerivedMesh *dm, const bool use_light,
}
dm->drawMappedFaces(dm, (DMSetDrawOptions)facemask_cb, GPU_enable_material, NULL, user_data,
- DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH);
+ DM_DRAW_USE_COLORS);
if (use_light) {
draw_mesh_paint_light_end();
@@ -1206,12 +1207,11 @@ void draw_mesh_paint_vcolor_faces(DerivedMesh *dm, const bool use_light,
if (me->mloopcol) {
dm->drawMappedFaces(dm, facemask_cb, GPU_enable_material, NULL, user_data,
- DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH);
+ DM_DRAW_USE_COLORS);
}
else {
glColor3f(1.0f, 1.0f, 1.0f);
- dm->drawMappedFaces(dm, facemask_cb, GPU_enable_material, NULL, user_data,
- DM_DRAW_ALWAYS_SMOOTH);
+ dm->drawMappedFaces(dm, facemask_cb, GPU_enable_material, NULL, user_data, 0);
}
if (use_light) {
@@ -1279,7 +1279,8 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
/* draw face selection on top */
if (draw_flags & DRAW_FACE_SELECT) {
- draw_mesh_face_select(rv3d, me, dm);
+ bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0;
+ draw_mesh_face_select(rv3d, me, dm, draw_select_edges);
}
else if ((use_light == false) || (ob->dtx & OB_DRAWWIRE)) {
const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) || !(ob->mode & OB_MODE_WEIGHT_PAINT);
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 28f806a9b7b..1cbc8e5567c 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -2953,21 +2953,23 @@ static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
if (!sel_only) wireCol[3] = 255;
}
- if (ts->selectmode == SCE_SELECT_FACE) {
- draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
- }
- else if ((me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE)) {
+ if ((me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE)) {
if (cageDM->drawMappedEdgesInterp &&
((ts->selectmode & SCE_SELECT_VERTEX) || (me->drawflag & ME_DRAWEIGHT)))
{
- glShadeModel(GL_SMOOTH);
if (draw_dm_edges_weight_check(me, v3d)) {
+ glShadeModel(GL_SMOOTH);
draw_dm_edges_weight_interp(em, cageDM, ts->weightuser);
+ glShadeModel(GL_FLAT);
+ }
+ else if (ts->selectmode == SCE_SELECT_FACE) {
+ draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
}
else {
+ glShadeModel(GL_SMOOTH);
draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
+ glShadeModel(GL_FLAT);
}
- glShadeModel(GL_FLAT);
}
else {
draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
@@ -3375,7 +3377,6 @@ static DMDrawOption draw_em_fancy__setFaceOpts(void *userData, int index)
efa = BM_face_at_index(em->bm, index);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- GPU_enable_material(efa->mat_nr + 1, NULL);
return DM_DRAW_OPTION_NORMAL;
}
else {
@@ -3773,7 +3774,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
glFrontFace(GL_CCW);
if (draw_flags & DRAW_FACE_SELECT)
- draw_mesh_face_select(rv3d, me, dm);
+ draw_mesh_face_select(rv3d, me, dm, false);
}
else {
draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
@@ -6859,15 +6860,18 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
glDepthMask(0);
if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
- DerivedMesh *dm = ob->derivedFinal;
+ DerivedMesh *dm;
bool has_faces = false;
- if (dm)
- DM_update_materials(dm, ob);
#ifdef SEQUENCER_DAG_WORKAROUND
ensure_curve_cache(scene, ob);
#endif
+ dm = ob->derivedFinal;
+ if (dm) {
+ DM_update_materials(dm, ob);
+ }
+
if (dm) {
has_faces = dm->getNumTessFaces(dm) > 0;
}
@@ -7975,7 +7979,7 @@ static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d,
cpack(0);
if (use_faceselect) {
- dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, GPU_enable_material, NULL, em->bm, 0);
+ dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, NULL, NULL, em->bm, 0);
if (check_ob_drawface_dot(scene, v3d, ob->dt)) {
glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
@@ -7987,7 +7991,7 @@ static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d,
}
else {
- dm->drawMappedFaces(dm, bbs_mesh_mask__setSolidDrawOptions, GPU_enable_material, NULL, em->bm, 0);
+ dm->drawMappedFaces(dm, bbs_mesh_mask__setSolidDrawOptions, NULL, NULL, em->bm, 0);
}
}
@@ -8048,9 +8052,9 @@ static void bbs_mesh_solid_faces(Scene *scene, Object *ob)
DM_update_materials(dm, ob);
if ((me->editflag & ME_EDIT_PAINT_FACE_SEL))
- dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, GPU_enable_material, NULL, me, 0);
+ dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, NULL, NULL, me, 0);
else
- dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, GPU_enable_material, NULL, me, 0);
+ dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, NULL, NULL, me, 0);
dm->release(dm);
}
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 59798f97d93..a220e1e39b0 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -27,8 +27,6 @@
* \ingroup spview3d
*/
-
-
#include <string.h>
#include <math.h>
@@ -38,7 +36,6 @@
#include "DNA_screen_types.h"
#include "DNA_smoke_types.h"
#include "DNA_view3d_types.h"
-#include "DNA_property_types.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -53,8 +50,6 @@
#include "ED_mesh.h"
-#include "BLF_api.h"
-
#include "view3d_intern.h" // own include
struct GPUTexture;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index b3accb431ee..55d5273b198 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -414,7 +414,7 @@ static void view3d_free(SpaceLink *sl)
/* matcap material, its preview rect gets freed via icons */
if (vd->defmaterial) {
if (vd->defmaterial->gpumaterial.first)
- GPU_material_free(vd->defmaterial);
+ GPU_material_free(&vd->defmaterial->gpumaterial);
BKE_previewimg_free(&vd->defmaterial->preview);
MEM_freeN(vd->defmaterial);
}
@@ -599,7 +599,7 @@ static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
return 1;
}
else if (drag->type == WM_DRAG_PATH) {
- if (ELEM(drag->icon, 0, ICON_FILE_IMAGE)) /* rule might not work? */
+ if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)) /* rule might not work? */
return 1;
}
return 0;
@@ -665,10 +665,14 @@ static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = (ID *)drag->poin;
- if (id)
+ if (id) {
RNA_string_set(drop->ptr, "name", id->name + 2);
- if (drag->path[0])
+ RNA_struct_property_unset(drop->ptr, "filepath");
+ }
+ else if (drag->path[0]) {
RNA_string_set(drop->ptr, "filepath", drag->path);
+ RNA_struct_property_unset(drop->ptr, "image");
+ }
}
@@ -950,8 +954,9 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
break;
case NC_GPENCIL:
- if (wmn->action == NA_EDITED)
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
ED_region_tag_redraw(ar);
+ }
break;
}
}
@@ -1007,6 +1012,10 @@ static void view3d_header_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
if (wmn->data == ND_SPACE_VIEW3D)
ED_region_tag_redraw(ar);
break;
+ case NC_GPENCIL:
+ if (wmn->data & ND_GPENCIL_EDITMODE)
+ ED_region_tag_redraw(ar);
+ break;
}
}
@@ -1104,7 +1113,7 @@ static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
ED_region_tag_redraw(ar);
break;
case NC_GPENCIL:
- if (wmn->data == ND_DATA || wmn->action == NA_EDITED)
+ if ((wmn->data & (ND_DATA | ND_GPENCIL_EDITMODE)) || (wmn->action == NA_EDITED))
ED_region_tag_redraw(ar);
break;
case NC_IMAGE:
@@ -1168,7 +1177,8 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot
case NC_WORLD:
switch (wmn->data) {
case ND_WORLD_DRAW:
- if (v3d->flag2 & V3D_RENDER_OVERRIDE)
+ case ND_WORLD:
+ if (v3d->flag3 & V3D_SHOW_WORLD)
ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
break;
}
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 899be6359ee..88f43ab340f 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -60,6 +60,7 @@
#include "BKE_editmesh.h"
#include "BKE_deform.h"
#include "BKE_object.h"
+#include "BKE_object_deform.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -68,7 +69,6 @@
#include "ED_armature.h"
#include "ED_gpencil.h"
-#include "ED_object.h"
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -844,9 +844,9 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
col = uiLayoutColumn(bcol, true);
- vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
for (i = 0, dg = ob->defbase.first; dg; i++, dg = dg->next) {
- bool locked = dg->flag & DG_LOCK_WEIGHT;
+ bool locked = (dg->flag & DG_LOCK_WEIGHT) != 0;
if (vgroup_validmap[i]) {
MDeformWeight *dw = defvert_find_index(dv, i);
if (dw) {
@@ -1185,14 +1185,6 @@ void view3d_buttons_register(ARegionType *art)
pt->poll = view3d_panel_transform_poll;
BLI_addtail(&art->paneltypes, pt);
- pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel gpencil");
- strcpy(pt->idname, "VIEW3D_PT_gpencil");
- strcpy(pt->label, N_("Grease Pencil")); /* XXX C panels are not available through RNA (bpy.types)! */
- strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw_header = ED_gpencil_panel_standard_header;
- pt->draw = ED_gpencil_panel_standard;
- BLI_addtail(&art->paneltypes, pt);
-
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel vgroup");
strcpy(pt->idname, "VIEW3D_PT_vgroup");
strcpy(pt->label, N_("Vertex Weights")); /* XXX C panels are not available through RNA (bpy.types)! */
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index ee0f3da18b4..95e918abdcf 100644
--- a/source/blender/editors/space_view3d/view3d_camera_control.c
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -51,14 +51,12 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BKE_object.h"
#include "BKE_depsgraph.h" /* for object updating */
-#include "ED_keyframing.h"
#include "ED_screen.h"
#include "view3d_intern.h" /* own include */
@@ -266,6 +264,8 @@ void ED_view3d_cameracontrol_update(
BKE_object_apply_mat4(v3d->camera, view_mat, true, true);
+ DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
+
copy_v3_v3(v3d->camera->size, size_back);
id_key = &v3d->camera->id;
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index e921a436c85..65721d52dff 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -787,7 +787,16 @@ static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
Camera *cam;
cam = v3d->camera->data;
- name = (cam->type != CAM_ORTHO) ? IFACE_("Camera Persp") : IFACE_("Camera Ortho");
+ if (cam->type == CAM_PERSP) {
+ name = IFACE_("Camera Persp");
+ }
+ else if (cam->type == CAM_ORTHO) {
+ name = IFACE_("Camera Ortho");
+ }
+ else {
+ BLI_assert(cam->type == CAM_PANO);
+ name = IFACE_("Camera Pano");
+ }
}
else {
name = IFACE_("Object as Camera");
@@ -1362,7 +1371,7 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
else
glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
- glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClearColor(0.0, 0.0, 0.0, 0.0);
if (v3d->zbuf) {
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -2646,10 +2655,7 @@ static void view3d_draw_objects(
if (!draw_offscreen) {
/* needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. */
- rv3d->gridview = v3d->grid;
- if (scene->unit.system) {
- rv3d->gridview /= scene->unit.scale_length;
- }
+ rv3d->gridview = ED_view3d_grid_scale(scene, v3d, grid_unit);
if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
@@ -2659,6 +2665,7 @@ static void view3d_draw_objects(
else {
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
ED_region_pixelspace(ar);
+ *grid_unit = NULL; /* drawgrid need this to detect/affect smallest valid unit... */
drawgrid(&scene->unit, ar, v3d, grid_unit);
/* XXX make function? replaces persp(1) */
glMatrixMode(GL_PROJECTION);
@@ -2801,6 +2808,203 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d)
gpu_update_lamps_shadows(scene, v3d);
}
+/*
+ * Function to clear the view
+ */
+static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar, bool force)
+{
+ /* clear background */
+ if (scene->world && ((v3d->flag3 & V3D_SHOW_WORLD) || force)) {
+ float alpha = (force) ? 1.0f : 0.0;
+ bool glsl = GPU_glsl_support() && BKE_scene_use_new_shading_nodes(scene) && scene->world->nodetree && scene->world->use_nodes;
+
+ if (glsl) {
+ RegionView3D *rv3d = ar->regiondata;
+ GPUMaterial *gpumat = GPU_material_world(scene, scene->world);
+
+ /* calculate full shader for background */
+ GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, (v3d->scenelock != 0));
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_QUADS);
+ glVertex3f(-1.0, -1.0, 1.0);
+ glVertex3f(1.0, -1.0, 1.0);
+ glVertex3f(1.0, 1.0, 1.0);
+ glVertex3f(-1.0, 1.0, 1.0);
+ glEnd();
+ glShadeModel(GL_FLAT);
+
+ GPU_material_unbind(gpumat);
+
+ glDepthFunc(GL_LEQUAL);
+ glDisable(GL_DEPTH_TEST);
+ }
+ else if (scene->world->skytype & WO_SKYBLEND) { /* blend sky */
+ int x, y;
+ float col_hor[3];
+ float col_zen[3];
+
+#define VIEWGRAD_RES_X 16
+#define VIEWGRAD_RES_Y 16
+
+ GLubyte grid_col[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][4];
+ static float grid_pos[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][3];
+ static GLushort indices[VIEWGRAD_RES_X - 1][VIEWGRAD_RES_X - 1][4];
+ static bool buf_calculated = false;
+
+ IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings,
+ &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v3(col_zen, &scene->world->zenr, &scene->view_settings,
+ &scene->display_settings);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glShadeModel(GL_SMOOTH);
+
+ /* calculate buffers the first time only */
+ if (!buf_calculated) {
+ for (x = 0; x < VIEWGRAD_RES_X; x++) {
+ for (y = 0; y < VIEWGRAD_RES_Y; y++) {
+ const float xf = (float)x / (float)(VIEWGRAD_RES_X - 1);
+ const float yf = (float)y / (float)(VIEWGRAD_RES_Y - 1);
+
+ /* -1..1 range */
+ grid_pos[x][y][0] = (xf - 0.5f) * 2.0f;
+ grid_pos[x][y][1] = (yf - 0.5f) * 2.0f;
+ grid_pos[x][y][2] = 1.0;
+ }
+ }
+
+ for (x = 0; x < VIEWGRAD_RES_X - 1; x++) {
+ for (y = 0; y < VIEWGRAD_RES_Y - 1; y++) {
+ indices[x][y][0] = x * VIEWGRAD_RES_X + y;
+ indices[x][y][1] = x * VIEWGRAD_RES_X + y + 1;
+ indices[x][y][2] = (x + 1) * VIEWGRAD_RES_X + y + 1;
+ indices[x][y][3] = (x + 1) * VIEWGRAD_RES_X + y;
+ }
+ }
+
+ buf_calculated = true;
+ }
+
+ for (x = 0; x < VIEWGRAD_RES_X; x++) {
+ for (y = 0; y < VIEWGRAD_RES_Y; y++) {
+ const float xf = (float)x / (float)(VIEWGRAD_RES_X - 1);
+ const float yf = (float)y / (float)(VIEWGRAD_RES_Y - 1);
+ const float mval[2] = {xf * (float)ar->winx, yf * ar->winy};
+ const float z_up[3] = {0.0f, 0.0f, 1.0f};
+ float out[3];
+ GLubyte *col_ub = grid_col[x][y];
+
+ float col_fac;
+ float col_fl[3];
+
+ ED_view3d_win_to_vector(ar, mval, out);
+
+ if (scene->world->skytype & WO_SKYPAPER) {
+ if (scene->world->skytype & WO_SKYREAL) {
+ col_fac = fabsf(((float)y / (float)VIEWGRAD_RES_Y) - 0.5f) * 2.0f;
+ }
+ else {
+ col_fac = (float)y / (float)VIEWGRAD_RES_Y;
+ }
+ }
+ else {
+ if (scene->world->skytype & WO_SKYREAL) {
+ col_fac = fabsf((angle_normalized_v3v3(z_up, out) / (float)M_PI) - 0.5f) * 2.0f;
+ }
+ else {
+ col_fac = 1.0f - (angle_normalized_v3v3(z_up, out) / (float)M_PI);
+ }
+ }
+
+ interp_v3_v3v3(col_fl, col_hor, col_zen, col_fac);
+
+ rgb_float_to_uchar(col_ub, col_fl);
+ col_ub[3] = alpha * 255;
+ }
+ }
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, grid_pos);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, grid_col);
+
+ glDrawElements(GL_QUADS, (VIEWGRAD_RES_X - 1) * (VIEWGRAD_RES_Y - 1) * 4, GL_UNSIGNED_SHORT, indices);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ glDepthFunc(GL_LEQUAL);
+ glDisable(GL_DEPTH_TEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ glShadeModel(GL_FLAT);
+
+#undef VIEWGRAD_RES_X
+#undef VIEWGRAD_RES_Y
+ }
+ else { /* solid sky */
+ float col_hor[3];
+ IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings,
+ &scene->display_settings);
+
+ glClearColor(col_hor[0], col_hor[1], col_hor[2], alpha);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ }
+ else {
+ if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_QUADS);
+ UI_ThemeColor(TH_LOW_GRAD);
+ glVertex3f(-1.0, -1.0, 1.0);
+ glVertex3f(1.0, -1.0, 1.0);
+ UI_ThemeColor(TH_HIGH_GRAD);
+ glVertex3f(1.0, 1.0, 1.0);
+ glVertex3f(-1.0, 1.0, 1.0);
+ glEnd();
+ glShadeModel(GL_FLAT);
+
+ glDepthFunc(GL_LEQUAL);
+ glDisable(GL_DEPTH_TEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+ else {
+ UI_ThemeClearColor(TH_HIGH_GRAD);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ }
+}
+
/* ED_view3d_draw_offscreen_init should be called before this to initialize
* stuff like shadow buffers
*/
@@ -2808,6 +3012,7 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
float viewmat[4][4], float winmat[4][4],
bool do_bgpic, bool do_sky)
{
+ struct bThemeState theme_state;
int bwinx, bwiny;
rcti brect;
@@ -2825,7 +3030,7 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
ar->winrct.xmax = winx;
ar->winrct.ymax = winy;
- /* set theme */
+ UI_Theme_Store(&theme_state);
UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
/* set flags */
@@ -2836,25 +3041,18 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
* warning! can be slow so only free animated images - campbell */
GPU_free_images_anim();
}
-
+ /* setup view matrices */
+ view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
+
/* clear opengl buffers */
if (do_sky) {
- float sky_color[3];
-
- ED_view3d_offscreen_sky_color_get(scene, sky_color);
- glClearColor(sky_color[0], sky_color[1], sky_color[2], 1.0f);
+ view3d_main_area_clear(scene, v3d, ar, true);
}
else {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-
- /* setup view matrices */
- view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
-
-
/* main drawing call */
view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true);
@@ -2879,8 +3077,7 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
glPopMatrix();
- /* XXX, without this the sequencer flickers with opengl draw enabled, need to find out why - campbell */
- glColor4ub(255, 255, 255, 255);
+ UI_Theme_Restore(&theme_state);
G.f &= ~G_RENDER_OGL;
}
@@ -2951,13 +3148,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
if (ibuf->rect_float && ibuf->rect)
IMB_rect_from_float(ibuf);
-
+
return ibuf;
}
/* creates own 3d views, used by the sequencer */
ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height, unsigned int flag, int drawtype,
- bool use_solid_tex, bool draw_background, int alpha_mode, char err_out[256])
+ bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, char err_out[256])
{
View3D v3d = {NULL};
ARegion ar = {NULL};
@@ -2972,6 +3169,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w
v3d.lay = scene->lay;
v3d.drawtype = drawtype;
v3d.flag2 = V3D_RENDER_OVERRIDE;
+
+ if (use_gpencil)
+ v3d.flag2 |= V3D_SHOW_GPENCIL;
if (use_solid_tex)
v3d.flag2 |= V3D_SOLID_TEX;
@@ -3205,178 +3405,6 @@ static void view3d_main_area_draw_engine_info(View3D *v3d, RegionView3D *rv3d, A
ED_region_info_draw(ar, rv3d->render_engine->text, 1, fill_color);
}
-/*
- * Function to clear the view
- */
-static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
-{
- /* clear background */
- if (scene->world && (v3d->flag2 & V3D_RENDER_OVERRIDE)) { /* clear with solid color */
- if (scene->world->skytype & WO_SKYBLEND) { /* blend sky */
- int x, y;
- float col_hor[3];
- float col_zen[3];
-
-#define VIEWGRAD_RES_X 16
-#define VIEWGRAD_RES_Y 16
-
- GLubyte grid_col[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][4];
- static float grid_pos[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][3];
- static GLushort indices[VIEWGRAD_RES_X - 1][VIEWGRAD_RES_X - 1][4];
- static bool buf_calculated = false;
-
- IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings,
- &scene->display_settings);
- IMB_colormanagement_pixel_to_display_space_v3(col_zen, &scene->world->zenr, &scene->view_settings,
- &scene->display_settings);
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- glShadeModel(GL_SMOOTH);
-
- /* calculate buffers the first time only */
- if (!buf_calculated) {
- for (x = 0; x < VIEWGRAD_RES_X; x++) {
- for (y = 0; y < VIEWGRAD_RES_Y; y++) {
- const float xf = (float)x / (float)(VIEWGRAD_RES_X - 1);
- const float yf = (float)y / (float)(VIEWGRAD_RES_Y - 1);
-
- /* -1..1 range */
- grid_pos[x][y][0] = (xf - 0.5f) * 2.0f;
- grid_pos[x][y][1] = (yf - 0.5f) * 2.0f;
- grid_pos[x][y][2] = 1.0;
- }
- }
-
- for (x = 0; x < VIEWGRAD_RES_X - 1; x++) {
- for (y = 0; y < VIEWGRAD_RES_Y - 1; y++) {
- indices[x][y][0] = x * VIEWGRAD_RES_X + y;
- indices[x][y][1] = x * VIEWGRAD_RES_X + y + 1;
- indices[x][y][2] = (x + 1) * VIEWGRAD_RES_X + y + 1;
- indices[x][y][3] = (x + 1) * VIEWGRAD_RES_X + y;
- }
- }
-
- buf_calculated = true;
- }
-
- for (x = 0; x < VIEWGRAD_RES_X; x++) {
- for (y = 0; y < VIEWGRAD_RES_Y; y++) {
- const float xf = (float)x / (float)(VIEWGRAD_RES_X - 1);
- const float yf = (float)y / (float)(VIEWGRAD_RES_Y - 1);
- const float mval[2] = {xf * (float)ar->winx, yf * ar->winy};
- const float z_up[3] = {0.0f, 0.0f, 1.0f};
- float out[3];
- GLubyte *col_ub = grid_col[x][y];
-
- float col_fac;
- float col_fl[3];
-
- ED_view3d_win_to_vector(ar, mval, out);
-
- if (scene->world->skytype & WO_SKYPAPER) {
- if (scene->world->skytype & WO_SKYREAL) {
- col_fac = fabsf(((float)y / (float)VIEWGRAD_RES_Y) - 0.5f) * 2.0f;
- }
- else {
- col_fac = (float)y / (float)VIEWGRAD_RES_Y;
- }
- }
- else {
- if (scene->world->skytype & WO_SKYREAL) {
- col_fac = fabsf((angle_normalized_v3v3(z_up, out) / (float)M_PI) - 0.5f) * 2.0f;
- }
- else {
- col_fac = 1.0f - (angle_normalized_v3v3(z_up, out) / (float)M_PI);
- }
- }
-
- interp_v3_v3v3(col_fl, col_hor, col_zen, col_fac);
-
- rgb_float_to_uchar(col_ub, col_fl);
- col_ub[3] = 0;
- }
- }
-
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_ALWAYS);
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, grid_pos);
- glColorPointer(4, GL_UNSIGNED_BYTE, 0, grid_col);
-
- glDrawElements(GL_QUADS, (VIEWGRAD_RES_X - 1) * (VIEWGRAD_RES_Y - 1) * 4, GL_UNSIGNED_SHORT, indices);
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
-
- glDepthFunc(GL_LEQUAL);
- glDisable(GL_DEPTH_TEST);
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- glShadeModel(GL_FLAT);
-
-#undef VIEWGRAD_RES_X
-#undef VIEWGRAD_RES_Y
- }
- else { /* solid sky */
- float col_hor[3];
- IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings,
- &scene->display_settings);
-
- glClearColor(col_hor[0], col_hor[1], col_hor[2], 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
- }
- else {
- if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_ALWAYS);
- glShadeModel(GL_SMOOTH);
- glBegin(GL_QUADS);
- UI_ThemeColor(TH_LOW_GRAD);
- glVertex3f(-1.0, -1.0, 1.0);
- glVertex3f(1.0, -1.0, 1.0);
- UI_ThemeColor(TH_HIGH_GRAD);
- glVertex3f(1.0, 1.0, 1.0);
- glVertex3f(-1.0, 1.0, 1.0);
- glEnd();
- glShadeModel(GL_FLAT);
-
- glDepthFunc(GL_LEQUAL);
- glDisable(GL_DEPTH_TEST);
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
-
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- }
- else {
- UI_ThemeClearColor(TH_HIGH_GRAD);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
- }
-}
-
-
#ifdef WITH_GAMEENGINE
static void update_lods(Scene *scene, float camera_pos[3])
{
@@ -3422,7 +3450,7 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
#endif
/* clear the background */
- view3d_main_area_clear(scene, v3d, ar);
+ view3d_main_area_clear(scene, v3d, ar, false);
/* enables anti-aliasing for 3D view drawing */
if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) {
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index d3bd59cacc8..aab307babe8 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -49,7 +49,6 @@
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_font.h"
-#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@@ -626,9 +625,9 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
* center, in other cases it's not clear what rotation center shall be
* so just rotate around object origin
*/
- if (ob->mode & OB_MODE_SCULPT) {
+ if (ob->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT)) {
float stroke[3];
- ED_sculpt_stroke_get_average(ob, stroke);
+ BKE_paint_stroke_get_average(scene, ob, stroke);
copy_v3_v3(lastofs, stroke);
}
else {
@@ -1119,6 +1118,8 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == MOUSEMOVE) {
@@ -1153,17 +1154,25 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event_code == VIEW_APPLY) {
viewrotate_apply(vod, event->x, event->y);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
}
else if (event_code == VIEW_CONFIRM) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true);
ED_view3d_depth_tag_update(vod->rv3d);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
- viewops_data_free(C, op);
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true);
+ }
- return OPERATOR_FINISHED;
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
}
- return OPERATOR_RUNNING_MODAL;
+ return ret;
}
/**
@@ -1221,26 +1230,31 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(vod->ar);
}
- if (event->type == MOUSEPAN) {
+ if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {
/* Rotate direction we keep always same */
- if (U.uiflag2 & USER_TRACKPAD_NATURAL)
- viewrotate_apply(vod, 2 * event->x - event->prevx, 2 * event->y - event->prevy);
- else
- viewrotate_apply(vod, event->prevx, event->prevy);
-
- ED_view3d_depth_tag_update(vod->rv3d);
-
- viewops_data_free(C, op);
-
- return OPERATOR_FINISHED;
- }
- else if (event->type == MOUSEROTATE) {
- /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
- viewrotate_apply(vod, event->prevx, event->y);
+ int x, y;
+
+ if (event->type == MOUSEPAN) {
+ if (U.uiflag2 & USER_TRACKPAD_NATURAL) {
+ x = 2 * event->x - event->prevx;
+ y = 2 * event->y - event->prevy;
+ }
+ else {
+ x = event->prevx;
+ y = event->prevy;
+ }
+ }
+ else {
+ /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
+ x = event->prevx;
+ y = event->y;
+ }
+
+ viewrotate_apply(vod, x, y);
ED_view3d_depth_tag_update(vod->rv3d);
-
+
viewops_data_free(C, op);
-
+
return OPERATOR_FINISHED;
}
else {
@@ -1946,6 +1960,8 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == MOUSEMOVE) {
@@ -1972,17 +1988,25 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event_code == VIEW_APPLY) {
viewmove_apply(vod, event->x, event->y);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
}
else if (event_code == VIEW_CONFIRM) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
ED_view3d_depth_tag_update(vod->rv3d);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
- viewops_data_free(C, op);
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+ }
- return OPERATOR_FINISHED;
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
}
- return OPERATOR_RUNNING_MODAL;
+ return ret;
}
static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -2214,6 +2238,8 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == TIMER && event->customdata == vod->timer) {
@@ -2244,16 +2270,25 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event_code == VIEW_APPLY) {
viewzoom_apply(vod, &event->x, U.viewzoom, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
}
else if (event_code == VIEW_CONFIRM) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
ED_view3d_depth_tag_update(vod->rv3d);
- viewops_data_free(C, op);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
- return OPERATOR_FINISHED;
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
}
- return OPERATOR_RUNNING_MODAL;
+ return ret;
}
static int viewzoom_exec(bContext *C, wmOperator *op)
@@ -2315,6 +2350,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
ED_view3d_depth_tag_update(rv3d);
ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
ED_region_tag_redraw(ar);
@@ -2389,8 +2425,10 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
vod->origy = vod->oldy = vod->origy + event->x - event->prevx;
viewzoom_apply(vod, &event->prevx, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) != 0);
}
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+
ED_view3d_depth_tag_update(vod->rv3d);
-
+
viewops_data_free(C, op);
return OPERATOR_FINISHED;
}
@@ -2486,6 +2524,8 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == MOUSEMOVE) {
@@ -2512,16 +2552,25 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event_code == VIEW_APPLY) {
viewdolly_apply(vod, event->x, event->y, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
}
else if (event_code == VIEW_CONFIRM) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
ED_view3d_depth_tag_update(vod->rv3d);
- viewops_data_free(C, op);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
- return OPERATOR_FINISHED;
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
}
- return OPERATOR_RUNNING_MODAL;
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
+ }
+
+ return ret;
}
static int viewdolly_exec(bContext *C, wmOperator *op)
@@ -2926,8 +2975,10 @@ static int viewselected_exec(bContext *C, wmOperator *op)
else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
ok = PE_minmax(scene, min, max);
}
- else if (ob && (ob->mode & OB_MODE_SCULPT)) {
- ok = ED_sculpt_minmax(C, min, max);
+ else if (ob && (ob->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT))) {
+ BKE_paint_stroke_get_average(scene, ob, min);
+ copy_v3_v3(max, min);
+ ok = true;
ok_dist = 0; /* don't zoom */
}
else {
@@ -3970,6 +4021,8 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == MOUSEMOVE) {
@@ -3996,16 +4049,25 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event_code == VIEW_APPLY) {
viewroll_apply(vod, event->x, event->y);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
}
else if (event_code == VIEW_CONFIRM) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, false);
ED_view3d_depth_tag_update(vod->rv3d);
- viewops_data_free(C, op);
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
- return OPERATOR_FINISHED;
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, false);
}
- return OPERATOR_RUNNING_MODAL;
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op);
+ }
+
+ return ret;
}
static EnumPropertyItem prop_view_roll_items[] = {
@@ -4279,32 +4341,16 @@ static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op))
static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
View3D *v3d = CTX_wm_view3d(C);
- Image *ima = NULL;
+ Image *ima;
BGpic *bgpic;
- char name[MAX_ID_NAME - 2];
-
- /* check input variables */
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
- char path[FILE_MAX];
-
- RNA_string_get(op->ptr, "filepath", path);
- ima = BKE_image_load_exists(path);
- }
- else if (RNA_struct_property_is_set(op->ptr, "name")) {
- RNA_string_get(op->ptr, "name", name);
- ima = (Image *)BKE_libblock_find_name(ID_IM, name);
- }
+ ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
+ /* may be NULL, continue anyway */
+
bgpic = background_image_add(C);
-
- if (ima) {
- bgpic->ima = ima;
-
- id_us_plus(&ima->id);
-
- if (!(v3d->flag & V3D_DISPBGPICS))
- v3d->flag |= V3D_DISPBGPICS;
- }
+ bgpic->ima = ima;
+
+ v3d->flag |= V3D_DISPBGPICS;
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
@@ -4330,7 +4376,8 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot)
/* properties */
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Image name to assign");
- RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path to image file");
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
}
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 4c19f59a148..11ed9867e2f 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -32,12 +32,9 @@
#include <stdio.h>
#include <stdlib.h>
-#include "DNA_brush_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLF_translation.h"
@@ -45,8 +42,6 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_main.h"
-#include "BKE_modifier.h"
-#include "BKE_paint.h"
#include "BKE_screen.h"
#include "BKE_editmesh.h"
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 84ac4f7d02d..d3a9f5ca967 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -163,7 +163,9 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* drawmesh.c */
void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
struct Object *ob, struct DerivedMesh *dm, const int draw_flags);
-void draw_mesh_face_select(struct RegionView3D *rv3d, struct Mesh *me, struct DerivedMesh *dm);
+void draw_mesh_face_select(
+ struct RegionView3D *rv3d, struct Mesh *me, struct DerivedMesh *dm,
+ bool draw_select_edges);
void draw_mesh_paint_weight_faces(struct DerivedMesh *dm, const bool do_light,
void *facemask_cb, void *user_data);
void draw_mesh_paint_vcolor_faces(struct DerivedMesh *dm, const bool use_light,
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 6a505959820..5df348408df 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -42,6 +42,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BKE_appdir.h"
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_main.h"
@@ -77,7 +78,7 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- BLI_make_file_string("/", str, BLI_temp_dir_base(), "copybuffer.blend");
+ BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
BKE_copybuffer_save(str, op->reports);
BKE_report(op->reports, RPT_INFO, "Copied selected objects to buffer");
@@ -102,7 +103,7 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
{
char str[FILE_MAX];
- BLI_make_file_string("/", str, BLI_temp_dir_base(), "copybuffer.blend");
+ BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
if (BKE_copybuffer_paste(C, str, op->reports)) {
WM_event_add_notifier(C, NC_WINDOW, NULL);
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index 48bc6448194..eba31866f54 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -70,7 +70,7 @@
* \param r_co hit location.
* \param r_no hit normal (optional).
* \param co_ss Screenspace coordinate.
- * \param use_depth Snap to the closest element, use when using more then one snap type.
+ * \param use_depth Snap to the closest element, use when using more than one snap type.
* \param use_obedit Use editmode cage.
* \param use_vert Snap to verts.
* \param use_edge Snap to edges.
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 08a69830c03..38ecbed3b5f 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -93,7 +93,6 @@
#include "ED_mball.h"
#include "UI_interface.h"
-#include "UI_resources.h"
#include "view3d_intern.h" /* own include */
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index 0e17d8fc354..f127f375a9f 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -39,7 +39,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 9faca757c62..5a3893f733f 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -37,9 +37,7 @@
#include "BLI_math.h"
#include "BLI_rect.h"
-#include "BLI_listbase.h"
#include "BLI_utildefines.h"
-#include "BLI_callbacks.h"
#include "BKE_anim.h"
#include "BKE_action.h"
@@ -55,7 +53,6 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "GPU_draw.h"
#include "GPU_select.h"
#include "WM_api.h"
@@ -64,14 +61,16 @@
#include "ED_screen.h"
#include "ED_armature.h"
-#include "RE_engine.h"
#ifdef WITH_GAMEENGINE
-#include "BL_System.h"
+# include "BLI_listbase.h"
+# include "BLI_callbacks.h"
+
+# include "GPU_draw.h"
+
+# include "BL_System.h"
#endif
-#include "RNA_access.h"
-#include "RNA_define.h"
#include "view3d_intern.h" /* own include */
@@ -356,6 +355,7 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w
view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d);
ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
}
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
@@ -382,6 +382,10 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w
v3d->lens = sms->dst.lens * step + sms->src.lens * step_inv;
ED_view3d_camera_lock_sync(v3d, rv3d);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
+ }
+
}
if (rv3d->viewlock & RV3D_BOXVIEW)
@@ -492,26 +496,22 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
Object *camera_ob = v3d ? v3d->camera : scene->camera;
float r_co[3]; /* the new location to apply */
+ float r_scale; /* only for ortho cameras */
if (camera_ob == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active camera");
return OPERATOR_CANCELLED;
}
- else if (camera_ob->type != OB_CAMERA) {
- BKE_report(op->reports, RPT_ERROR, "Object not a camera");
- return OPERATOR_CANCELLED;
- }
- else if (((Camera *)camera_ob->data)->type == R_ORTHO) {
- BKE_report(op->reports, RPT_ERROR, "Orthographic cameras not supported");
- return OPERATOR_CANCELLED;
- }
/* this function does all the important stuff */
- if (BKE_camera_view_frame_fit_to_scene(scene, v3d, camera_ob, r_co)) {
-
+ if (BKE_camera_view_frame_fit_to_scene(scene, v3d, camera_ob, r_co, &r_scale)) {
ObjectTfmProtectedChannels obtfm;
float obmat_new[4][4];
+ if ((camera_ob->type == OB_CAMERA) && (((Camera *)camera_ob->data)->type == CAM_ORTHO)) {
+ ((Camera *)camera_ob->data)->ortho_scale = r_scale;
+ }
+
copy_m4_m4(obmat_new, camera_ob->obmat);
copy_v3_v3(obmat_new[3], r_co);
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 9b9b7a8d258..191eeb05c71 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -42,8 +42,6 @@
#include "BLF_translation.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "BIF_gl.h"
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 9547f0bc77f..b727b96c8cc 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -200,6 +200,12 @@ static bool transdata_check_local_center(TransInfo *t, short around)
);
}
+bool transdata_check_local_islands(TransInfo *t, short around)
+{
+ return ((around == V3D_LOCAL) && (
+ (t->obedit && ELEM(t->obedit->type, OB_MESH))));
+}
+
/* ************************** SPACE DEPENDANT CODE **************************** */
void setTransformViewMatrices(TransInfo *t)
@@ -579,7 +585,10 @@ void removeAspectRatio(TransInfo *t, float vec[2])
static void viewRedrawForce(const bContext *C, TransInfo *t)
{
- if (t->spacetype == SPACE_VIEW3D) {
+ if (t->options & CTX_GPENCIL_STROKES) {
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ }
+ else if (t->spacetype == SPACE_VIEW3D) {
if (t->options & CTX_PAINT_CURVE) {
wmWindow *window = CTX_wm_window(C);
WM_paint_cursor_tag_redraw(window, t->ar);
@@ -2007,6 +2016,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
options |= CTX_TEXTURE;
}
}
+
+ if ((prop = RNA_struct_find_property(op->ptr, "gpencil_strokes")) && RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ options |= CTX_GPENCIL_STROKES;
+ }
+ }
t->options = options;
@@ -4061,6 +4076,11 @@ static void initTranslation(TransInfo *t)
t->snap[1] = ED_node_grid_size() * NODE_GRID_STEPS;
t->snap[2] = ED_node_grid_size();
}
+ else if (t->spacetype == SPACE_IPO) {
+ t->snap[0] = 0.0f;
+ t->snap[1] = 1.0;
+ t->snap[2] = 0.1f;
+ }
else {
t->snap[0] = 0.0f;
t->snap[1] = t->snap[2] = 1.0f;
@@ -5837,12 +5857,12 @@ void projectEdgeSlideData(TransInfo *t, bool is_final)
l_ed_sel = l_ed_sel->prev;
if (sld->perc < 0.0f) {
- if (BM_vert_in_face(l_ed_sel->radial_next->f, sv->v_b)) {
+ if (BM_vert_in_face(sv->v_b, l_ed_sel->radial_next->f)) {
f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_ed_sel->radial_next->f);
}
}
else if (sld->perc > 0.0f) {
- if (BM_vert_in_face(l_ed_sel->radial_next->f, sv->v_a)) {
+ if (BM_vert_in_face(sv->v_a, l_ed_sel->radial_next->f)) {
f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_ed_sel->radial_next->f);
}
}
@@ -5902,18 +5922,18 @@ void projectEdgeSlideData(TransInfo *t, bool is_final)
BMLoop *l_adj = NULL;
if (sld->perc < 0.0f) {
- if (BM_vert_in_face(e_sel->l->f, sv->v_b)) {
+ if (BM_vert_in_face(sv->v_b, e_sel->l->f)) {
l_adj = e_sel->l;
}
- else if (BM_vert_in_face(e_sel->l->radial_next->f, sv->v_b)) {
+ else if (BM_vert_in_face(sv->v_b, e_sel->l->radial_next->f)) {
l_adj = e_sel->l->radial_next;
}
}
else if (sld->perc > 0.0f) {
- if (BM_vert_in_face(e_sel->l->f, sv->v_a)) {
+ if (BM_vert_in_face(sv->v_a, e_sel->l->f)) {
l_adj = e_sel->l;
}
- else if (BM_vert_in_face(e_sel->l->radial_next->f, sv->v_a)) {
+ else if (BM_vert_in_face(sv->v_a, e_sel->l->radial_next->f)) {
l_adj = e_sel->l->radial_next;
}
}
@@ -7121,10 +7141,11 @@ static void headerSeqSlide(TransInfo *t, float val[2], char str[MAX_INFO_LEN])
WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
}
-static void applySeqSlideValue(TransInfo *t, const float val[2])
+static void applySeqSlideValue(TransInfo *t, const float val[2], int frame)
{
TransData *td = t->data;
int i;
+ TransSeq *ts = t->customData;
for (i = 0; i < t->total; i++, td++) {
float tvec[2];
@@ -7139,15 +7160,21 @@ static void applySeqSlideValue(TransInfo *t, const float val[2])
mul_v2_fl(tvec, td->factor);
- td->loc[0] = td->iloc[0] + tvec[0];
+ if (t->modifiers & MOD_SNAP_INVERT) {
+ td->loc[0] = frame + td->factor * (td->iloc[0] - ts->min);
+ }
+ else {
+ td->loc[0] = td->iloc[0] + tvec[0];
+ }
+
td->loc[1] = td->iloc[1] + tvec[1];
}
}
-static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
+static void applySeqSlide(TransInfo *t, const int mval[2])
{
char str[MAX_INFO_LEN];
-
+ int snap_frame = 0;
if (t->con.mode & CON_APPLY) {
float pvec[3] = {0.0f, 0.0f, 0.0f};
float tvec[3];
@@ -7155,7 +7182,8 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
copy_v3_v3(t->values, tvec);
}
else {
- snapGridIncrement(t, t->values);
+ snap_frame = snapSequenceBounds(t, mval);
+ // snapGridIncrement(t, t->values);
applyNumInput(&t->num, t->values);
}
@@ -7163,7 +7191,7 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
t->values[1] = floor(t->values[1] + 0.5f);
headerSeqSlide(t, t->values, str);
- applySeqSlideValue(t, t->values);
+ applySeqSlideValue(t, t->values, snap_frame);
recalcData(t);
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 67d55639528..0d824be862e 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -173,6 +173,13 @@ typedef struct TransDataSeq {
} TransDataSeq;
+typedef struct TransSeq {
+ TransDataSeq *tdseq;
+ int min;
+ int max;
+ bool snap_left;
+} TransSeq;
+
/* for NLA transform (stored in td->extra pointer) */
typedef struct TransDataNla {
ID *id; /* ID-block NLA-data is attached to */
@@ -545,6 +552,7 @@ void special_aftertrans_update(struct bContext *C, TransInfo *t);
int special_transform_moving(TransInfo *t);
void transform_autoik_update(TransInfo *t, short mode);
+bool transdata_check_local_islands(TransInfo *t, short around);
int count_set_pose_transflags(int *out_mode, short around, struct Object *ob);
@@ -588,6 +596,8 @@ typedef enum {
void snapGridIncrement(TransInfo *t, float *val);
void snapGridIncrementAction(TransInfo *t, float *val, GearsType action);
+int snapSequenceBounds(TransInfo *t, const int mval[2]);
+
bool activeSnap(TransInfo *t);
bool validSnap(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index e2859b2821a..c1350b1f076 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -54,7 +54,6 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_smallhash.h"
#include "BLI_listbase.h"
#include "BLI_linklist_stack.h"
#include "BLI_string.h"
@@ -90,7 +89,6 @@
#include "BKE_editmesh.h"
#include "BKE_tracking.h"
#include "BKE_mask.h"
-#include "BKE_lattice.h"
#include "BIK_api.h"
@@ -107,6 +105,7 @@
#include "ED_uvedit.h"
#include "ED_clip.h"
#include "ED_mask.h"
+#include "ED_gpencil.h"
#include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
#include "WM_types.h"
@@ -218,6 +217,9 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
float _proj_vec[3];
const float *proj_vec = NULL;
+ /* support for face-islands */
+ const bool use_island = transdata_check_local_islands(t, t->around);
+
if (t->flag & T_PROP_PROJECTED) {
if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = t->ar->regiondata;
@@ -239,7 +241,12 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
for (i = 0, td = t->data; i < t->total; i++, td++) {
if (td->flag & TD_SELECTED) {
- sub_v3_v3v3(vec, tob->center, td->center);
+ if (use_island) {
+ sub_v3_v3v3(vec, tob->iloc, td->iloc);
+ }
+ else {
+ sub_v3_v3v3(vec, tob->center, td->center);
+ }
mul_m3_v3(tob->mtx, vec);
if (proj_vec) {
@@ -251,6 +258,10 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
dist_sq = len_squared_v3(vec);
if ((tob->rdist == -1.0f) || (dist_sq < SQUARE(tob->rdist))) {
tob->rdist = sqrtf(dist_sq);
+ if (use_island) {
+ copy_v3_v3(tob->center, td->center);
+ copy_m3_m3(tob->axismtx, td->axismtx);
+ }
}
}
else {
@@ -2806,8 +2817,8 @@ void flushTransUVs(TransInfo *t)
td->loc2d[1] = td->loc[1] * invy;
if ((sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
- td->loc2d[0] = floorf(width * td->loc2d[0] + 0.5f) / width;
- td->loc2d[1] = floorf(height * td->loc2d[1] + 0.5f) / height;
+ td->loc2d[0] = roundf(width * td->loc2d[0]) / width;
+ td->loc2d[1] = roundf(height * td->loc2d[1]) / height;
}
}
}
@@ -3769,7 +3780,6 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
BezTriple *bezt;
int count = 0, i;
- float cfra;
float mtx[3][3], smtx[3][3];
const bool is_translation_mode = graph_edit_is_translation_mode(t);
const bool use_handle = !(sipo->flag & SIPO_NOHANDLES);
@@ -3804,7 +3814,12 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
-
+ float cfra;
+
+ /* F-Curve may not have any keyframes */
+ if (fcu->bezt == NULL)
+ continue;
+
/* convert current-frame to action-time (slightly less accurate, especially under
* higher scaling ratios, but is faster than converting all points)
*/
@@ -3812,45 +3827,27 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
else
cfra = (float)CFRA;
-
- /* F-Curve may not have any keyframes */
- if (fcu->bezt == NULL)
- continue;
-
+
/* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
- const bool sel2 = bezt->f2 & SELECT;
- const bool sel1 = use_handle ? bezt->f1 & SELECT : sel2;
- const bool sel3 = use_handle ? bezt->f3 & SELECT : sel2;
-
- if (is_translation_mode) {
- /* for 'normal' pivots - just include anything that is selected.
- * this works a bit differently in translation modes */
- if (sel2) {
+ const bool sel2 = (bezt->f2 & SELECT) != 0;
+ const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
+ const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
+
+ if (!is_translation_mode || !(sel2)) {
+ if (sel1) {
count++;
}
- else {
- if (sel1) count++;
- if (sel3) count++;
- }
- }
- else if (use_local_center) {
- /* for local-pivot we only need to count the number of selected handles only,
- * so that centerpoints don't get moved wrong
- */
- if (bezt->ipo == BEZT_IPO_BEZ) {
- if (sel1) count++;
- if (sel3) count++;
+
+ if (sel3) {
+ count++;
}
- /* else if (sel2) count++; // TODO: could this cause problems? */
- /* - yes this causes problems, because no td is created for the center point */
}
- else {
- /* for 'normal' pivots - just include anything that is selected */
- if (sel1) count++;
- if (sel2) count++;
- if (sel3) count++;
+
+ /* only include main vert if selected */
+ if (sel2 && !use_local_center) {
+ count++;
}
}
}
@@ -3899,8 +3896,13 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
- bool intvals = (fcu->flag & FCURVE_INT_VALUES);
+ bool intvals = (fcu->flag & FCURVE_INT_VALUES) != 0;
float unit_scale;
+ float cfra;
+
+ /* F-Curve may not have any keyframes */
+ if (fcu->bezt == NULL)
+ continue;
/* convert current-frame to action-time (slightly less accurate, especially under
* higher scaling ratios, but is faster than converting all points)
@@ -3909,19 +3911,15 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
else
cfra = (float)CFRA;
-
- /* F-Curve may not have any keyframes */
- if (fcu->bezt == NULL)
- continue;
-
+
unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, anim_map_flag);
/* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
- const bool sel2 = bezt->f2 & SELECT;
- const bool sel1 = use_handle ? bezt->f1 & SELECT : sel2;
- const bool sel3 = use_handle ? bezt->f3 & SELECT : sel2;
+ const bool sel2 = (bezt->f2 & SELECT) != 0;
+ const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
+ const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
TransDataCurveHandleFlags *hdata = NULL;
/* short h1=1, h2=1; */ /* UNUSED */
@@ -4528,10 +4526,47 @@ static int SeqToTransData_Recursive(TransInfo *t, ListBase *seqbase, TransData *
}
}
}
-
return tot;
}
+
+static void SeqTransDataBounds(TransInfo *t, ListBase *seqbase, TransSeq *ts)
+{
+ Sequence *seq;
+ int recursive, count, flag;
+ int max = INT32_MIN, min = INT32_MAX;
+
+ for (seq = seqbase->first; seq; seq = seq->next) {
+
+ /* just to get the flag since there are corner cases where this isn't totally obvious */
+ SeqTransInfo(t, seq, &recursive, &count, &flag);
+
+ /* use 'flag' which is derived from seq->flag but modified for special cases */
+ if (flag & SELECT) {
+ if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
+ if (flag & SEQ_LEFTSEL) {
+ min = min_ii(seq->startdisp, min);
+ max = max_ii(seq->startdisp, max);
+ }
+ if (flag & SEQ_RIGHTSEL) {
+ min = min_ii(seq->enddisp, min);
+ max = max_ii(seq->enddisp, max);
+ }
+ }
+ else {
+ min = min_ii(seq->startdisp, min);
+ max = max_ii(seq->enddisp, max);
+ }
+ }
+ }
+
+ if (ts) {
+ ts->max = max;
+ ts->min = min;
+ }
+}
+
+
static void freeSeqData(TransInfo *t)
{
Editing *ed = BKE_sequencer_editing_get(t->scene, false);
@@ -4694,6 +4729,8 @@ static void freeSeqData(TransInfo *t)
}
if ((t->customData != NULL) && (t->flag & T_FREE_CUSTOMDATA)) {
+ TransSeq *ts = t->customData;
+ MEM_freeN(ts->tdseq);
MEM_freeN(t->customData);
t->customData = NULL;
}
@@ -4713,6 +4750,8 @@ static void createTransSeqData(bContext *C, TransInfo *t)
TransData *td = NULL;
TransData2D *td2d = NULL;
TransDataSeq *tdsq = NULL;
+ TransSeq *ts = NULL;
+ int xmouse;
int count = 0;
@@ -4723,12 +4762,11 @@ static void createTransSeqData(bContext *C, TransInfo *t)
t->customFree = freeSeqData;
+ xmouse = (int)UI_view2d_region_to_view_x(v2d, t->imval[0]);
+
/* which side of the current frame should be allowed */
if (t->mode == TFM_TIME_EXTEND) {
/* only side on which mouse is gets transformed */
- float xmouse, ymouse;
-
- UI_view2d_region_to_view(v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
}
else {
@@ -4768,15 +4806,19 @@ static void createTransSeqData(bContext *C, TransInfo *t)
return;
}
+ t->customData = ts = MEM_mallocN(sizeof(TransSeq), "transseq");
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransSeq TransData");
td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransSeq TransData2D");
- tdsq = t->customData = MEM_callocN(t->total * sizeof(TransDataSeq), "TransSeq TransDataSeq");
+ ts->tdseq = tdsq = MEM_callocN(t->total * sizeof(TransDataSeq), "TransSeq TransDataSeq");
t->flag |= T_FREE_CUSTOMDATA;
-
-
/* loop 2: build transdata array */
SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq);
+ SeqTransDataBounds(t, ed->seqbasep, ts);
+
+ /* set the snap mode based on how close the mouse is at the end/start points */
+ if (abs(xmouse - ts->max) > abs(xmouse - ts->min))
+ ts->snap_left = true;
#undef XXX_DURIAN_ANIM_TX_HACK
}
@@ -5572,7 +5614,10 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
}
- if (t->spacetype == SPACE_SEQ) {
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* pass */
+ }
+ else if (t->spacetype == SPACE_SEQ) {
/* freeSeqData in transform_conversions.c does this
* keep here so the else at the end wont run... */
@@ -7239,6 +7284,230 @@ void flushTransPaintCurve(TransInfo *t)
}
+static void createTransGPencil(bContext *C, TransInfo *t)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl;
+ TransData *td = NULL;
+ float mtx[3][3], smtx[3][3];
+
+ const Scene *scene = CTX_data_scene(C);
+ const int cfra = CFRA;
+
+ const int propedit = (t->flag & T_PROP_EDIT);
+ const int propedit_connected = (t->flag & T_PROP_CONNECTED);
+
+
+ /* == Grease Pencil Strokes to Transform Data ==
+ * Grease Pencil stroke points can be a mixture of 2D (screen-space),
+ * or 3D coordinates. However, they're always saved as 3D points.
+ * For now, we just do these without creating TransData2D for the 2D
+ * strokes. This may cause issues in future though.
+ */
+ t->total = 0;
+
+ if (gpd == NULL)
+ return;
+
+ /* First Pass: Count the number of datapoints required for the strokes,
+ * (and additional info about the configuration - e.g. 2D/3D?)
+ */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* only editable and visible layers are considered */
+ if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0 &&
+ (gpl->actframe != NULL))
+ {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (propedit) {
+ /* Proportional Editing... */
+ if (propedit_connected) {
+ /* connected only - so only if selected */
+ if (gps->flag & GP_STROKE_SELECT)
+ t->total += gps->totpoints;
+ }
+ else {
+ /* everything goes - connection status doesn't matter */
+ t->total += gps->totpoints;
+ }
+ }
+ else {
+ /* only selected stroke points are considered */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ // TODO: 2D vs 3D?
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT)
+ t->total++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Stop trying if nothing selected */
+ if (t->total == 0) {
+ return;
+ }
+
+ /* Allocate memory for data */
+ t->data = MEM_callocN(t->total * sizeof(TransData), "TransData(GPencil)");
+ td = t->data;
+
+ unit_m3(smtx);
+ unit_m3(mtx);
+
+ /* Second Pass: Build transdata array */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* only editable and visible layers are considered */
+ if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0 &&
+ (gpl->actframe != NULL))
+ {
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+
+ /* Make a new frame to work on if the layer's frame and the current scene frame don't match up
+ * - This is useful when animating as it saves that "uh-oh" moment when you realize you've
+ * spent too much time editing the wrong frame...
+ */
+ // XXX: should this be allowed when framelock is enabled?
+ if (gpf->framenum != cfra) {
+ bGPDframe *new_frame = gpencil_frame_duplicate(gpf);
+ bGPDframe *gf;
+ bool found = false;
+
+ /* Find frame to insert it before */
+ for (gf = gpf->next; gf; gf = gf->next) {
+ if (gf->framenum > cfra) {
+ /* Add it here */
+ BLI_insertlinkbefore(&gpl->frames, gf, new_frame);
+
+ found = true;
+ break;
+ }
+ else if (gf->framenum == cfra) {
+ /* This only happens when we're editing with framelock on...
+ * - Delete the new frame and don't do anything else here...
+ */
+ //printf("GP Frame convert to TransData - Copy aborted for frame %d -> %d\n", gpf->framenum, gf->framenum);
+ free_gpencil_strokes(new_frame);
+ MEM_freeN(new_frame);
+ new_frame = NULL;
+
+ found = true;
+ break;
+ }
+ }
+
+ if (found == false) {
+ /* Add new frame to the end */
+ BLI_addtail(&gpl->frames, new_frame);
+ }
+
+ /* Edit the new frame instead, if it did get created + added */
+ if (new_frame) {
+ // TODO: tag this one as being "newly created" so that we can remove it if the edit is cancelled
+ new_frame->framenum = cfra;
+
+ gpf = new_frame;
+ }
+ }
+
+ /* Loop over strokes, adding TransData for points as needed... */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ TransData *head = td;
+ TransData *tail = td;
+ bool stroke_ok;
+
+ /* What we need to include depends on proportional editing settings... */
+ if (propedit) {
+ if (propedit_connected) {
+ /* A) "Connected" - Only those in selected strokes */
+ stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
+ }
+ else {
+ /* B) All points, always */
+ stroke_ok = true;
+ }
+ }
+ else {
+ /* C) Only selected points in selected strokes */
+ stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
+ }
+
+ /* Do stroke... */
+ if (stroke_ok && gps->totpoints) {
+ bGPDspoint *pt;
+ int i;
+
+#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or propedit breaks */
+ const float ninv = 1.0f / gps->totpoints;
+ float center[3] = {0.0f};
+
+ /* compute midpoint of stroke */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ madd_v3_v3v3fl(center, center, &pt->x, ninv);
+ }
+#endif
+
+ /* add all necessary points... */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ bool point_ok;
+
+ /* include point? */
+ if (propedit) {
+ /* Always all points in strokes that get included */
+ point_ok = true;
+ }
+ else {
+ /* Only selected points in selected strokes */
+ point_ok = (pt->flag & GP_SPOINT_SELECT) != 0;
+ }
+
+ /* do point... */
+ if (point_ok) {
+ copy_v3_v3(td->iloc, &pt->x);
+ copy_v3_v3(td->center, &pt->x); // XXX: what about t->around == local?
+
+ td->loc = &pt->x;
+
+ td->flag = 0;
+
+ if (pt->flag & GP_SPOINT_SELECT)
+ td->flag |= TD_SELECTED;
+
+ /* configure 2D points so that they don't play up... */
+ if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) {
+ td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
+ // XXX: matrices may need to be different?
+ }
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ unit_m3(td->axismtx); // XXX?
+
+ td++;
+ tail++;
+ }
+ }
+
+ /* March over these points, and calculate the proportional editing distances */
+ if (propedit && (head != tail)) {
+ /* XXX: for now, we are similar enough that this works... */
+ calc_distanceCurveVerts(head, tail - 1);
+ }
+ }
+ }
+ }
+ }
+}
+
+
void createTransData(bContext *C, TransInfo *t)
{
Scene *scene = t->scene;
@@ -7259,6 +7528,16 @@ void createTransData(bContext *C, TransInfo *t)
sort_trans_data_dist(t);
}
}
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ t->flag |= T_POINTS; // XXX...
+ createTransGPencil(C, t);
+
+ if (t->data && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
else if (t->spacetype == SPACE_IMAGE) {
t->flag |= T_POINTS | T_2D_EDIT;
if (t->options & CTX_MASK) {
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 52f02e5dc86..fcf789546e8 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -109,21 +109,7 @@
void getViewVector(TransInfo *t, float coord[3], float vec[3])
{
if (t->persp != RV3D_ORTHO) {
- float p1[4], p2[4];
-
- copy_v3_v3(p1, coord);
- p1[3] = 1.0f;
- copy_v3_v3(p2, p1);
- p2[3] = 1.0f;
- mul_m4_v4(t->viewmat, p2);
-
- p2[0] = 2.0f * p2[0];
- p2[1] = 2.0f * p2[1];
- p2[2] = 2.0f * p2[2];
-
- mul_m4_v4(t->viewinv, p2);
-
- sub_v3_v3v3(vec, p1, p2);
+ sub_v3_v3v3(vec, coord, t->viewinv[3]);
}
else {
copy_v3_v3(vec, t->viewinv[2]);
@@ -975,6 +961,9 @@ void recalcData(TransInfo *t)
else if (t->options & CTX_PAINT_CURVE) {
flushTransPaintCurve(t);
}
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ /* pass? */
+ }
else if (t->spacetype == SPACE_IMAGE) {
recalcData_image(t);
}
@@ -1205,7 +1194,11 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
/* exceptional case */
if (t->around == V3D_LOCAL) {
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
- t->options |= CTX_NO_PET;
+ const bool use_island = transdata_check_local_islands(t, t->around);
+
+ if (!use_island) {
+ t->options |= CTX_NO_PET;
+ }
}
}
@@ -1325,6 +1318,9 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
if (t->obedit) {
t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
}
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
+ }
else if (t->options & CTX_MASK) {
if (ts->proportional_mask) {
t->flag |= T_PROP_EDIT;
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index ece681b228e..25dee50a192 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -324,6 +324,9 @@ static void transformops_loopsel_hack(bContext *C, wmOperator *op)
}
}
}
+#else
+/* prevent removal by cleanup */
+# error "loopslide hack removed!"
#endif /* USE_LOOPSLIDE_HACK */
@@ -543,7 +546,11 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
}
}
}
-
+
+ if (flags & P_GPENCIL_EDIT) {
+ RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes");
+ }
+
if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) {
RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space");
prop = RNA_def_boolean(ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel");
@@ -578,7 +585,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
RNA_def_float_vector_xyz(ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
- Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS);
+ Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
@@ -598,7 +605,7 @@ static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
- Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS);
+ Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS | P_GPENCIL_EDIT);
}
static int skin_resize_poll(bContext *C)
@@ -652,7 +659,7 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
prop = RNA_def_float_vector(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
RNA_def_property_subtype(prop, PROP_ANGLE);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
@@ -675,7 +682,7 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
prop = RNA_def_float(ot->srna, "value", 0.0f, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
RNA_def_property_subtype(prop, PROP_ANGLE);
- Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP);
+ Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_tilt(struct wmOperatorType *ot)
@@ -721,7 +728,7 @@ static void TRANSFORM_OT_bend(struct wmOperatorType *ot)
RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_shear(struct wmOperatorType *ot)
@@ -741,7 +748,7 @@ static void TRANSFORM_OT_shear(struct wmOperatorType *ot)
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
// XXX Shear axis?
}
@@ -803,7 +810,7 @@ static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot)
RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
@@ -821,7 +828,7 @@ static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
- Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL);
+ Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index ba93d4463b7..79262396fb4 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -24,7 +24,6 @@
* \ingroup edtransform
*/
-
#include <string.h>
#include <stddef.h>
#include <ctype.h>
@@ -57,10 +56,6 @@
#include "ED_armature.h"
-#include "RNA_define.h"
-
-#include "UI_interface.h"
-
#include "transform.h"
/* *********************** TransSpace ************************** */
@@ -738,7 +733,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
v_pair_swap = true;
}
else if (eed && BM_edge_is_boundary(eed)) {
- /* pradictable direction for boundary edges */
+ /* predictable direction for boundary edges */
if (eed->l->v != v_pair[0]) {
v_pair_swap = true;
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index cd636591212..4a2927ace00 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -59,6 +59,7 @@
#include "BKE_anim.h" /* for duplis */
#include "BKE_context.h"
#include "BKE_editmesh.h"
+#include "BKE_sequencer.h"
#include "BKE_main.h"
#include "BKE_tracking.h"
@@ -2430,6 +2431,27 @@ void snapGridIncrement(TransInfo *t, float *val)
snapGridIncrementAction(t, val, action);
}
+int snapSequenceBounds(TransInfo *t, const int mval[2])
+{
+ float xmouse, ymouse;
+ int frame;
+ int mframe;
+ TransSeq *ts = t->customData;
+ /* reuse increment, strictly speaking could be another snap mode, but leave as is */
+ if (!(t->modifiers & MOD_SNAP_INVERT))
+ return 0;
+
+ /* convert to frame range */
+ UI_view2d_region_to_view(&t->ar->v2d, mval[0], mval[1], &xmouse, &ymouse);
+ mframe = iroundf(xmouse);
+ /* now find the closest sequence */
+ frame = BKE_sequencer_find_next_prev_edit(t->scene, mframe, SEQ_SIDE_BOTH, true, false, true);
+
+ if (!ts->snap_left)
+ frame = frame - (ts->max - ts->min);
+
+ return frame;
+}
static void applyGridIncrement(TransInfo *t, float *val, int max_index, const float fac[3], GearsType action)
{
@@ -2457,6 +2479,19 @@ static void applyGridIncrement(TransInfo *t, float *val, int max_index, const fl
ED_space_image_get_uv_aspect(t->sa->spacedata.first, asp, asp + 1);
}
}
+ else if ((t->spacetype == SPACE_IPO) && (t->mode == TFM_TRANSLATION)) {
+ View2D *v2d = &t->ar->v2d;
+ View2DGrid *grid;
+ SpaceIpo *sipo = t->sa->spacedata.first;
+ int unity = V2D_UNIT_VALUES;
+ int unitx = (sipo->flag & SIPO_DRAWTIME) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMESCALE;
+
+ /* grid */
+ grid = UI_view2d_grid_calc(t->scene, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, t->ar->winx, t->ar->winy);
+
+ UI_view2d_grid_size(grid, &asp[0], &asp[1]);
+ UI_view2d_grid_free(grid);
+ }
for (i = 0; i <= max_index; i++) {
val[i] = fac[action] * asp[i] * floorf(val[i] / (fac[action] * asp[i]) + 0.5f);
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 86b96968047..32d4f2e5a15 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -174,7 +174,7 @@ bool ED_editors_flush_edits(const bContext *C, bool for_render)
}
else {
/* Set reorder=false so that saving the file doesn't reorder
- * the BMesh's elements */
+ * the BMesh's elements */
BKE_sculptsession_bm_to_me(ob, false);
}
}
diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c
index ef95e4cb3ff..2428ee21367 100644
--- a/source/blender/editors/util/editmode_undo.c
+++ b/source/blender/editors/util/editmode_undo.c
@@ -48,8 +48,6 @@
#include "ED_util.h"
#include "ED_mesh.h"
-#include "UI_interface.h"
-#include "UI_resources.h"
#include "util_intern.h"
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index 6c0efad6f26..fac57490b44 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -29,8 +29,6 @@
* \ingroup edutil
*/
-
-
#include <stdlib.h>
#include <string.h>
#include <math.h>
@@ -47,6 +45,7 @@
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_screen.h"
#include "ED_armature.h"
@@ -124,6 +123,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
Object *obact = CTX_data_active_object(C);
@@ -146,7 +146,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname) && undoname) {
if (U.uiflag & USER_GLOBALUNDO) {
- ED_viewport_render_kill_jobs(C, true);
+ ED_viewport_render_kill_jobs(wm, bmain, true);
BKE_undo_name(C, undoname);
}
}
@@ -199,7 +199,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
/* for example, texface stores image pointers */
undo_editmode_clear();
- ED_viewport_render_kill_jobs(C, true);
+ ED_viewport_render_kill_jobs(wm, bmain, true);
if (undoname)
BKE_undo_name(C, undoname);
@@ -379,7 +379,7 @@ int ED_undo_operator_repeat(bContext *C, struct wmOperator *op)
{
int retval;
- ED_viewport_render_kill_jobs(C, true);
+ ED_viewport_render_kill_jobs(wm, CTX_data_main(C), true);
if (G.debug & G_DEBUG)
printf("redo_cb: operator redo %s\n", op->type->name);
@@ -583,7 +583,7 @@ static int undo_history_exec(bContext *C, wmOperator *op)
ED_undo_paint_step_num(C, UNDO_PAINT_IMAGE, item );
}
else {
- ED_viewport_render_kill_jobs(C, true);
+ ED_viewport_render_kill_jobs(CTX_wm_manager(C), CTX_data_main(C), true);
BKE_undo_number(C, item);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
}
diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c
index d0db3595c37..a15259e7d2d 100644
--- a/source/blender/editors/uvedit/uvedit_buttons.c
+++ b/source/blender/editors/uvedit/uvedit_buttons.c
@@ -53,7 +53,6 @@
#include "ED_uvedit.h"
#include "UI_interface.h"
-#include "UI_resources.h"
#include "WM_api.h"
#include "WM_types.h"
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 4c93cfa2cc5..b2c4970479a 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -43,7 +43,6 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_alloca.h"
#include "BLI_buffer.h"
#include "BLI_bitmap.h"
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 8865bc6775b..d1fd8d969a4 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -72,7 +72,6 @@ void uv_find_nearest_edge(struct Scene *scene, struct Image *ima, struct BMEditM
/* utility tool functions */
void uvedit_live_unwrap_update(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit);
-void uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMesh *em, float *aspx, float *aspy);
/* operators */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index b58944e4003..c70fcdbbd94 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -3189,8 +3189,8 @@ static void UV_OT_select_lasso(wmOperatorType *ot)
static void uv_snap_to_pixel(float uvco[2], float w, float h)
{
- uvco[0] = ((float)((int)((uvco[0] * w) + 0.5f))) / w;
- uvco[1] = ((float)((int)((uvco[1] * h) + 0.5f))) / h;
+ uvco[0] = roundf(uvco[0] * w) / w;
+ uvco[1] = roundf(uvco[1] * h) / h;
}
static void uv_snap_cursor_to_pixels(SpaceImage *sima)
@@ -3877,6 +3877,15 @@ static int uv_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *e
ARegion *ar = CTX_wm_region(C);
float location[2];
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ if (event->mval[1] <= 16) {
+ SpaceImage *sima = CTX_wm_space_image(C);
+ if (sima && ED_space_image_show_cache(sima)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+ }
+
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
RNA_float_set_array(op->ptr, "location", location);
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 79f53e1d971..569fe1c326d 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -35,7 +35,6 @@
#include "BLI_boxpack2d.h"
#include "BLI_convexhull2d.h"
-#include "uvedit_intern.h"
#include "uvedit_parametrizer.h"
#include <math.h>
@@ -3403,8 +3402,8 @@ static void p_chart_stretch_minimize(PChart *chart, RNG *rng)
static int p_compare_geometric_uv(const void *a, const void *b)
{
- PVert *v1 = *(PVert **)a;
- PVert *v2 = *(PVert **)b;
+ const PVert *v1 = *(const PVert * const *)a;
+ const PVert *v2 = *(const PVert * const *)b;
if (v1->uv[0] < v2->uv[0])
return -1;
@@ -3789,11 +3788,14 @@ static PBool p_node_intersect(SmoothNode *node, float co[2])
/* smoothing */
-static int p_compare_float(const void *a, const void *b)
+static int p_compare_float(const void *a_, const void *b_)
{
- if (*((float *)a) < *((float *)b))
+ const float a = *(const float *)a_;
+ const float b = *(const float *)b_;
+
+ if (a < b)
return -1;
- else if (*((float *)a) == *((float *)b))
+ else if (a == b)
return 0;
else
return 1;
@@ -4194,7 +4196,7 @@ void param_delete(ParamHandle *handle)
static void p_add_ngon(ParamHandle *handle, ParamKey key, int nverts,
ParamKey *vkeys, float **co, float **uv,
- ParamBool *pin, ParamBool *select, float normal[3])
+ ParamBool *pin, ParamBool *select, const float normal[3])
{
int *boundary = BLI_array_alloca(boundary, nverts);
int i;
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 9359baa5020..c5931cf2943 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -1354,16 +1354,15 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
/* Stitch hash initialization functions */
static unsigned int uv_edge_hash(const void *key)
{
- UvEdge *edge = (UvEdge *)key;
- return
- BLI_ghashutil_uinthash(edge->uv2) +
- BLI_ghashutil_uinthash(edge->uv1);
+ const UvEdge *edge = key;
+ return (BLI_ghashutil_uinthash(edge->uv2) +
+ BLI_ghashutil_uinthash(edge->uv1));
}
static bool uv_edge_compare(const void *a, const void *b)
{
- UvEdge *edge1 = (UvEdge *)a;
- UvEdge *edge2 = (UvEdge *)b;
+ const UvEdge *edge1 = a;
+ const UvEdge *edge2 = b;
if ((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)) {
return 0;
@@ -1660,7 +1659,7 @@ static int stitch_init(bContext *C, wmOperator *op)
return 0;
}
- uvedit_get_aspect(scene, obedit, em->bm, &aspx, &aspy);
+ ED_uvedit_get_aspect(scene, obedit, em->bm, &aspx, &aspy);
state->aspect = aspx / aspy;
/* Entirely possible if redoing last operator that static island is bigger than total number of islands.
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 6a33351753e..b5e27ab0cf6 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -190,7 +190,7 @@ static bool uvedit_have_selection(Scene *scene, BMEditMesh *em, bool implicit)
return false;
}
-void uvedit_get_aspect(Scene *scene, Object *ob, BMesh *bm, float *aspx, float *aspy)
+void ED_uvedit_get_aspect(Scene *scene, Object *ob, BMesh *bm, float *aspx, float *aspy)
{
bool sloppy = true;
bool selected = false;
@@ -264,7 +264,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMesh *bm,
if (correct_aspect) {
float aspx, aspy;
- uvedit_get_aspect(scene, ob, bm, &aspx, &aspy);
+ ED_uvedit_get_aspect(scene, ob, bm, &aspx, &aspy);
if (aspx != aspy)
param_aspect_ratio(handle, aspx, aspy);
@@ -376,7 +376,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
if (correct_aspect) {
float aspx, aspy;
- uvedit_get_aspect(scene, ob, em->bm, &aspx, &aspy);
+ ED_uvedit_get_aspect(scene, ob, em->bm, &aspx, &aspy);
if (aspx != aspy)
param_aspect_ratio(handle, aspx, aspy);
@@ -1010,7 +1010,7 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- uvedit_get_aspect(scene, ob, em->bm, &aspx, &aspy);
+ ED_uvedit_get_aspect(scene, ob, em->bm, &aspx, &aspy);
if (aspx == aspy)
return;
diff --git a/source/blender/freestyle/CMakeLists.txt b/source/blender/freestyle/CMakeLists.txt
index cb187eca6ac..6860afe64c2 100644
--- a/source/blender/freestyle/CMakeLists.txt
+++ b/source/blender/freestyle/CMakeLists.txt
@@ -392,6 +392,8 @@ set(SRC
intern/scene_graph/NodeGroup.h
intern/scene_graph/NodeLight.cpp
intern/scene_graph/NodeLight.h
+ intern/scene_graph/NodeSceneRenderLayer.cpp
+ intern/scene_graph/NodeSceneRenderLayer.h
intern/scene_graph/NodeShape.cpp
intern/scene_graph/NodeShape.h
intern/scene_graph/NodeTransform.cpp
diff --git a/source/blender/freestyle/intern/application/AppConfig.cpp b/source/blender/freestyle/intern/application/AppConfig.cpp
index cf7959ffaef..44f8e9b135e 100644
--- a/source/blender/freestyle/intern/application/AppConfig.cpp
+++ b/source/blender/freestyle/intern/application/AppConfig.cpp
@@ -31,7 +31,7 @@
using namespace std;
extern "C" {
-#include "BLI_path_util.h"
+#include "BKE_appdir.h"
}
namespace Freestyle {
@@ -43,7 +43,7 @@ Path::Path()
{
// get the root directory
// soc
- setRootDir(BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, NULL));
+ setRootDir(BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, NULL));
_pInstance = this;
}
diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp
index 7ecb4164caf..f8931d32f56 100644
--- a/source/blender/freestyle/intern/application/Controller.cpp
+++ b/source/blender/freestyle/intern/application/Controller.cpp
@@ -40,6 +40,7 @@ extern "C" {
#include "../scene_graph/NodeDrawingStyle.h"
#include "../scene_graph/NodeShape.h"
#include "../scene_graph/NodeTransform.h"
+#include "../scene_graph/NodeSceneRenderLayer.h"
#include "../scene_graph/ScenePrettyPrinter.h"
#include "../scene_graph/VertexRep.h"
@@ -67,6 +68,7 @@ extern "C" {
#include "BKE_global.h"
#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
#include "DNA_freestyle_types.h"
@@ -219,11 +221,10 @@ bool Controller::hitViewMapCache()
if (!_EnableViewMapCache) {
return false;
}
- real hashCode = sceneHashFunc.getValue();
- if (prevSceneHash == hashCode) {
+ if (sceneHashFunc.match()) {
return (NULL != _ViewMap);
}
- prevSceneHash = hashCode;
+ sceneHashFunc.store();
return false;
}
@@ -280,10 +281,27 @@ int Controller::LoadMesh(Render *re, SceneRenderLayer *srl)
return 0;
if (_EnableViewMapCache) {
+
+ NodeCamera *cam;
+ if (freestyle_proj[3][3] != 0.0)
+ cam = new NodeOrthographicCamera;
+ else
+ cam = new NodePerspectiveCamera;
+ double proj[16];
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ proj[i * 4 + j] = freestyle_proj[i][j];
+ }
+ }
+ cam->setProjectionMatrix(proj);
+ _RootNode->AddChild(cam);
+ _RootNode->AddChild(new NodeSceneRenderLayer(*srl));
+
sceneHashFunc.reset();
- blenderScene->accept(sceneHashFunc);
+ //blenderScene->accept(sceneHashFunc);
+ _RootNode->accept(sceneHashFunc);
if (G.debug & G_DEBUG_FREESTYLE) {
- printf("Scene hash : %.16e\n", sceneHashFunc.getValue());
+ cout << "Scene hash : " << sceneHashFunc.toString() << endl;
}
if (hitViewMapCache()) {
ClearRootNode();
@@ -864,10 +882,13 @@ void Controller::ResetRenderCount()
Render *Controller::RenderStrokes(Render *re, bool render)
{
+ int totmesh = 0;
_Chrono.start();
BlenderStrokeRenderer *blenderRenderer = new BlenderStrokeRenderer(re, ++_render_count);
- if (render)
+ if (render) {
_Canvas->Render(blenderRenderer);
+ totmesh = blenderRenderer->GenerateScene();
+ }
real d = _Chrono.stop();
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Temporary scene generation: " << d << endl;
@@ -886,8 +907,8 @@ Render *Controller::RenderStrokes(Render *re, bool render)
float mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0);
float megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
- printf("%d verts, %d faces, mem %.2fM (%.2fM, peak %.2fM)\n",
- freestyle_render->i.totvert, freestyle_render->i.totface,
+ printf("%d objs, %d verts, %d faces, mem %.2fM (%.2fM, peak %.2fM)\n",
+ totmesh, freestyle_render->i.totvert, freestyle_render->i.totface,
megs_used_memory, mmap_used_memory, megs_peak_memory);
}
delete blenderRenderer;
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index 09701ab6acd..29f3bfe0d94 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -66,6 +66,8 @@ extern "C" {
namespace Freestyle {
+const char *BlenderStrokeRenderer::uvNames[] = {"along_stroke", "along_stroke_tips"};
+
BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : StrokeRenderer()
{
freestyle_bmain = re->freestyle_bmain;
@@ -208,6 +210,8 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer()
if (_use_shading_nodes)
BLI_ghash_free(_nodetree_hash, NULL, NULL);
+
+ FreeStrokeGroups();
}
float BlenderStrokeRenderer::get_stroke_vertex_z(void) const
@@ -414,10 +418,10 @@ Material* BlenderStrokeRenderer::GetStrokeShader(Main *bmain, bNodeTree *iNodeTr
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));
+ BLI_strncpy(storage->uv_map, uvNames[1], sizeof(storage->uv_map));
}
else {
- BLI_strncpy(storage->uv_map, "along_stroke", sizeof(storage->uv_map));
+ BLI_strncpy(storage->uv_map, uvNames[0], sizeof(storage->uv_map));
}
fromsock = (bNodeSocket *)BLI_findlink(&input_uvmap->outputs, 0); // UV
@@ -440,6 +444,11 @@ Material* BlenderStrokeRenderer::GetStrokeShader(Main *bmain, bNodeTree *iNodeTr
void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
+{
if (_use_shading_nodes) {
bNodeTree *nt = iStrokeRep->getNodeTree();
Material *ma = (Material *)BLI_ghash_lookup(_nodetree_hash, nt);
@@ -509,10 +518,10 @@ void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
// We'll generate both with tips and without tips
// coordinates, on two different UV layers.
if (ma->mtex[a]->texflag & MTEX_TIPS) {
- BLI_strncpy(ma->mtex[a]->uvname, "along_stroke_tips", sizeof(ma->mtex[a]->uvname));
+ BLI_strncpy(ma->mtex[a]->uvname, uvNames[1], sizeof(ma->mtex[a]->uvname));
}
else {
- BLI_strncpy(ma->mtex[a]->uvname, "along_stroke", sizeof(ma->mtex[a]->uvname));
+ BLI_strncpy(ma->mtex[a]->uvname, uvNames[0], sizeof(ma->mtex[a]->uvname));
}
a++;
}
@@ -521,7 +530,42 @@ void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
}
}
- RenderStrokeRepBasic(iStrokeRep);
+ const vector<Strip*>& strips = iStrokeRep->getStrips();
+ const bool hasTex = iStrokeRep->hasTex();
+ int totvert = 0, totedge = 0, totpoly = 0, totloop = 0;
+ int visible_faces, visible_segments;
+ for (vector<Strip*>::const_iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
+ Strip::vertex_container& strip_vertices = (*s)->vertices();
+
+ // count visible faces and strip segments
+ test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
+ if (visible_faces == 0)
+ continue;
+
+ totvert += visible_faces + visible_segments * 2;
+ totedge += visible_faces * 2 + visible_segments;
+ totpoly += visible_faces;
+ totloop += visible_faces * 3;
+ }
+
+ BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this); // FIXME
+ vector<StrokeGroup*> *groups = hasTex ? &self->texturedStrokeGroups : &self->strokeGroups;
+ StrokeGroup *group;
+ if (groups->empty() || !(groups->back()->totvert + totvert < MESH_MAX_VERTS &&
+ groups->back()->totcol + 1 < MAXMAT))
+ {
+ group = new StrokeGroup;
+ groups->push_back(group);
+ }
+ else {
+ group = groups->back();
+ }
+ group->strokes.push_back(iStrokeRep);
+ group->totvert += totvert;
+ group->totedge += totedge;
+ group->totpoly += totpoly;
+ group->totloop += totloop;
+ group->totcol++;
}
// Check if the triangle is visible (i.e., within the render image boundary)
@@ -578,127 +622,168 @@ void BlenderStrokeRenderer::test_strip_visibility(Strip::vertex_container& strip
}
}
-// Build a mesh object representing a stroke
-void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
+// Release allocated memory for stroke groups
+void BlenderStrokeRenderer::FreeStrokeGroups()
{
- vector<Strip*>& strips = iStrokeRep->getStrips();
- const bool hasTex = iStrokeRep->hasTex();
- Strip::vertex_container::iterator v[3];
- StrokeVertexRep *svRep[3];
- unsigned int vertex_index, edge_index, loop_index;
- Vec2r p;
+ vector<StrokeGroup*>::const_iterator it, itend;
- int totvert = 0, totedge = 0, totpoly = 0, totloop = 0;
- int visible_faces, visible_segments;
-
- bool visible;
- for (vector<Strip*>::iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
- Strip::vertex_container& strip_vertices = (*s)->vertices();
+ for (it = strokeGroups.begin(), itend = strokeGroups.end();
+ it != itend; ++it)
+ {
+ delete (*it);
+ }
+ for (it = texturedStrokeGroups.begin(), itend = texturedStrokeGroups.end();
+ it != itend; ++it)
+ {
+ delete (*it);
+ }
+}
- // count visible faces and strip segments
- test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
- if (visible_faces == 0)
- continue;
+// Build a scene populated by mesh objects representing stylized strokes
+int BlenderStrokeRenderer::GenerateScene()
+{
+ vector<StrokeGroup*>::const_iterator it, itend;
- totvert += visible_faces + visible_segments * 2;
- totedge += visible_faces * 2 + visible_segments;
- totpoly += visible_faces;
- totloop += visible_faces * 3;
+ for (it = strokeGroups.begin(), itend = strokeGroups.end();
+ it != itend; ++it)
+ {
+ GenerateStrokeMesh(*it, false);
+ }
+ for (it = texturedStrokeGroups.begin(), itend = texturedStrokeGroups.end();
+ it != itend; ++it)
+ {
+ GenerateStrokeMesh(*it, true);
}
+ return strokeGroups.size() + texturedStrokeGroups.size();
+}
+// Build a mesh object representing a group of stylized strokes
+void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
+{
#if 0
Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, OB_MESH);
#else
Object *object_mesh = NewMesh();
#endif
Mesh *mesh = (Mesh *)object_mesh->data;
- mesh->mat = (Material **)MEM_mallocN(1 * sizeof(Material *), "MaterialList");
- mesh->mat[0] = iStrokeRep->getMaterial();
- mesh->totcol = 1;
- test_object_materials(freestyle_bmain, (ID *)mesh);
- // vertices allocation
- mesh->totvert = totvert; // visible_faces + visible_segments * 2;
- CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
+ mesh->totvert = group->totvert;
+ mesh->totedge = group->totedge;
+ mesh->totpoly = group->totpoly;
+ mesh->totloop = group->totloop;
+ mesh->totcol = group->totcol;
- // edges allocation
- mesh->totedge = totedge; // visible_faces * 2 + visible_segments;
- CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
+ mesh->mvert = (MVert *)CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
+ mesh->medge = (MEdge *)CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
+ mesh->mpoly = (MPoly *)CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
+ mesh->mloop = (MLoop *)CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
- // faces allocation
- mesh->totpoly = totpoly; // visible_faces;
- CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
-
- // loops allocation
- mesh->totloop = totloop; // visible_faces * 3;
- CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
-
- // uv maps
+ MVert *vertices = mesh->mvert;
+ MEdge *edges = mesh->medge;
+ MPoly *polys = mesh->mpoly;
+ MLoop *loops = mesh->mloop;
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");
+ if (hasTex) {
+ // First UV layer
+ CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, uvNames[0]);
+ CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[0]);
+ 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, uvNames[1]);
+ CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[1]);
+ 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;
}
// 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");
+ mesh->mloopcol = colors;
- BKE_mesh_update_customdata_pointers(mesh, true);
+ mesh->mat = (Material **)MEM_mallocN(sizeof(Material *) * mesh->totcol, "MaterialList");
////////////////////
// Data copy
////////////////////
- MVert *vertices = mesh->mvert;
- MEdge *edges = mesh->medge;
- MPoly *polys = mesh->mpoly;
- MLoop *loops = mesh->mloop;
+ int vertex_index = 0, edge_index = 0, loop_index = 0, material_index = 0;
+ int visible_faces, visible_segments;
+ bool visible;
+ Strip::vertex_container::iterator v[3];
+ StrokeVertexRep *svRep[3];
+ Vec2r p;
- vertex_index = edge_index = loop_index = 0;
+ for (vector<StrokeRep*>::const_iterator it = group->strokes.begin(), itend = group->strokes.end();
+ it != itend; ++it)
+ {
+ mesh->mat[material_index] = (*it)->getMaterial();
+ material_index++;
- for (vector<Strip*>::iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
- Strip::vertex_container& strip_vertices = (*s)->vertices();
- int strip_vertex_count = strip_vertices.size();
+ vector<Strip*>& strips = (*it)->getStrips();
+ for (vector<Strip*>::const_iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
+ Strip::vertex_container& strip_vertices = (*s)->vertices();
+ int strip_vertex_count = strip_vertices.size();
- // count visible faces and strip segments
- test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
- if (visible_faces == 0)
- continue;
+ // count visible faces and strip segments
+ test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
+ if (visible_faces == 0)
+ continue;
- v[0] = strip_vertices.begin();
- v[1] = v[0] + 1;
- v[2] = v[0] + 2;
+ v[0] = strip_vertices.begin();
+ v[1] = v[0] + 1;
+ v[2] = v[0] + 2;
- visible = false;
+ visible = false;
- // Note: Mesh generation in the following loop assumes stroke strips
- // to be triangle strips.
- for (int n = 2; n < strip_vertex_count; n++, v[0]++, v[1]++, v[2]++) {
- svRep[0] = *(v[0]);
- svRep[1] = *(v[1]);
- svRep[2] = *(v[2]);
- if (!test_triangle_visibility(svRep)) {
- visible = false;
- }
- else {
- if (!visible) {
- // first vertex
- vertices->co[0] = svRep[0]->point2d()[0];
- vertices->co[1] = svRep[0]->point2d()[1];
- vertices->co[2] = get_stroke_vertex_z();
- vertices->no[0] = 0;
- vertices->no[1] = 0;
- vertices->no[2] = SHRT_MAX;
- ++vertices;
- ++vertex_index;
+ // Note: Mesh generation in the following loop assumes stroke strips
+ // to be triangle strips.
+ for (int n = 2; n < strip_vertex_count; n++, v[0]++, v[1]++, v[2]++) {
+ svRep[0] = *(v[0]);
+ svRep[1] = *(v[1]);
+ svRep[2] = *(v[2]);
+ if (!test_triangle_visibility(svRep)) {
+ visible = false;
+ }
+ else {
+ if (!visible) {
+ // first vertex
+ vertices->co[0] = svRep[0]->point2d()[0];
+ vertices->co[1] = svRep[0]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+ vertices->no[0] = 0;
+ vertices->no[1] = 0;
+ vertices->no[2] = SHRT_MAX;
+ ++vertices;
+ ++vertex_index;
+
+ // second vertex
+ vertices->co[0] = svRep[1]->point2d()[0];
+ vertices->co[1] = svRep[1]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+ vertices->no[0] = 0;
+ vertices->no[1] = 0;
+ vertices->no[2] = SHRT_MAX;
+ ++vertices;
+ ++vertex_index;
+
+ // first edge
+ edges->v1 = vertex_index - 2;
+ edges->v2 = vertex_index - 1;
+ ++edges;
+ ++edge_index;
+ }
+ visible = true;
- // second vertex
- vertices->co[0] = svRep[1]->point2d()[0];
- vertices->co[1] = svRep[1]->point2d()[1];
+ // vertex
+ vertices->co[0] = svRep[2]->point2d()[0];
+ vertices->co[1] = svRep[2]->point2d()[1];
vertices->co[2] = get_stroke_vertex_z();
vertices->no[0] = 0;
vertices->no[1] = 0;
@@ -706,140 +791,127 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
++vertices;
++vertex_index;
- // first edge
- edges->v1 = vertex_index - 2;
- edges->v2 = vertex_index - 1;
+ // edges
+ edges->v1 = vertex_index - 1;
+ edges->v2 = vertex_index - 3;
++edges;
++edge_index;
- }
- visible = true;
-
- // vertex
- vertices->co[0] = svRep[2]->point2d()[0];
- vertices->co[1] = svRep[2]->point2d()[1];
- vertices->co[2] = get_stroke_vertex_z();
- vertices->no[0] = 0;
- vertices->no[1] = 0;
- vertices->no[2] = SHRT_MAX;
- ++vertices;
- ++vertex_index;
-
- // edges
- edges->v1 = vertex_index - 1;
- edges->v2 = vertex_index - 3;
- ++edges;
- ++edge_index;
-
- edges->v1 = vertex_index - 1;
- edges->v2 = vertex_index - 2;
- ++edges;
- ++edge_index;
-
- // poly
- polys->loopstart = loop_index;
- polys->totloop = 3;
- ++polys;
-
- // Even and odd loops connect triangles vertices differently
- bool is_odd = n % 2;
- // loops
- if (is_odd) {
- loops[0].v = vertex_index - 1;
- loops[0].e = edge_index - 2;
-
- loops[1].v = vertex_index - 3;
- loops[1].e = edge_index - 3;
-
- loops[2].v = vertex_index - 2;
- loops[2].e = edge_index - 1;
- }
- else {
- loops[0].v = vertex_index - 1;
- loops[0].e = edge_index - 1;
- loops[1].v = vertex_index - 2;
- loops[1].e = edge_index - 3;
+ edges->v1 = vertex_index - 1;
+ edges->v2 = vertex_index - 2;
+ ++edges;
+ ++edge_index;
- loops[2].v = vertex_index - 3;
- loops[2].e = edge_index - 2;
- }
- loops += 3;
- loop_index += 3;
-
- // UV
- if (hasTex) {
- // First UV layer (loopsuv[0]) has no tips (texCoord(0)).
- // Second UV layer (loopsuv[1]) has tips: (texCoord(1)).
- for (int L = 0; L < 2; L++) {
- if (is_odd) {
- loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
- loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
-
- loopsuv[L][1].uv[0] = svRep[0]->texCoord(L).x();
- loopsuv[L][1].uv[1] = svRep[0]->texCoord(L).y();
-
- loopsuv[L][2].uv[0] = svRep[1]->texCoord(L).x();
- loopsuv[L][2].uv[1] = svRep[1]->texCoord(L).y();
- }
- else {
- loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
- loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
+ // poly
+ polys->loopstart = loop_index;
+ polys->totloop = 3;
+ ++polys;
+
+ // Even and odd loops connect triangles vertices differently
+ bool is_odd = n % 2;
+ // loops
+ if (is_odd) {
+ loops[0].v = vertex_index - 1;
+ loops[0].e = edge_index - 2;
- loopsuv[L][1].uv[0] = svRep[1]->texCoord(L).x();
- loopsuv[L][1].uv[1] = svRep[1]->texCoord(L).y();
+ loops[1].v = vertex_index - 3;
+ loops[1].e = edge_index - 3;
- loopsuv[L][2].uv[0] = svRep[0]->texCoord(L).x();
- loopsuv[L][2].uv[1] = svRep[0]->texCoord(L).y();
+ loops[2].v = vertex_index - 2;
+ loops[2].e = edge_index - 1;
+ }
+ else {
+ loops[0].v = vertex_index - 1;
+ loops[0].e = edge_index - 1;
+
+ loops[1].v = vertex_index - 2;
+ loops[1].e = edge_index - 3;
+
+ loops[2].v = vertex_index - 3;
+ loops[2].e = edge_index - 2;
+ }
+ loops += 3;
+ loop_index += 3;
+
+ // UV
+ if (hasTex) {
+ // First UV layer (loopsuv[0]) has no tips (texCoord(0)).
+ // Second UV layer (loopsuv[1]) has tips: (texCoord(1)).
+ for (int L = 0; L < 2; L++) {
+ if (is_odd) {
+ loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
+ loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
+
+ loopsuv[L][1].uv[0] = svRep[0]->texCoord(L).x();
+ loopsuv[L][1].uv[1] = svRep[0]->texCoord(L).y();
+
+ loopsuv[L][2].uv[0] = svRep[1]->texCoord(L).x();
+ loopsuv[L][2].uv[1] = svRep[1]->texCoord(L).y();
+ }
+ else {
+ loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
+ loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
+
+ loopsuv[L][1].uv[0] = svRep[1]->texCoord(L).x();
+ loopsuv[L][1].uv[1] = svRep[1]->texCoord(L).y();
+
+ loopsuv[L][2].uv[0] = svRep[0]->texCoord(L).x();
+ loopsuv[L][2].uv[1] = svRep[0]->texCoord(L).y();
+ }
+ loopsuv[L] += 3;
}
- loopsuv[L] += 3;
}
- }
- // 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]);
- colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
- colors[0].a = (short)(255.0f * svRep[2]->alpha());
-
- colors[1].r = (short)(255.0f * svRep[0]->color()[0]);
- colors[1].g = (short)(255.0f * svRep[0]->color()[1]);
- colors[1].b = (short)(255.0f * svRep[0]->color()[2]);
- colors[1].a = (short)(255.0f * svRep[0]->alpha());
-
- colors[2].r = (short)(255.0f * svRep[1]->color()[0]);
- 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]);
- colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
- colors[0].a = (short)(255.0f * svRep[2]->alpha());
-
- colors[1].r = (short)(255.0f * svRep[1]->color()[0]);
- colors[1].g = (short)(255.0f * svRep[1]->color()[1]);
- colors[1].b = (short)(255.0f * svRep[1]->color()[2]);
- colors[1].a = (short)(255.0f * svRep[1]->alpha());
-
- colors[2].r = (short)(255.0f * svRep[0]->color()[0]);
- colors[2].g = (short)(255.0f * svRep[0]->color()[1]);
- colors[2].b = (short)(255.0f * svRep[0]->color()[2]);
- colors[2].a = (short)(255.0f * svRep[0]->alpha());
+ // 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]);
+ colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
+ colors[0].a = (short)(255.0f * svRep[2]->alpha());
+
+ colors[1].r = (short)(255.0f * svRep[0]->color()[0]);
+ colors[1].g = (short)(255.0f * svRep[0]->color()[1]);
+ colors[1].b = (short)(255.0f * svRep[0]->color()[2]);
+ colors[1].a = (short)(255.0f * svRep[0]->alpha());
+
+ colors[2].r = (short)(255.0f * svRep[1]->color()[0]);
+ 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]);
+ colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
+ colors[0].a = (short)(255.0f * svRep[2]->alpha());
+
+ colors[1].r = (short)(255.0f * svRep[1]->color()[0]);
+ colors[1].g = (short)(255.0f * svRep[1]->color()[1]);
+ colors[1].b = (short)(255.0f * svRep[1]->color()[2]);
+ colors[1].a = (short)(255.0f * svRep[1]->alpha());
+
+ colors[2].r = (short)(255.0f * svRep[0]->color()[0]);
+ colors[2].g = (short)(255.0f * svRep[0]->color()[1]);
+ 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;
}
- 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
-#if 0
- BLI_assert(totvert == vertex_index);
- BLI_assert(totedge == edge_index);
- BLI_assert(totloop == loop_index);
+ } // loop over strip vertices
+ } // loop over strips
+ } // loop over strokes
+
+ test_object_materials(freestyle_bmain, (ID *)mesh);
+
+#if 0 // XXX
+ BLI_assert(mesh->totvert == vertex_index);
+ BLI_assert(mesh->totedge == edge_index);
+ BLI_assert(mesh->totloop == loop_index);
+ BLI_assert(mesh->totcol == material_index);
BKE_mesh_validate(mesh, true);
#endif
}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
index 74e5d321df2..a381932e9e7 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
@@ -53,6 +53,21 @@ public:
Object *NewMesh() const;
+ struct StrokeGroup {
+ explicit StrokeGroup() : totvert(0), totedge(0), totpoly(0), totloop(0), totcol(0) {}
+ vector<StrokeRep*> strokes;
+ int totvert;
+ int totedge;
+ int totpoly;
+ int totloop;
+ int totcol;
+ };
+ vector<StrokeGroup*> strokeGroups, texturedStrokeGroups;
+
+ int GenerateScene();
+ void GenerateStrokeMesh(StrokeGroup *group, bool hasTex);
+ void FreeStrokeGroups();
+
Render *RenderScene(Render *re, bool render);
static Material* GetStrokeShader(Main *bmain, bNodeTree *iNodeTree, bool do_id_user);
@@ -68,12 +83,16 @@ protected:
bool _use_shading_nodes;
struct GHash *_nodetree_hash;
+ static const char *uvNames[];
+
float get_stroke_vertex_z(void) const;
unsigned int get_stroke_mesh_id(void) const;
bool test_triangle_visibility(StrokeVertexRep *svRep[3]) const;
void test_strip_visibility(Strip::vertex_container& strip_vertices,
int *visible_faces, int *visible_segments) const;
+ vector<StrokeRep *> _strokeReps;
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderStrokeRenderer")
#endif
diff --git a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
index dd678ee6fbd..ad54a81f156 100644
--- a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
+++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
@@ -92,10 +92,11 @@ ContextFunctions_get_border(PyObject *self)
{
BBox<Vec2i> border(ContextFunctions::GetBorderCF());
PyObject *v = PyTuple_New(4);
- PyTuple_SET_ITEM(v, 0, PyLong_FromLong(border.getMin().x()));
- PyTuple_SET_ITEM(v, 1, PyLong_FromLong(border.getMin().y()));
- PyTuple_SET_ITEM(v, 2, PyLong_FromLong(border.getMax().x()));
- PyTuple_SET_ITEM(v, 3, PyLong_FromLong(border.getMax().y()));
+ PyTuple_SET_ITEMS(v,
+ PyLong_FromLong(border.getMin().x()),
+ PyLong_FromLong(border.getMin().y()),
+ PyLong_FromLong(border.getMax().x()),
+ PyLong_FromLong(border.getMax().y()));
return v;
}
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.cpp b/source/blender/freestyle/intern/python/BPy_Convert.cpp
index dbd836bc562..4e1a0a119aa 100644
--- a/source/blender/freestyle/intern/python/BPy_Convert.cpp
+++ b/source/blender/freestyle/intern/python/BPy_Convert.cpp
@@ -81,7 +81,7 @@ PyObject *Vector_from_Vec2f(Vec2f& vec)
float vec_data[2]; // because vec->_coord is protected
vec_data[0] = vec.x();
vec_data[1] = vec.y();
- return Vector_CreatePyObject(vec_data, 2, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec_data, 2, NULL);
}
PyObject *Vector_from_Vec3f(Vec3f& vec)
@@ -90,7 +90,7 @@ PyObject *Vector_from_Vec3f(Vec3f& vec)
vec_data[0] = vec.x();
vec_data[1] = vec.y();
vec_data[2] = vec.z();
- return Vector_CreatePyObject(vec_data, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec_data, 3, NULL);
}
PyObject *Vector_from_Vec3r(Vec3r& vec)
@@ -99,7 +99,7 @@ PyObject *Vector_from_Vec3r(Vec3r& vec)
vec_data[0] = vec.x();
vec_data[1] = vec.y();
vec_data[2] = vec.z();
- return Vector_CreatePyObject(vec_data, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec_data, 3, NULL);
}
PyObject *BPy_Id_from_Id(Id& id)
@@ -401,8 +401,9 @@ PyObject *BPy_CurvePoint_from_CurvePoint(CurvePoint& cp)
PyObject *BPy_directedViewEdge_from_directedViewEdge(ViewVertex::directedViewEdge& dve)
{
PyObject *py_dve = PyTuple_New(2);
- PyTuple_SET_ITEM(py_dve, 0, BPy_ViewEdge_from_ViewEdge(*(dve.first)));
- PyTuple_SET_ITEM(py_dve, 1, PyBool_from_bool(dve.second));
+ PyTuple_SET_ITEMS(py_dve,
+ BPy_ViewEdge_from_ViewEdge(*(dve.first)),
+ PyBool_from_bool(dve.second));
return py_dve;
}
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.h b/source/blender/freestyle/intern/python/BPy_Convert.h
index e6e763e763e..35c1e58369c 100644
--- a/source/blender/freestyle/intern/python/BPy_Convert.h
+++ b/source/blender/freestyle/intern/python/BPy_Convert.h
@@ -92,6 +92,7 @@ extern "C" {
///////////////////////////////////////////////////////////////////////////////////////////
#include "mathutils/mathutils.h"
+#include "generic/python_utildefines.h"
//==============================
// C++ => Python
diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
index 5b8d50eb5eb..f4ead300d5e 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 "BKE_appdir.h"
#include "DNA_scene_types.h"
#include "bpy_rna.h" /* pyrna_struct_CreatePyObject() */
@@ -152,7 +153,7 @@ static PyObject *Freestyle_blendRamp(PyObject *self, PyObject *args)
return NULL;
}
ramp_blend(type, a, fac, b);
- return Vector_CreatePyObject(a, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(a, 3, NULL);
}
#include "BKE_texture.h" /* do_colorband() */
@@ -186,7 +187,7 @@ static PyObject *Freestyle_evaluateColorRamp(PyObject *self, PyObject *args)
PyErr_SetString(PyExc_ValueError, "failed to evaluate the color ramp");
return NULL;
}
- return Vector_CreatePyObject(out, 4, Py_NEW, NULL);
+ return Vector_CreatePyObject(out, 4, NULL);
}
#include "DNA_color_types.h"
@@ -492,7 +493,7 @@ PyObject *Freestyle_Init(void)
PyDict_SetItemString(PySys_GetObject("modules"), module_definition.m_name, module);
// update 'sys.path' for Freestyle Python API modules
- const char * const path = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, "freestyle");
+ const char * const path = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, "freestyle");
if (path) {
char modpath[FILE_MAX];
BLI_join_dirfile(modpath, sizeof(modpath), path, "modules");
diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp
index d3cb44f5903..57ec15f4150 100644
--- a/source/blender/freestyle/intern/python/BPy_Operators.cpp
+++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp
@@ -532,8 +532,9 @@ static PyObject *Operators_create(BPy_Operators *self, PyObject *args, PyObject
return NULL;
}
vector<StrokeShader *> shaders;
+ shaders.reserve(PyList_Size(obj2));
for (int i = 0; i < PyList_Size(obj2); i++) {
- PyObject *py_ss = PyList_GetItem(obj2, i);
+ PyObject *py_ss = PyList_GET_ITEM(obj2, i);
if (!BPy_StrokeShader_Check(py_ss)) {
PyErr_SetString(PyExc_TypeError, "Operators.create(): 2nd argument must be a list of StrokeShader objects");
return NULL;
diff --git a/source/blender/freestyle/intern/python/BPy_SShape.cpp b/source/blender/freestyle/intern/python/BPy_SShape.cpp
index e5a38171ecd..11ed07df5de 100644
--- a/source/blender/freestyle/intern/python/BPy_SShape.cpp
+++ b/source/blender/freestyle/intern/python/BPy_SShape.cpp
@@ -227,13 +227,14 @@ PyDoc_STRVAR(SShape_vertices_doc,
static PyObject *SShape_vertices_get(BPy_SShape *self, void *UNUSED(closure))
{
- PyObject *py_vertices = PyList_New(0);
vector< SVertex * > vertices = self->ss->getVertexList();
vector< SVertex * >::iterator it;
+ PyObject *py_vertices = PyList_New(vertices.size());
+ unsigned int i = 0;
for (it = vertices.begin(); it != vertices.end(); it++) {
- PyList_Append(py_vertices, BPy_SVertex_from_SVertex(*(*it)));
+ PyList_SET_ITEM(py_vertices, i++, BPy_SVertex_from_SVertex(*(*it)));
}
return py_vertices;
@@ -246,13 +247,14 @@ PyDoc_STRVAR(SShape_edges_doc,
static PyObject *SShape_edges_get(BPy_SShape *self, void *UNUSED(closure))
{
- PyObject *py_edges = PyList_New(0);
vector< FEdge * > edges = self->ss->getEdgeList();
vector< FEdge * >::iterator it;
+ PyObject *py_edges = PyList_New(edges.size());
+ unsigned int i = 0;
for (it = edges.begin(); it != edges.end(); it++) {
- PyList_Append(py_edges, Any_BPy_FEdge_from_FEdge(*(*it)));
+ PyList_SET_ITEM(py_edges, i++, Any_BPy_FEdge_from_FEdge(*(*it)));
}
return py_edges;
diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
index 2c767eacaec..6c6e821a1e4 100644
--- a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
+++ b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
@@ -207,12 +207,13 @@ PyDoc_STRVAR(ViewShape_vertices_doc,
static PyObject *ViewShape_vertices_get(BPy_ViewShape *self, void *UNUSED(closure))
{
- PyObject *py_vertices = PyList_New(0);
-
vector<ViewVertex *> vertices = self->vs->vertices();
vector<ViewVertex *>::iterator it;
+ PyObject *py_vertices = PyList_New(vertices.size());
+ unsigned int i = 0;
+
for (it = vertices.begin(); it != vertices.end(); it++) {
- PyList_Append( py_vertices, Any_BPy_ViewVertex_from_ViewVertex(*(*it)));
+ PyList_SET_ITEM(py_vertices, i++, Any_BPy_ViewVertex_from_ViewVertex(*(*it)));
}
return py_vertices;
}
@@ -227,8 +228,10 @@ static int ViewShape_vertices_set(BPy_ViewShape *self, PyObject *value, void *UN
PyErr_SetString(PyExc_TypeError, "value must be a list of ViewVertex objects");
return -1;
}
- for (int i = 0; i < PyList_Size(list); i++) {
- item = PyList_GetItem(list, i);
+
+ v.reserve(PyList_Size(list));
+ for (unsigned int i = 0; i < PyList_Size(list); i++) {
+ item = PyList_GET_ITEM(list, i);
if (BPy_ViewVertex_Check(item)) {
v.push_back(((BPy_ViewVertex *)item)->vv);
}
@@ -248,13 +251,13 @@ PyDoc_STRVAR(ViewShape_edges_doc,
static PyObject *ViewShape_edges_get(BPy_ViewShape *self, void *UNUSED(closure))
{
- PyObject *py_edges = PyList_New(0);
-
vector<ViewEdge *> edges = self->vs->edges();
vector<ViewEdge *>::iterator it;
+ PyObject *py_edges = PyList_New(edges.size());
+ unsigned int i = 0;
for (it = edges.begin(); it != edges.end(); it++) {
- PyList_Append(py_edges, BPy_ViewEdge_from_ViewEdge(*(*it)));
+ PyList_SET_ITEM(py_edges, i++, BPy_ViewEdge_from_ViewEdge(*(*it)));
}
return py_edges;
}
@@ -269,8 +272,10 @@ static int ViewShape_edges_set(BPy_ViewShape *self, PyObject *value, void *UNUSE
PyErr_SetString(PyExc_TypeError, "value must be a list of ViewEdge objects");
return -1;
}
+
+ v.reserve(PyList_Size(list));
for (int i = 0; i < PyList_Size(list); i++) {
- item = PyList_GetItem(list, i);
+ item = PyList_GET_ITEM(list, i);
if (BPy_ViewEdge_Check(item)) {
v.push_back(((BPy_ViewEdge *)item)->ve);
}
diff --git a/source/blender/freestyle/intern/python/Director.cpp b/source/blender/freestyle/intern/python/Director.cpp
index 653fd0b1d29..9f85e84e297 100644
--- a/source/blender/freestyle/intern/python/Director.cpp
+++ b/source/blender/freestyle/intern/python/Director.cpp
@@ -265,8 +265,9 @@ int Director_BPy_UnaryFunction0D___call__(void *uf0D, void *py_uf0D, Interface0D
}
else if (BPy_UnaryFunction0DVectorViewShape_Check(obj)) {
vector<ViewShape*> vec;
+ vec.reserve(PyList_Size(result));
for (int i = 0; i < PyList_Size(result); i++) {
- ViewShape *b = ((BPy_ViewShape *)PyList_GetItem(result, i))->vs;
+ ViewShape *b = ((BPy_ViewShape *)PyList_GET_ITEM(result, i))->vs;
vec.push_back(b);
}
((UnaryFunction0D< vector<ViewShape*> > *)uf0D)->result = vec;
@@ -318,8 +319,9 @@ int Director_BPy_UnaryFunction1D___call__(void *uf1D, void *py_uf1D, Interface1D
}
else if (BPy_UnaryFunction1DVectorViewShape_Check(obj)) {
vector<ViewShape*> vec;
+ vec.reserve(PyList_Size(result));
for (int i = 1; i < PyList_Size(result); i++) {
- ViewShape *b = ((BPy_ViewShape *)PyList_GetItem(result, i))->vs;
+ ViewShape *b = ((BPy_ViewShape *)PyList_GET_ITEM(result, i))->vs;
vec.push_back(b);
}
((UnaryFunction1D< vector<ViewShape*> > *)uf1D)->result = vec;
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
index 6f47ce93ca8..1d51bf287af 100644
--- a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
@@ -342,13 +342,14 @@ PyDoc_STRVAR(SVertex_normals_doc,
static PyObject *SVertex_normals_get(BPy_SVertex *self, void *UNUSED(closure))
{
PyObject *py_normals;
- set< Vec3r > normals;
-
- py_normals = PyList_New(0);
- normals = self->sv->normals();
- for (set< Vec3r >::iterator set_iterator = normals.begin(); set_iterator != normals.end(); set_iterator++) {
- Vec3r v(*set_iterator);
- PyList_Append(py_normals, Vector_from_Vec3r(v));
+ set< Vec3r > normals = self->sv->normals();
+ set< Vec3r >::iterator it;
+ py_normals = PyList_New(normals.size());
+ unsigned int i = 0;
+
+ for (it = normals.begin(); it != normals.end(); it++) {
+ Vec3r v(*it);
+ PyList_SET_ITEM(py_normals, i++, Vector_from_Vec3r(v));
}
return py_normals;
}
@@ -399,13 +400,14 @@ static PyObject *SVertex_curvatures_get(BPy_SVertex *self, void *UNUSED(closure)
Vec3r e2(info->e2.x(), info->e2.y(), info->e2.z());
Vec3r er(info->er.x(), info->er.y(), info->er.z());
PyObject *retval = PyTuple_New(7);
- PyTuple_SET_ITEM(retval, 0, PyFloat_FromDouble(info->K1));
- PyTuple_SET_ITEM(retval, 2, Vector_from_Vec3r(e1));
- PyTuple_SET_ITEM(retval, 1, PyFloat_FromDouble(info->K2));
- PyTuple_SET_ITEM(retval, 3, Vector_from_Vec3r(e2));
- PyTuple_SET_ITEM(retval, 4, PyFloat_FromDouble(info->Kr));
- PyTuple_SET_ITEM(retval, 5, Vector_from_Vec3r(er));
- PyTuple_SET_ITEM(retval, 6, PyFloat_FromDouble(info->dKr));
+ PyTuple_SET_ITEMS(retval,
+ PyFloat_FromDouble(info->K1),
+ PyFloat_FromDouble(info->K2),
+ Vector_from_Vec3r(e1),
+ Vector_from_Vec3r(e2),
+ PyFloat_FromDouble(info->Kr),
+ Vector_from_Vec3r(er),
+ PyFloat_FromDouble(info->dKr));
return retval;
}
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
index c72ab2aba71..2a61dfb075a 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
@@ -112,20 +112,14 @@ static PyObject *UnaryFunction0DVectorViewShape___call__(BPy_UnaryFunction0DVect
}
return NULL;
}
- PyObject *list = PyList_New(0);
- PyObject *item;
- for (unsigned int i = 0; i < self->uf0D_vectorviewshape->result.size(); i++) {
+
+ const unsigned int list_len = self->uf0D_vectorviewshape->result.size();
+ PyObject *list = PyList_New(list_len);
+ for (unsigned int i = 0; i < list_len; i++) {
ViewShape *v = self->uf0D_vectorviewshape->result[i];
- if (v) {
- item = BPy_ViewShape_from_ViewShape(*v);
- }
- else {
- item = Py_None;
- Py_INCREF(item);
- }
- PyList_Append(list, item);
+ PyList_SET_ITEM(list, i, v ? BPy_ViewShape_from_ViewShape(*v) : (Py_INCREF(Py_None), Py_None));
}
-
+
return list;
}
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
index a028952fa69..c15d974e771 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
@@ -142,18 +142,12 @@ static PyObject *UnaryFunction1DVectorViewShape___call__(BPy_UnaryFunction1DVect
}
return NULL;
}
- PyObject *list = PyList_New(0);
- PyObject *item;
- for (unsigned int i = 0; i < self->uf1D_vectorviewshape->result.size(); i++) {
+
+ const unsigned int list_len = self->uf1D_vectorviewshape->result.size();
+ PyObject *list = PyList_New(list_len);
+ for (unsigned int i = 0; i < list_len; i++) {
ViewShape *v = self->uf1D_vectorviewshape->result[i];
- if (v) {
- item = BPy_ViewShape_from_ViewShape(*v);
- }
- else {
- item = Py_None;
- Py_INCREF(item);
- }
- PyList_Append(list, item);
+ PyList_SET_ITEM(list, i, v ? BPy_ViewShape_from_ViewShape(*v) : (Py_INCREF(Py_None), Py_None));
}
return list;
diff --git a/source/blender/freestyle/intern/scene_graph/NodeCamera.h b/source/blender/freestyle/intern/scene_graph/NodeCamera.h
index 5d84a624830..78c34fdef6d 100644
--- a/source/blender/freestyle/intern/scene_graph/NodeCamera.h
+++ b/source/blender/freestyle/intern/scene_graph/NodeCamera.h
@@ -53,7 +53,9 @@ public:
/*! Default matrices: Identity for both projection and modelview. */
NodeCamera(CameraType camera_type = GENERIC);
+#if 0 /* UNUSED, gives warning in gcc */
NodeCamera(const NodeCamera& iBrother);
+#endif
virtual ~NodeCamera() {}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp b/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp
new file mode 100644
index 00000000000..24c56ff4e28
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp
@@ -0,0 +1,35 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp
+ * \ingroup freestyle
+ * \brief Class to represent a scene render layer in Blender.
+ */
+
+#include "NodeSceneRenderLayer.h"
+
+namespace Freestyle {
+
+void NodeSceneRenderLayer::accept(SceneVisitor& v)
+{
+ v.visitNodeSceneRenderLayer(*this);
+}
+
+} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h b/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h
new file mode 100644
index 00000000000..2fc08bb1175
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h
@@ -0,0 +1,64 @@
+/*
+ * ***** 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 __FREESTYLE_NODE_SCENE_RENDER_LAYER_H__
+#define __FREESTYLE_NODE_SCENE_RENDER_LAYER_H__
+
+/** \file blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h
+ * \ingroup freestyle
+ * \brief Class to represent a scene render layer in Blender.
+ */
+
+#include "Node.h"
+
+extern "C" {
+#include "DNA_scene_types.h" /* for SceneRenderLayer */
+}
+
+using namespace std;
+
+namespace Freestyle {
+
+class NodeSceneRenderLayer : public Node
+{
+public:
+ inline NodeSceneRenderLayer(SceneRenderLayer& srl) : Node(), _SceneRenderLayer(srl) {}
+ virtual ~NodeSceneRenderLayer() {}
+
+ inline struct SceneRenderLayer& sceneRenderLayer() const
+ {
+ return _SceneRenderLayer;
+ }
+
+ inline void setSceneRenderLayer(SceneRenderLayer& srl)
+ {
+ _SceneRenderLayer = srl;
+ }
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+protected:
+ SceneRenderLayer& _SceneRenderLayer;
+};
+
+} /* namespace Freestyle */
+
+#endif // __FREESTYLE_NODE_SCENE_RENDER_LAYER_H__
diff --git a/source/blender/freestyle/intern/scene_graph/SceneHash.cpp b/source/blender/freestyle/intern/scene_graph/SceneHash.cpp
index 6e8856f1b93..ee1d0c53b87 100644
--- a/source/blender/freestyle/intern/scene_graph/SceneHash.cpp
+++ b/source/blender/freestyle/intern/scene_graph/SceneHash.cpp
@@ -24,16 +24,56 @@
#include "SceneHash.h"
+#include <sstream>
+
namespace Freestyle {
+string SceneHash::toString()
+{
+ stringstream ss;
+ ss << hex << _sum;
+ return ss.str();
+}
+
+void SceneHash::visitNodeSceneRenderLayer(NodeSceneRenderLayer& srl)
+{
+ struct FreestyleConfig *config = &srl.sceneRenderLayer().freestyleConfig;
+ adler32((unsigned char *)&config->flags, sizeof(int));
+ adler32((unsigned char *)&config->crease_angle, sizeof(float));
+ adler32((unsigned char *)&config->sphere_radius, sizeof(float));
+ adler32((unsigned char *)&config->dkr_epsilon, sizeof(float));
+}
+
+void SceneHash::visitNodeCamera(NodeCamera& cam)
+{
+ double *proj = cam.projectionMatrix();
+ for (int i = 0; i < 16; i++) {
+ adler32((unsigned char *)&proj[i], sizeof(double));
+ }
+}
+
void SceneHash::visitIndexedFaceSet(IndexedFaceSet& ifs)
{
const real *v = ifs.vertices();
const unsigned n = ifs.vsize();
for (unsigned i = 0; i < n; i++) {
- _hashcode += v[i];
+ adler32((unsigned char *)&v[i], sizeof(v[i]));
+ }
+}
+
+static const int MOD_ADLER = 65521;
+
+void SceneHash::adler32(unsigned char *data, int size)
+{
+ uint32_t sum1 = _sum & 0xffff;
+ uint32_t sum2 = (_sum >> 16) & 0xffff;
+
+ for (int i = 0; i < size; i++) {
+ sum1 = (sum1 + data[i]) % MOD_ADLER;
+ sum2 = (sum1 + sum2) % MOD_ADLER;
}
+ _sum = sum1 | (sum2 << 16);
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/scene_graph/SceneHash.h b/source/blender/freestyle/intern/scene_graph/SceneHash.h
index 8f5f847eaab..9da711673f0 100644
--- a/source/blender/freestyle/intern/scene_graph/SceneHash.h
+++ b/source/blender/freestyle/intern/scene_graph/SceneHash.h
@@ -26,8 +26,12 @@
*/
#include "IndexedFaceSet.h"
+#include "NodeSceneRenderLayer.h"
+#include "NodeCamera.h"
#include "SceneVisitor.h"
+#include "BLI_sys_types.h"
+
#ifdef WITH_CXX_GUARDEDALLOC
#include "MEM_guardedalloc.h"
#endif
@@ -39,23 +43,34 @@ class SceneHash : public SceneVisitor
public:
inline SceneHash() : SceneVisitor()
{
- _hashcode = 0.0;
+ _sum = 1;
}
virtual ~SceneHash() {}
+ VISIT_DECL(NodeCamera)
+ VISIT_DECL(NodeSceneRenderLayer)
VISIT_DECL(IndexedFaceSet)
- inline real getValue() {
- return _hashcode;
+ string toString();
+
+ inline bool match() {
+ return _sum == _prevSum;
+ }
+
+ inline void store() {
+ _prevSum = _sum;
}
inline void reset() {
- _hashcode = 0.0;
+ _sum = 1;
}
private:
- real _hashcode;
+ void adler32(unsigned char *data, int size);
+
+ uint32_t _sum;
+ uint32_t _prevSum;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SceneHash")
diff --git a/source/blender/freestyle/intern/scene_graph/SceneVisitor.h b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
index c00f5124a31..712585c4064 100644
--- a/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
+++ b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
@@ -56,6 +56,7 @@ class NodeLight;
class NodeCamera;
class NodeDrawingStyle;
class NodeTransform;
+class NodeSceneRenderLayer;
class Rep;
class LineRep;
@@ -87,6 +88,7 @@ public:
VISIT_COMPLETE_DEF(NodeCamera)
VISIT_COMPLETE_DEF(NodeDrawingStyle)
VISIT_COMPLETE_DEF(NodeTransform)
+ VISIT_COMPLETE_DEF(NodeSceneRenderLayer)
VISIT_COMPLETE_DEF(Rep)
VISIT_COMPLETE_DEF(LineRep)
diff --git a/source/blender/freestyle/intern/stroke/Curve.cpp b/source/blender/freestyle/intern/stroke/Curve.cpp
index 32cfac016d6..69c5dcdfe28 100644
--- a/source/blender/freestyle/intern/stroke/Curve.cpp
+++ b/source/blender/freestyle/intern/stroke/Curve.cpp
@@ -25,6 +25,8 @@
* \date 11/01/2003
*/
+#include <stdio.h> /* printf */
+
#include "Curve.h"
#include "CurveIterators.h"
#include "CurveAdvancedIterators.h"
diff --git a/source/blender/freestyle/intern/stroke/Stroke.cpp b/source/blender/freestyle/intern/stroke/Stroke.cpp
index 863da069259..244b20f6b89 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.cpp
+++ b/source/blender/freestyle/intern/stroke/Stroke.cpp
@@ -400,6 +400,7 @@ Stroke::Stroke()
}
_nodeTree = NULL;
_tips = false;
+ _rep = NULL;
}
Stroke::Stroke(const Stroke& iBrother)
@@ -427,6 +428,10 @@ Stroke::Stroke(const Stroke& iBrother)
}
_nodeTree = iBrother._nodeTree;
_tips = iBrother._tips;
+ if (iBrother._rep)
+ _rep = new StrokeRep(*(iBrother._rep));
+ else
+ _rep = NULL;
}
Stroke::~Stroke()
@@ -439,6 +444,10 @@ Stroke::~Stroke()
}
_ViewEdges.clear();
+ if (_rep) {
+ delete _rep;
+ _rep = NULL;
+ }
}
Stroke& Stroke::operator=(const Stroke& iBrother)
@@ -456,6 +465,12 @@ 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));
+ else
+ _rep = NULL;
return *this;
}
@@ -757,14 +772,16 @@ void Stroke::ScaleThickness(float iFactor)
void Stroke::Render(const StrokeRenderer *iRenderer)
{
- StrokeRep rep(this);
- iRenderer->RenderStrokeRep(&rep);
+ if (!_rep)
+ _rep = new StrokeRep(this);
+ iRenderer->RenderStrokeRep(_rep);
}
void Stroke::RenderBasic(const StrokeRenderer *iRenderer)
{
- StrokeRep rep(this);
- iRenderer->RenderStrokeRepBasic(&rep);
+ if (!_rep)
+ _rep = new StrokeRep(this);
+ iRenderer->RenderStrokeRep(_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 8ff801ed144..5f0b4eab309 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.h
+++ b/source/blender/freestyle/intern/stroke/Stroke.h
@@ -549,6 +549,7 @@ private:
MTex *_mtex[MAX_MTEX];
bNodeTree *_nodeTree;
bool _tips;
+ StrokeRep *_rep;
Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity
public:
diff --git a/source/blender/freestyle/intern/system/StringUtils.h b/source/blender/freestyle/intern/system/StringUtils.h
index 77b543c7886..e11798762e4 100644
--- a/source/blender/freestyle/intern/system/StringUtils.h
+++ b/source/blender/freestyle/intern/system/StringUtils.h
@@ -36,7 +36,8 @@
extern "C" {
#include "BKE_utildefines.h"
-#include "BLI_blenlib.h"
+#include "BLI_string.h"
+#include "BLI_path_util.h"
}
using namespace std;
diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
index 38941b23357..31396688422 100644
--- a/source/blender/freestyle/intern/winged_edge/Curvature.cpp
+++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
@@ -535,6 +535,7 @@ void gts_vertex_principal_directions(WVertex *v, Vec3r Kh, real Kg, Vec3r &e1, V
namespace OGF {
+#if 0
inline static real angle(WOEdge *h)
{
const Vec3r& n1 = h->GetbFace()->GetNormal();
@@ -549,6 +550,7 @@ inline static real angle(WOEdge *h)
}
return ::asin(sine);
}
+#endif
// precondition1: P is inside the sphere
// precondition2: P,V points to the outside of the sphere (i.e. OP.V > 0)
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 63eea9486ed..361c247767f 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -73,6 +73,7 @@ data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_simple_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_simple_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC)
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index ba461d5f8a2..e9b600a9267 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -54,6 +54,7 @@ typedef struct GPUBuffer {
int size; /* in bytes */
void *pointer; /* used with vertex arrays */
unsigned int id; /* used with vertex buffer objects */
+ bool use_vbo; /* true for VBOs, false for vertex arrays */
} GPUBuffer;
typedef struct GPUBufferMaterial {
@@ -85,6 +86,7 @@ typedef struct GPUDrawObject {
GPUBuffer *points;
GPUBuffer *normals;
GPUBuffer *uv;
+ GPUBuffer *uv_tex;
GPUBuffer *colors;
GPUBuffer *edges;
GPUBuffer *uvedges;
@@ -113,10 +115,6 @@ typedef struct GPUDrawObject {
/* caches of the original DerivedMesh values */
int totvert;
int totedge;
-
- /* if there was a failure allocating some buffer, use old
- * rendering code */
- bool legacy;
} GPUDrawObject;
/* used for GLSL materials */
@@ -129,7 +127,7 @@ typedef struct GPUAttrib {
void GPU_global_buffer_pool_free(void);
void GPU_global_buffer_pool_free_unused(void);
-GPUBuffer *GPU_buffer_alloc(int size);
+GPUBuffer *GPU_buffer_alloc(int size, bool force_vertex_arrays);
void GPU_buffer_free(GPUBuffer *buffer);
GPUDrawObject *GPU_drawobject_new(struct DerivedMesh *dm);
@@ -161,9 +159,6 @@ void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start,
/* called after drawing */
void GPU_buffer_unbind(void);
-/* used to check whether to use the old (without buffers) code */
-bool GPU_buffer_legacy(struct DerivedMesh *dm);
-
/* Buffers for non-DerivedMesh drawing */
typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 3daf8585539..bb0cf2dd2b9 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -140,12 +140,15 @@ int GPU_texture_opengl_bindcode(GPUTexture *tex);
* - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must
* be called before rendering to the window framebuffer again */
+void GPU_texture_bind_as_framebuffer(GPUTexture *tex);
+
GPUFrameBuffer *GPU_framebuffer_create(void);
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err_out[256]);
-void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex);
-void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex, int w, int h);
+int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]);
+void GPU_framebuffer_texture_detach(GPUTexture *tex);
+void GPU_framebuffer_slot_bind(GPUFrameBuffer *fb, int slot);
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex);
void GPU_framebuffer_free(GPUFrameBuffer *fb);
+bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
void GPU_framebuffer_restore(void);
void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex);
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index fab9c28cb61..09a5653b1ec 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -58,6 +58,7 @@ struct GPUMaterial;
struct GPUTexture;
struct GPULamp;
struct PreviewImage;
+struct World;
typedef struct GPUNode GPUNode;
typedef struct GPUNodeLink GPUNodeLink;
@@ -95,6 +96,12 @@ typedef enum GPUOpenGLBuiltin {
GPU_COLOR = 2,
} GPUOpenGLBuiltin;
+typedef enum GPUMatType {
+ GPU_MATERIAL_TYPE_MESH = 1,
+ GPU_MATERIAL_TYPE_WORLD = 2,
+} GPUMatType;
+
+
typedef enum GPUBlendMode {
GPU_BLEND_SOLID = 0,
GPU_BLEND_ADD = 1,
@@ -131,10 +138,11 @@ void GPU_material_enable_alpha(GPUMaterial *material);
GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]);
/* High level functions to create and use GPU materials */
+GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo);
GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma);
GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma);
-void GPU_material_free(struct Material *ma);
+void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(void);
@@ -144,6 +152,7 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float
void GPU_material_unbind(GPUMaterial *material);
int GPU_material_bound(GPUMaterial *material);
struct Scene *GPU_material_scene(GPUMaterial *material);
+GPUMatType GPU_Material_get_type(GPUMaterial *material);
void GPU_material_vertex_attributes(GPUMaterial *material,
struct GPUVertexAttribs *attrib);
diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript
index f11ecafc986..e44a99286a8 100644
--- a/source/blender/gpu/SConscript
+++ b/source/blender/gpu/SConscript
@@ -69,6 +69,7 @@ sources.extend((
os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex_world.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.glsl.c"),
))
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index b5a576b509c..f0ef55ae673 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -46,13 +46,11 @@
#include "BLI_ghash.h"
#include "BLI_threads.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_userdef_types.h"
@@ -76,7 +74,6 @@ typedef enum {
#define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
/* -1 - undefined, 0 - vertex arrays, 1 - VBOs */
-static int useVBOs = -1;
static GPUBufferState GLStates = 0;
static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } };
@@ -111,10 +108,6 @@ static GPUBufferPool *gpu_buffer_pool_new(void)
{
GPUBufferPool *pool;
- /* enable VBOs if supported */
- if (useVBOs == -1)
- useVBOs = (GLEW_ARB_vertex_buffer_object ? 1 : 0);
-
pool = MEM_callocN(sizeof(GPUBufferPool), "GPUBuffer_Pool");
pool->maxsize = MAX_FREE_GPU_BUFFERS;
@@ -158,7 +151,7 @@ static void gpu_buffer_pool_delete_last(GPUBufferPool *pool)
return;
/* delete the buffer's data */
- if (useVBOs)
+ if (last->use_vbo)
glDeleteBuffersARB(1, &last->id);
else
MEM_freeN(last->pointer);
@@ -226,7 +219,7 @@ void GPU_global_buffer_pool_free_unused(void)
*
* Thread-unsafe version for internal usage only.
*/
-static GPUBuffer *gpu_buffer_alloc_intern(int size)
+static GPUBuffer *gpu_buffer_alloc_intern(int size, bool use_VBO)
{
GPUBufferPool *pool;
GPUBuffer *buf;
@@ -251,6 +244,10 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size)
for (i = 0; i < pool->totbuf; i++) {
bufsize = pool->buffers[i]->size;
+ /* only return a buffer that matches the VBO preference */
+ if (pool->buffers[i]->use_vbo != use_VBO)
+ continue;
+
/* check for an exact size match */
if (bufsize == size) {
bestfit = i;
@@ -279,8 +276,9 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size)
/* no acceptable buffer found in the pool, create a new one */
buf = MEM_callocN(sizeof(GPUBuffer), "GPUBuffer");
buf->size = size;
+ buf->use_vbo = use_VBO;
- if (useVBOs == 1) {
+ if (use_VBO) {
/* create a new VBO and initialize it to the requested
* size */
glGenBuffersARB(1, &buf->id);
@@ -307,9 +305,10 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size)
}
/* Same as above, but safe for threading. */
-GPUBuffer *GPU_buffer_alloc(int size)
+GPUBuffer *GPU_buffer_alloc(int size, bool force_vertex_arrays)
{
GPUBuffer *buffer;
+ bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO) && !force_vertex_arrays;
if (size == 0) {
/* Early out, no lock needed in this case. */
@@ -317,7 +316,7 @@ GPUBuffer *GPU_buffer_alloc(int size)
}
BLI_mutex_lock(&buffer_mutex);
- buffer = gpu_buffer_alloc_intern(size);
+ buffer = gpu_buffer_alloc_intern(size, use_VBOs);
BLI_mutex_unlock(&buffer_mutex);
return buffer;
@@ -577,6 +576,7 @@ void GPU_drawobject_free(DerivedMesh *dm)
GPU_buffer_free(gdo->points);
GPU_buffer_free(gdo->normals);
GPU_buffer_free(gdo->uv);
+ GPU_buffer_free(gdo->uv_tex);
GPU_buffer_free(gdo->colors);
GPU_buffer_free(gdo->edges);
GPU_buffer_free(gdo->uvedges);
@@ -585,6 +585,22 @@ void GPU_drawobject_free(DerivedMesh *dm)
dm->drawObject = NULL;
}
+static GPUBuffer *gpu_try_realloc(GPUBufferPool *pool, GPUBuffer *buffer, int size, bool use_VBOs)
+{
+ gpu_buffer_free_intern(buffer);
+ gpu_buffer_pool_delete_last(pool);
+ buffer = NULL;
+
+ /* try freeing an entry from the pool
+ * and reallocating the buffer */
+ if (pool->totbuf > 0) {
+ gpu_buffer_pool_delete_last(pool);
+ buffer = gpu_buffer_alloc_intern(size, use_VBOs);
+ }
+
+ return buffer;
+}
+
typedef void (*GPUBufferCopyFunc)(DerivedMesh *dm, float *varray, int *index,
int *mat_orig_to_new, void *user_data);
@@ -598,7 +614,7 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
int *mat_orig_to_new;
int *cur_index_per_mat;
int i;
- bool success;
+ bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO);
GLboolean uploaded;
pool = gpu_get_global_buffer_pool();
@@ -606,11 +622,7 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
BLI_mutex_lock(&buffer_mutex);
/* alloc a GPUBuffer; fall back to legacy mode on failure */
- if (!(buffer = gpu_buffer_alloc_intern(size)))
- dm->drawObject->legacy = 1;
-
- /* nothing to do for legacy mode */
- if (dm->drawObject->legacy) {
+ if (!(buffer = gpu_buffer_alloc_intern(size, use_VBOs))) {
BLI_mutex_unlock(&buffer_mutex);
return NULL;
}
@@ -628,8 +640,8 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
mat_orig_to_new[object->materials[i].mat_nr] = i;
}
- if (useVBOs) {
- success = 0;
+ if (use_VBOs) {
+ bool success = false;
while (!success) {
/* bind the buffer and discard previous data,
@@ -639,32 +651,22 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
/* attempt to map the buffer */
if (!(varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB))) {
- /* failed to map the buffer; delete it */
- gpu_buffer_free_intern(buffer);
- gpu_buffer_pool_delete_last(pool);
- buffer = NULL;
-
- /* try freeing an entry from the pool
- * and reallocating the buffer */
- if (pool->totbuf > 0) {
- gpu_buffer_pool_delete_last(pool);
- buffer = gpu_buffer_alloc_intern(size);
- }
-
+ buffer = gpu_try_realloc(pool, buffer, size, true);
+
/* allocation still failed; fall back
* to legacy mode */
if (!buffer) {
- dm->drawObject->legacy = 1;
- success = 1;
+ use_VBOs = false;
+ success = true;
}
}
else {
- success = 1;
+ success = true;
}
}
/* check legacy fallback didn't happen */
- if (dm->drawObject->legacy == 0) {
+ if (use_VBOs) {
uploaded = GL_FALSE;
/* attempt to upload the data to the VBO */
while (uploaded == GL_FALSE) {
@@ -677,15 +679,16 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
}
glBindBufferARB(target, 0);
}
- else {
+ if (!use_VBOs) {
/* VBO not supported, use vertex array fallback */
- if (buffer->pointer) {
+ if (!buffer || !buffer->pointer) {
+ buffer = gpu_try_realloc(pool, buffer, size, false);
+ }
+
+ if (buffer) {
varray = buffer->pointer;
(*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
}
- else {
- dm->drawObject->legacy = 1;
- }
}
MEM_freeN(cur_index_per_mat);
@@ -1019,7 +1022,7 @@ static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBuffer
case GPU_BUFFER_UV:
return &gdo->uv;
case GPU_BUFFER_UV_TEXPAINT:
- return &gdo->uv;
+ return &gdo->uv_tex;
case GPU_BUFFER_EDGE:
return &gdo->edges;
case GPU_BUFFER_UVEDGE:
@@ -1105,7 +1108,7 @@ void GPU_vertex_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_VERTEX_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->points->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id);
glVertexPointer(3, GL_FLOAT, 0, 0);
}
@@ -1122,7 +1125,7 @@ void GPU_normal_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_NORMAL_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->normals->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->normals->id);
glNormalPointer(GL_FLOAT, 0, 0);
}
@@ -1139,7 +1142,7 @@ void GPU_uv_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->uv->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
}
@@ -1156,8 +1159,8 @@ void GPU_texpaint_uv_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- if (useVBOs) {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id);
+ if (dm->drawObject->uv_tex->use_vbo) {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv_tex->id);
glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0);
glClientActiveTexture(GL_TEXTURE2);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -1165,10 +1168,10 @@ void GPU_texpaint_uv_setup(DerivedMesh *dm)
glClientActiveTexture(GL_TEXTURE0);
}
else {
- glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), dm->drawObject->uv->pointer);
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), dm->drawObject->uv_tex->pointer);
glClientActiveTexture(GL_TEXTURE2);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)dm->drawObject->uv->pointer + 2 * sizeof(float));
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)dm->drawObject->uv_tex->pointer + 2 * sizeof(float));
glClientActiveTexture(GL_TEXTURE0);
}
@@ -1202,7 +1205,7 @@ void GPU_color_setup(DerivedMesh *dm, int colType)
return;
glEnableClientState(GL_COLOR_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->colors->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->colors->id);
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
}
@@ -1222,7 +1225,7 @@ void GPU_edge_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_VERTEX_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->points->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id);
glVertexPointer(3, GL_FLOAT, 0, 0);
}
@@ -1232,7 +1235,7 @@ void GPU_edge_setup(DerivedMesh *dm)
GLStates |= GPU_BUFFER_VERTEX_STATE;
- if (useVBOs)
+ if (dm->drawObject->edges->use_vbo)
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->edges->id);
GLStates |= GPU_BUFFER_ELEMENT_STATE;
@@ -1244,7 +1247,7 @@ void GPU_uvedge_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_VERTEX_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->uvedges->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uvedges->id);
glVertexPointer(2, GL_FLOAT, 0, 0);
}
@@ -1290,6 +1293,7 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda
int i;
int elementsize;
intptr_t offset = 0;
+ char *basep;
for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
if (attribData[i].index != -1) {
@@ -1300,28 +1304,26 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda
}
elementsize = GPU_attrib_element_size(data, numdata);
- if (useVBOs) {
+ if (buffer->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
- for (i = 0; i < numdata; i++) {
- glEnableVertexAttribArrayARB(data[i].index);
- glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type,
- GL_FALSE, elementsize, (void *)offset);
- offset += data[i].size * GPU_typesize(data[i].type);
-
- attribData[i].index = data[i].index;
- attribData[i].size = data[i].size;
- attribData[i].type = data[i].type;
- }
- attribData[numdata].index = -1;
+ basep = NULL;
}
else {
- for (i = 0; i < numdata; i++) {
- glEnableVertexAttribArrayARB(data[i].index);
- glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type,
- GL_FALSE, elementsize, (char *)buffer->pointer + offset);
- offset += data[i].size * GPU_typesize(data[i].type);
- }
+ basep = buffer->pointer;
}
+
+ for (i = 0; i < numdata; i++) {
+ glEnableVertexAttribArrayARB(data[i].index);
+ glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type,
+ GL_FALSE, elementsize, (void *)(basep + offset));
+ offset += data[i].size * GPU_typesize(data[i].type);
+
+ attribData[i].index = data[i].index;
+ attribData[i].size = data[i].size;
+ attribData[i].type = data[i].type;
+ }
+
+ attribData[numdata].index = -1;
}
@@ -1343,7 +1345,8 @@ void GPU_buffer_unbind(void)
if (GLStates & GPU_BUFFER_COLOR_STATE)
glDisableClientState(GL_COLOR_ARRAY);
if (GLStates & GPU_BUFFER_ELEMENT_STATE) {
- if (useVBOs) {
+ /* not guaranteed we used VBOs but in that case it's just a no-op */
+ if (GLEW_ARB_vertex_buffer_object) {
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
}
@@ -1359,7 +1362,8 @@ void GPU_buffer_unbind(void)
break;
}
- if (useVBOs)
+ /* not guaranteed we used VBOs but in that case it's just a no-op */
+ if (GLEW_ARB_vertex_buffer_object)
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
@@ -1377,19 +1381,6 @@ void GPU_color_switch(int mode)
}
}
-/* return 1 if drawing should be done using old immediate-mode
- * code, 0 otherwise */
-bool GPU_buffer_legacy(DerivedMesh *dm)
-{
- int test = (U.gameflags & USER_DISABLE_VBO);
- if (test)
- return 1;
-
- if (dm->drawObject == NULL)
- dm->drawObject = GPU_drawobject_new(dm);
- return dm->drawObject->legacy;
-}
-
void *GPU_buffer_lock(GPUBuffer *buffer)
{
float *varray;
@@ -1397,7 +1388,7 @@ void *GPU_buffer_lock(GPUBuffer *buffer)
if (!buffer)
return 0;
- if (useVBOs) {
+ if (buffer->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
varray = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
return varray;
@@ -1414,7 +1405,7 @@ void *GPU_buffer_lock_stream(GPUBuffer *buffer)
if (!buffer)
return 0;
- if (useVBOs) {
+ if (buffer->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
/* discard previous data, avoid stalling gpu */
glBufferDataARB(GL_ARRAY_BUFFER_ARB, buffer->size, 0, GL_STREAM_DRAW_ARB);
@@ -1428,12 +1419,10 @@ void *GPU_buffer_lock_stream(GPUBuffer *buffer)
void GPU_buffer_unlock(GPUBuffer *buffer)
{
- if (useVBOs) {
- if (buffer) {
- /* note: this operation can fail, could return
- * an error code from this function? */
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
- }
+ if (buffer->use_vbo) {
+ /* note: this operation can fail, could return
+ * an error code from this function? */
+ glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
}
@@ -1442,7 +1431,7 @@ void GPU_buffer_unlock(GPUBuffer *buffer)
void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, int count)
{
glDrawElements(mode, count, GL_UNSIGNED_INT,
- (useVBOs ?
+ (elements->use_vbo ?
(void *)(start * sizeof(unsigned int)) :
((int *)elements->pointer) + start));
}
@@ -2748,7 +2737,7 @@ void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
/* debug function, draws the pbvh BB */
void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf)
{
- float quads[4][4][3] = {
+ const float quads[4][4][3] = {
{
{min[0], min[1], min[2]},
{max[0], min[1], min[2]},
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 4182f51561b..1f9efdcbefd 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -51,13 +51,12 @@
#include "gpu_codegen.h"
-#include "node_util.h" /* For muting node stuff... */
-
#include <string.h>
#include <stdarg.h>
extern char datatoc_gpu_shader_material_glsl[];
extern char datatoc_gpu_shader_vertex_glsl[];
+extern char datatoc_gpu_shader_vertex_world_glsl[];
static char *glsl_material_library = NULL;
@@ -239,7 +238,7 @@ GPUFunction *GPU_lookup_function(const char *name)
gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
}
- return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, (void *)name);
+ return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name);
}
void gpu_codegen_init(void)
@@ -252,7 +251,7 @@ void gpu_codegen_exit(void)
extern Material defmaterial; // render module abuse...
if (defmaterial.gpumaterial.first)
- GPU_material_free(&defmaterial);
+ GPU_material_free(&defmaterial.gpumaterial);
if (FUNCTION_HASH) {
BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN);
@@ -624,8 +623,7 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const ch
if (builtins & GPU_VIEW_NORMAL)
BLI_dynstr_append(ds, "\tvec3 facingnormal = (gl_FrontFacing)? varnormal: -varnormal;\n");
-
-
+
codegen_declare_tmps(ds, nodes);
codegen_call_functions(ds, nodes, output);
@@ -640,12 +638,13 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const ch
return code;
}
-static char *code_generate_vertex(ListBase *nodes)
+static char *code_generate_vertex(ListBase *nodes, int type)
{
DynStr *ds = BLI_dynstr_new();
GPUNode *node;
GPUInput *input;
char *code;
+ char *vertcode;
for (node=nodes->first; node; node=node->next) {
for (input=node->inputs.first; input; input=input->next) {
@@ -659,8 +658,21 @@ static char *code_generate_vertex(ListBase *nodes)
}
BLI_dynstr_append(ds, "\n");
- BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl);
+ switch (type) {
+ case GPU_MATERIAL_TYPE_MESH:
+ vertcode = datatoc_gpu_shader_vertex_glsl;
+ break;
+ case GPU_MATERIAL_TYPE_WORLD:
+ vertcode = datatoc_gpu_shader_vertex_world_glsl;
+ break;
+ default:
+ fprintf(stderr, "invalid material type, set one after GPU_material_construct_begin\n");
+ break;
+ }
+
+ BLI_dynstr_append(ds, vertcode);
+
for (node=nodes->first; node; node=node->next)
for (input=node->inputs.first; input; input=input->next)
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
@@ -1386,7 +1398,7 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
}
}
-GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name)
+GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, int type, const char *name)
{
GPUShader *shader;
GPUPass *pass;
@@ -1405,7 +1417,7 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
/* generate code and compile with opengl */
fragmentcode = code_generate_fragment(nodes, outlink->output, name);
- vertexcode = code_generate_vertex(nodes);
+ vertexcode = code_generate_vertex(nodes, type);
shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library, NULL);
/* failed? */
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 69213925931..a0698235db6 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -175,7 +175,7 @@ struct GPUPass {
typedef struct GPUPass GPUPass;
GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
- struct GPUVertexAttribs *attribs, int *builtin, const char *name);
+ struct GPUVertexAttribs *attribs, int *builtin, int type, const char *name);
struct GPUShader *GPU_pass_shader(GPUPass *pass);
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 622e7b5ce9e..5f58e3fe65b 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -724,8 +724,12 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int
glBindTexture(GL_TEXTURE_2D, *bind);
if (!(GPU_get_mipmap() && mipmap)) {
- if (use_high_bit_depth)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
+ if (use_high_bit_depth) {
+ if (GLEW_ARB_texture_float)
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
+ else
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
+ }
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -733,8 +737,12 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int
}
else {
if (GTS.gpu_mipmap) {
- if (use_high_bit_depth)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
+ if (use_high_bit_depth) {
+ if (GLEW_ARB_texture_float)
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
+ else
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
+ }
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);
@@ -1389,9 +1397,10 @@ static struct GPUMaterialState {
} GMS = {NULL};
/* fixed function material, alpha handed by caller */
-static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, const int gamma, const Object *ob, const int new_shading_nodes)
+static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, const int gamma, const Object *ob, const int new_shading_nodes,
+ const bool dimdown)
{
- if (new_shading_nodes || bmat->mode & MA_SHLESS) {
+ if (bmat->mode & MA_SHLESS) {
copy_v3_v3(smat->diff, &bmat->r);
smat->diff[3]= 1.0;
@@ -1401,6 +1410,24 @@ static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat,
zero_v4(smat->spec);
smat->hard= 0;
}
+ else if (new_shading_nodes) {
+ copy_v3_v3(smat->diff, &bmat->r);
+ smat->diff[3]= 1.0;
+
+ copy_v3_v3(smat->spec, &bmat->specr);
+ smat->spec[3] = 1.0;
+ smat->hard= CLAMPIS(bmat->har, 0, 128);
+
+ if (dimdown) {
+ mul_v3_fl(smat->diff, 0.8f);
+ mul_v3_fl(smat->spec, 0.5f);
+ }
+
+ if (gamma) {
+ linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
+ linearrgb_to_srgb_v3_v3(smat->spec, smat->spec);
+ }
+ }
else {
mul_v3_v3fl(smat->diff, &bmat->r, bmat->ref + bmat->emit);
smat->diff[3]= 1.0; /* caller may set this to bmat->alpha */
@@ -1501,7 +1528,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
/* no materials assigned? */
if (ob->totcol==0) {
- gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes);
+ gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes, true);
/* do material 1 too, for displists! */
memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
@@ -1531,7 +1558,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
}
else {
/* fixed function opengl materials */
- gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes);
+ gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes, false);
if (GMS.use_alpha_pass && ((ma->mode & MA_TRANSP) || (new_shading_nodes && ma->alpha != 1.0f))) {
GMS.matbuf[a].diff[3]= ma->alpha;
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 04f8e68431a..a6b711fd556 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -49,7 +49,6 @@
#include "GPU_extensions.h"
#include "GPU_simple_shader.h"
-#include "intern/gpu_codegen.h"
#include "intern/gpu_extensions_private.h"
#include <stdlib.h>
@@ -103,6 +102,16 @@ static struct GPUGlobal {
GPUTexture *invalid_tex_3D;
} GG = {1, 0};
+/* Number of maximum output slots. We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */
+#define GPU_FB_MAX_SLOTS 4
+
+struct GPUFrameBuffer {
+ GLuint object;
+ GPUTexture *colortex[GPU_FB_MAX_SLOTS];
+ GPUTexture *depthtex;
+};
+
+
/* GPU Types */
int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
@@ -259,7 +268,7 @@ int GPU_print_error(const char *str)
{
GLenum errCode;
- if (G.debug & G_DEBUG) {
+ if ((G.debug & G_DEBUG)) {
if ((errCode = glGetError()) != GL_NO_ERROR) {
fprintf(stderr, "%s opengl error: %s\n", str, gluErrorString(errCode));
return 1;
@@ -323,6 +332,7 @@ struct GPUTexture {
int fromblender; /* we got the texture from Blender */
GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
+ int fb_attachment; /* slot the texture is attached to */
int depth; /* is a depth texture? */
};
@@ -370,6 +380,7 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
tex->refcount = 1;
tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D;
tex->depth = depth;
+ tex->fb_attachment = -1;
glGenTextures(1, &tex->bindcode);
@@ -451,15 +462,8 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
}
if (tex->target != GL_TEXTURE_1D) {
- /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */
- GLenum wrapmode = (depth || tex->h == 1)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER;
- glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode);
- glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode);
-
-#if 0
- float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
- glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
-#endif
+ glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
else
glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -737,7 +741,13 @@ void GPU_texture_bind(GPUTexture *tex, int number)
return;
}
- if (number == -1)
+ if ((G.debug & G_DEBUG)) {
+ if (tex->fb && tex->fb->object == GG.currentfb) {
+ fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
+ }
+ }
+
+ if (number < 0)
return;
GPU_print_error("Pre Texture Bind");
@@ -791,7 +801,7 @@ void GPU_texture_free(GPUTexture *tex)
if (tex->refcount == 0) {
if (tex->fb)
- GPU_framebuffer_texture_detach(tex->fb, tex);
+ GPU_framebuffer_texture_detach(tex);
if (tex->bindcode && !tex->fromblender)
glDeleteTextures(1, &tex->bindcode);
@@ -831,12 +841,6 @@ GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
/* GPUFrameBuffer */
-struct GPUFrameBuffer {
- GLuint object;
- GPUTexture *colortex;
- GPUTexture *depthtex;
-};
-
GPUFrameBuffer *GPU_framebuffer_create(void)
{
GPUFrameBuffer *fb;
@@ -854,19 +858,35 @@ GPUFrameBuffer *GPU_framebuffer_create(void)
return NULL;
}
+ /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glReadBuffer(GL_NONE);
+ glDrawBuffer(GL_NONE);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
return fb;
}
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err_out[256])
+int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
{
- GLenum status;
GLenum attachment;
GLenum error;
+ if (slot >= GPU_FB_MAX_SLOTS) {
+ fprintf(stderr, "Attaching to index %d framebuffer slot unsupported in blender use at most %d\n", slot, GPU_FB_MAX_SLOTS);
+ return 0;
+ }
+
+ if ((G.debug & G_DEBUG)) {
+ if (tex->number != -1) {
+ fprintf(stderr, "Feedback loop warning!: Attempting to attach texture to framebuffer while still bound to texture unit for drawing!");
+ }
+ }
+
if (tex->depth)
attachment = GL_DEPTH_ATTACHMENT_EXT;
else
- attachment = GL_COLOR_ATTACHMENT0_EXT;
+ attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
GG.currentfb = fb->object;
@@ -885,42 +905,29 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err
return 0;
}
- if (tex->depth) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- }
- else {
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
- }
-
- status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- GPU_framebuffer_restore();
- GPU_print_framebuffer_error(status, err_out);
- return 0;
- }
-
if (tex->depth)
fb->depthtex = tex;
else
- fb->colortex = tex;
+ fb->colortex[slot] = tex;
tex->fb= fb;
+ tex->fb_attachment = slot;
return 1;
}
-void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
+void GPU_framebuffer_texture_detach(GPUTexture *tex)
{
GLenum attachment;
+ GPUFrameBuffer *fb;
if (!tex->fb)
return;
- if (GG.currentfb != tex->fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
+ fb = tex->fb;
+
+ if (GG.currentfb != fb->object) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
GG.currentfb = tex->fb->object;
}
@@ -929,18 +936,25 @@ void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
attachment = GL_DEPTH_ATTACHMENT_EXT;
}
else {
- fb->colortex = NULL;
- attachment = GL_COLOR_ATTACHMENT0_EXT;
+ BLI_assert(fb->colortex[tex->fb_attachment] == tex);
+ fb->colortex[tex->fb_attachment] = NULL;
+ attachment = GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment;
}
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
tex->target, 0, 0);
tex->fb = NULL;
+ tex->fb_attachment = -1;
}
-void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, int w, int h)
+void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
{
+ if (!tex->fb) {
+ fprintf(stderr, "Error, texture not bound to framebuffer!");
+ return;
+ }
+
/* push attributes */
glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
glDisable(GL_SCISSOR_TEST);
@@ -948,8 +962,18 @@ void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, i
/* bind framebuffer */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
+ if (tex->depth) {
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+ }
+ else {
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
+ }
+
/* push matrices and set default viewport and matrix */
- glViewport(0, 0, w, h);
+ glViewport(0, 0, tex->w, tex->h);
GG.currentfb = tex->fb->object;
glMatrixMode(GL_PROJECTION);
@@ -958,6 +982,35 @@ void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, i
glPushMatrix();
}
+void GPU_framebuffer_slot_bind(GPUFrameBuffer *fb, int slot)
+{
+ if (!fb->colortex[slot]) {
+ fprintf(stderr, "Error, framebuffer slot empty!");
+ return;
+ }
+
+ /* push attributes */
+ glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
+ glDisable(GL_SCISSOR_TEST);
+
+ /* bind framebuffer */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+
+ /* push matrices and set default viewport and matrix */
+ glViewport(0, 0, fb->colortex[slot]->w, fb->colortex[slot]->h);
+ GG.currentfb = fb->object;
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+}
+
+
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
{
/* restore matrix */
@@ -968,15 +1021,42 @@ void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUS
/* restore attributes */
glPopAttrib();
- glEnable(GL_SCISSOR_TEST);
}
+
+bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
+{
+ GLenum status;
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ GG.currentfb = fb->object;
+
+ /* Clean glError buffer. */
+ while (glGetError() != GL_NO_ERROR) {}
+
+ status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ GPU_framebuffer_restore();
+ GPU_print_framebuffer_error(status, err_out);
+ return false;
+ }
+
+ return true;
+}
+
+
void GPU_framebuffer_free(GPUFrameBuffer *fb)
{
+ int i;
if (fb->depthtex)
- GPU_framebuffer_texture_detach(fb, fb->depthtex);
- if (fb->colortex)
- GPU_framebuffer_texture_detach(fb, fb->colortex);
+ GPU_framebuffer_texture_detach(fb->depthtex);
+
+ for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
+ if (fb->colortex[i]) {
+ GPU_framebuffer_texture_detach(fb->colortex[i]);
+ }
+ }
if (fb->object) {
glDeleteFramebuffersEXT(1, &fb->object);
@@ -1017,6 +1097,10 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
/* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
* pushing unnecessary matrices onto the OpenGL stack. */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
+
+ /* avoid warnings from texture binding */
+ GG.currentfb = blurfb->object;
GPU_shader_bind(blur_shader);
GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scaleh);
@@ -1046,6 +1130,10 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
/* Blurring vertically */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
+
+ GG.currentfb = fb->object;
+
glViewport(0, 0, GPU_texture_opengl_width(tex), GPU_texture_opengl_height(tex));
GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scalev);
GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
@@ -1067,10 +1155,6 @@ struct GPUOffScreen {
GPUFrameBuffer *fb;
GPUTexture *color;
GPUTexture *depth;
-
- /* requested width/height, may be smaller than actual texture size due
- * to missing non-power of two support, so we compensate for that */
- int w, h;
};
GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
@@ -1078,8 +1162,6 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
GPUOffScreen *ofs;
ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
- ofs->w= width;
- ofs->h= height;
ofs->fb = GPU_framebuffer_create();
if (!ofs->fb) {
@@ -1093,7 +1175,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, err_out)) {
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
GPU_offscreen_free(ofs);
return NULL;
}
@@ -1104,10 +1186,16 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, err_out)) {
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
GPU_offscreen_free(ofs);
return NULL;
}
+
+ /* check validity at the very end! */
+ if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
+ GPU_offscreen_free(ofs);
+ return NULL;
+ }
GPU_framebuffer_restore();
@@ -1129,7 +1217,7 @@ void GPU_offscreen_free(GPUOffScreen *ofs)
void GPU_offscreen_bind(GPUOffScreen *ofs)
{
glDisable(GL_SCISSOR_TEST);
- GPU_framebuffer_texture_bind(ofs->fb, ofs->color, ofs->w, ofs->h);
+ GPU_texture_bind_as_framebuffer(ofs->color);
}
void GPU_offscreen_unbind(GPUOffScreen *ofs)
@@ -1141,17 +1229,17 @@ void GPU_offscreen_unbind(GPUOffScreen *ofs)
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
{
- glReadPixels(0, 0, ofs->w, ofs->h, GL_RGBA, type, pixels);
+ glReadPixels(0, 0, ofs->color->w, ofs->color->h, GL_RGBA, type, pixels);
}
int GPU_offscreen_width(GPUOffScreen *ofs)
{
- return ofs->w;
+ return ofs->color->w;
}
int GPU_offscreen_height(GPUOffScreen *ofs)
{
- return ofs->h;
+ return ofs->color->h;
}
/* GPUShader */
@@ -1173,8 +1261,8 @@ static void shader_print_errors(const char *task, char *log, const char **code,
for (i = 0; i < totcode; i++) {
const char *c, *pos, *end = code[i] + strlen(code[i]);
int line = 1;
-
- if (G.debug & G_DEBUG) {
+
+ if ((G.debug & G_DEBUG)) {
fprintf(stderr, "===== shader string %d ====\n", i + 1);
c = code[i];
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 912774cd345..fd99595b6a4 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -31,7 +31,6 @@
#include "BLI_sys_types.h"
#include "GPU_init_exit.h" /* interface */
-#include "GPU_extensions.h" /* library */
#include "intern/gpu_codegen.h"
#include "intern/gpu_extensions_private.h"
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index fa22783ba2a..75a9572f54f 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -76,10 +76,15 @@ typedef enum DynMatProperty {
DYN_LAMP_PERSMAT = 8,
} DynMatProperty;
+
struct GPUMaterial {
Scene *scene;
Material *ma;
+ /* material for mesh surface, worlds or something else.
+ * some code generation is done differently depending on the use case */
+ int type;
+
/* for creating the material */
ListBase nodes;
GPUNodeLink *outlink;
@@ -194,7 +199,7 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
attribs->totlayer = b;
}
-static int GPU_material_construct_end(GPUMaterial *material)
+static int GPU_material_construct_end(GPUMaterial *material, const char *passname)
{
if (material->outlink) {
GPUNodeLink *outlink;
@@ -202,7 +207,7 @@ static int GPU_material_construct_end(GPUMaterial *material)
outlink = material->outlink;
material->pass = GPU_generate_pass(&material->nodes, outlink,
- &material->attribs, &material->builtins, material->ma->id.name);
+ &material->attribs, &material->builtins, material->type, passname);
if (!material->pass)
return 0;
@@ -229,12 +234,12 @@ static int GPU_material_construct_end(GPUMaterial *material)
return 0;
}
-void GPU_material_free(Material *ma)
+void GPU_material_free(ListBase *gpumaterial)
{
LinkData *link;
LinkData *nlink, *mlink, *next;
- for (link=ma->gpumaterial.first; link; link=link->next) {
+ for (link=gpumaterial->first; link; link=link->next) {
GPUMaterial *material = link->data;
if (material->pass)
@@ -243,19 +248,23 @@ void GPU_material_free(Material *ma)
for (nlink=material->lamps.first; nlink; nlink=nlink->next) {
GPULamp *lamp = nlink->data;
- for (mlink=lamp->materials.first; mlink; mlink=next) {
- next = mlink->next;
- if (mlink->data == ma)
- BLI_freelinkN(&lamp->materials, mlink);
+ if (material->ma) {
+ Material *ma = material->ma;
+
+ for (mlink=lamp->materials.first; mlink; mlink=next) {
+ next = mlink->next;
+ if (mlink->data == ma)
+ BLI_freelinkN(&lamp->materials, mlink);
+ }
}
}
-
+
BLI_freelistN(&material->lamps);
MEM_freeN(material);
}
- BLI_freelistN(&ma->gpumaterial);
+ BLI_freelistN(gpumaterial);
}
bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
@@ -280,42 +289,44 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
viewlay &= srl->lay;
/* handle layer lamps */
- for (nlink=material->lamps.first; nlink; nlink=nlink->next) {
- lamp= nlink->data;
-
- if (!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))
- && GPU_lamp_override_visible(lamp, srl, material->ma)) {
- lamp->dynenergy = lamp->energy;
- copy_v3_v3(lamp->dyncol, lamp->col);
- }
- else {
- lamp->dynenergy = 0.0f;
- lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f;
- }
-
- if (material->dynproperty & DYN_LAMP_VEC) {
- copy_v3_v3(lamp->dynvec, lamp->vec);
- normalize_v3(lamp->dynvec);
- negate_v3(lamp->dynvec);
- mul_mat3_m4_v3(viewmat, lamp->dynvec);
- }
-
- if (material->dynproperty & DYN_LAMP_CO) {
- copy_v3_v3(lamp->dynco, lamp->co);
- mul_m4_v3(viewmat, lamp->dynco);
- }
-
- if (material->dynproperty & DYN_LAMP_IMAT) {
- mul_m4_m4m4(lamp->dynimat, lamp->imat, viewinv);
- }
-
- if (material->dynproperty & DYN_LAMP_PERSMAT) {
- if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */
- GPU_lamp_update_buffer_mats(lamp);
- mul_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv);
+ if (material->type == GPU_MATERIAL_TYPE_MESH) {
+ for (nlink=material->lamps.first; nlink; nlink=nlink->next) {
+ lamp= nlink->data;
+
+ if (!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))
+ && GPU_lamp_override_visible(lamp, srl, material->ma)) {
+ lamp->dynenergy = lamp->energy;
+ copy_v3_v3(lamp->dyncol, lamp->col);
+ }
+ else {
+ lamp->dynenergy = 0.0f;
+ lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f;
+ }
+
+ if (material->dynproperty & DYN_LAMP_VEC) {
+ copy_v3_v3(lamp->dynvec, lamp->vec);
+ normalize_v3(lamp->dynvec);
+ negate_v3(lamp->dynvec);
+ mul_mat3_m4_v3(viewmat, lamp->dynvec);
+ }
+
+ if (material->dynproperty & DYN_LAMP_CO) {
+ copy_v3_v3(lamp->dynco, lamp->co);
+ mul_m4_v3(viewmat, lamp->dynco);
+ }
+
+ if (material->dynproperty & DYN_LAMP_IMAT) {
+ mul_m4_m4m4(lamp->dynimat, lamp->imat, viewinv);
+ }
+
+ if (material->dynproperty & DYN_LAMP_PERSMAT) {
+ if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */
+ GPU_lamp_update_buffer_mats(lamp);
+ mul_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv);
+ }
}
}
-
+
/* note material must be bound before setting uniforms */
GPU_pass_bind(material->pass, time, mipmap);
@@ -376,6 +387,12 @@ Scene *GPU_material_scene(GPUMaterial *material)
return material->scene;
}
+GPUMatType GPU_Material_get_type(GPUMaterial *material)
+{
+ return material->type;
+}
+
+
void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
{
*attribs = material->attribs;
@@ -1589,6 +1606,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
/* allocate material */
mat = GPU_material_construct_begin(ma);
mat->scene = scene;
+ mat->type = GPU_MATERIAL_TYPE_MESH;
if (ma->preview && ma->preview->rect[0]) {
outlink = gpu_material_preview_matcap(mat, ma);
@@ -1599,7 +1617,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
GPU_material_output_link(mat, outlink);
- GPU_material_construct_end(mat);
+ GPU_material_construct_end(mat, "matcap_pass");
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
@@ -1612,6 +1630,45 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
return mat;
}
+GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo)
+{
+ LinkData *link;
+ GPUMaterial *mat;
+
+ for (link=wo->gpumaterial.first; link; link=link->next)
+ if (((GPUMaterial*)link->data)->scene == scene)
+ return link->data;
+
+ /* allocate material */
+ mat = GPU_material_construct_begin(NULL);
+ mat->scene = scene;
+ mat->type = GPU_MATERIAL_TYPE_WORLD;
+
+ /* create nodes */
+ if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes)
+ ntreeGPUMaterialNodes(wo->nodetree, mat, NODE_NEW_SHADING);
+ else {
+ /* old fixed function world */
+ }
+
+ if (GPU_material_do_color_management(mat))
+ if (mat->outlink)
+ GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
+
+ GPU_material_construct_end(mat, wo->id.name);
+
+ /* note that even if building the shader fails in some way, we still keep
+ * it to avoid trying to compile again and again, and simple do not use
+ * the actual shader on drawing */
+
+ link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
+ link->data = mat;
+ BLI_addtail(&wo->gpumaterial, link);
+
+ return mat;
+}
+
+
GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
{
GPUMaterial *mat;
@@ -1625,6 +1682,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
/* allocate material */
mat = GPU_material_construct_begin(ma);
mat->scene = scene;
+ mat->type = GPU_MATERIAL_TYPE_MESH;
/* render pipeline option */
if (ma->mode & MA_TRANSP)
@@ -1654,7 +1712,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
if (mat->outlink)
GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
- GPU_material_construct_end(mat);
+ GPU_material_construct_end(mat, ma->id.name);
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
@@ -1671,12 +1729,16 @@ void GPU_materials_free(void)
{
Object *ob;
Material *ma;
+ World *wo;
extern Material defmaterial;
for (ma=G.main->mat.first; ma; ma=ma->id.next)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
- GPU_material_free(&defmaterial);
+ for (wo=G.main->world.first; wo; wo=wo->id.next)
+ GPU_material_free(&wo->gpumaterial);
+
+ GPU_material_free(&defmaterial.gpumaterial);
for (ob=G.main->object.first; ob; ob=ob->id.next)
GPU_lamp_free(ob);
@@ -1851,7 +1913,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
@@ -1863,11 +1925,16 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
/* FBO and texture for blurring */
lamp->blurfb = GPU_framebuffer_create();
if (!lamp->blurfb) {
@@ -1881,10 +1948,20 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
+
+ /* we need to properly bind to test for completeness */
+ GPU_texture_bind_as_framebuffer(lamp->blurtex);
+
+ if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
}
else {
lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
@@ -1893,10 +1970,15 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
+
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
}
GPU_framebuffer_restore();
@@ -1930,7 +2012,7 @@ void GPU_lamp_free(Object *ob)
BLI_freelinkN(&lamp->materials, nlink);
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
}
gpu_lamp_shadow_free(lamp);
@@ -1979,8 +2061,7 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsiz
/* opengl */
glDisable(GL_SCISSOR_TEST);
- GPU_framebuffer_texture_bind(lamp->fb, lamp->tex,
- GPU_texture_opengl_width(lamp->tex), GPU_texture_opengl_height(lamp->tex));
+ GPU_texture_bind_as_framebuffer(lamp->tex);
if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index afd6af9efae..d8e1fab9f80 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -33,12 +33,12 @@
#include "GPU_extensions.h"
#include "GPU_glew.h"
-#include "BLI_utildefines.h"
-
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
+#include "BLI_utildefines.h"
+
/* Ad hoc number of queries to allocate to skip doing many glGenQueries */
#define ALLOC_QUERIES 200
diff --git a/source/blender/gpu/intern/gpu_simple_shader.c b/source/blender/gpu/intern/gpu_simple_shader.c
index c0d7ebd4abb..3fa5975ef15 100644
--- a/source/blender/gpu/intern/gpu_simple_shader.c
+++ b/source/blender/gpu/intern/gpu_simple_shader.c
@@ -47,9 +47,6 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "DNA_mesh_types.h"
-#include "DNA_object_types.h"
-
#include "GPU_extensions.h"
#include "GPU_simple_shader.h"
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index a737741975e..1e0927d90b3 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -357,6 +357,12 @@ void normal(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
outdot = -dot(dir, nor);
}
+void normal_new_shading(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
+{
+ outnor = normalize(nor);
+ outdot = dot(normalize(dir), nor);
+}
+
void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
{
outvec.x = texture2D(curvemap, vec2((vec.x + 1.0)*0.5, 0.0)).x;
@@ -2256,6 +2262,22 @@ void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
result = color*strength;
}
+/* background */
+
+void background_transform_to_world(vec3 viewvec, out vec3 worldvec)
+{
+ vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
+
+ vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+ worldvec = (gl_ModelViewMatrixInverse * co).xyz;
+}
+
+void node_background(vec4 color, float strength, vec3 N, out vec4 result)
+{
+ result = color*strength;
+}
+
/* closures */
void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader)
@@ -2350,13 +2372,13 @@ 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 = mtex_2d_mapping(attr_orco);
+ generated = attr_orco * 0.5 + vec3(0.5);
normal = normalize((obinvmat*(viewinvmat*vec4(N, 0.0))).xyz);
uv = attr_uv;
object = (obinvmat*(viewinvmat*vec4(I, 1.0))).xyz;
- camera = I;
+ camera = vec3(I.xy, -I.z);
vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0);
- window = mtex_2d_mapping(projvec.xyz/projvec.w);
+ window = vec3(mtex_2d_mapping(projvec.xyz/projvec.w).xy, 0.0);
vec3 shade_I;
shade_view(I, shade_I);
@@ -2364,6 +2386,30 @@ void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat,
reflection = (viewinvmat*vec4(view_reflection, 0.0)).xyz;
}
+void node_tex_coord_background(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat,
+ vec3 attr_orco, vec3 attr_uv,
+ out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
+ out vec3 camera, out vec3 window, out vec3 reflection)
+{
+ vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
+
+ vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+
+ co = normalize(co);
+ vec3 coords = (gl_ModelViewMatrixInverse * co).xyz;
+
+ generated = coords;
+ normal = -coords;
+ uv = vec3(attr_uv.xy, 0.0);
+ object = coords;
+
+ camera = vec3(co.xy, -co.z);
+ window = (gl_ProjectionMatrix[3][3] == 0.0) ? vec3(mtex_2d_mapping(I).xy, 0.0) : vec3(0.5, 0.5, 0.0);
+
+ reflection = -coords;
+}
+
/* textures */
void node_tex_gradient(vec3 co, out vec4 color, out float fac)
@@ -2390,17 +2436,34 @@ void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac)
fac = 1.0;
}
-void node_tex_environment(vec3 co, sampler2D ima, out vec4 color)
+void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color)
+{
+ vec3 nco = normalize(co);
+ float u = -atan(nco.y, nco.x)/(2.0*M_PI) + 0.5;
+ float v = atan(nco.z, hypot(nco.x, nco.y))/M_PI + 0.5;
+
+ color = texture2D(ima, vec2(u, v));
+}
+
+void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color)
{
- float u = (atan(co.y, co.x) + M_PI)/(2.0*M_PI);
- float v = atan(co.z, hypot(co.x, co.y))/M_PI + 0.5;
+ vec3 nco = normalize(co);
+
+ nco.y -= 1.0;
+
+ float div = 2.0*sqrt(max(-0.5*nco.y, 0.0));
+ if(div > 0.0)
+ nco /= div;
+
+ float u = 0.5*(nco.x + 1.0);
+ float v = 0.5*(nco.z + 1.0);
color = texture2D(ima, vec2(u, v));
}
void node_tex_environment_empty(vec3 co, out vec4 color)
{
- color = vec4(0.0);
+ color = vec4(1.0, 0.0, 1.0, 1.0);
}
void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha)
@@ -2508,6 +2571,11 @@ void node_output_material(vec4 surface, vec4 volume, float displacement, out vec
result = surface;
}
+void node_output_world(vec4 surface, vec4 volume, out vec4 result)
+{
+ result = surface;
+}
+
/* ********************** matcap style render ******************** */
void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result)
diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
index 978b6db1b9a..5f406c959f1 100644
--- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
@@ -10,7 +10,7 @@ void main()
color += texture2D( textureSource, gl_TexCoord[0].st + vec2(0.0, 0.0)) * 0.3125;
color += texture2D( textureSource, gl_TexCoord[0].st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y ) ) * 0.234375;
color += texture2D( textureSource, gl_TexCoord[0].st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y ) ) * 0.09375;
- color += texture2D( textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, -3.0 * ScaleU.y ) ) * 0.015625;
+ color += texture2D( textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y ) ) * 0.015625;
gl_FragColor = color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
new file mode 100644
index 00000000000..9dbcaeb7a32
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
@@ -0,0 +1,13 @@
+
+varying vec3 varposition;
+varying vec3 varnormal;
+
+void main()
+{
+ /* position does not need to be transformed, we already have it */
+ gl_Position = gl_Vertex;
+
+ varposition = gl_Vertex.xyz;
+
+ varnormal = normalize(-varposition);
+
diff --git a/source/blender/ikplugin/intern/ikplugin_api.c b/source/blender/ikplugin/intern/ikplugin_api.c
index 2ca50afb0f2..0f81fb34a63 100644
--- a/source/blender/ikplugin/intern/ikplugin_api.c
+++ b/source/blender/ikplugin/intern/ikplugin_api.c
@@ -30,19 +30,12 @@
* \ingroup ikplugin
*/
-
-
#include "BIK_api.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
-
-#include "BKE_armature.h"
#include "DNA_object_types.h"
#include "DNA_action_types.h"
#include "DNA_scene_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_armature_types.h"
#include "ikplugin_api.h"
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 612517775f4..556c4beeae7 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -47,8 +47,8 @@
#include "MEM_guardedalloc.h"
-#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_threads.h"
static SpinLock refcounter_spin;
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index eef7964ef3f..b8f6e66adfe 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -70,12 +70,8 @@
#include "MEM_guardedalloc.h"
-#include "DNA_userdef_types.h"
-
#include "BKE_global.h"
-#include "imbuf.h"
-
#ifdef WITH_AVI
# include "AVI_avi.h"
#endif
@@ -89,7 +85,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_anim.h"
#include "IMB_indexer.h"
diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c
index dabeec74a62..8853fe449ba 100644
--- a/source/blender/imbuf/intern/bmp.c
+++ b/source/blender/imbuf/intern/bmp.c
@@ -36,7 +36,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
#include "IMB_colormanagement.h"
diff --git a/source/blender/imbuf/intern/cache.c b/source/blender/imbuf/intern/cache.c
index 677c3dbe700..759f8cc82c2 100644
--- a/source/blender/imbuf/intern/cache.c
+++ b/source/blender/imbuf/intern/cache.c
@@ -22,7 +22,6 @@
* \ingroup imbuf
*/
-
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
@@ -31,8 +30,6 @@
#include "BLI_memarena.h"
#include "BLI_threads.h"
-
-
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_filetype.h"
diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c
index 880df0ce5c3..0e71206517e 100644
--- a/source/blender/imbuf/intern/cineon/cineonlib.c
+++ b/source/blender/imbuf/intern/cineon/cineonlib.c
@@ -135,7 +135,7 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t
{
CineonMainHeader header;
LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
- char *filename = (char *)byteStuff;
+ const char *filename = (const char *)byteStuff;
int i;
unsigned int dataOffset;
diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c
index 626d05b05c5..f7362d76913 100644
--- a/source/blender/imbuf/intern/cineon/dpxlib.c
+++ b/source/blender/imbuf/intern/cineon/dpxlib.c
@@ -67,7 +67,7 @@ static void fillDpxMainHeader(LogImageFile *dpx, DpxMainHeader *header, const ch
/* --- File header --- */
header->fileHeader.magic_num = swap_uint(DPX_FILE_MAGIC, dpx->isMSB);
header->fileHeader.offset = swap_uint(dpx->element[0].dataOffset, dpx->isMSB);
- strcpy(header->fileHeader.version, "v2.0");
+ strcpy(header->fileHeader.version, "V2.0");
header->fileHeader.file_size = swap_uint(dpx->element[0].dataOffset + dpx->height * getRowLength(dpx->width, dpx->element[0]), dpx->isMSB);
header->fileHeader.ditto_key = 0;
header->fileHeader.gen_hdr_size = swap_uint(sizeof(DpxFileHeader) + sizeof(DpxImageHeader) + sizeof(DpxOrientationHeader), dpx->isMSB);
@@ -134,7 +134,7 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
{
DpxMainHeader header;
LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
- char *filename = (char *)byteStuff;
+ const char *filename = (const char *)byteStuff;
int i;
if (dpx == NULL) {
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 5dd6b366a93..049d8bdcff1 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -44,7 +44,6 @@
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
-#include "IMB_filter.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_filetype.h"
@@ -53,14 +52,13 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_fileops.h"
#include "BLI_math.h"
#include "BLI_math_color.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_threads.h"
#include "BLI_rect.h"
+#include "BKE_appdir.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_image.h"
@@ -245,7 +243,7 @@ static ColormnaageCacheData *colormanage_cachedata_get(const ImBuf *ibuf)
static unsigned int colormanage_hashhash(const void *key_v)
{
- ColormanageCacheKey *key = (ColormanageCacheKey *)key_v;
+ const ColormanageCacheKey *key = key_v;
unsigned int rval = (key->display << 16) | (key->view % 0xffff);
@@ -254,8 +252,8 @@ static unsigned int colormanage_hashhash(const void *key_v)
static bool colormanage_hashcmp(const void *av, const void *bv)
{
- const ColormanageCacheKey *a = (ColormanageCacheKey *) av;
- const ColormanageCacheKey *b = (ColormanageCacheKey *) bv;
+ const ColormanageCacheKey *a = av;
+ const ColormanageCacheKey *b = bv;
return ((a->view != b->view) ||
(a->display != b->display));
@@ -625,7 +623,7 @@ void colormanagement_init(void)
}
if (config == NULL) {
- configdir = BLI_get_folder(BLENDER_DATAFILES, "colormanagement");
+ configdir = BKE_appdir_folder_id(BLENDER_DATAFILES, "colormanagement");
if (configdir) {
BLI_join_dirfile(configfile, sizeof(configfile), configdir, BCM_CONFIG_FILE);
diff --git a/source/blender/imbuf/intern/dds/Stream.cpp b/source/blender/imbuf/intern/dds/Stream.cpp
index 57a251261a1..d8387b92530 100644
--- a/source/blender/imbuf/intern/dds/Stream.cpp
+++ b/source/blender/imbuf/intern/dds/Stream.cpp
@@ -30,10 +30,13 @@
#include <stdio.h> // printf
#include <string.h> // memcpy
+static const char *msg_error_seek = "DDS: trying to seek beyond end of stream (corrupt file?)";
+static const char *msg_error_read = "DDS: trying to read beyond end of stream (corrupt file?)";
+
unsigned int Stream::seek(unsigned int p)
{
if (p > size) {
- printf("DDS: trying to seek beyond end of stream (corrupt file?)");
+ puts(msg_error_seek);
}
else {
pos = p;
@@ -45,7 +48,7 @@ unsigned int Stream::seek(unsigned int p)
unsigned int mem_read(Stream & mem, unsigned long long & i)
{
if (mem.pos + 8 > mem.size) {
- printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ puts(msg_error_seek);
return(0);
}
memcpy(&i, mem.mem + mem.pos, 8); // @@ todo: make sure little endian
@@ -56,7 +59,7 @@ unsigned int mem_read(Stream & mem, unsigned long long & i)
unsigned int mem_read(Stream & mem, unsigned int & i)
{
if (mem.pos + 4 > mem.size) {
- printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ puts(msg_error_read);
return(0);
}
memcpy(&i, mem.mem + mem.pos, 4); // @@ todo: make sure little endian
@@ -67,7 +70,7 @@ unsigned int mem_read(Stream & mem, unsigned int & i)
unsigned int mem_read(Stream & mem, unsigned short & i)
{
if (mem.pos + 2 > mem.size) {
- printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ puts(msg_error_read);
return(0);
}
memcpy(&i, mem.mem + mem.pos, 2); // @@ todo: make sure little endian
@@ -78,7 +81,7 @@ unsigned int mem_read(Stream & mem, unsigned short & i)
unsigned int mem_read(Stream & mem, unsigned char & i)
{
if (mem.pos + 1 > mem.size) {
- printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ puts(msg_error_read);
return(0);
}
i = (mem.mem + mem.pos)[0];
@@ -89,7 +92,7 @@ unsigned int mem_read(Stream & mem, unsigned char & i)
unsigned int mem_read(Stream & mem, unsigned char *i, unsigned int cnt)
{
if (mem.pos + cnt > mem.size) {
- printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ puts(msg_error_read);
return(0);
}
memcpy(i, mem.mem + mem.pos, cnt);
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 03cd5ecd646..81aef4ac6e4 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -37,7 +37,6 @@
#include "imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filter.h"
#include "IMB_colormanagement.h"
diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c
index b6b46c72384..c6e358dd3d2 100644
--- a/source/blender/imbuf/intern/filetype.c
+++ b/source/blender/imbuf/intern/filetype.c
@@ -51,8 +51,6 @@
#include "quicktime_import.h"
#endif
-#include "imbuf.h"
-
static int imb_ftype_default(ImFileType *type, ImBuf *ibuf)
{
return (ibuf->ftype & type->filetype);
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 547a8df4438..e66be77ecaf 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -1170,7 +1170,7 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Timecod
return context;
- (void)tcs_in_use, (void)proxy_sizes_in_use, (void)quality;
+ UNUSED_VARS(tcs_in_use, proxy_sizes_in_use, quality);
}
void IMB_anim_index_rebuild(struct IndexBuildContext *context,
@@ -1189,7 +1189,7 @@ void IMB_anim_index_rebuild(struct IndexBuildContext *context,
#endif
}
- (void)stop, (void)do_update, (void)progress;
+ UNUSED_VARS(stop, do_update, progress);
}
void IMB_anim_index_rebuild_finish(IndexBuildContext *context, short stop)
@@ -1207,8 +1207,8 @@ void IMB_anim_index_rebuild_finish(IndexBuildContext *context, short stop)
#endif
}
- (void)stop;
- (void)proxy_sizes; /* static defined at top of the file */
+ /* static defined at top of the file */
+ UNUSED_VARS(stop, proxy_sizes);
}
diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c
index 8f98f240053..ea5acf27e99 100644
--- a/source/blender/imbuf/intern/iris.c
+++ b/source/blender/imbuf/intern/iris.c
@@ -40,7 +40,6 @@
#include "imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
#include "IMB_colormanagement.h"
diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c
index 18c096450af..8750b825fb6 100644
--- a/source/blender/imbuf/intern/jp2.c
+++ b/source/blender/imbuf/intern/jp2.c
@@ -29,11 +29,8 @@
#include "BLI_math.h"
#include "BLI_fileops.h"
-#include "imbuf.h"
-
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
#include "IMB_colormanagement.h"
diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c
index 1641bd3089b..cb789cc8491 100644
--- a/source/blender/imbuf/intern/moviecache.c
+++ b/source/blender/imbuf/intern/moviecache.c
@@ -99,22 +99,22 @@ typedef struct MovieCacheItem {
static unsigned int moviecache_hashhash(const void *keyv)
{
- MovieCacheKey *key = (MovieCacheKey *)keyv;
+ const MovieCacheKey *key = keyv;
return key->cache_owner->hashfp(key->userkey);
}
static bool moviecache_hashcmp(const void *av, const void *bv)
{
- const MovieCacheKey *a = (MovieCacheKey *)av;
- const MovieCacheKey *b = (MovieCacheKey *)bv;
+ const MovieCacheKey *a = av;
+ const MovieCacheKey *b = bv;
return a->cache_owner->cmpfp(a->userkey, b->userkey);
}
static void moviecache_keyfree(void *val)
{
- MovieCacheKey *key = (MovieCacheKey *)val;
+ MovieCacheKey *key = val;
BLI_mempool_free(key->cache_owner->userkeys_pool, key->userkey);
@@ -167,8 +167,8 @@ static void check_unused_keys(MovieCache *cache)
static int compare_int(const void *av, const void *bv)
{
- const int *a = (int *)av;
- const int *b = (int *)bv;
+ const int *a = av;
+ const int *b = bv;
return *a - *b;
}
@@ -363,8 +363,7 @@ static void do_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf, boo
item->priority_data = cache->getprioritydatafp(userkey);
}
- BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree);
- BLI_ghash_insert(cache->hash, key, item);
+ BLI_ghash_reinsert(cache->hash, key, item, moviecache_keyfree, moviecache_valfree);
if (cache->last_userkey) {
memcpy(cache->last_userkey, userkey, cache->keysize);
diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c
index d00a836667e..3266dc97c78 100644
--- a/source/blender/imbuf/intern/png.c
+++ b/source/blender/imbuf/intern/png.c
@@ -41,8 +41,6 @@
#include "MEM_guardedalloc.h"
-#include "imbuf.h"
-
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c
index db268546480..318bb7e96e3 100644
--- a/source/blender/imbuf/intern/radiance_hdr.c
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -38,7 +38,7 @@
*/
#ifdef WIN32
-# include <io.h>
+# include "BLI_utildefines.h"
#endif
#include "MEM_guardedalloc.h"
@@ -72,10 +72,13 @@ typedef float fCOLOR[3];
#define COPY_RGBE(c1, c2) (c2[RED] = c1[RED], c2[GRN] = c1[GRN], c2[BLU] = c1[BLU], c2[EXP] = c1[EXP])
/* read routines */
-static unsigned char *oldreadcolrs(RGBE *scan, unsigned char *mem, int xmax)
+static unsigned char *oldreadcolrs(RGBE *scan, unsigned char *mem, int xmax, unsigned char *mem_eof)
{
int i, rshift = 0, len = xmax;
while (len > 0) {
+ if (mem_eof - mem < 4) {
+ return NULL;
+ }
scan[0][RED] = *mem++;
scan[0][GRN] = *mem++;
scan[0][BLU] = *mem++;
@@ -97,34 +100,62 @@ static unsigned char *oldreadcolrs(RGBE *scan, unsigned char *mem, int xmax)
return mem;
}
-static unsigned char *freadcolrs(RGBE *scan, unsigned char *mem, int xmax)
+static unsigned char *freadcolrs(RGBE *scan, unsigned char *mem, int xmax, unsigned char *mem_eof)
{
int i, j, code, val;
- if ((xmax < MINELEN) | (xmax > MAXELEN)) return oldreadcolrs(scan, mem, xmax);
+ if (mem_eof - mem < 4) {
+ return NULL;
+ }
+
+ if ((xmax < MINELEN) | (xmax > MAXELEN)) {
+ return oldreadcolrs(scan, mem, xmax, mem_eof);
+ }
i = *mem++;
- if (i != 2) return oldreadcolrs(scan, mem - 1, xmax);
+ if (i != 2) {
+ return oldreadcolrs(scan, mem - 1, xmax, mem_eof);
+ }
scan[0][GRN] = *mem++;
scan[0][BLU] = *mem++;
i = *mem++;
- if (((scan[0][BLU] << 8) | i) != xmax) return NULL;
- for (i = 0; i < 4; i++)
+ if (scan[0][GRN] != 2 || scan[0][BLU] & 128) {
+ scan[0][RED] = 2;
+ scan[0][EXP] = i;
+ return oldreadcolrs(scan + 1, mem, xmax - 1, mem_eof);
+ }
+
+ if (((scan[0][BLU] << 8) | i) != xmax) {
+ return NULL;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (mem_eof - mem < 2) {
+ return NULL;
+ }
for (j = 0; j < xmax; ) {
code = *mem++;
if (code > 128) {
code &= 127;
val = *mem++;
- while (code--)
+ while (code--) {
scan[j++][i] = (unsigned char)val;
+ }
}
- else
- while (code--)
+ else {
+ if (mem_eof - mem < code) {
+ return NULL;
+ }
+ while (code--) {
scan[j++][i] = *mem++;
+ }
+ }
}
+ }
+
return mem;
}
@@ -182,7 +213,7 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char color
int found = 0;
int width = 0, height = 0;
int x, y;
- unsigned char *ptr;
+ unsigned char *ptr, *mem_eof = mem + size;
char oriY[80], oriX[80];
if (imb_is_a_hdr((void *)mem)) {
@@ -218,15 +249,14 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char color
if (flags & IB_test) return ibuf;
/* read in and decode the actual data */
- sline = (RGBE *)MEM_mallocN(sizeof(RGBE) * width, "radhdr_read_tmpscan");
+ sline = (RGBE *)MEM_mallocN(sizeof(*sline) * width, __func__);
rect_float = ibuf->rect_float;
for (y = 0; y < height; y++) {
- ptr = freadcolrs(sline, ptr, width);
+ ptr = freadcolrs(sline, ptr, width, mem_eof);
if (ptr == NULL) {
- printf("HDR decode error\n");
- MEM_freeN(sline);
- return ibuf;
+ printf("WARNING! HDR decode error, image may be just truncated, or completely wrong...\n");
+ break;
}
for (x = 0; x < width; x++) {
/* convert to ldr */
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
index dd2406e234e..4001b681ad9 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -39,11 +39,9 @@
#include "BLI_math_color_blend.h"
#include "BLI_math_vector.h"
-#include "imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_colormanagement.h"
void IMB_blend_color_byte(unsigned char dst[4], unsigned char src1[4], unsigned char src2[4], IMB_BlendMode mode)
diff --git a/source/blender/imbuf/intern/rotate.c b/source/blender/imbuf/intern/rotate.c
index e98757883be..886944f6190 100644
--- a/source/blender/imbuf/intern/rotate.c
+++ b/source/blender/imbuf/intern/rotate.c
@@ -39,8 +39,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
-
void IMB_flipy(struct ImBuf *ibuf)
{
int x, y;
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index e480f06da2b..2601fe62c2f 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -33,7 +33,6 @@
#include "BLI_utildefines.h"
-#include "BLI_math_base.h"
#include "BLI_math_color.h"
#include "BLI_math_interp.h"
#include "MEM_guardedalloc.h"
@@ -42,7 +41,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filter.h"
#include "BLI_sys_types.h" // for intptr_t support
diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c
index 2dcb27a05d4..70b71ec4182 100644
--- a/source/blender/imbuf/intern/targa.c
+++ b/source/blender/imbuf/intern/targa.c
@@ -44,7 +44,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
#include "IMB_colormanagement.h"
diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c
index 73ced4095f9..af353461f1f 100644
--- a/source/blender/imbuf/intern/thumbs_blend.c
+++ b/source/blender/imbuf/intern/thumbs_blend.c
@@ -29,8 +29,6 @@
#include "zlib.h"
-#include "MEM_guardedalloc.h"
-
#include "BLI_utildefines.h"
#include "BLI_endian_switch.h"
#include "BLI_fileops.h"
diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c
index eb8f94cbc6e..e3b8e271387 100644
--- a/source/blender/imbuf/intern/tiff.c
+++ b/source/blender/imbuf/intern/tiff.c
@@ -53,9 +53,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
-#include "IMB_filter.h"
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c
index d4a9bf7dc09..087330d10d2 100644
--- a/source/blender/imbuf/intern/writeimage.c
+++ b/source/blender/imbuf/intern/writeimage.c
@@ -41,8 +41,6 @@
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
-#include "imbuf.h"
-
static ImBuf *prepare_write_imbuf(ImFileType *type, ImBuf *ibuf)
{
ImBuf *write_ibuf = ibuf;
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 33d1445fb93..c00435faa9d 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -44,54 +44,65 @@ struct FileData;
struct ID;
struct PackedFile;
struct GPUTexture;
-
+
typedef struct IDPropertyData {
void *pointer;
ListBase group;
- int val, val2; /*note, we actually fit a double into these two ints*/
+ int val, val2; /* note, we actually fit a double into these two ints */
} IDPropertyData;
typedef struct IDProperty {
struct IDProperty *next, *prev;
char type, subtype;
short flag;
- char name[64]; /* MAX_IDPROP_NAME */
- int saved; /* saved is used to indicate if this struct has been saved yet.
- * seemed like a good idea as a pad var was needed anyway :)*/
- IDPropertyData data; /* note, alignment for 64 bits */
- int len; /* array length, also (this is important!) string length + 1.
- * the idea is to be able to reuse array realloc functions on strings.*/
+ char name[64]; /* MAX_IDPROP_NAME */
+
+ /* saved is used to indicate if this struct has been saved yet.
+ * seemed like a good idea as a pad var was needed anyway :) */
+ int saved;
+ IDPropertyData data; /* note, alignment for 64 bits */
+
+ /* array length, also (this is important!) string length + 1.
+ * the idea is to be able to reuse array realloc functions on strings.*/
+ int len;
+
+ /* Strings and arrays are both buffered, though the buffer isn't saved. */
/* totallen is total length of allocated array/string, including a buffer.
- * Note that the buffering is mild; the code comes from python's list implementation.*/
- int totallen; /*strings and arrays are both buffered, though the buffer isn't saved.*/
+ * Note that the buffering is mild; the code comes from python's list implementation. */
+ int totallen;
} IDProperty;
-#define MAX_IDPROP_NAME 64
-#define DEFAULT_ALLOC_FOR_NULL_STRINGS 64
+#define MAX_IDPROP_NAME 64
+#define DEFAULT_ALLOC_FOR_NULL_STRINGS 64
/*->type*/
-#define IDP_STRING 0
-#define IDP_INT 1
-#define IDP_FLOAT 2
-#define IDP_ARRAY 5
-#define IDP_GROUP 6
-/* the ID link property type hasn't been implemented yet, this will require
- * some cleanup of blenkernel, most likely.*/
-#define IDP_ID 7
-#define IDP_DOUBLE 8
-#define IDP_IDPARRAY 9
-#define IDP_NUMTYPES 10
+enum {
+ IDP_STRING = 0,
+ IDP_INT = 1,
+ IDP_FLOAT = 2,
+ IDP_ARRAY = 5,
+ IDP_GROUP = 6,
+ /* the ID link property type hasn't been implemented yet, this will require
+ * some cleanup of blenkernel, most likely. */
+ IDP_ID = 7,
+ IDP_DOUBLE = 8,
+ IDP_IDPARRAY = 9,
+ IDP_NUMTYPES = 10,
+};
/*->subtype */
/* IDP_STRING */
-#define IDP_STRING_SUB_UTF8 0 /* default */
-#define IDP_STRING_SUB_BYTE 1 /* arbitrary byte array, _not_ null terminated */
-/*->flag*/
-#define IDP_FLAG_GHOST (1<<7) /* this means the property is set but RNA will return
- * false when checking 'RNA_property_is_set',
- * currently this is a runtime flag */
+enum {
+ IDP_STRING_SUB_UTF8 = 0, /* default */
+ IDP_STRING_SUB_BYTE = 1, /* arbitrary byte array, _not_ null terminated */
+};
+/*->flag*/
+enum {
+ IDP_FLAG_GHOST = 1 << 7, /* this means the property is set but RNA will return false when checking
+ * 'RNA_property_is_set', currently this is a runtime flag */
+};
/* add any future new id property types here.*/
@@ -102,7 +113,7 @@ typedef struct IDProperty {
* */
/* 2 characters for ID code and 64 for actual name */
-#define MAX_ID_NAME 66
+#define MAX_ID_NAME 66
/* There's a nasty circular dependency here.... 'void *' to the rescue! I
* really wonder why this is needed. */
@@ -129,14 +140,14 @@ typedef struct Library {
ID id;
ID *idblock;
struct FileData *filedata;
- char name[1024]; /* path name used for reading, can be relative and edited in the outliner */
- char filepath[1024]; /* absolute filepath, this is only for convenience,
- * 'name' is the real path used on file read but in
- * some cases its useful to access the absolute one,
- * This is set on file read.
- * Use BKE_library_filepath_set() rather than
- * setting 'name' directly and it will be kept in
- * sync - campbell */
+ char name[1024]; /* path name used for reading, can be relative and edited in the outliner */
+
+ /* absolute filepath, this is only for convenience, 'name' is the real path used on file read but in
+ * some cases its useful to access the absolute one.
+ * This is set on file read.
+ * Use BKE_library_filepath_set() rather than setting 'name' directly and it will be kept in sync - campbell */
+ char filepath[1024];
+
struct Library *parent; /* set for indirectly linked libs, used in the outliner and while reading */
struct PackedFile *packedfile;
@@ -232,33 +243,34 @@ typedef struct PreviewImage {
#ifdef GS
# undef GS
#endif
-// #define GS(a) (*((short *)(a)))
-#define GS(a) (CHECK_TYPE_INLINE(a, char *), (*((short *)(a))))
+#define GS(a) (CHECK_TYPE_ANY(a, char *, const char *, char [66], const char[66]), (*((const 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++; }
#define ID_NEW_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; }
-/* id->flag: set frist 8 bits always at zero while reading */
-#define LIB_LOCAL 0
-#define LIB_EXTERN 1
-#define LIB_INDIRECT 2
-#define LIB_NEED_EXPAND 8
-#define LIB_TESTEXT (LIB_NEED_EXPAND | LIB_EXTERN)
-#define LIB_TESTIND (LIB_NEED_EXPAND | LIB_INDIRECT)
-#define LIB_READ 16
-#define LIB_NEED_LINK 32
-
-#define LIB_NEW 256
-#define LIB_FAKEUSER 512
-/* free test flag */
-#define LIB_DOIT 1024
-/* tag existing data before linking so we know what is new */
-#define LIB_PRE_EXISTING 2048
-/* runtime */
-#define LIB_ID_RECALC 4096
-#define LIB_ID_RECALC_DATA 8192
-#define LIB_ANIM_NO_RECALC 16384
+/* id->flag: set first 8 bits always at zero while reading */
+enum {
+ LIB_LOCAL = 0,
+ LIB_EXTERN = 1 << 0,
+ LIB_INDIRECT = 1 << 1,
+ LIB_NEED_EXPAND = 1 << 3,
+ LIB_TESTEXT = (LIB_NEED_EXPAND | LIB_EXTERN),
+ LIB_TESTIND = (LIB_NEED_EXPAND | LIB_INDIRECT),
+ LIB_READ = 1 << 4,
+ LIB_NEED_LINK = 1 << 5,
+
+ LIB_NEW = 1 << 8,
+ LIB_FAKEUSER = 1 << 9,
+ /* free test flag */
+ LIB_DOIT = 1 << 10,
+ /* tag existing data before linking so we know what is new */
+ LIB_PRE_EXISTING = 1 << 11,
+ /* runtime */
+ LIB_ID_RECALC = 1 << 12,
+ LIB_ID_RECALC_DATA = 1 << 13,
+ LIB_ANIM_NO_RECALC = 1 << 14,
+};
#ifdef __cplusplus
}
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index dab825c856e..243e747c006 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -250,6 +250,7 @@ typedef enum ePchan_Flag {
POSE_ROT = (1 << 1),
POSE_SIZE = (1 << 2),
/* old IK/cache stuff... */
+#if 0
POSE_IK_MAT = (1 << 3),
POSE_UNUSED2 = (1 << 4),
POSE_UNUSED3 = (1 << 5),
@@ -257,6 +258,7 @@ typedef enum ePchan_Flag {
POSE_UNUSED5 = (1 << 7),
/* has Standard IK */
POSE_HAS_IK = (1 << 8),
+#endif
/* IK/Pose solving*/
POSE_CHAIN = (1 << 9),
POSE_DONE = (1 << 10),
@@ -265,8 +267,10 @@ typedef enum ePchan_Flag {
POSE_STRIDE = (1 << 12),
/* standard IK solving */
POSE_IKTREE = (1 << 13),
+#if 0
/* has Spline IK */
POSE_HAS_IKS = (1 << 14),
+#endif
/* spline IK solving */
POSE_IKSPLINE = (1 << 15)
} ePchan_Flag;
@@ -541,7 +545,7 @@ typedef enum eDopeSheet_FilterFlag {
ADS_FILTER_ONLYNLA = (1 << 2), /* for 'NLA' editor - only include NLA data from AnimData */
ADS_FILTER_SELEDIT = (1 << 3), /* for Graph Editor - used to indicate whether to include a filtering flag or not */
- /* general filtering 2 */
+ /* general filtering */
ADS_FILTER_SUMMARY = (1 << 4), /* for 'DopeSheet' Editors - include 'summary' line */
ADS_FILTER_ONLYOBGROUP = (1 << 5), /* only the objects in the specified object group get used */
@@ -564,6 +568,8 @@ typedef enum eDopeSheet_FilterFlag {
ADS_FILTER_NOSPK = (1 << 21),
ADS_FILTER_NOLINESTYLE = (1 << 22),
ADS_FILTER_NOMODIFIERS = (1 << 23),
+ ADS_FILTER_NOGPENCIL = (1 << 24),
+ /* NOTE: all new datablock filters will have to go in filterflag2 (see below) */
/* NLA-specific filters */
ADS_FILTER_NLA_NOACT = (1 << 25), /* if the AnimData block has no NLA data, don't include to just show Action-line */
@@ -581,6 +587,8 @@ typedef enum eDopeSheet_FilterFlag {
typedef enum eDopeSheet_Flag {
ADS_FLAG_SUMMARY_COLLAPSED = (1 << 0), /* when summary is shown, it is collapsed, so all other channels get hidden */
ADS_FLAG_SHOW_DBFILTERS = (1 << 1) /* show filters for datablocks */
+
+ /* NOTE: datablock filter flags continued (1 << 10) onwards... */
} eDopeSheet_Flag;
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index b14861fcf47..89c8316002b 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -93,7 +93,7 @@ typedef struct Brush {
float plane_offset; /* offset for plane brushes (clay, flatten, fill, scrape) */
- float pad;
+ int flag2;
int gradient_spacing;
int gradient_stroke_mode; /* source for stroke color gradient application */
int gradient_fill_mode; /* source for fill tool color gradient application */
@@ -102,7 +102,7 @@ typedef struct Brush {
char vertexpaint_tool; /* active vertex/weight paint blend mode (poorly named) */
char imagepaint_tool; /* active image paint tool */
char mask_tool; /* enum BrushMaskTool, only used if sculpt_tool is SCULPT_TOOL_MASK */
-
+
float autosmooth_factor;
float crease_pinch_factor;
@@ -192,7 +192,7 @@ typedef enum BrushFlags {
BRUSH_JITTER_PRESSURE = (1 << 4),
BRUSH_SPACING_PRESSURE = (1 << 5),
BRUSH_UNUSED = (1 << 6),
- BRUSH_RAKE = (1 << 7),
+// BRUSH_RAKE = (1 << 7), deprecated, use brush_angle_mode
BRUSH_ANCHORED = (1 << 8),
BRUSH_DIR_IN = (1 << 9),
BRUSH_SPACE = (1 << 10),
@@ -209,7 +209,7 @@ typedef enum BrushFlags {
BRUSH_EDGE_TO_EDGE = (1 << 22),
BRUSH_DRAG_DOT = (1 << 23),
BRUSH_INVERSE_SMOOTH_PRESSURE = (1 << 24),
- BRUSH_RANDOM_ROTATION = (1 << 25),
+// BRUSH_RANDOM_ROTATION = (1 << 25), deprecated, use brush_angle_mode
BRUSH_PLANE_TRIM = (1 << 26),
BRUSH_FRONTFACE = (1 << 27),
BRUSH_CUSTOM_ICON = (1 << 28),
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index fb33879e2c1..86991245068 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -173,6 +173,12 @@ typedef struct bSplineIKConstraint {
/* settings */
short flag; /* general settings for constraint */
short xzScaleMode; /* method used for determining the x & z scaling of the bones */
+
+ /* volume preservation settings */
+ float bulge;
+ float bulge_min;
+ float bulge_max;
+ float bulge_smooth;
} bSplineIKConstraint;
@@ -680,15 +686,19 @@ typedef enum eKinematic_Flags {
/* bSplineIKConstraint->flag */
typedef enum eSplineIK_Flags {
/* chain has been attached to spline */
- CONSTRAINT_SPLINEIK_BOUND = (1<<0),
+ CONSTRAINT_SPLINEIK_BOUND = (1 << 0),
/* root of chain is not influenced by the constraint */
- CONSTRAINT_SPLINEIK_NO_ROOT = (1<<1),
+ CONSTRAINT_SPLINEIK_NO_ROOT = (1 << 1),
/* bones in the chain should not scale to fit the curve */
- CONSTRAINT_SPLINEIK_SCALE_LIMITED = (1<<2),
+ CONSTRAINT_SPLINEIK_SCALE_LIMITED = (1 << 2),
/* evenly distribute the bones along the path regardless of length */
- CONSTRAINT_SPLINEIK_EVENSPLITS = (1<<3),
+ CONSTRAINT_SPLINEIK_EVENSPLITS = (1 << 3),
/* don't adjust the x and z scaling of the bones by the curve radius */
- CONSTRAINT_SPLINEIK_NO_CURVERAD = (1<<4)
+ CONSTRAINT_SPLINEIK_NO_CURVERAD = (1 << 4),
+
+ /* for "volumetric" xz scale mode, limit the minimum or maximum scale values */
+ CONSTRAINT_SPLINEIK_USE_BULGE_MIN = (1 << 5),
+ CONSTRAINT_SPLINEIK_USE_BULGE_MAX = (1 << 6),
} eSplineIK_Flags;
/* bSplineIKConstraint->xzScaleMode */
@@ -698,7 +708,9 @@ typedef enum eSplineIK_XZScaleModes {
/* bones in the chain should take their x/z scales from the original scaling */
CONSTRAINT_SPLINEIK_XZS_ORIGINAL = 1,
/* x/z scales are the inverse of the y-scale */
- CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC = 2
+ CONSTRAINT_SPLINEIK_XZS_INVERSE = 2,
+ /* x/z scales are computed using a volume preserving technique (from Stretch To constraint) */
+ CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC = 3
} eSplineIK_XZScaleModes;
/* MinMax (floor) flags */
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 87496fb491f..288743d5e2f 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -270,86 +270,101 @@ typedef struct Curve {
/* **************** CURVE ********************* */
-/* texflag */
-#define CU_AUTOSPACE 1
-
-/* drawflag */
-#define CU_HIDE_HANDLES (1 << 0)
-#define CU_HIDE_NORMALS (1 << 1)
-
-/* flag */
-#define CU_3D 1
-#define CU_FRONT 2
-#define CU_BACK 4
-#define CU_PATH 8
-#define CU_FOLLOW 16
-#define CU_UV_ORCO 32
-#define CU_DEFORM_BOUNDS_OFF 64
-#define CU_STRETCH 128
-/* #define CU_OFFS_PATHDIST 256 */ /* DEPRECATED */
-#define CU_FAST 512 /* Font: no filling inside editmode */
-/* #define CU_RETOPO 1024 */ /* DEPRECATED */
-#define CU_DS_EXPAND 2048
-#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 beveled area */
-
-/* twist mode */
-#define CU_TWIST_Z_UP 0
-// #define CU_TWIST_Y_UP 1 // not used yet
-// #define CU_TWIST_X_UP 2
-#define CU_TWIST_MINIMUM 3
-#define CU_TWIST_TANGENT 4
-
-/* bevel factor mapping */
+/* Curve.texflag */
enum {
- CU_BEVFAC_MAP_RESOLU = 0,
+ CU_AUTOSPACE = 1,
+};
+
+/* Curve.drawflag */
+enum {
+ CU_HIDE_HANDLES = 1 << 0,
+ CU_HIDE_NORMALS = 1 << 1,
+};
+
+/* Curve.flag */
+enum {
+ CU_3D = 1 << 0,
+ CU_FRONT = 1 << 1,
+ CU_BACK = 1 << 2,
+ CU_PATH = 1 << 3,
+ CU_FOLLOW = 1 << 4,
+ CU_UV_ORCO = 1 << 5,
+ CU_DEFORM_BOUNDS_OFF = 1 << 6,
+ CU_STRETCH = 1 << 7,
+ /* CU_OFFS_PATHDIST = 1 << 8, */ /* DEPRECATED */
+ CU_FAST = 1 << 9, /* Font: no filling inside editmode */
+ /* CU_RETOPO = 1 << 10, */ /* DEPRECATED */
+ CU_DS_EXPAND = 1 << 11,
+ CU_PATH_RADIUS = 1 << 12, /* make use of the path radius if this is enabled (default for new curves) */
+ CU_DEFORM_FILL = 1 << 13, /* fill 2d curve after deformation */
+ CU_FILL_CAPS = 1 << 14, /* fill bevel caps */
+ CU_MAP_TAPER = 1 << 15, /* map taper object to beveled area */
+};
+
+/* Curve.twist_mode */
+enum {
+ CU_TWIST_Z_UP = 0,
+ /* CU_TWIST_Y_UP = 1, */ /* not used yet */
+ /* CU_TWIST_X_UP = 2, */
+ CU_TWIST_MINIMUM = 3,
+ CU_TWIST_TANGENT = 4,
+};
+
+/* Curve.bevfac1_mapping, Curve.bevfac2_mapping, bevel factor mapping */
+enum {
+ CU_BEVFAC_MAP_RESOLU = 0,
CU_BEVFAC_MAP_SEGMENT = 1,
- CU_BEVFAC_MAP_SPLINE = 2
+ CU_BEVFAC_MAP_SPLINE = 2,
+};
+
+/* Curve.spacemode */
+enum {
+ CU_LEFT = 0,
+ CU_MIDDLE = 1,
+ CU_RIGHT = 2,
+ CU_JUSTIFY = 3,
+ CU_FLUSH = 4,
};
-/* spacemode */
-#define CU_LEFT 0
-#define CU_MIDDLE 1
-#define CU_RIGHT 2
-#define CU_JUSTIFY 3
-#define CU_FLUSH 4
-
-/* flag (nurb) */
-#define CU_SMOOTH 1
-#define CU_2D 8 /* moved from type since 2.4x */
-
-/* type (nurb) */
-#define CU_POLY 0
-#define CU_BEZIER 1
-#define CU_BSPLINE 2
-#define CU_CARDINAL 3
-#define CU_NURBS 4
-#define CU_TYPE (CU_POLY|CU_BEZIER|CU_BSPLINE|CU_CARDINAL|CU_NURBS)
-
- /* only for adding */
-#define CU_PRIMITIVE 0xF00
-
- /* 2 or 4 points */
-#define CU_PRIM_CURVE 0x100
- /* 8 points circle */
-#define CU_PRIM_CIRCLE 0x200
- /* 4x4 patch Nurb */
-#define CU_PRIM_PATCH 0x300
-#define CU_PRIM_TUBE 0x400
-#define CU_PRIM_SPHERE 0x500
-#define CU_PRIM_DONUT 0x600
- /* 5 points, 5th order straight line (for anim path) */
-#define CU_PRIM_PATH 0x700
-
-
-/* flagu flagv (nurb) */
-#define CU_NURB_CYCLIC 1
-#define CU_NURB_ENDPOINT 2
-#define CU_NURB_BEZIER 4
-
-#define CU_ACT_NONE -1
+/* Nurb.flag */
+enum {
+ CU_SMOOTH = 1 << 0,
+ CU_2D = 1 << 3, /* moved from type since 2.4x */
+};
+
+/* Nurb.type */
+enum {
+ CU_POLY = 0,
+ CU_BEZIER = 1,
+ CU_BSPLINE = 2,
+ CU_CARDINAL = 3,
+ CU_NURBS = 4,
+ CU_TYPE = (CU_POLY | CU_BEZIER | CU_BSPLINE | CU_CARDINAL | CU_NURBS),
+
+ /* only for adding */
+ CU_PRIMITIVE = 0xF00,
+
+ /* 2 or 4 points */
+ CU_PRIM_CURVE = 0x100,
+ /* 8 points circle */
+ CU_PRIM_CIRCLE = 0x200,
+ /* 4x4 patch Nurb */
+ CU_PRIM_PATCH = 0x300,
+ CU_PRIM_TUBE = 0x400,
+ CU_PRIM_SPHERE = 0x500,
+ CU_PRIM_DONUT = 0x600,
+ /* 5 points, 5th order straight line (for anim path) */
+ CU_PRIM_PATH = 0x700,
+};
+
+/* Nurb.flagu, Nurb.flagv */
+enum {
+ CU_NURB_CYCLIC = 1 << 0,
+ CU_NURB_ENDPOINT = 1 << 1,
+ CU_NURB_BEZIER = 1 << 2,
+};
+
+#define CU_ACT_NONE -1
/* *************** BEZTRIPLE **************** */
@@ -366,9 +381,9 @@ typedef enum eBezTriple_Handle {
/* interpolation modes (used only for BezTriple->ipo) */
typedef enum eBezTriple_Interpolation {
/* traditional interpolation */
- BEZT_IPO_CONST = 0, /* constant interpolation */
- BEZT_IPO_LIN = 1, /* linear interpolation */
- BEZT_IPO_BEZ = 2, /* bezier interpolation */
+ BEZT_IPO_CONST = 0, /* constant interpolation */
+ BEZT_IPO_LIN = 1, /* linear interpolation */
+ BEZT_IPO_BEZ = 2, /* bezier interpolation */
/* easing equations */
BEZT_IPO_BACK = 3,
@@ -380,7 +395,7 @@ typedef enum eBezTriple_Interpolation {
BEZT_IPO_QUAD = 9,
BEZT_IPO_QUART = 10,
BEZT_IPO_QUINT = 11,
- BEZT_IPO_SINE = 12
+ BEZT_IPO_SINE = 12,
} eBezTriple_Interpolation;
/* easing modes (used only for Keyframes - BezTriple->easing) */
@@ -389,15 +404,15 @@ typedef enum eBezTriple_Easing {
BEZT_IPO_EASE_IN = 1,
BEZT_IPO_EASE_OUT = 2,
- BEZT_IPO_EASE_IN_OUT = 3
+ BEZT_IPO_EASE_IN_OUT = 3,
} eBezTriple_Easing;
/* types of keyframe (used only for BezTriple->hide when BezTriple is used in F-Curves) */
typedef enum eBezTriple_KeyframeType {
- BEZT_KEYTYPE_KEYFRAME = 0, /* default - 'proper' Keyframe */
- BEZT_KEYTYPE_EXTREME = 1, /* 'extreme' keyframe */
- BEZT_KEYTYPE_BREAKDOWN = 2, /* 'breakdown' keyframe */
- BEZT_KEYTYPE_JITTER = 3, /* 'jitter' keyframe (for adding 'filler' secondary motion) */
+ BEZT_KEYTYPE_KEYFRAME = 0, /* default - 'proper' Keyframe */
+ BEZT_KEYTYPE_EXTREME = 1, /* 'extreme' keyframe */
+ BEZT_KEYTYPE_BREAKDOWN = 2, /* 'breakdown' keyframe */
+ BEZT_KEYTYPE_JITTER = 3, /* 'jitter' keyframe (for adding 'filler' secondary motion) */
} eBezTriple_KeyframeType;
/* checks if the given BezTriple is selected */
@@ -406,14 +421,16 @@ typedef enum eBezTriple_KeyframeType {
/* *************** CHARINFO **************** */
-/* flag */
-/* note: CU_CHINFO_WRAP and CU_CHINFO_SMALLCAPS_TEST are set dynamically */
-#define CU_CHINFO_BOLD (1<<0)
-#define CU_CHINFO_ITALIC (1<<1)
-#define CU_CHINFO_UNDERLINE (1<<2)
-#define CU_CHINFO_WRAP (1<<3) /* wordwrap occurred here */
-#define CU_CHINFO_SMALLCAPS (1<<4)
-#define CU_CHINFO_SMALLCAPS_CHECK (1<<5) /* set at runtime, checks if case switching is needed */
+/* CharInfo.flag */
+enum {
+ /* note: CU_CHINFO_WRAP and CU_CHINFO_SMALLCAPS_TEST are set dynamically */
+ CU_CHINFO_BOLD = 1 << 0,
+ CU_CHINFO_ITALIC = 1 << 1,
+ CU_CHINFO_UNDERLINE = 1 << 2,
+ CU_CHINFO_WRAP = 1 << 3, /* wordwrap occurred here */
+ CU_CHINFO_SMALLCAPS = 1 << 4,
+ CU_CHINFO_SMALLCAPS_CHECK = 1 << 5, /* set at runtime, checks if case switching is needed */
+};
/* mixed with KEY_LINEAR but define here since only curve supports */
#define KEY_CU_EASE 3
diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h
index fd435317426..939b14a5d32 100644
--- a/source/blender/makesdna/DNA_dynamicpaint_types.h
+++ b/source/blender/makesdna/DNA_dynamicpaint_types.h
@@ -34,55 +34,71 @@ struct CurveMapping;
struct PaintSurfaceData;
/* surface format */
-#define MOD_DPAINT_SURFACE_F_PTEX 0
-#define MOD_DPAINT_SURFACE_F_VERTEX 1
-#define MOD_DPAINT_SURFACE_F_IMAGESEQ 2
+enum {
+ MOD_DPAINT_SURFACE_F_PTEX = 0,
+ MOD_DPAINT_SURFACE_F_VERTEX = 1,
+ MOD_DPAINT_SURFACE_F_IMAGESEQ = 2,
+};
/* surface type */
-#define MOD_DPAINT_SURFACE_T_PAINT 0
-#define MOD_DPAINT_SURFACE_T_DISPLACE 1
-#define MOD_DPAINT_SURFACE_T_WEIGHT 2
-#define MOD_DPAINT_SURFACE_T_WAVE 3
+enum {
+ MOD_DPAINT_SURFACE_T_PAINT = 0,
+ MOD_DPAINT_SURFACE_T_DISPLACE = 1,
+ MOD_DPAINT_SURFACE_T_WEIGHT = 2,
+ MOD_DPAINT_SURFACE_T_WAVE = 3,
+};
/* surface flags */
-#define MOD_DPAINT_ACTIVE (1<<0) /* Is surface enabled */
+enum {
+ MOD_DPAINT_ACTIVE = 1 << 0, /* Is surface enabled */
-#define MOD_DPAINT_ANTIALIAS (1<<1) /* do antialiasing */
-#define MOD_DPAINT_DISSOLVE (1<<2) /* do dissolve */
-#define MOD_DPAINT_MULALPHA (1<<3) /* Multiply color by alpha when saving image */
-#define MOD_DPAINT_DISSOLVE_LOG (1<<4) /* Use 1/x for surface dissolve */
-#define MOD_DPAINT_DRY_LOG (1<<5) /* Use 1/x for drying paint */
-#define MOD_DPAINT_PREVIEW (1<<6) /* preview this surface on viewport*/
+ MOD_DPAINT_ANTIALIAS = 1 << 1, /* do antialiasing */
+ MOD_DPAINT_DISSOLVE = 1 << 2, /* do dissolve */
+ MOD_DPAINT_MULALPHA = 1 << 3, /* Multiply color by alpha when saving image */
+ MOD_DPAINT_DISSOLVE_LOG = 1 << 4, /* Use 1/x for surface dissolve */
+ MOD_DPAINT_DRY_LOG = 1 << 5, /* Use 1/x for drying paint */
+ MOD_DPAINT_PREVIEW = 1 << 6, /* preview this surface on viewport*/
-#define MOD_DPAINT_WAVE_OPEN_BORDERS (1<<7) /* passes waves through mesh edges */
-#define MOD_DPAINT_DISP_INCREMENTAL (1<<8) /* builds displace on top of earlier values */
-#define MOD_DPAINT_USE_DRYING (1<<9) /* use drying */
+ MOD_DPAINT_WAVE_OPEN_BORDERS = 1 << 7, /* passes waves through mesh edges */
+ MOD_DPAINT_DISP_INCREMENTAL = 1 << 8, /* builds displace on top of earlier values */
+ MOD_DPAINT_USE_DRYING = 1 << 9, /* use drying */
-#define MOD_DPAINT_OUT1 (1<<10) /* output primary surface */
-#define MOD_DPAINT_OUT2 (1<<11) /* output secondary surface */
+ MOD_DPAINT_OUT1 = 1 << 10, /* output primary surface */
+ MOD_DPAINT_OUT2 = 1 << 11, /* output secondary surface */
+};
/* image_fileformat */
-#define MOD_DPAINT_IMGFORMAT_PNG 0
-#define MOD_DPAINT_IMGFORMAT_OPENEXR 1
+enum {
+ MOD_DPAINT_IMGFORMAT_PNG = 0,
+ MOD_DPAINT_IMGFORMAT_OPENEXR = 1,
+};
/* disp_format */
-#define MOD_DPAINT_DISP_DISPLACE 0 /* displacement output displace map */
-#define MOD_DPAINT_DISP_DEPTH 1 /* displacement output depth data */
+enum {
+ MOD_DPAINT_DISP_DISPLACE = 0, /* displacement output displace map */
+ MOD_DPAINT_DISP_DEPTH = 1, /* displacement output depth data */
+};
/* effect */
-#define MOD_DPAINT_EFFECT_DO_SPREAD (1<<0) /* do spread effect */
-#define MOD_DPAINT_EFFECT_DO_DRIP (1<<1) /* do drip effect */
-#define MOD_DPAINT_EFFECT_DO_SHRINK (1<<2) /* do shrink effect */
+enum {
+ MOD_DPAINT_EFFECT_DO_SPREAD = 1 << 0, /* do spread effect */
+ MOD_DPAINT_EFFECT_DO_DRIP = 1 << 1, /* do drip effect */
+ MOD_DPAINT_EFFECT_DO_SHRINK = 1 << 2, /* do shrink effect */
+};
/* preview_id */
-#define MOD_DPAINT_SURFACE_PREV_PAINT 0
-#define MOD_DPAINT_SURFACE_PREV_WETMAP 1
+enum {
+ MOD_DPAINT_SURFACE_PREV_PAINT = 0,
+ MOD_DPAINT_SURFACE_PREV_WETMAP = 1,
+};
/* init_color_type */
-#define MOD_DPAINT_INITIAL_NONE 0
-#define MOD_DPAINT_INITIAL_COLOR 1
-#define MOD_DPAINT_INITIAL_TEXTURE 2
-#define MOD_DPAINT_INITIAL_VERTEXCOLOR 3
+enum {
+ MOD_DPAINT_INITIAL_NONE = 0,
+ MOD_DPAINT_INITIAL_COLOR = 1,
+ MOD_DPAINT_INITIAL_TEXTURE = 2,
+ MOD_DPAINT_INITIAL_VERTEXCOLOR = 3,
+};
typedef struct DynamicPaintSurface {
@@ -137,11 +153,14 @@ typedef struct DynamicPaintSurface {
} DynamicPaintSurface;
/* canvas flags */
-#if 0 /* This should not be needed, having a valid WEIGHT_MCOL layer should be enough.
- * And if not, should be a general flag. But seems unnecessary for now... */
-#define MOD_DPAINT_PREVIEW_READY (1<<0) /* if viewport preview is ready */
+enum {
+ /* This should not be needed, having a valid WEIGHT_MCOL layer should be enough.
+ * And if not, should be a general flag. But seems unnecessary for now... */
+#if 0
+ MOD_DPAINT_PREVIEW_READY = 1 << 0, /* if viewport preview is ready */
#endif
-#define MOD_DPAINT_BAKING (1<<1) /* surface is already baking, so it wont get updated (loop) */
+ MOD_DPAINT_BAKING = 1 << 1, /* surface is already baking, so it wont get updated (loop) */
+};
/* Canvas settings */
typedef struct DynamicPaintCanvasSettings {
@@ -158,47 +177,56 @@ typedef struct DynamicPaintCanvasSettings {
/* flags */
-#define MOD_DPAINT_PART_RAD (1<<0) /* use particle radius */
-#define MOD_DPAINT_USE_MATERIAL (1<<1) /* use object material */
-#define MOD_DPAINT_ABS_ALPHA (1<<2) /* don't increase alpha unless
- * paint alpha is higher than existing */
-#define MOD_DPAINT_ERASE (1<<3) /* removes paint */
-
-#define MOD_DPAINT_RAMP_ALPHA (1<<4) /* only read falloff ramp alpha */
-#define MOD_DPAINT_PROX_PROJECT (1<<5) /* do proximity check only in defined dir */
-#define MOD_DPAINT_INVERSE_PROX (1<<6) /* inverse proximity painting */
-#define MOD_DPAINT_NEGATE_VOLUME (1<<7) /* negates volume influence on "volume + prox" mode */
-
-#define MOD_DPAINT_DO_SMUDGE (1<<8) /* brush smudges existing paint */
-#define MOD_DPAINT_VELOCITY_ALPHA (1<<9) /* multiply brush influence by velocity */
-#define MOD_DPAINT_VELOCITY_COLOR (1<<10) /* replace brush color by velocity color ramp */
-#define MOD_DPAINT_VELOCITY_DEPTH (1<<11) /* multiply brush intersection depth by velocity */
-
-#define MOD_DPAINT_USES_VELOCITY ((1<<8)|(1<<9)|(1<<10)|(1<<11))
+enum {
+ MOD_DPAINT_PART_RAD = 1 << 0, /* use particle radius */
+ MOD_DPAINT_USE_MATERIAL = 1 << 1, /* use object material */
+ MOD_DPAINT_ABS_ALPHA = 1 << 2, /* don't increase alpha unless paint alpha is higher than existing */
+ MOD_DPAINT_ERASE = 1 << 3, /* removes paint */
+
+ MOD_DPAINT_RAMP_ALPHA = 1 << 4, /* only read falloff ramp alpha */
+ MOD_DPAINT_PROX_PROJECT = 1 << 5, /* do proximity check only in defined dir */
+ MOD_DPAINT_INVERSE_PROX = 1 << 6, /* inverse proximity painting */
+ MOD_DPAINT_NEGATE_VOLUME = 1 << 7, /* negates volume influence on "volume + prox" mode */
+
+ MOD_DPAINT_DO_SMUDGE = 1 << 8, /* brush smudges existing paint */
+ MOD_DPAINT_VELOCITY_ALPHA = 1 << 9, /* multiply brush influence by velocity */
+ MOD_DPAINT_VELOCITY_COLOR = 1 << 10, /* replace brush color by velocity color ramp */
+ MOD_DPAINT_VELOCITY_DEPTH = 1 << 11, /* multiply brush intersection depth by velocity */
+
+ MOD_DPAINT_USES_VELOCITY = (MOD_DPAINT_DO_SMUDGE | MOD_DPAINT_VELOCITY_ALPHA |
+ MOD_DPAINT_VELOCITY_COLOR | MOD_DPAINT_VELOCITY_DEPTH),
+};
/* collision type */
-#define MOD_DPAINT_COL_VOLUME 0 /* paint with mesh volume */
-#define MOD_DPAINT_COL_DIST 1 /* paint using distance to mesh surface */
-#define MOD_DPAINT_COL_VOLDIST 2 /* use both volume and distance */
-#define MOD_DPAINT_COL_PSYS 3 /* use particle system */
-#define MOD_DPAINT_COL_POINT 4 /* use distance to object center point */
+enum {
+ MOD_DPAINT_COL_VOLUME = 0, /* paint with mesh volume */
+ MOD_DPAINT_COL_DIST = 1, /* paint using distance to mesh surface */
+ MOD_DPAINT_COL_VOLDIST = 2, /* use both volume and distance */
+ MOD_DPAINT_COL_PSYS = 3, /* use particle system */
+ MOD_DPAINT_COL_POINT = 4, /* use distance to object center point */
+};
/* proximity_falloff */
-#define MOD_DPAINT_PRFALL_CONSTANT 0 /* no-falloff */
-#define MOD_DPAINT_PRFALL_SMOOTH 1 /* smooth, linear falloff */
-#define MOD_DPAINT_PRFALL_RAMP 2 /* use color ramp */
+enum {
+ MOD_DPAINT_PRFALL_CONSTANT = 0, /* no-falloff */
+ MOD_DPAINT_PRFALL_SMOOTH = 1, /* smooth, linear falloff */
+ MOD_DPAINT_PRFALL_RAMP = 2, /* use color ramp */
+};
/* wave_brush_type */
-#define MOD_DPAINT_WAVEB_DEPTH 0 /* use intersection depth */
-#define MOD_DPAINT_WAVEB_FORCE 1 /* act as a force on intersection area */
-#define MOD_DPAINT_WAVEB_REFLECT 2 /* obstacle that reflects waves */
-#define MOD_DPAINT_WAVEB_CHANGE 3 /* use change of intersection depth from previous frame */
+enum {
+ MOD_DPAINT_WAVEB_DEPTH = 0, /* use intersection depth */
+ MOD_DPAINT_WAVEB_FORCE = 1, /* act as a force on intersection area */
+ MOD_DPAINT_WAVEB_REFLECT = 2, /* obstacle that reflects waves */
+ MOD_DPAINT_WAVEB_CHANGE = 3, /* use change of intersection depth from previous frame */
+};
/* brush ray_dir */
-#define MOD_DPAINT_RAY_CANVAS 0
-#define MOD_DPAINT_RAY_BRUSH_AVG 1
-#define MOD_DPAINT_RAY_ZPLUS 2
-
+enum {
+ MOD_DPAINT_RAY_CANVAS = 0,
+ MOD_DPAINT_RAY_BRUSH_AVG = 1,
+ MOD_DPAINT_RAY_ZPLUS = 2,
+};
/* Brush settings */
typedef struct DynamicPaintBrushSettings {
diff --git a/source/blender/makesdna/DNA_freestyle_types.h b/source/blender/makesdna/DNA_freestyle_types.h
index d099511a088..2359d1e9738 100644
--- a/source/blender/makesdna/DNA_freestyle_types.h
+++ b/source/blender/makesdna/DNA_freestyle_types.h
@@ -44,60 +44,74 @@ struct Group;
struct Text;
/* FreestyleConfig::flags */
-#define FREESTYLE_SUGGESTIVE_CONTOURS_FLAG (1 << 0)
-#define FREESTYLE_RIDGES_AND_VALLEYS_FLAG (1 << 1)
-#define FREESTYLE_MATERIAL_BOUNDARIES_FLAG (1 << 2)
-#define FREESTYLE_FACE_SMOOTHNESS_FLAG (1 << 3)
-#define FREESTYLE_ADVANCED_OPTIONS_FLAG (1 << 4)
-#define FREESTYLE_CULLING (1 << 5)
-#define FREESTYLE_VIEW_MAP_CACHE (1 << 6)
+enum {
+ FREESTYLE_SUGGESTIVE_CONTOURS_FLAG = 1 << 0,
+ FREESTYLE_RIDGES_AND_VALLEYS_FLAG = 1 << 1,
+ FREESTYLE_MATERIAL_BOUNDARIES_FLAG = 1 << 2,
+ FREESTYLE_FACE_SMOOTHNESS_FLAG = 1 << 3,
+ FREESTYLE_ADVANCED_OPTIONS_FLAG = 1 << 4,
+ FREESTYLE_CULLING = 1 << 5,
+ FREESTYLE_VIEW_MAP_CACHE = 1 << 6,
+};
/* FreestyleConfig::mode */
-#define FREESTYLE_CONTROL_SCRIPT_MODE 1
-#define FREESTYLE_CONTROL_EDITOR_MODE 2
+enum {
+ FREESTYLE_CONTROL_SCRIPT_MODE = 1,
+ FREESTYLE_CONTROL_EDITOR_MODE = 2,
+};
/* FreestyleLineSet::flags */
-#define FREESTYLE_LINESET_CURRENT (1 << 0)
-#define FREESTYLE_LINESET_ENABLED (1 << 1)
-#define FREESTYLE_LINESET_FE_NOT (1 << 2)
-#define FREESTYLE_LINESET_FE_AND (1 << 3)
-#define FREESTYLE_LINESET_GR_NOT (1 << 4)
-#define FREESTYLE_LINESET_FM_NOT (1 << 5)
-#define FREESTYLE_LINESET_FM_BOTH (1 << 6)
+enum {
+ FREESTYLE_LINESET_CURRENT = 1 << 0,
+ FREESTYLE_LINESET_ENABLED = 1 << 1,
+ FREESTYLE_LINESET_FE_NOT = 1 << 2,
+ FREESTYLE_LINESET_FE_AND = 1 << 3,
+ FREESTYLE_LINESET_GR_NOT = 1 << 4,
+ FREESTYLE_LINESET_FM_NOT = 1 << 5,
+ FREESTYLE_LINESET_FM_BOTH = 1 << 6,
+};
/* FreestyleLineSet::selection */
-#define FREESTYLE_SEL_VISIBILITY (1 << 0)
-#define FREESTYLE_SEL_EDGE_TYPES (1 << 1)
-#define FREESTYLE_SEL_GROUP (1 << 2)
-#define FREESTYLE_SEL_IMAGE_BORDER (1 << 3)
-#define FREESTYLE_SEL_FACE_MARK (1 << 4)
+enum {
+ FREESTYLE_SEL_VISIBILITY = 1 << 0,
+ FREESTYLE_SEL_EDGE_TYPES = 1 << 1,
+ FREESTYLE_SEL_GROUP = 1 << 2,
+ FREESTYLE_SEL_IMAGE_BORDER = 1 << 3,
+ FREESTYLE_SEL_FACE_MARK = 1 << 4,
+};
/* FreestyleLineSet::edge_types, exclude_edge_types */
-#define FREESTYLE_FE_SILHOUETTE (1 << 0)
-#define FREESTYLE_FE_BORDER (1 << 1)
-#define FREESTYLE_FE_CREASE (1 << 2)
-#define FREESTYLE_FE_RIDGE_VALLEY (1 << 3)
-/* Note: FREESTYLE_FE_VALLEY = (1 << 4) is no longer used */
-#define FREESTYLE_FE_SUGGESTIVE_CONTOUR (1 << 5)
-#define FREESTYLE_FE_MATERIAL_BOUNDARY (1 << 6)
-#define FREESTYLE_FE_CONTOUR (1 << 7)
-#define FREESTYLE_FE_EXTERNAL_CONTOUR (1 << 8)
-#define FREESTYLE_FE_EDGE_MARK (1 << 9)
+enum {
+ FREESTYLE_FE_SILHOUETTE = 1 << 0,
+ FREESTYLE_FE_BORDER = 1 << 1,
+ FREESTYLE_FE_CREASE = 1 << 2,
+ FREESTYLE_FE_RIDGE_VALLEY = 1 << 3,
+ /* FREESTYLE_FE_VALLEY = 1 << 4, */ /* No longer used */
+ FREESTYLE_FE_SUGGESTIVE_CONTOUR = 1 << 5,
+ FREESTYLE_FE_MATERIAL_BOUNDARY = 1 << 6,
+ FREESTYLE_FE_CONTOUR = 1 << 7,
+ FREESTYLE_FE_EXTERNAL_CONTOUR = 1 << 8,
+ FREESTYLE_FE_EDGE_MARK = 1 << 9,
+};
/* FreestyleLineSet::qi */
-#define FREESTYLE_QI_VISIBLE 1
-#define FREESTYLE_QI_HIDDEN 2
-#define FREESTYLE_QI_RANGE 3
+enum {
+ FREESTYLE_QI_VISIBLE = 1,
+ FREESTYLE_QI_HIDDEN = 2,
+ FREESTYLE_QI_RANGE = 3,
+};
/* FreestyleConfig::raycasting_algorithm */
/* Defines should be replaced with ViewMapBuilder::visibility_algo */
-#define FREESTYLE_ALGO_REGULAR 1
-#define FREESTYLE_ALGO_FAST 2
-#define FREESTYLE_ALGO_VERYFAST 3
-#define FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL 4
-#define FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL 5
-#define FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE 6
-#define FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE 7
+enum {
+ FREESTYLE_ALGO_REGULAR = 1,
+ FREESTYLE_ALGO_FAST = 2,
+ FREESTYLE_ALGO_VERYFAST = 3,
+ FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL = 4,
+ FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL = 5,
+ FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE = 6,
+ FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE = 7,
+};
typedef struct FreestyleLineSet {
struct FreestyleLineSet *next, *prev;
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 2bf874d3a85..3fb047ebbe7 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -33,6 +33,9 @@
#include "DNA_listBase.h"
#include "DNA_ID.h"
+struct AnimData;
+
+
/* Grease-Pencil Annotations - 'Stroke Point'
* -> Coordinates may either be 2d or 3d depending on settings at the time
* -> Coordinates of point on stroke, in proportions of window size
@@ -42,8 +45,15 @@ typedef struct bGPDspoint {
float x, y, z; /* co-ordinates of point (usually 2d, but can be 3d as well) */
float pressure; /* pressure of input device (from 0 to 1) at this point */
float time; /* seconds since start of stroke */
+ int flag; /* additional options (NOTE: can shrink this field down later if needed) */
} bGPDspoint;
+/* bGPDspoint->flag */
+typedef enum eGPDspoint_Flag {
+ /* stroke point is selected (for editing) */
+ GP_SPOINT_SELECT = (1 << 0)
+} eGPSPoint_Flag;
+
/* Grease-Pencil Annotations - 'Stroke'
* -> A stroke represents a (simplified version) of the curve
* drawn by the user in one 'mousedown'->'mouseup' operation
@@ -61,15 +71,18 @@ typedef struct bGPDstroke {
} bGPDstroke;
/* bGPDstroke->flag */
+typedef enum eGPDstroke_Flag {
/* stroke is in 3d-space */
-#define GP_STROKE_3DSPACE (1<<0)
+ GP_STROKE_3DSPACE = (1 << 0),
/* stroke is in 2d-space */
-#define GP_STROKE_2DSPACE (1<<1)
+ GP_STROKE_2DSPACE = (1 << 1),
/* stroke is in 2d-space (but with special 'image' scaling) */
-#define GP_STROKE_2DIMAGE (1<<2)
+ GP_STROKE_2DIMAGE = (1 << 2),
+ /* stroke is selected */
+ GP_STROKE_SELECT = (1 << 3),
/* only for use with stroke-buffer (while drawing eraser) */
-#define GP_STROKE_ERASER (1<<15)
-
+ GP_STROKE_ERASER = (1 << 15)
+} eGPDstroke_Flag;
/* Grease-Pencil Annotations - 'Frame'
* -> Acts as storage for the 'image' formed by strokes
@@ -80,15 +93,18 @@ typedef struct bGPDframe {
ListBase strokes; /* list of the simplified 'strokes' that make up the frame's data */
int framenum; /* frame number of this frame */
- int flag; /* temp settings */
+
+ short flag; /* temp settings */
+ short key_type; /* keyframe type (eBezTriple_KeyframeType) */
} bGPDframe;
-/* bGPDframe->flag */
+/* bGPDframe->flag */
+typedef enum eGPDframe_Flag {
/* frame is being painted on */
-#define GP_FRAME_PAINT (1<<0)
+ GP_FRAME_PAINT = (1 << 0),
/* for editing in Action Editor */
-#define GP_FRAME_SELECT (1<<1)
-
+ GP_FRAME_SELECT = (1 << 1)
+} eGPDframe_Flag;
/* Grease-Pencil Annotations - 'Layer' */
typedef struct bGPDlayer {
@@ -97,38 +113,52 @@ typedef struct bGPDlayer {
ListBase frames; /* list of annotations to display for frames (bGPDframe list) */
bGPDframe *actframe; /* active frame (should be the frame that is currently being displayed) */
- int flag; /* settings for layer */
+ short flag; /* settings for layer */
short thickness; /* current thickness to apply to strokes */
- short gstep; /* max number of frames between active and ghost to show (0=only those on either side) */
+
+ short gstep; /* Ghosts Before: max number of ghost frames to show between active frame and the one before it (0 = only the ghost itself) */
+ short gstep_next; /* Ghosts After: max number of ghost frames to show after active frame and the following it (0 = only the ghost itself) */
+
+ float gcolor_prev[3]; /* optional color for ghosts before the active frame */
+ float gcolor_next[3]; /* optional color for ghosts after the active frame */
float color[4]; /* color that should be used to draw all the strokes in this layer */
+ float fill[4]; /* color that should be used for drawing "fills" for strokes */
char info[128]; /* optional reference info about this layer (i.e. "director's comments, 12/3")
* this is used for the name of the layer too and kept unique. */
} bGPDlayer;
/* bGPDlayer->flag */
+typedef enum eGPDlayer_Flag {
/* don't display layer */
-#define GP_LAYER_HIDE (1<<0)
+ GP_LAYER_HIDE = (1 << 0),
/* protected from further editing */
-#define GP_LAYER_LOCKED (1<<1)
+ GP_LAYER_LOCKED = (1 << 1),
/* layer is 'active' layer being edited */
-#define GP_LAYER_ACTIVE (1<<2)
+ GP_LAYER_ACTIVE = (1 << 2),
/* draw points of stroke for debugging purposes */
-#define GP_LAYER_DRAWDEBUG (1<<3)
- /* do onionskinning */
-#define GP_LAYER_ONIONSKIN (1<<4)
+ GP_LAYER_DRAWDEBUG = (1 << 3),
+ /* do onion skinning */
+ GP_LAYER_ONIONSKIN = (1 << 4),
/* for editing in Action Editor */
-#define GP_LAYER_SELECT (1<<5)
+ GP_LAYER_SELECT = (1 << 5),
/* current frame for layer can't be changed */
-#define GP_LAYER_FRAMELOCK (1<<6)
+ GP_LAYER_FRAMELOCK = (1 << 6),
/* don't render xray (which is default) */
-#define GP_LAYER_NO_XRAY (1<<7)
-
+ GP_LAYER_NO_XRAY = (1 << 7),
+ /* use custom color for ghosts before current frame */
+ GP_LAYER_GHOST_PREVCOL = (1 << 8),
+ /* use custom color for ghosts after current frame */
+ GP_LAYER_GHOST_NEXTCOL = (1 << 9),
+ /* "volumetric" strokes (i.e. GLU Quadric discs in 3D) */
+ GP_LAYER_VOLUMETRIC = (1 << 10),
+} eGPDlayer_Flag;
/* Grease-Pencil Annotations - 'DataBlock' */
typedef struct bGPdata {
- ID id; /* Grease Pencil data is */
+ ID id; /* Grease Pencil data is a datablock */
+ struct AnimData *adt; /* animation data - for animating draw settings */
/* saved Grease-Pencil data */
ListBase layers; /* bGPDlayers */
@@ -144,23 +174,33 @@ typedef struct bGPdata {
} bGPdata;
/* bGPdata->flag */
-// XXX many of these flags should be deprecated for more general ideas in 2.5
+/* NOTE: A few flags have been deprecated since early 2.5,
+ * since they have been made redundant by interaction
+ * changes made during the porting process.
+ */
+typedef enum eGPdata_Flag {
/* don't allow painting to occur at all */
- // XXX is deprecated - not well understood
-// #define GP_DATA_LMBPLOCK (1<<0)
+ /* GP_DATA_LMBPLOCK = (1 << 0), */
+
/* show debugging info in viewport (i.e. status print) */
-#define GP_DATA_DISPINFO (1<<1)
+ GP_DATA_DISPINFO = (1 << 1),
/* in Action Editor, show as expanded channel */
-#define GP_DATA_EXPAND (1<<2)
+ GP_DATA_EXPAND = (1 << 2),
+
/* is the block overriding all clicks? */
- // XXX is deprecated - nasty old concept
-// #define GP_DATA_EDITPAINT (1<<3)
+ /* GP_DATA_EDITPAINT = (1 << 3), */
+
/* new strokes are added in viewport space */
-#define GP_DATA_VIEWALIGN (1<<4)
- /* Project into the screens Z values */
-#define GP_DATA_DEPTH_VIEW (1<<5)
-#define GP_DATA_DEPTH_STROKE (1<<6)
+ GP_DATA_VIEWALIGN = (1 << 4),
+
+ /* Project into the screen's Z values */
+ GP_DATA_DEPTH_VIEW = (1 << 5),
+ GP_DATA_DEPTH_STROKE = (1 << 6),
-#define GP_DATA_DEPTH_STROKE_ENDPOINTS (1<<7)
+ GP_DATA_DEPTH_STROKE_ENDPOINTS = (1 << 7),
+
+ /* Stroke Editing Mode - Toggle to enable alternative keymap for easier editing of stroke points */
+ GP_DATA_STROKE_EDITMODE = (1 << 8)
+} eGPdata_Flag;
#endif /* __DNA_GPENCIL_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h
index 16e40fa52e1..60ab01c901b 100644
--- a/source/blender/makesdna/DNA_key_types.h
+++ b/source/blender/makesdna/DNA_key_types.h
@@ -91,10 +91,10 @@ typedef struct Key {
ID *from;
- short type; /* absolute or relative shape key */
- short totkey; /* (totkey == BLI_listbase_count(&key->block)) */
- short slurph; /* quaint feature to delay moving points based on their order (Key->type == KEY_NORMAL) only */
+ int totkey; /* (totkey == BLI_listbase_count(&key->block)) */
short flag;
+ char type; /* absolute or relative shape key */
+ char pad2;
/* only used when (Key->type == KEY_NORMAL), this value is used as a time slider,
* rather then using the scenes time, this value can be animated to give greater control */
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 688e17ef56a..8067fa5db2d 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -201,7 +201,7 @@ enum {
ME_DRAW_VNORMALS = 1 << 3,
ME_DRAWEIGHT = 1 << 4,
- ME_HIDDENEDGES = 1 << 5,
+ /* ME_HIDDENEDGES = 1 << 5, */ /* DEPRECATED */
ME_DRAWCREASES = 1 << 6,
ME_DRAWSEAMS = 1 << 7,
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 5ab82f86ff5..7b1a9bba3a2 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -82,7 +82,8 @@ typedef enum ModifierType {
eModifierType_MeshCache = 46,
eModifierType_LaplacianDeform = 47,
eModifierType_Wireframe = 48,
- eModifierType_PointCache = 49,
+ eModifierType_DataTransfer = 49,
+ eModifierType_PointCache = 50,
NUM_MODIFIER_TYPES
} ModifierType;
@@ -1367,6 +1368,49 @@ enum {
MOD_WIREFRAME_CREASE = (1 << 5),
};
+
+typedef struct DataTransferModifierData {
+ ModifierData modifier;
+
+ struct Object *ob_source;
+
+ int data_types; /* See DT_TYPE_ enum in ED_object.h */
+
+ /* See MREMAP_MODE_ enum in BKE_mesh_mapping.h */
+ int vmap_mode;
+ int emap_mode;
+ int lmap_mode;
+ int pmap_mode;
+
+ float map_max_distance;
+ float map_ray_radius;
+ float islands_precision;
+
+ int pad_i1;
+
+ int layers_select_src[4]; /* DT_MULTILAYER_INDEX_MAX; See DT_FROMLAYERS_ enum in ED_object.h */
+ int layers_select_dst[4]; /* DT_MULTILAYER_INDEX_MAX; See DT_TOLAYERS_ enum in ED_object.h */
+
+ int mix_mode; /* See CDT_MIX_ enum in BKE_customdata.h */
+ float mix_factor;
+ char defgrp_name[64]; /* MAX_VGROUP_NAME */
+
+ int flags;
+} DataTransferModifierData;
+
+/* DataTransferModifierData.flags */
+enum {
+ MOD_DATATRANSFER_OBSRC_TRANSFORM = 1 << 0,
+ MOD_DATATRANSFER_MAP_MAXDIST = 1 << 1,
+ MOD_DATATRANSFER_INVERT_VGROUP = 1 << 2,
+
+ /* Only for UI really. */
+ MOD_DATATRANSFER_USE_VERT = 1 << 28,
+ MOD_DATATRANSFER_USE_EDGE = 1 << 29,
+ MOD_DATATRANSFER_USE_LOOP = 1 << 30,
+ MOD_DATATRANSFER_USE_POLY = 1 << 31,
+};
+
/* point cache modifier */
typedef struct PointCacheModifierData {
ModifierData modifier;
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 745b21618ca..49f8b3cd4d0 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -985,25 +985,36 @@ typedef struct UnifiedPaintSettings {
/* record movement of mouse so that rake can start at an intuitive angle */
float last_rake[2];
+ float last_rake_angle;
+
+ int last_stroke_valid;
+ float average_stroke_accum[3];
+ int average_stroke_counter;
+
float brush_rotation;
+ float brush_rotation_sec;
/*********************************************************************************
* all data below are used to communicate with cursor drawing and tex sampling *
*********************************************************************************/
- int draw_anchored;
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*/
+ char draw_inverted;
+ /* check is there an ongoing stroke right now */
+ char stroke_active;
+
+ char draw_anchored;
+ char do_linear_conversion;
+
float anchored_initial_mouse[2];
- /* check is there an ongoing stroke right now */
- int stroke_active;
+ /* radius of brush, premultiplied with pressure.
+ * In case of anchored brushes contains the anchored radius */
+ float pixel_radius;
/* drawing pressure */
float size_pressure_value;
@@ -1015,13 +1026,7 @@ typedef struct UnifiedPaintSettings {
float mask_tex_mouse[2];
/* ColorSpace cache to avoid locking up during sampling */
- int do_linear_conversion;
struct ColorSpace *colorspace;
-
- /* radius of brush, premultiplied with pressure.
- * In case of anchored brushes contains the anchored radius */
- float pixel_radius;
- int pad4;
} UnifiedPaintSettings;
typedef enum {
@@ -1093,9 +1098,10 @@ typedef struct ToolSettings {
short autoik_chainlen; /* runtime only */
/* Grease Pencil */
- char gpencil_flags;
+ char gpencil_flags; /* flags/options for how the tool works */
+ char gpencil_src; /* for main 3D view Grease Pencil, where data comes from */
- char pad[5];
+ char pad[4];
/* Image Paint (8 byttse aligned please!) */
struct ImagePaintSettings imapaint;
@@ -1769,6 +1775,12 @@ typedef enum ImagePaintMode {
/* toolsettings->gpencil_flags */
#define GP_TOOL_FLAG_PAINTSESSIONS_ON (1<<0)
+/* toolsettings->gpencil_src */
+typedef enum eGPencil_Source_3D {
+ GP_TOOL_SOURCE_SCENE = 0,
+ GP_TOOL_SOURCE_OBJECT = 1
+} eGPencil_Source_3d;
+
/* toolsettings->particle flag */
#define PE_KEEP_LENGTHS 1
#define PE_LOCK_FIRST 2
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 47a08c62f95..7372f55c3de 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -57,24 +57,23 @@ typedef struct bScreen {
struct Scene *scene;
struct Scene *newscene; /* temporary when switching */
- int redraws_flag; /* user-setting for which editors get redrawn during anim playback (used to be time->redraws) */
- int pad1;
-
- short state; /* temp screen for image render display or fileselect */
- short temp; /* temp screen in a temp window, don't save (like user prefs) */
short winid; /* winid from WM, starts with 1 */
- short do_draw; /* notifier for drawing edges */
- short do_refresh; /* notifier for scale screen, changed screen, etc */
- short do_draw_gesture; /* notifier for gesture draw. */
- short do_draw_paintcursor; /* notifier for paint cursor draw. */
- short do_draw_drag; /* notifier for dragging draw. */
- short swap; /* indicator to survive swap-exchange systems */
+ short redraws_flag; /* user-setting for which editors get redrawn during anim playback (used to be time->redraws) */
+
+ char temp; /* temp screen in a temp window, don't save (like user prefs) */
+ char state; /* temp screen for image render display or fileselect */
+ char do_draw; /* notifier for drawing edges */
+ char do_refresh; /* notifier for scale screen, changed screen, etc */
+ char do_draw_gesture; /* notifier for gesture draw. */
+ char do_draw_paintcursor; /* notifier for paint cursor draw. */
+ char do_draw_drag; /* notifier for dragging draw. */
+ char swap; /* indicator to survive swap-exchange systems */
+ char skip_handling; /* set to delay screen handling after switching back from maximized area */
+ char pad[7];
short mainwin; /* screensize subwindow, for screenedges and global menus */
short subwinactive; /* active subwindow */
-
- short pad;
-
+
struct wmTimer *animtimer; /* if set, screen has timer handler added in window */
void *context; /* context callback */
} bScreen;
@@ -215,7 +214,7 @@ typedef struct ScrArea {
short do_refresh; /* private, for spacetype refresh callback */
short flag;
short region_active_win; /* index of last used region of 'RGN_TYPE_WINDOW'
- * runtuime variable, updated by executing operators */
+ * runtime variable, updated by executing operators */
char temp, pad;
struct SpaceType *type; /* callbacks for this space type */
@@ -272,12 +271,16 @@ typedef struct ARegion {
// #define WIN_EQUAL 3 // UNUSED
/* area->flag */
-#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)
+enum {
+ HEADER_NO_PULLDOWN = (1 << 0),
+ AREA_FLAG_DRAWJOINTO = (1 << 1),
+ AREA_FLAG_DRAWJOINFROM = (1 << 2),
+ AREA_TEMP_INFO = (1 << 3),
+ AREA_FLAG_DRAWSPLIT_H = (1 << 4),
+ AREA_FLAG_DRAWSPLIT_V = (1 << 5),
+ /* used to check if we should switch back to prevspace (of a different type) */
+ AREA_FLAG_TEMP_TYPE = (1 << 6),
+};
#define EDGEWIDTH 1
#define AREAGRID 4
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index af33ae80ed9..20678bdae49 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -131,10 +131,11 @@ typedef struct Sequence {
int flag, type; /*flags bitmap (see below) and the type of sequence*/
int len; /* the length of the contents of this strip - before handles are applied */
- int start, startofs, endofs;
- int startstill, endstill;
+ int start; /* start frame of contents of strip in absolute frame coordinates. For metastrips start of first strip startdisp */
+ int startofs, endofs; /* frames after the first frame where display starts, frames before the last frame where display ends */
+ int startstill, endstill; /* frames that use the first frame before data begins, frames that use the last frame after data ends */
int machine, depth; /*machine - the strip channel, depth - the depth in the sequence when dealing with metastrips */
- int startdisp, enddisp; /*starting and ending points in the sequence*/
+ int startdisp, enddisp; /* starting and ending points of the strip in the sequence*/
float sat;
float mul, handsize;
@@ -362,6 +363,9 @@ enum {
SEQ_AUDIO_PITCH_ANIMATED = (1 << 25),
SEQ_AUDIO_PAN_ANIMATED = (1 << 26),
SEQ_AUDIO_DRAW_WAVEFORM = (1 << 27),
+
+ /* don't include Grease Pencil in OpenGL previews of Scene strips */
+ SEQ_SCENE_NO_GPENCIL = (1 << 28),
SEQ_INVALID_EFFECT = (1 << 31),
};
diff --git a/source/blender/makesdna/DNA_sound_types.h b/source/blender/makesdna/DNA_sound_types.h
index d7a51359777..4ab22e4f7b7 100644
--- a/source/blender/makesdna/DNA_sound_types.h
+++ b/source/blender/makesdna/DNA_sound_types.h
@@ -95,6 +95,8 @@ typedef struct bSound {
*/
void *playback_handle;
+ /* mutex for asynchronous loading of sounds */
+ void *mutex;
/* XXX unused currently (SOUND_TYPE_LIMITER) */
/* float start, end; */
} bSound;
@@ -116,9 +118,10 @@ enum {
};
enum {
- SOUND_FLAGS_3D = (1 << 3), /* deprecated! used for sound actuator loading */
- SOUND_FLAGS_CACHING = (1 << 4),
- SOUND_FLAGS_MONO = (1 << 5),
+ SOUND_FLAGS_3D = (1 << 3), /* deprecated! used for sound actuator loading */
+ SOUND_FLAGS_CACHING = (1 << 4),
+ SOUND_FLAGS_MONO = (1 << 5),
+ SOUND_FLAGS_WAVEFORM_LOADING = (1 << 6),
};
#if (DNA_DEPRECATED_GCC_POISON == 1)
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index a8fe8ceb6b0..f65cef1a0d1 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -497,6 +497,8 @@ typedef struct SpaceSeq {
float zoom DNA_DEPRECATED; /* deprecated, handled by View2D now */
int view; /* see SEQ_VIEW_* below */
int overlay_type;
+ int draw_flag; /* overlay an image of the editing on below the strips */
+ int pad;
struct bGPdata *gpd; /* grease-pencil data */
@@ -513,6 +515,13 @@ typedef enum eSpaceSeq_RegionType {
SEQ_DRAW_IMG_HISTOGRAM = 4,
} eSpaceSeq_RegionType;
+/* sseq->draw_flag */
+typedef enum eSpaceSeq_DrawFlag {
+ SEQ_DRAW_BACKDROP = (1 << 0),
+ SEQ_DRAW_OFFSET_EXT = (1 << 1),
+} eSpaceSeq_DrawFlag;
+
+
/* sseq->flag */
typedef enum eSpaceSeq_Flag {
SEQ_DRAWFRAMES = (1 << 0),
@@ -522,6 +531,8 @@ typedef enum eSpaceSeq_Flag {
SEQ_SHOW_GPENCIL = (1 << 4),
SEQ_NO_DRAW_CFRANUM = (1 << 5),
SEQ_USE_ALPHA = (1 << 6), /* use RGBA display mode for preview */
+ SEQ_ALL_WAVEFORMS = (1 << 7), /* draw all waveforms */
+ SEQ_NO_WAVEFORMS = (1 << 8), /* draw no waveforms */
} eSpaceSeq_Flag;
/* sseq->view */
@@ -565,14 +576,17 @@ typedef enum eSpaceSeq_OverlayType {
/* Config and Input for File Selector */
typedef struct FileSelectParams {
char title[96]; /* title, also used for the text of the execute button */
- char dir[1056]; /* directory, FILE_MAX_LIBEXTRA, 1024 + 32, this is for extreme case when 1023 length path
+ char dir[1090]; /* directory, FILE_MAX_LIBEXTRA, 1024 + 66, this is for extreme case when 1023 length path
* needs to be linked in, where foo.blend/Armature need adding */
+ char pad_c1[2];
char file[256]; /* file */
char renamefile[256];
char renameedit[256]; /* annoying but the first is only used for initialization */
char filter_glob[64]; /* list of filetypes to filter */
+ char filter_search[64]; /* text items' name must match to be shown. */
+
int active_file;
int sel_first;
int sel_last;
@@ -680,28 +694,28 @@ typedef enum eFileSel_Params_Flag {
/* files in filesel list: file types */
typedef enum eFileSel_File_Types {
- BLENDERFILE = (1 << 2),
- BLENDERFILE_BACKUP = (1 << 3),
- IMAGEFILE = (1 << 4),
- MOVIEFILE = (1 << 5),
- PYSCRIPTFILE = (1 << 6),
- FTFONTFILE = (1 << 7),
- SOUNDFILE = (1 << 8),
- TEXTFILE = (1 << 9),
- MOVIEFILE_ICON = (1 << 10), /* movie file that preview can't load */
- FOLDERFILE = (1 << 11), /* represents folders for filtering */
- BTXFILE = (1 << 12),
- COLLADAFILE = (1 << 13),
- OPERATORFILE = (1 << 14), /* from filter_glob operator property */
- APPLICATIONBUNDLE = (1 << 15),
+ FILE_TYPE_BLENDER = (1 << 2),
+ FILE_TYPE_BLENDER_BACKUP = (1 << 3),
+ FILE_TYPE_IMAGE = (1 << 4),
+ FILE_TYPE_MOVIE = (1 << 5),
+ FILE_TYPE_PYSCRIPT = (1 << 6),
+ FILE_TYPE_FTFONT = (1 << 7),
+ FILE_TYPE_SOUND = (1 << 8),
+ FILE_TYPE_TEXT = (1 << 9),
+ FILE_TYPE_MOVIE_ICON = (1 << 10), /* movie file that preview can't load */
+ FILE_TYPE_FOLDER = (1 << 11), /* represents folders for filtering */
+ FILE_TYPE_BTX = (1 << 12),
+ FILE_TYPE_COLLADA = (1 << 13),
+ FILE_TYPE_OPERATOR = (1 << 14), /* from filter_glob operator property */
+ FILE_TYPE_APPLICATIONBUNDLE = (1 << 15),
} eFileSel_File_Types;
/* Selection Flags in filesel: struct direntry, unsigned char selflag */
typedef enum eDirEntry_SelectFlag {
-/* ACTIVE_FILE = (1 << 1), */ /* UNUSED */
- HILITED_FILE = (1 << 2),
- SELECTED_FILE = (1 << 3),
- EDITING_FILE = (1 << 4),
+/* FILE_SEL_ACTIVE = (1 << 1), */ /* UNUSED */
+ FILE_SEL_HIGHLIGHTED = (1 << 2),
+ FILE_SEL_SELECTED = (1 << 3),
+ FILE_SEL_EDITING = (1 << 4),
} eDirEntry_SelectFlag;
/* Image/UV Editor ======================================== */
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
index d256cfb2e85..042645eeb76 100644
--- a/source/blender/makesdna/DNA_texture_types.h
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -62,11 +62,12 @@ typedef struct MTex {
char uvname[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
char projx, projy, projz, mapping;
- float ofs[3], size[3], rot;
-
+ char brush_map_mode, brush_angle_mode;
+ char pad[2];
+ float ofs[3], size[3], rot, random_angle;
+
short texflag, colormodel, pmapto, pmaptoneg;
short normapspace, which_output;
- char brush_map_mode, pad[7];
float r, g, b, k;
float def_var, rt;
@@ -512,6 +513,10 @@ typedef struct ColorMapping {
#define MTEX_MAP_MODE_RANDOM 4
#define MTEX_MAP_MODE_STENCIL 5
+/* brush_angle_mode */
+#define MTEX_ANGLE_RANDOM 1
+#define MTEX_ANGLE_RAKE 2
+
/* **************** ColorBand ********************* */
/* colormode */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index d8653e1f5fe..11807ba5338 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -168,7 +168,7 @@ typedef struct ThemeUI {
uiPanelColors panel; /* depricated, but we keep it for do_versions (2.66.1) */
- char emboss[4];
+ char widget_emboss[4];
/* fac: 0 - 1 for blend factor, width in pixels */
float menu_shadow_fac;
@@ -251,6 +251,7 @@ typedef struct ThemeSpace {
char bone_solid[4], bone_pose[4], bone_pose_active[4];
char strip[4], strip_select[4];
char cframe[4];
+ char time_keyframe[4], time_gp_keyframe[4];
char freestyle_edge_mark[4], freestyle_face_mark[4];
char nurb_uline[4], nurb_vline[4];
@@ -295,7 +296,10 @@ typedef struct ThemeSpace {
char bundle_solid[4];
char path_before[4], path_after[4];
char camera_path[4];
- char hpad[3];
+ char hpad[2];
+
+ char gp_vertex_size;
+ char gp_vertex[4], gp_vertex_select[4];
char preview_back[4];
char preview_stitch_face[4];
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 3efba488299..0eee28e73d9 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -201,7 +201,9 @@ typedef struct View3D {
char gridflag;
/* transform widget info */
- char twtype, twmode, twflag, pad2[2];
+ char twtype, twmode, twflag;
+
+ short flag3;
/* afterdraw, for xray & transparent */
struct ListBase afterdraw_transp;
@@ -267,21 +269,24 @@ typedef struct View3D {
((view >= RV3D_VIEW_FRONT) && (view <= RV3D_VIEW_BOTTOM))
/* View3d->flag2 (short) */
-#define V3D_RENDER_OVERRIDE 4
-#define V3D_SOLID_TEX 8
-#define V3D_SHOW_GPENCIL 16
-#define V3D_LOCK_CAMERA 32
-#define V3D_RENDER_SHADOW 64 /* This is a runtime only flag that's used to tell draw_mesh_object() that we're doing a shadow pass instead of a regular draw */
-#define V3D_SHOW_RECONSTRUCTION 128
-#define V3D_SHOW_CAMERAPATH 256
-#define V3D_SHOW_BUNDLENAME 512
-#define V3D_BACKFACE_CULLING 1024
-#define V3D_RENDER_BORDER 2048
-#define V3D_SOLID_MATCAP 4096 /* user flag */
-#define V3D_SHOW_SOLID_MATCAP 8192 /* runtime flag */
-#define V3D_OCCLUDE_WIRE 16384
-#define V3D_SHADELESS_TEX 32768
-
+#define V3D_RENDER_OVERRIDE (1 << 2)
+#define V3D_SOLID_TEX (1 << 3)
+#define V3D_SHOW_GPENCIL (1 << 4)
+#define V3D_LOCK_CAMERA (1 << 5)
+#define V3D_RENDER_SHADOW (1 << 6) /* This is a runtime only flag that's used to tell draw_mesh_object() that we're doing a shadow pass instead of a regular draw */
+#define V3D_SHOW_RECONSTRUCTION (1 << 7)
+#define V3D_SHOW_CAMERAPATH (1 << 8)
+#define V3D_SHOW_BUNDLENAME (1 << 9)
+#define V3D_BACKFACE_CULLING (1 << 10)
+#define V3D_RENDER_BORDER (1 << 11)
+#define V3D_SOLID_MATCAP (1 << 12) /* user flag */
+#define V3D_SHOW_SOLID_MATCAP (1 << 13) /* runtime flag */
+#define V3D_OCCLUDE_WIRE (1 << 14)
+#define V3D_SHADELESS_TEX (1 << 15)
+
+
+/* View3d->flag3 (short) */
+#define V3D_SHOW_WORLD (1 << 0)
/* View3D->around */
#define V3D_CENTER 0
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 73a70b48712..1a0562ae8c5 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -165,6 +165,13 @@ enum {
WM_INIT_KEYMAP = (1<<1),
};
+/* IME is win32 only! */
+#ifndef WIN32
+# ifdef __GNUC__
+# define ime_data ime_data __attribute__ ((deprecated))
+# endif
+#endif
+
/* the savable part, rest of data is local in ghostwinlay */
typedef struct wmWindow {
struct wmWindow *next, *prev;
@@ -197,6 +204,10 @@ typedef struct wmWindow {
struct wmGesture *tweak; /* internal for wm_operators.c */
+ /* Input Method Editor data - complex character input (esp. for asian character input)
+ * Currently WIN32, runtime-only data */
+ struct wmIMEData *ime_data;
+
int drawmethod, drawfail; /* internal for wm_draw.c only */
void *drawdata; /* internal for wm_draw.c only */
@@ -208,6 +219,10 @@ typedef struct wmWindow {
ListBase gesture; /* gesture stuff */
} wmWindow;
+#ifdef ime_data
+# undef ime_data
+#endif
+
/* These two Lines with # tell makesdna this struct can be excluded. */
/* should be something like DNA_EXCLUDE
* but the preprocessor first removes all comments, spaces etc */
diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h
index 50542797f0b..2a9bcc20a9f 100644
--- a/source/blender/makesdna/DNA_world_types.h
+++ b/source/blender/makesdna/DNA_world_types.h
@@ -128,6 +128,7 @@ typedef struct World {
/* nodes */
struct bNodeTree *nodetree;
+ ListBase gpumaterial; /* runtime */
} World;
/* **************** WORLD ********************* */
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 46b51080419..5f5714ec831 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -910,7 +910,7 @@ static void dna_write(FILE *file, const void *pntr, const int size)
int i;
const char *data;
- data = (char *) pntr;
+ data = (const char *)pntr;
for (i = 0; i < size; i++) {
fprintf(file, "%d, ", data[i]);
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index c8902de756f..3e1a029567d 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -199,6 +199,7 @@ extern StructRNA RNA_CurveMapping;
extern StructRNA RNA_CurveModifier;
extern StructRNA RNA_CurvePoint;
extern StructRNA RNA_DampedTrackConstraint;
+extern StructRNA RNA_DataTransferModifier;
extern StructRNA RNA_DecimateModifier;
extern StructRNA RNA_DelaySensor;
extern StructRNA RNA_DisplaceModifier;
@@ -506,6 +507,7 @@ extern StructRNA RNA_ShaderNodeMaterial;
extern StructRNA RNA_ShaderNodeMath;
extern StructRNA RNA_ShaderNodeMixRGB;
extern StructRNA RNA_ShaderNodeNormal;
+extern StructRNA RNA_ShaderNodeGamma;
extern StructRNA RNA_ShaderNodeOutput;
extern StructRNA RNA_ShaderNodeScript;
extern StructRNA RNA_ShaderNodeRGB;
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 3d4ed0d6f51..4d836601ac4 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -184,6 +184,14 @@ extern EnumPropertyItem linestyle_geometry_modifier_type_items[];
extern EnumPropertyItem window_cursor_items[];
+extern EnumPropertyItem DT_method_vertex_items[];
+extern EnumPropertyItem DT_method_edge_items[];
+extern EnumPropertyItem DT_method_loop_items[];
+extern EnumPropertyItem DT_method_poly_items[];
+extern EnumPropertyItem DT_mix_mode_items[];
+extern EnumPropertyItem DT_layers_select_src_items[];
+extern EnumPropertyItem DT_layers_select_dst_items[];
+
struct bContext;
struct PointerRNA;
struct PropertyRNA;
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 83f3870c29a..a9c0f591858 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -147,7 +147,7 @@ typedef enum PropertySubType {
} PropertySubType;
/* Make sure enums are updated with these */
-/* HIGHEST FLAG IN USE: 1 << 30 */
+/* HIGHEST FLAG IN USE: 1 << 31 */
typedef enum PropertyFlag {
/* editable means the property is editable in the user
* interface, properties are editable by default except
@@ -165,6 +165,10 @@ typedef enum PropertyFlag {
* and collections */
PROP_ANIMATABLE = (1 << 1),
+ /* This flag means when the property's widget is in 'textedit' mode, it will be updated after every typed char,
+ * instead of waiting final validation. Used e.g. for text searchbox. */
+ PROP_TEXTEDIT_UPDATE = (1 << 31),
+
/* icon */
PROP_ICONS_CONSECUTIVE = (1 << 12),
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 40d752a3ed2..0c1701f6089 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -35,7 +35,6 @@
#include "BLI_utildefines.h"
-#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_types.h"
@@ -47,6 +46,14 @@
# endif
#endif
+/* stub for BLI_abort() */
+#ifndef NDEBUG
+void BLI_system_backtrace(FILE *fp)
+{
+ (void)fp;
+}
+#endif
+
/* Replace if different */
#define TMP_EXT ".tmp"
@@ -1621,7 +1628,7 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
int i;
- if (eprop->item) {
+ if (eprop->item && eprop->totitem) {
fprintf(f, "enum {\n");
for (i = 0; i < eprop->totitem; i++)
@@ -3676,7 +3683,7 @@ static const char *cpp_classes = ""
" int length;\n"
"\n"
" DynamicArray() : data(NULL), length(0) {}\n"
-" DynamicArray(int new_length) : data(NULL), length(new_length) { data = (float *)malloc(sizeof(T) * new_length); }\n"
+" DynamicArray(int new_length) : data(NULL), length(new_length) { data = (T *)malloc(sizeof(T) * new_length); }\n"
" DynamicArray(const DynamicArray<T>& other) { copy_from(other); }\n"
" const DynamicArray<T>& operator = (const DynamicArray<T>& other) { copy_from(other); return *this; }\n"
"\n"
@@ -3687,7 +3694,7 @@ static const char *cpp_classes = ""
"protected:\n"
" void copy_from(const DynamicArray<T>& other) {\n"
" if (data) free(data);\n"
-" data = (float *)malloc(sizeof(T) * other.length);\n"
+" data = (T *)malloc(sizeof(T) * other.length);\n"
" memcpy(data, other.data, sizeof(T) * other.length);\n"
" length = other.length;\n"
" }\n"
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 51d81295f8c..009e3799c49 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -64,6 +64,7 @@ EnumPropertyItem id_type_items[] = {
{ID_MA, "MATERIAL", ICON_MATERIAL_DATA, "Material", ""},
{ID_MB, "META", ICON_META_DATA, "MetaBall", ""},
{ID_ME, "MESH", ICON_MESH_DATA, "Mesh", ""},
+ {ID_MC, "MOVIECLIP", ICON_CLIP, "MovieClip", ""},
{ID_NT, "NODETREE", ICON_NODETREE, "NodeTree", ""},
{ID_OB, "OBJECT", ICON_OBJECT_DATA, "Object", ""},
{ID_PC, "PAINTCURVE", ICON_CURVE_BEZCURVE, "Paint Curve", ""},
@@ -71,12 +72,12 @@ EnumPropertyItem id_type_items[] = {
{ID_PA, "PARTICLE", ICON_PARTICLE_DATA, "Particle", ""},
{ID_SCE, "SCENE", ICON_SCENE_DATA, "Scene", ""},
{ID_SCR, "SCREEN", ICON_SPLITSCREEN, "Screen", ""},
+ {ID_SO, "SOUND", ICON_PLAY_AUDIO, "Sound", ""},
{ID_SPK, "SPEAKER", ICON_SPEAKER, "Speaker", ""},
- {ID_SO, "SOUND", ICON_PLAY_AUDIO, "Sound", ""},
{ID_TXT, "TEXT", ICON_TEXT, "Text", ""},
{ID_TE, "TEXTURE", ICON_TEXTURE_DATA, "Texture", ""},
- {ID_WO, "WORLD", ICON_WORLD_DATA, "World", ""},
{ID_WM, "WINDOWMANAGER", ICON_FULLSCREEN, "Window Manager", ""},
+ {ID_WO, "WORLD", ICON_WORLD_DATA, "World", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -141,23 +142,23 @@ short RNA_type_to_ID_code(StructRNA *type)
if (RNA_struct_is_a(type, &RNA_Lattice)) return ID_LT;
if (RNA_struct_is_a(type, &RNA_Material)) return ID_MA;
if (RNA_struct_is_a(type, &RNA_MetaBall)) return ID_MB;
- if (RNA_struct_is_a(type, &RNA_NodeTree)) return ID_NT;
+ if (RNA_struct_is_a(type, &RNA_MovieClip)) return ID_MC;
if (RNA_struct_is_a(type, &RNA_Mesh)) return ID_ME;
+ if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK;
+ if (RNA_struct_is_a(type, &RNA_NodeTree)) return ID_NT;
if (RNA_struct_is_a(type, &RNA_Object)) return ID_OB;
if (RNA_struct_is_a(type, &RNA_ParticleSettings)) return ID_PA;
+ if (RNA_struct_is_a(type, &RNA_Palette)) return ID_PAL;
+ if (RNA_struct_is_a(type, &RNA_PaintCurve)) return ID_PC;
if (RNA_struct_is_a(type, &RNA_Scene)) return ID_SCE;
if (RNA_struct_is_a(type, &RNA_Screen)) return ID_SCR;
- if (RNA_struct_is_a(type, &RNA_Speaker)) return ID_SPK;
if (RNA_struct_is_a(type, &RNA_Sound)) return ID_SO;
- if (RNA_struct_is_a(type, &RNA_Text)) return ID_TXT;
+ if (RNA_struct_is_a(type, &RNA_Speaker)) return ID_SPK;
if (RNA_struct_is_a(type, &RNA_Texture)) return ID_TE;
+ if (RNA_struct_is_a(type, &RNA_Text)) return ID_TXT;
if (RNA_struct_is_a(type, &RNA_VectorFont)) return ID_VF;
if (RNA_struct_is_a(type, &RNA_World)) return ID_WO;
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;
}
@@ -180,23 +181,23 @@ StructRNA *ID_code_to_RNA_type(short idcode)
case ID_LT: return &RNA_Lattice;
case ID_MA: return &RNA_Material;
case ID_MB: return &RNA_MetaBall;
- case ID_NT: return &RNA_NodeTree;
+ case ID_MC: return &RNA_MovieClip;
case ID_ME: return &RNA_Mesh;
+ case ID_MSK: return &RNA_Mask;
+ case ID_NT: return &RNA_NodeTree;
case ID_OB: return &RNA_Object;
case ID_PA: return &RNA_ParticleSettings;
+ case ID_PAL: return &RNA_Palette;
+ case ID_PC: return &RNA_PaintCurve;
case ID_SCE: return &RNA_Scene;
case ID_SCR: return &RNA_Screen;
- case ID_SPK: return &RNA_Speaker;
case ID_SO: return &RNA_Sound;
- case ID_TXT: return &RNA_Text;
+ case ID_SPK: return &RNA_Speaker;
case ID_TE: return &RNA_Texture;
+ case ID_TXT: return &RNA_Text;
case ID_VF: return &RNA_VectorFont;
- case ID_WO: return &RNA_World;
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;
+ case ID_WO: return &RNA_World;
default: return &RNA_ID;
}
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index e681552103b..09b970fe7fd 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -466,7 +466,7 @@ static const char *rna_ensure_property_identifier(const PropertyRNA *prop)
if (prop->magic == RNA_MAGIC)
return prop->identifier;
else
- return ((IDProperty *)prop)->name;
+ return ((const IDProperty *)prop)->name;
}
static const char *rna_ensure_property_description(PropertyRNA *prop)
@@ -499,7 +499,7 @@ static const char *rna_ensure_property_name(const PropertyRNA *prop)
if (prop->magic == RNA_MAGIC)
name = prop->name;
else
- name = ((IDProperty *)prop)->name;
+ name = ((const IDProperty *)prop)->name;
return name;
}
@@ -4284,7 +4284,7 @@ char *RNA_path_append(const char *path, PointerRNA *UNUSED(ptr), PropertyRNA *pr
/* add .identifier */
if (path) {
- BLI_dynstr_append(dynstr, (char *)path);
+ BLI_dynstr_append(dynstr, path);
if (*path)
BLI_dynstr_append(dynstr, ".");
}
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 8d7a05896a3..e256d145016 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -462,6 +462,12 @@ static void rna_def_dopesheet(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Display Speaker", "Include visualization of speaker related animation data");
RNA_def_property_ui_icon(prop, ICON_SPEAKER, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ prop = RNA_def_property(srna, "show_gpencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOGPENCIL);
+ RNA_def_property_ui_text(prop, "Display Grease Pencil", "Include visualization of Grease Pencil related animation data and frames");
+ RNA_def_property_ui_icon(prop, ICON_GREASEPENCIL, 0);
+ RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
}
static void rna_def_action_group(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index 0114ffa35c0..6792dd7e5f8 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -55,16 +55,16 @@ static EnumPropertyItem actuator_type_items[] = {
{ACT_2DFILTER, "FILTER_2D", 0, "Filter 2D", ""},
{ACT_GAME, "GAME", 0, "Game", ""},
{ACT_MESSAGE, "MESSAGE", 0, "Message", ""},
- {ACT_MOUSE, "MOUSE", 0, "Mouse", ""},
{ACT_OBJECT, "MOTION", 0, "Motion", ""},
+ {ACT_MOUSE, "MOUSE", 0, "Mouse", ""},
{ACT_PARENT, "PARENT", 0, "Parent", ""},
{ACT_PROPERTY, "PROPERTY", 0, "Property", ""},
{ACT_RANDOM, "RANDOM", 0, "Random", ""},
{ACT_SCENE, "SCENE", 0, "Scene", ""},
{ACT_SOUND, "SOUND", 0, "Sound", ""},
{ACT_STATE, "STATE", 0, "State", ""},
- {ACT_VISIBILITY, "VISIBILITY", 0, "Visibility", ""},
{ACT_STEERING, "STEERING", 0, "Steering", ""},
+ {ACT_VISIBILITY, "VISIBILITY", 0, "Visibility", ""},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index bbc2e0572fa..81ba3a9066f 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -194,14 +194,20 @@ static int rna_SculptToolCapabilities_has_random_texture_angle_get(PointerRNA *p
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
-static int rna_BrushCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
+static int rna_TextureCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
{
- Brush *br = (Brush *)ptr->data;
- return (ELEM(br->mtex.brush_map_mode,
+ MTex *mtex = (MTex *)ptr->data;
+ return ELEM(mtex->brush_map_mode,
MTEX_MAP_MODE_VIEW,
MTEX_MAP_MODE_AREA,
- MTEX_MAP_MODE_RANDOM) &&
- !(br->flag & BRUSH_ANCHORED));
+ MTEX_MAP_MODE_RANDOM);
+}
+
+
+static int rna_BrushCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
+{
+ Brush *br = (Brush *)ptr->data;
+ return !(br->flag & BRUSH_ANCHORED);
}
static int rna_SculptToolCapabilities_has_sculpt_plane_get(PointerRNA *ptr)
@@ -270,15 +276,10 @@ static int rna_SculptToolCapabilities_has_strength_pressure_get(PointerRNA *ptr)
return !ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK);
}
-static int rna_BrushCapabilities_has_texture_angle_get(PointerRNA *ptr)
+static int rna_TextureCapabilities_has_texture_angle_get(PointerRNA *ptr)
{
- Brush *br = (Brush *)ptr->data;
- 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);
+ MTex *mtex = (MTex *)ptr->data;
+ return mtex->brush_map_mode != MTEX_MAP_MODE_3D;
}
static int rna_SculptToolCapabilities_has_gravity_get(PointerRNA *ptr)
@@ -287,10 +288,10 @@ static int rna_SculptToolCapabilities_has_gravity_get(PointerRNA *ptr)
return !ELEM(br->sculpt_tool, SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH);
}
-static int rna_BrushCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
+static int rna_TextureCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
{
- Brush *br = (Brush *)ptr->data;
- return ELEM(br->mtex.brush_map_mode,
+ MTex *mtex = (MTex *)ptr->data;
+ return ELEM(mtex->brush_map_mode,
MTEX_MAP_MODE_VIEW,
MTEX_MAP_MODE_AREA,
MTEX_MAP_MODE_RANDOM);
@@ -627,6 +628,15 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+#define TEXTURE_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_TextureCapabilities_" \
+ #prop_name_ "_get", NULL); \
+ RNA_def_property_ui_text(prop, ui_name_, NULL)
+
+
srna = RNA_def_struct(brna, "BrushTextureSlot", "TextureSlot");
RNA_def_struct_sdna(srna, "MTex");
RNA_def_struct_ui_text(srna, "Brush Texture Slot", "Texture slot for textures in a Brush datablock");
@@ -654,6 +664,25 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna)
RNA_def_property_enum_items(prop, prop_mask_paint_map_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
RNA_def_property_update(prop, 0, "rna_TextureSlot_brush_update");
+
+ prop = RNA_def_property(srna, "use_rake", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "brush_angle_mode", MTEX_ANGLE_RAKE);
+ RNA_def_property_ui_text(prop, "Rake", "");
+ RNA_def_property_update(prop, 0, "rna_TextureSlot_brush_update");
+
+ prop = RNA_def_property(srna, "use_random", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "brush_angle_mode", MTEX_ANGLE_RANDOM);
+ RNA_def_property_ui_text(prop, "Random", "");
+ RNA_def_property_update(prop, 0, "rna_TextureSlot_brush_update");
+
+ prop = RNA_def_property(srna, "random_angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_range(prop, 0, M_PI * 2);
+ RNA_def_property_ui_text(prop, "Random Angle", "Brush texture random angle");
+ RNA_def_property_update(prop, 0, "rna_TextureSlot_brush_update");
+
+ TEXTURE_CAPABILITY(has_texture_angle_source, "Has Texture Angle Source");
+ TEXTURE_CAPABILITY(has_random_texture_angle, "Has Random Texture Angle");
+ TEXTURE_CAPABILITY(has_texture_angle, "Has Texture Angle Source");
}
static void rna_def_sculpt_capabilities(BlenderRNA *brna)
@@ -717,8 +746,6 @@ static void rna_def_brush_capabilities(BlenderRNA *brna)
BRUSH_CAPABILITY(has_overlay, "Has Overlay");
BRUSH_CAPABILITY(has_random_texture_angle, "Has Random Texture Angle");
- 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");
@@ -786,19 +813,6 @@ static void rna_def_brush(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem texture_angle_source_items[] = {
- {0, "USER", 0, "User", "Rotate the brush texture by given angle"},
- {BRUSH_RAKE, "RAKE", 0, "Rake", "Rotate the brush texture to match the stroke direction"},
- {BRUSH_RANDOM_ROTATION, "RANDOM", 0, "Random", "Rotate the brush texture at random"},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem texture_angle_source_no_random_items[] = {
- {0, "USER", 0, "User", "Rotate the brush texture by given angle"},
- {BRUSH_RAKE, "RAKE", 0, "Rake", "Rotate the brush texture to match the stroke direction"},
- {0, NULL, 0, NULL, NULL}
- };
-
static EnumPropertyItem brush_sculpt_plane_items[] = {
{SCULPT_DISP_DIR_AREA, "AREA", 0, "Area Plane", ""},
{SCULPT_DISP_DIR_VIEW, "VIEW", 0, "View Plane", ""},
@@ -881,18 +895,6 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Stroke Method", "");
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");
- RNA_def_property_enum_items(prop, texture_angle_source_items);
- RNA_def_property_ui_text(prop, "Texture Angle Source", "");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
-
- prop = RNA_def_property(srna, "texture_angle_source_no_random", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
- RNA_def_property_enum_items(prop, texture_angle_source_no_random_items);
- RNA_def_property_ui_text(prop, "Texture Angle Source", "");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
-
prop = RNA_def_property(srna, "sculpt_plane", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_sculpt_plane_items);
RNA_def_property_ui_text(prop, "Sculpt Plane", "");
@@ -1158,22 +1160,12 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Inverse Smooth Pressure", "Lighter pressure causes more smoothing to be applied");
RNA_def_property_update(prop, 0, "rna_Brush_update");
- prop = RNA_def_property(srna, "use_rake", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RAKE);
- RNA_def_property_ui_text(prop, "Rake", "Rotate the brush texture to match the stroke direction");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
-
prop = RNA_def_property(srna, "use_relative_jitter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BRUSH_ABSOLUTE_JITTER);
RNA_def_property_ui_icon(prop, ICON_UNLOCKED, true);
RNA_def_property_ui_text(prop, "Absolute Jitter", "Jittering happens in screen space, not relative to brush size");
RNA_def_property_update(prop, 0, "rna_Brush_update");
- prop = RNA_def_property(srna, "use_random_rotation", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RANDOM_ROTATION);
- RNA_def_property_ui_text(prop, "Random Rotation", "Rotate the brush texture at random");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
-
prop = RNA_def_property(srna, "use_plane_trim", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_PLANE_TRIM);
RNA_def_property_ui_text(prop, "Use Plane Trim", "Enable Plane Trim");
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index fa2a3258d1a..37201eca5f6 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -614,6 +614,10 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain)
IMB_free_anim(seq->anim);
seq->anim = NULL;
}
+ if (seq->strip->proxy && seq->strip->proxy->anim) {
+ IMB_free_anim(seq->strip->proxy->anim);
+ seq->strip->proxy->anim = NULL;
+ }
BKE_sequence_invalidate_cache(scene, seq);
BKE_sequencer_preprocessed_cache_cleanup_sequence(seq);
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 77355dbad0e..b6845b1df2e 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -1388,7 +1388,7 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna)
prop = RNA_def_property(srna, "bulge_smooth", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0, 1.0f);
- RNA_def_property_ui_text(prop, "Volume Variation Smoothness", "");
+ RNA_def_property_ui_text(prop, "Volume Variation Smoothness", "Strength of volume stretching clamping");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
}
@@ -2272,8 +2272,10 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
{CONSTRAINT_SPLINEIK_XZS_NONE, "NONE", 0, "None", "Don't scale the X and Z axes (Default)"},
{CONSTRAINT_SPLINEIK_XZS_ORIGINAL, "BONE_ORIGINAL", 0, "Bone Original",
"Use the original scaling of the bones"},
+ {CONSTRAINT_SPLINEIK_XZS_INVERSE, "INVERSE_PRESERVE", 0, "Inverse Scale",
+ "Scale of the X and Z axes is the inverse of the Y-Scale"},
{CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC, "VOLUME_PRESERVE", 0, "Volume Preservation",
- "Scale of the X and Z axes is the inverse of the Y-Scale"},
+ "Scale of the X and Z axes are adjusted to preserve the volume of the bones"},
{0, NULL, 0, NULL, NULL}
};
@@ -2333,12 +2335,44 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
"on top of XZ Scale mode");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ /* xz scaling mode */
prop = RNA_def_property(srna, "xz_scale_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "xzScaleMode");
RNA_def_property_enum_items(prop, splineik_xz_scale_mode);
RNA_def_property_ui_text(prop, "XZ Scale Mode",
"Method used for determining the scaling of the X and Z axes of the bones");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ /* volume presevation for "volumetric" scale mode */
+ prop = RNA_def_property(srna, "bulge", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 100.f);
+ RNA_def_property_ui_text(prop, "Volume Variation", "Factor between volume variation and stretching");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "use_bulge_min", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_USE_BULGE_MIN);
+ RNA_def_property_ui_text(prop, "Use Volume Variation Minimum", "Use lower limit for volume variation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "use_bulge_max", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_USE_BULGE_MAX);
+ RNA_def_property_ui_text(prop, "Use Volume Variation Maximum", "Use upper limit for volume variation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "bulge_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_property_ui_text(prop, "Volume Variation Minimum", "Minimum volume stretching factor");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "bulge_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 1.0, 100.0f);
+ RNA_def_property_ui_text(prop, "Volume Variation Maximum", "Maximum volume stretching factor");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "bulge_smooth", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_property_ui_text(prop, "Volume Variation Smoothness", "Strength of volume stretching clamping");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
}
static void rna_def_constraint_pivot(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 6668ce812cf..54c08009792 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -639,7 +639,7 @@ void RNA_struct_free(BlenderRNA *brna, StructRNA *srna)
if (srna->flag & STRUCT_RUNTIME)
rna_freelinkN(&brna->structs, srna);
#else
- (void)brna, (void)srna;
+ UNUSED_VARS(brna, srna);
#endif
}
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index c4677710676..6b61b37ce5c 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -44,6 +44,8 @@
#ifdef RNA_RUNTIME
+#include "BLI_math.h"
+
#include "WM_api.h"
#include "BKE_gpencil.h"
@@ -53,6 +55,16 @@ static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
+static char *rna_GPencilLayer_path(PointerRNA *ptr)
+{
+ bGPDlayer *gpl = (bGPDlayer *)ptr->data;
+ char name_esc[sizeof(gpl->info) * 2];
+
+ BLI_strescape(name_esc, gpl->info, sizeof(name_esc));
+
+ return BLI_sprintfN("layers[\"%s\"]", name_esc);
+}
+
static int rna_GPencilLayer_active_frame_editable(PointerRNA *ptr)
{
bGPDlayer *gpl = (bGPDlayer *)ptr->data;
@@ -64,9 +76,54 @@ static int rna_GPencilLayer_active_frame_editable(PointerRNA *ptr)
return 1;
}
-static PointerRNA rna_GPencil_active_layer_get(PointerRNA *ptr)
+static void rna_GPencilLayer_line_width_range(PointerRNA *ptr, int *min, int *max,
+ int *softmin, int *softmax)
{
+ bGPDlayer *gpl = ptr->data;
+
+ /* The restrictions on max width here are due to OpenGL on Windows not supporting
+ * any widths greater than 10 (for driver-drawn) strokes/points.
+ *
+ * Although most of our 2D strokes also don't suffer from this restriction,
+ * it's relatively hard to test for that. So, for now, only volumetric strokes
+ * get to be larger...
+ */
+ if (gpl->flag & GP_LAYER_VOLUMETRIC) {
+ *min = 1;
+ *max = 300;
+
+ *softmin = 1;
+ *softmax = 100;
+ }
+ else {
+ *min = 1;
+ *max = 10;
+
+ *softmin = 1;
+ *softmax = 10;
+ }
+}
+static int rna_GPencilLayer_is_stroke_visible_get(PointerRNA *ptr)
+{
+ /* see drawgpencil.c -> gp_draw_data_layers() for more details
+ * about this limit for showing/not showing
+ */
+ bGPDlayer *gpl = (bGPDlayer *)ptr->data;
+ return (gpl->color[3] > 0.001f);
+}
+
+static int rna_GPencilLayer_is_fill_visible_get(PointerRNA *ptr)
+{
+ /* see drawgpencil.c -> gp_draw_data_layers() for more details
+ * about this limit for showing/not showing
+ */
+ bGPDlayer *gpl = (bGPDlayer *)ptr->data;
+ return (gpl->fill[3] > 0.001f);
+}
+
+static PointerRNA rna_GPencil_active_layer_get(PointerRNA *ptr)
+{
bGPdata *gpd = ptr->id.data;
if (GS(gpd->id.name) == ID_GD) { /* why would this ever be not GD */
@@ -106,6 +163,33 @@ static void rna_GPencil_active_layer_set(PointerRNA *ptr, PointerRNA value)
}
}
+static int rna_GPencil_active_layer_index_get(PointerRNA *ptr)
+{
+ bGPdata *gpd = (bGPdata *)ptr->id.data;
+ bGPDlayer *gpl = gpencil_layer_getactive(gpd);
+
+ return BLI_findindex(&gpd->layers, gpl);
+}
+
+static void rna_GPencil_active_layer_index_set(PointerRNA *ptr, int value)
+{
+ bGPdata *gpd = (bGPdata *)ptr->id.data;
+ bGPDlayer *gpl = BLI_findlink(&gpd->layers, value);
+
+ gpencil_layer_setactive(gpd, gpl);
+}
+
+static void rna_GPencil_active_layer_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+{
+ bGPdata *gpd = (bGPdata *)ptr->id.data;
+
+ *min = 0;
+ *max = max_ii(0, BLI_listbase_count(&gpd->layers) - 1);
+
+ *softmin = *min;
+ *softmax = *max;
+}
+
static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value)
{
bGPdata *gpd = ptr->id.data;
@@ -117,6 +201,63 @@ static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value)
BLI_uniquename(&gpd->layers, gpl, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl->info));
}
+
+static bGPDstroke *rna_GPencil_stroke_point_find_stroke(const bGPdata *gpd, const bGPDspoint *pt, bGPDlayer **r_gpl, bGPDframe **r_gpf)
+{
+ bGPDlayer *gpl;
+ bGPDstroke *gps;
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, pt)) {
+ return NULL;
+ }
+
+ if (r_gpl) *r_gpl = NULL;
+ if (r_gpf) *r_gpf = NULL;
+
+ /* there's no faster alternative than just looping over everything... */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->actframe) {
+ for (gps = gpl->actframe->strokes.first; gps; gps = gps->next) {
+ if ((pt >= gps->points) && (pt < &gps->points[gps->totpoints])) {
+ /* found it */
+ if (r_gpl) *r_gpl = gpl;
+ if (r_gpf) *r_gpf = gpl->actframe;
+
+ return gps;
+ }
+ }
+ }
+ }
+
+ /* didn't find it */
+ return NULL;
+}
+
+static void rna_GPencil_stroke_point_select_set(PointerRNA *ptr, const int value)
+{
+ bGPdata *gpd = ptr->id.data;
+ bGPDspoint *pt = ptr->data;
+ bGPDstroke *gps = NULL;
+
+ /* Ensure that corresponding stroke is set
+ * - Since we don't have direct access, we're going to have to search
+ * - We don't apply selection value unless we can find the corresponding
+ * stroke, so that they don't get out of sync
+ */
+ gps = rna_GPencil_stroke_point_find_stroke(gpd, pt, NULL, NULL);
+ if (gps) {
+ /* Set the new selection state for the point */
+ if (value)
+ pt->flag |= GP_SPOINT_SELECT;
+ else
+ pt->flag &= ~GP_SPOINT_SELECT;
+
+ /* Check if the stroke should be selected or not... */
+ gpencil_stroke_sync_selection(gps);
+ }
+}
+
static void rna_GPencil_stroke_point_add(bGPDstroke *stroke, int count)
{
if (count > 0) {
@@ -180,6 +321,27 @@ static void rna_GPencil_stroke_remove(bGPDframe *frame, ReportList *reports, Poi
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
+static void rna_GPencil_stroke_select_set(PointerRNA *ptr, const int value)
+{
+ bGPDstroke *gps = ptr->data;
+ bGPDspoint *pt;
+ int i;
+
+ /* set new value */
+ if (value)
+ gps->flag |= GP_STROKE_SELECT;
+ else
+ gps->flag &= ~GP_STROKE_SELECT;
+
+ /* ensure that the stroke's points are selected in the same way */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (value)
+ pt->flag |= GP_SPOINT_SELECT;
+ else
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+}
+
static bGPDframe *rna_GPencil_frame_new(bGPDlayer *layer, ReportList *reports, int frame_number)
{
bGPDframe *frame;
@@ -291,6 +453,12 @@ static void rna_def_gpencil_stroke_point(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Pressure", "Pressure of tablet at point when drawing it");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SPOINT_SELECT);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencil_stroke_point_select_set");
+ RNA_def_property_ui_text(prop, "Select", "Point is selected for viewport editing");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
}
static void rna_def_gpencil_stroke_points_api(BlenderRNA *brna, PropertyRNA *cprop)
@@ -338,12 +506,19 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "GPencilStrokePoint");
RNA_def_property_ui_text(prop, "Stroke Points", "Stroke data points");
rna_def_gpencil_stroke_points_api(brna, prop);
-
+
+ /* Settings */
prop = RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, stroke_draw_mode_items);
RNA_def_property_ui_text(prop, "Draw Mode", "");
RNA_def_property_update(prop, 0, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STROKE_SELECT);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencil_stroke_select_set");
+ RNA_def_property_ui_text(prop, "Select", "Stroke is selected for viewport editing");
+ RNA_def_property_update(prop, 0, "rna_GPencil_update");
}
static void rna_def_gpencil_strokes_api(BlenderRNA *brna, PropertyRNA *cprop)
@@ -455,6 +630,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
srna = RNA_def_struct(brna, "GPencilLayer", NULL);
RNA_def_struct_sdna(srna, "bGPDlayer");
RNA_def_struct_ui_text(srna, "Grease Pencil Layer", "Collection of related sketches");
+ RNA_def_struct_path_func(srna, "rna_GPencilLayer_path");
/* Name */
prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE);
@@ -477,7 +653,14 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_editable_func(prop, "rna_GPencilLayer_active_frame_editable");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
- /* Drawing Color */
+ /* Draw Style */
+ // TODO: replace these with a "draw type" combo (i.e. strokes only, filled strokes, strokes + fills, volumetric)?
+ prop = RNA_def_property(srna, "use_volumetric_strokes", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_VOLUMETRIC);
+ RNA_def_property_ui_text(prop, "Volumetric Strokes", "Draw strokes as a series of circular blobs, resulting in a volumetric effect");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ /* Stroke Drawing Color */
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -486,14 +669,29 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "color[3]");
- RNA_def_property_range(prop, 0.3, 1.0f);
+ RNA_def_property_range(prop, 0.0, 1.0f);
RNA_def_property_ui_text(prop, "Opacity", "Layer Opacity");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+ /* Fill Drawing Color */
+ prop = RNA_def_property(srna, "fill_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "fill");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Fill Color", "Color for filling region bounded by each stroke");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "fill_alpha", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "fill[3]");
+ RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_property_ui_text(prop, "Fill Opacity", "Opacity for filling region bounded by each stroke");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
/* Line Thickness */
prop = RNA_def_property(srna, "line_width", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "thickness");
- RNA_def_property_range(prop, 1, 10);
+ //RNA_def_property_range(prop, 1, 10); /* 10 px limit comes from Windows OpenGL limits for natively-drawn strokes */
+ RNA_def_property_int_funcs(prop, NULL, NULL, "rna_GPencilLayer_line_width_range");
RNA_def_property_ui_text(prop, "Thickness", "Thickness of strokes (in pixels)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
@@ -503,29 +701,59 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Onion Skinning", "Ghost frames on either side of frame");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
- prop = RNA_def_property(srna, "ghost_range_max", PROP_INT, PROP_NONE);
+ prop = RNA_def_property(srna, "ghost_before_range", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "gstep");
RNA_def_property_range(prop, 0, 120);
- RNA_def_property_ui_text(prop, "Max Ghost Range",
- "Maximum number of frames on either side of the active frame to show "
- "(0 = show the 'first' available sketch on either side)");
+ RNA_def_property_ui_text(prop, "Frames Before",
+ "Maximum number of frames to show before current frame "
+ "(0 = show only the previous sketch)");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "ghost_after_range", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "gstep_next");
+ RNA_def_property_range(prop, 0, 120);
+ RNA_def_property_ui_text(prop, "Frames After",
+ "Maximum number of frames to show after current frame "
+ "(0 = show only the next sketch)");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "use_ghost_custom_colors", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_GHOST_PREVCOL | GP_LAYER_GHOST_NEXTCOL);
+ RNA_def_property_ui_text(prop, "Use Custom Ghost Colors", "Use custom colors for ghost frames");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "before_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "gcolor_prev");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Before Color", "Base color for ghosts before the active frame");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "after_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "gcolor_next");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "After Color", "Base color for ghosts after the active frame");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* Flags */
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_HIDE);
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1);
RNA_def_property_ui_text(prop, "Hide", "Set layer Visibility");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_LOCKED);
+ RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1);
RNA_def_property_ui_text(prop, "Locked", "Protect layer from further editing and/or frame changes");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "lock_frame", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_FRAMELOCK);
+ RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1);
RNA_def_property_ui_text(prop, "Frame Locked", "Lock current frame displayed by layer");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* expose as layers.active */
#if 0
@@ -539,7 +767,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_SELECT);
RNA_def_property_ui_text(prop, "Select", "Layer is selected for editing in the Dope Sheet");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* XXX keep this option? */
prop = RNA_def_property(srna, "show_points", PROP_BOOLEAN, PROP_NONE);
@@ -554,6 +782,17 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+ /* Read-only state props (for simpler UI code) */
+ prop = RNA_def_property(srna, "is_stroke_visible", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_GPencilLayer_is_stroke_visible_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Is Stroke Visible", "True when opacity of stroke is set high enough to be visible");
+
+ prop = RNA_def_property(srna, "is_fill_visible", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_GPencilLayer_is_fill_visible_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Is Fill Visible", "True when opacity of fill is set high enough to be visible");
+
/* Layers API */
func = RNA_def_function(srna, "clear", "rna_GPencil_layer_clear");
RNA_def_function_ui_description(func, "Remove all the grease pencil layer data");
@@ -592,6 +831,14 @@ static void rna_def_gpencil_layers_api(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_pointer_funcs(prop, "rna_GPencil_active_layer_get", "rna_GPencil_active_layer_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Active Layer", "Active grease pencil layer");
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
+
+ RNA_def_property_int_funcs(prop,
+ "rna_GPencil_active_layer_index_get",
+ "rna_GPencil_active_layer_index_set",
+ "rna_GPencil_active_layer_index_range");
+ RNA_def_property_ui_text(prop, "Active Layer Index", "Index of active grease pencil layer");
}
static void rna_def_gpencil_data(BlenderRNA *brna)
@@ -620,6 +867,9 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layers", "");
rna_def_gpencil_layers_api(brna, prop);
+ /* Animation Data */
+ rna_def_animdata_common(srna);
+
/* Flags */
prop = RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
@@ -631,7 +881,13 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_DEPTH_STROKE_ENDPOINTS);
RNA_def_property_ui_text(prop, "Only Endpoints", "Only use the first and last parts of the stroke for snapping");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
+
+ prop = RNA_def_property(srna, "use_stroke_edit_mode", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_STROKE_EDITMODE);
+ RNA_def_property_ui_text(prop, "Stroke Edit Mode", "Enable alternative keymap to make editing stroke points easier");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, "rna_GPencil_update");
+
+ /* API Functions */
func = RNA_def_function(srna, "clear", "rna_GPencil_clear");
RNA_def_function_ui_description(func, "Remove all the grease pencil data");
}
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 141de511a09..b1935b34251 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -292,11 +292,21 @@ static int rna_Image_depth_get(PointerRNA *ptr)
static int rna_Image_frame_duration_get(PointerRNA *ptr)
{
- Image *im = (Image *)ptr->data;
+ Image *ima = ptr->id.data;
+ int duration = 1;
+
+ if (!ima->anim) {
+ /* acquire ensures ima->anim is set, if possible! */
+ void *lock;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ }
+
+ if (ima->anim) {
+ duration = IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN);
+ }
- if (im->anim)
- return IMB_anim_get_duration(im->anim, IMB_TC_RECORD_RUN);
- return 1;
+ return duration;
}
static int rna_Image_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
@@ -665,7 +675,7 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- prop = RNA_def_property(srna, "generated_color", PROP_FLOAT, PROP_COLOR);
+ prop = RNA_def_property(srna, "generated_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "gen_color");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Color", "Fill color for the generated image");
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index d9a59c4dc55..90f90ea8632 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -74,7 +74,7 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports
}
if (scene) {
- ImageUser iuser;
+ ImageUser iuser = {0};
void *lock;
iuser.scene = scene;
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 2b1df7a713e..2c00b70d1a9 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -288,6 +288,7 @@ void RNA_api_ui_layout(struct StructRNA *srna);
void RNA_api_window(struct StructRNA *srna);
void RNA_api_wm(struct StructRNA *srna);
void RNA_api_space_node(struct StructRNA *srna);
+void RNA_api_space_text(struct StructRNA *srna);
void RNA_api_region_view3d(struct StructRNA *srna);
void RNA_api_sensor(struct StructRNA *srna);
void RNA_api_controller(struct StructRNA *srna);
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index 7d10511d1c4..8a3626de81d 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -675,13 +675,6 @@ static void rna_def_key(BlenderRNA *brna)
RNA_def_property_range(prop, MINFRAME, MAXFRAME);
RNA_def_property_ui_text(prop, "Evaluation Time", "Evaluation time for absolute shape keys");
RNA_def_property_update(prop, 0, "rna_Key_update_data");
-
- prop = RNA_def_property(srna, "slurph", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "slurph");
- RNA_def_property_range(prop, -500, 500);
- RNA_def_property_ui_text(prop, "Slurph",
- "Create a delay (in frames) in applying key positions, first vertex goes first");
- RNA_def_property_update(prop, 0, "rna_Key_update_data");
}
void RNA_def_key(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index b0b99dcd2ca..3d6eab2bc88 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -1415,8 +1415,6 @@ static char *rna_FaceCustomData_data_path(PointerRNA *ptr, const char *collectio
}
-
-
static char *rna_MeshUVLoop_path(PointerRNA *ptr)
{
return rna_LoopCustomData_data_path(ptr, "uv_layers", CD_MLOOPUV);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 5c63b95eaaf..d8d27a06bb5 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -43,10 +43,15 @@
#include "BLF_translation.h"
#include "BKE_animsys.h"
+#include "BKE_data_transfer.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_dynamicpaint.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h"
#include "BKE_multires.h"
#include "BKE_smoke.h" /* For smokeModifier_free & smokeModifier_createType */
+#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -57,6 +62,7 @@
EnumPropertyItem modifier_type_items[] = {
{0, "", 0, N_("Modify"), ""},
+ {eModifierType_DataTransfer, "DATA_TRANSFER", ICON_MOD_DATA_TRANSFER, "Data Transfer", ""},
{eModifierType_MeshCache, "MESH_CACHE", ICON_MOD_MESHDEFORM, "Mesh Cache", ""},
{eModifierType_PointCache, "POINT_CACHE", ICON_MOD_MESHDEFORM, "Point Cache", ""},
{eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""},
@@ -128,9 +134,114 @@ EnumPropertyItem modifier_triangulate_ngon_method_items[] = {
{0, NULL, 0, NULL, NULL}
};
+/* ***** Data Transfer ***** */
+
+EnumPropertyItem DT_method_vertex_items[] = {
+ {MREMAP_MODE_TOPOLOGY, "TOPOLOGY", 0, "Topology",
+ "Copy from identical topology meshes"},
+ {MREMAP_MODE_VERT_NEAREST, "NEAREST", 0, "Nearest vertex",
+ "Copy from closest vertex"},
+ {MREMAP_MODE_VERT_EDGE_NEAREST, "EDGE_NEAREST", 0, "Nearest Edge Vertex",
+ "Copy from closest vertex of closest edge"},
+ {MREMAP_MODE_VERT_EDGEINTERP_NEAREST, "EDGEINTERP_NEAREST", 0, "Nearest Edge Interpolated",
+ "Copy from interpolated values of vertices from closest point on closest edge"},
+ {MREMAP_MODE_VERT_POLY_NEAREST, "POLY_NEAREST", 0, "Nearest Face Vertex",
+ "Copy from closest vertex of closest face"},
+ {MREMAP_MODE_VERT_POLYINTERP_NEAREST, "POLYINTERP_NEAREST", 0, "Nearest Face Interpolated",
+ "Copy from interpolated values of vertices from closest point on closest face"},
+ {MREMAP_MODE_VERT_POLYINTERP_VNORPROJ, "POLYINTERP_VNORPROJ", 0, "Projected Face Interpolated",
+ "Copy from interpolated values of vertices from point on closest face hit by normal-projection"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem DT_method_edge_items[] = {
+ {MREMAP_MODE_TOPOLOGY, "TOPOLOGY", 0, "Topology",
+ "Copy from identical topology meshes"},
+ {MREMAP_MODE_EDGE_VERT_NEAREST, "VERT_NEAREST", 0, "Nearest Vertices",
+ "Copy from most similar edge (edge which vertices are the closest of destination edge’s ones)"},
+ {MREMAP_MODE_EDGE_NEAREST, "NEAREST", 0, "Nearest Edge",
+ "Copy from closest edge (using midpoints)"},
+ {MREMAP_MODE_EDGE_POLY_NEAREST, "POLY_NEAREST", 0, "Nearest Face Edge",
+ "Copy from closest edge of closest face (using midpoints)"},
+ {MREMAP_MODE_EDGE_EDGEINTERP_VNORPROJ, "EDGEINTERP_VNORPROJ", 0, "Projected Edge Interpolated",
+ "Interpolate all source edges hit by the projection of destination one along its own normal (from vertices)"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem DT_method_loop_items[] = {
+ {MREMAP_MODE_TOPOLOGY, "TOPOLOGY", 0, "Topology",
+ "Copy from identical topology meshes"},
+ {MREMAP_MODE_LOOP_NEAREST_LOOPNOR, "NEAREST_NORMAL", 0, "Nearest Corner And Best Matching Normal",
+ "Copy from nearest corner which has the best matching normal"},
+ {MREMAP_MODE_LOOP_NEAREST_POLYNOR, "NEAREST_POLYNOR", 0, "Nearest Corner And Best Matching Face Normal",
+ "Copy from nearest corner which has the face with the best matching normal to destination corner's face one"},
+ {MREMAP_MODE_LOOP_POLY_NEAREST, "NEAREST_POLY", 0, "Nearest Corner Of Nearest Face",
+ "Copy from nearest corner of nearest polygon"},
+ {MREMAP_MODE_LOOP_POLYINTERP_NEAREST, "POLYINTERP_NEAREST", 0, "Nearest Face Interpolated",
+ "Copy from interpolated corners of the nearest source polygon"},
+ {MREMAP_MODE_LOOP_POLYINTERP_LNORPROJ, "POLYINTERP_LNORPROJ", 0, "Projected Face Interpolated",
+ "Copy from interpolated corners of the source polygon hit by corner normal projection"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem DT_method_poly_items[] = {
+ {MREMAP_MODE_TOPOLOGY, "TOPOLOGY", 0, "Topology",
+ "Copy from identical topology meshes"},
+ {MREMAP_MODE_POLY_NEAREST, "NEAREST", 0, "Nearest Face",
+ "Copy from nearest polygon (using center points)"},
+ {MREMAP_MODE_POLY_NOR, "NORMAL", 0, "Best Normal-Matching",
+ "Copy from source polygon which normal is the closest to destination one"},
+ {MREMAP_MODE_POLY_POLYINTERP_PNORPROJ, "POLYINTERP_PNORPROJ", 0, "Projected Face Interpolated",
+ "Interpolate all source polygons intersected by the projection of destination one along its own normal"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem DT_mix_mode_items[] = {
+ {CDT_MIX_TRANSFER, "REPLACE", 0, "Replace",
+ "Overwrite all elements' data"},
+ {CDT_MIX_REPLACE_ABOVE_THRESHOLD, "ABOVE_THRESHOLD", 0, "Above Threshold",
+ "Only replace destination elements where data is above given threshold (exact behavior depends on data type)"},
+ {CDT_MIX_REPLACE_BELOW_THRESHOLD, "BELOW_THRESHOLD", 0, "Below Threshold",
+ "Only replace destination elements where data is below given threshold (exact behavior depends on data type)"},
+ {CDT_MIX_MIX, "MIX", 0, "Mix",
+ "Mix source value into destination one, using given threshold as factor"},
+ {CDT_MIX_ADD, "ADD", 0, "Add",
+ "Add source value to destination one, using given threshold as factor"},
+ {CDT_MIX_SUB, "SUB", 0, "Subtract",
+ "Subtract source value to destination one, using given threshold as factor"},
+ {CDT_MIX_MUL, "MUL", 0, "Multiply",
+ "Multiply source value to destination one, using given threshold as factor"},
+ /* etc. etc. */
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem DT_layers_select_src_items[] = {
+ {DT_LAYERS_ACTIVE_SRC, "ACTIVE", 0, "Active Layer",
+ "Only transfer active data layer"},
+ {DT_LAYERS_ALL_SRC, "ALL", 0, "All Layers",
+ "Transfer all data layers"},
+ {DT_LAYERS_VGROUP_SRC_BONE_SELECT, "BONE_SELECT", 0, "Selected Pose Bones",
+ "Transfer all vertex groups used by selected pose bones"},
+ {DT_LAYERS_VGROUP_SRC_BONE_DEFORM, "BONE_DEFORM", 0, "Deform Pose Bones",
+ "Transfer all vertex groups used by deform bones"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem DT_layers_select_dst_items[] = {
+ {DT_LAYERS_ACTIVE_DST, "ACTIVE", 0, "Active Layer",
+ "Affect active data layer of all targets"},
+ {DT_LAYERS_NAME_DST, "NAME", 0, "By Name",
+ "Match target data layers to affect by name"},
+ {DT_LAYERS_INDEX_DST, "INDEX", 0, "By Order",
+ "Match target data layers to affect by order (indices)"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+
#ifdef RNA_RUNTIME
#include "DNA_particle_types.h"
+#include "DNA_curve_types.h"
#include "DNA_smoke_types.h"
#include "BKE_context.h"
@@ -245,6 +356,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
return &RNA_LaplacianDeformModifier;
case eModifierType_Wireframe:
return &RNA_WireframeModifier;
+ case eModifierType_DataTransfer:
+ return &RNA_DataTransferModifier;
case eModifierType_PointCache:
return &RNA_PointCacheModifier;
/* Default */
@@ -312,6 +425,7 @@ RNA_MOD_VGROUP_NAME_SET(Armature, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Bevel, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Cast, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Curve, name);
+RNA_MOD_VGROUP_NAME_SET(DataTransfer, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Decimate, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Displace, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Hook, name);
@@ -402,6 +516,7 @@ RNA_MOD_OBJECT_SET(Array, curve_ob, OB_CURVE);
RNA_MOD_OBJECT_SET(Boolean, object, OB_MESH);
RNA_MOD_OBJECT_SET(Cast, object, OB_EMPTY);
RNA_MOD_OBJECT_SET(Curve, object, OB_CURVE);
+RNA_MOD_OBJECT_SET(DataTransfer, ob_source, OB_MESH);
RNA_MOD_OBJECT_SET(Lattice, object, OB_LATTICE);
RNA_MOD_OBJECT_SET(Mask, ob_arm, OB_ARMATURE);
RNA_MOD_OBJECT_SET(MeshDeform, object, OB_MESH);
@@ -607,6 +722,299 @@ static int rna_LaplacianDeformModifier_is_bind_get(PointerRNA *ptr)
return ((lmd->flag & MOD_LAPLACIANDEFORM_BIND) && (lmd->cache_system != NULL));
}
+/* NOTE: Curve and array modifiers requires curve path to be evaluated,
+ * dependency graph will make sure that curve eval would create such a path,
+ * but if curve was already evaluated we might miss path.
+ *
+ * So what we do here is: if path was not calculated for target curve we
+ * tag it for update.
+ */
+
+static void rna_CurveModifier_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ CurveModifierData *cmd = (CurveModifierData *)ptr->data;
+ rna_Modifier_update(bmain, scene, ptr);
+ DAG_relations_tag_update(bmain);
+ if (cmd->object != NULL) {
+ Curve *curve = cmd->object->data;
+ if ((curve->flag & CU_PATH) == 0) {
+ DAG_id_tag_update(&curve->id, OB_RECALC_DATA);
+ }
+ }
+}
+
+static void rna_ArrayModifier_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ ArrayModifierData *amd = (ArrayModifierData *)ptr->data;
+ rna_Modifier_update(bmain, scene, ptr);
+ DAG_relations_tag_update(bmain);
+ if (amd->curve_ob != NULL) {
+ Curve *curve = amd->curve_ob->data;
+ if ((curve->flag & CU_PATH) == 0) {
+ DAG_id_tag_update(&curve->id, OB_RECALC_DATA);
+ }
+ }
+}
+
+
+static void rna_DataTransferModifier_use_data_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *)ptr->data;
+
+ if (!(dtmd->flags & MOD_DATATRANSFER_USE_VERT)) {
+ dtmd->data_types &= ~DT_TYPE_VERT_ALL;
+ }
+ if (!(dtmd->flags & MOD_DATATRANSFER_USE_EDGE)) {
+ dtmd->data_types &= ~DT_TYPE_EDGE_ALL;
+ }
+ if (!(dtmd->flags & MOD_DATATRANSFER_USE_LOOP)) {
+ dtmd->data_types &= ~DT_TYPE_LOOP_ALL;
+ }
+ if (!(dtmd->flags & MOD_DATATRANSFER_USE_POLY)) {
+ dtmd->data_types &= ~DT_TYPE_POLY_ALL;
+ }
+
+ rna_Modifier_update(bmain, scene, ptr);
+}
+
+static void rna_DataTransferModifier_data_types_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *)ptr->data;
+ const int item_types = BKE_object_data_transfer_get_dttypes_item_types(dtmd->data_types);
+
+ if (item_types & ME_VERT) {
+ dtmd->flags |= MOD_DATATRANSFER_USE_VERT;
+ }
+ if (item_types & ME_EDGE) {
+ dtmd->flags |= MOD_DATATRANSFER_USE_EDGE;
+ }
+ if (item_types & ME_LOOP) {
+ dtmd->flags |= MOD_DATATRANSFER_USE_LOOP;
+ }
+ if (item_types & ME_POLY) {
+ dtmd->flags |= MOD_DATATRANSFER_USE_POLY;
+ }
+
+ rna_Modifier_update(bmain, scene, ptr);
+}
+
+static EnumPropertyItem *rna_DataTransferModifier_layers_select_src_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *)ptr->data;
+ EnumPropertyItem *item = NULL, tmp_item = {0};
+ int totitem = 0;
+
+ if (!C) { /* needed for docs and i18n tools */
+ return DT_layers_select_src_items;
+ }
+
+ /* No active here! */
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_ALL_SRC);
+
+ if (STREQ(RNA_property_identifier(prop), "layers_vgroup_select_src")) {
+ Object *ob_src = dtmd->ob_source;
+
+#if 0 /* XXX Don't think we want this in modifier version... */
+ if (BKE_object_pose_armature_get(ob_src)) {
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT);
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM);
+ }
+#endif
+
+ if (ob_src) {
+ bDeformGroup *dg;
+ int i;
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = dg->name;
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ else if (STREQ(RNA_property_identifier(prop), "layers_shapekey_select_src")) {
+ /* TODO */
+ }
+ else if (STREQ(RNA_property_identifier(prop), "layers_uv_select_src")) {
+ Object *ob_src = dtmd->ob_source;
+
+ if (ob_src) {
+ DerivedMesh *dm_src;
+ CustomData *pdata;
+ int num_data, i;
+
+ /* XXX Is this OK? */
+ dm_src = mesh_get_derived_final(dtmd->modifier.scene, ob_src, CD_MASK_BAREMESH | CD_MTEXPOLY);
+ pdata = dm_src->getPolyDataLayout(dm_src);
+ num_data = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(pdata, CD_MTEXPOLY, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ else if (STREQ(RNA_property_identifier(prop), "layers_vcol_select_src")) {
+ Object *ob_src = dtmd->ob_source;
+
+ if (ob_src) {
+ DerivedMesh *dm_src;
+ CustomData *ldata;
+ int num_data, i;
+
+ /* XXX Is this OK? */
+ dm_src = mesh_get_derived_final(dtmd->modifier.scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL);
+ ldata = dm_src->getLoopDataLayout(dm_src);
+ num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPCOL, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static EnumPropertyItem *rna_DataTransferModifier_layers_select_dst_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *)ptr->data;
+ EnumPropertyItem *item = NULL, tmp_item = {0};
+ int totitem = 0;
+
+ if (!C) { /* needed for docs and i18n tools */
+ return DT_layers_select_dst_items;
+ }
+
+ /* No active here! */
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_dst_items, DT_LAYERS_NAME_DST);
+ RNA_enum_items_add_value(&item, &totitem, DT_layers_select_dst_items, DT_LAYERS_INDEX_DST);
+
+ if (STREQ(RNA_property_identifier(prop), "layers_vgroup_select_dst")) {
+ /* Only list destination layers if we have a single source! */
+ if (dtmd->layers_select_src[DT_MULTILAYER_INDEX_MDEFORMVERT] >= 0) {
+ Object *ob_dst = CTX_data_active_object(C); /* XXX Is this OK? */
+
+ if (ob_dst) {
+ bDeformGroup *dg;
+ int i;
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0, dg = ob_dst->defbase.first; dg; i++, dg = dg->next) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = dg->name;
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ }
+ else if (STREQ(RNA_property_identifier(prop), "layers_shapekey_select_dst")) {
+ /* TODO */
+ }
+ else if (STREQ(RNA_property_identifier(prop), "layers_uv_select_dst")) {
+ /* Only list destination layers if we have a single source! */
+ if (dtmd->layers_select_src[DT_MULTILAYER_INDEX_UV] >= 0) {
+ Object *ob_dst = CTX_data_active_object(C); /* XXX Is this OK? */
+
+ if (ob_dst && ob_dst->data) {
+ Mesh *me_dst;
+ CustomData *pdata;
+ int num_data, i;
+
+ me_dst = ob_dst->data;
+ pdata = &me_dst->pdata;
+ num_data = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(pdata, CD_MTEXPOLY, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ }
+ else if (STREQ(RNA_property_identifier(prop), "layers_vcol_select_dst")) {
+ /* Only list destination layers if we have a single source! */
+ if (dtmd->layers_select_src[DT_MULTILAYER_INDEX_VCOL] >= 0) {
+ Object *ob_dst = CTX_data_active_object(C); /* XXX Is this OK? */
+
+ if (ob_dst && ob_dst->data) {
+ Mesh *me_dst;
+ CustomData *ldata;
+ int num_data, i;
+
+ me_dst = ob_dst->data;
+ ldata = &me_dst->ldata;
+ num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPCOL, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ }
+
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static EnumPropertyItem *rna_DataTransferModifier_mix_mode_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *)ptr->data;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+ bool support_advanced_mixing, support_threshold;
+
+ if (!C) { /* needed for docs and i18n tools */
+ return DT_mix_mode_items;
+ }
+
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_TRANSFER);
+
+ BKE_object_data_transfer_get_dttypes_capacity(dtmd->data_types, &support_advanced_mixing, &support_threshold);
+
+ if (support_threshold) {
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_REPLACE_ABOVE_THRESHOLD);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_REPLACE_BELOW_THRESHOLD);
+ }
+
+ if (support_advanced_mixing) {
+ RNA_enum_item_add_separator(&item, &totitem);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_MIX);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_ADD);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_SUB);
+ RNA_enum_items_add_value(&item, &totitem, DT_mix_mode_items, CDT_MIX_MUL);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
#else
static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const char type[])
@@ -879,7 +1287,7 @@ static void rna_def_modifier_curve(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Object", "Curve object to deform with");
RNA_def_property_pointer_funcs(prop, NULL, "rna_CurveModifier_object_set", NULL, "rna_Curve_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+ RNA_def_property_update(prop, 0, "rna_CurveModifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "name");
@@ -1402,7 +1810,7 @@ static void rna_def_modifier_array(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Curve", "Curve object to fit array length to");
RNA_def_property_pointer_funcs(prop, NULL, "rna_ArrayModifier_curve_ob_set", NULL, "rna_Curve_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+ RNA_def_property_update(prop, 0, "rna_ArrayModifier_dependency_update");
/* Offset parameters */
prop = RNA_def_property(srna, "use_constant_offset", PROP_BOOLEAN, PROP_NONE);
@@ -2456,7 +2864,7 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "origin", PROP_POINTER, PROP_NONE);
- RNA_def_property_ui_text(prop, "Origin", "Origin of modifier space coordinates");
+ RNA_def_property_ui_text(prop, "Origin", "Offset the origin and orientation of the deformation");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
@@ -3667,6 +4075,251 @@ static void rna_def_modifier_wireframe(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
+static void rna_def_modifier_datatransfer(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem DT_layer_vert_items[] = {
+#if 0 /* XXX When SkinModifier is enabled, it seems to erase its own CD_MVERT_SKIN layer from final DM :( */
+ {DT_TYPE_SKIN, "SKIN", 0, "Skin Weight", "Transfer skin weights"},
+#endif
+ {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem DT_layer_vert_vgroup_items[] = {
+ {DT_TYPE_MDEFORMVERT, "VGROUP_WEIGHTS", 0, "Vertex Group(s)", "Transfer active or all vertex groups"},
+ {0, NULL, 0, NULL, NULL}
+ };
+#if 0 /* XXX For now, would like to finish/merge work from 2014 gsoc first. */
+ static EnumPropertyItem DT_layer_vert_shapekey_items[] = {
+ {DT_TYPE_SHAPEKEY, "SHAPEKEYS", 0, "Shapekey(s)", "Transfer active or all shape keys"},
+ {0, NULL, 0, NULL, NULL}
+ };
+#endif
+
+ static EnumPropertyItem DT_layer_edge_items[] = {
+ {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"},
+ {DT_TYPE_SEAM, "SEAM", 0, "UV Seam", "Transfer UV seam mark"},
+ {DT_TYPE_CREASE, "CREASE", 0, "Subsurf Crease", "Transfer crease values"},
+ {DT_TYPE_BWEIGHT_EDGE, "BEVEL_WEIGHT_EDGE", 0, "Bevel Weight", "Transfer bevel weights"},
+ {DT_TYPE_FREESTYLE_EDGE, "FREESTYLE_EDGE", 0, "Freestyle Mark", "Transfer Freestyle edge mark"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem DT_layer_loop_items[] = {
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem DT_layer_loop_vcol_items[] = {
+ {DT_TYPE_VCOL, "VCOL", 0, "VCol", "Vertex (face corners) colors"},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem DT_layer_loop_uv_items[] = {
+ {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem DT_layer_poly_items[] = {
+ {DT_TYPE_SHARP_FACE, "SMOOTH", 0, "Smooth", "Transfer flat/smooth mark"},
+ {DT_TYPE_FREESTYLE_FACE, "FREESTYLE_FACE", 0, "Freestyle Mark", "Transfer Freestyle face mark"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "DataTransferModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "Data Transfer Modifier", "Modifier transferring some data from a source mesh");
+ RNA_def_struct_sdna(srna, "DataTransferModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_DATA_TRANSFER);
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "ob_source");
+ RNA_def_property_ui_text(prop, "Source Object", "Object to transfer data from");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_DataTransferModifier_ob_source_set", NULL, "rna_Mesh_object_poll");
+ RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ prop = RNA_def_boolean(srna, "use_object_transform", true, "Object Transform",
+ "Evaluate source and destination meshes in their respective object spaces");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_OBSRC_TRANSFORM);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /* Generic, UI-only data types toggles. */
+ prop = RNA_def_boolean(srna, "use_vert_data", false, "Vertex Data", "Enable vertex data transfer");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_USE_VERT);
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_use_data_update");
+
+ prop = RNA_def_boolean(srna, "use_edge_data", false, "Edge Data", "Enable edge data transfer");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_USE_EDGE);
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_use_data_update");
+
+ prop = RNA_def_boolean(srna, "use_loop_data", false, "Face Corner Data", "Enable face corner data transfer");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_USE_LOOP);
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_use_data_update");
+
+ prop = RNA_def_boolean(srna, "use_poly_data", false, "Face Data", "Enable face data transfer");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_USE_POLY);
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_use_data_update");
+
+ /* Actual data types selection. */
+ prop = RNA_def_enum(srna, "data_types_verts", DT_layer_vert_items, 0, "Vertex Data Types",
+ "Which vertex data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+ prop = RNA_def_enum(srna, "data_types_verts_vgroup", DT_layer_vert_vgroup_items, 0, "Vertex Data Types",
+ "Which vertex data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+
+ prop = RNA_def_enum(srna, "data_types_edges", DT_layer_edge_items, 0, "Edge Data Types",
+ "Which edge data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+
+ prop = RNA_def_enum(srna, "data_types_loops", DT_layer_loop_items, 0, "Face Corner Data Types",
+ "Which face corner data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+ prop = RNA_def_enum(srna, "data_types_loops_vcol", DT_layer_loop_vcol_items, 0, "Face Corner Data Types",
+ "Which face corner data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+ prop = RNA_def_enum(srna, "data_types_loops_uv", DT_layer_loop_uv_items, 0, "Face Corner Data Types",
+ "Which face corner data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+
+ prop = RNA_def_enum(srna, "data_types_polys", DT_layer_poly_items, 0, "Poly Data Types",
+ "Which poly data layers to transfer");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_enum_sdna(prop, NULL, "data_types");
+ RNA_def_property_update(prop, 0, "rna_DataTransferModifier_data_types_update");
+
+ /* Mapping methods. */
+ prop = RNA_def_enum(srna, "vert_mapping", DT_method_vertex_items, MREMAP_MODE_VERT_NEAREST, "Vertex Mapping",
+ "Method used to map source vertices to destination ones");
+ RNA_def_property_enum_sdna(prop, NULL, "vmap_mode");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_enum(srna, "edge_mapping", DT_method_edge_items, MREMAP_MODE_EDGE_NEAREST, "Edge Mapping",
+ "Method used to map source edges to destination ones");
+ RNA_def_property_enum_sdna(prop, NULL, "emap_mode");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_enum(srna, "loop_mapping", DT_method_loop_items, MREMAP_MODE_LOOP_NEAREST_POLYNOR,
+ "Face Corner Mapping", "Method used to map source faces' corners to destination ones");
+ RNA_def_property_enum_sdna(prop, NULL, "lmap_mode");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_enum(srna, "poly_mapping", DT_method_poly_items, MREMAP_MODE_POLY_NEAREST, "Face Mapping",
+ "Method used to map source faces to destination ones");
+ RNA_def_property_enum_sdna(prop, NULL, "pmap_mode");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /* Mapping options and filtering. */
+ prop = RNA_def_boolean(srna, "use_max_distance", false, "Only Neighbor Geometry",
+ "Source elements must be closer than given distance from destination one");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_MAP_MAXDIST);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_float(srna, "max_distance", 1.0f, 0.0f, FLT_MAX, "Max Distance",
+ "Maximum allowed distance between source and destination element, for non-topology mappings",
+ 0.0f, 100.0f);
+ RNA_def_property_float_sdna(prop, NULL, "map_max_distance");
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_float(srna, "ray_radius", 0.0f, 0.0f, FLT_MAX, "Ray Radius",
+ "'Width' of rays (especially useful when raycasting against vertices or edges)", 0.0f, 10.0f);
+ RNA_def_property_float_sdna(prop, NULL, "map_ray_radius");
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_float(srna, "islands_precision", 0.0f, 0.0f, 1.0f, "Islands Handling Refinement",
+ "Factor controlling precision of islands handling "
+ "(typically, 0.1 should be enough, higher values can make things really slow)", 0.0f, 1.0f);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /* How to handle multi-layers types of data. */
+ prop = RNA_def_enum(srna, "layers_vgroup_select_src", DT_layers_select_src_items, DT_LAYERS_ALL_SRC,
+ "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_src[DT_MULTILAYER_INDEX_MDEFORMVERT]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_src_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+#if 0
+ prop = RNA_def_enum(srna, "layers_shapekey_select_src", DT_layers_select_src_items, DT_LAYERS_ALL_SRC,
+ "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_src[DT_MULTILAYER_INDEX_SHAPEKEY]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_src_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+#endif
+
+ prop = RNA_def_enum(srna, "layers_vcol_select_src", DT_layers_select_src_items, DT_LAYERS_ALL_SRC,
+ "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_src[DT_MULTILAYER_INDEX_VCOL]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_src_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_enum(srna, "layers_uv_select_src", DT_layers_select_src_items, DT_LAYERS_ALL_SRC,
+ "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_src[DT_MULTILAYER_INDEX_UV]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_src_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_enum(srna, "layers_vgroup_select_dst", DT_layers_select_dst_items, DT_LAYERS_NAME_DST,
+ "Destination Layers Matching", "How to match source and destination layers");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_dst[DT_MULTILAYER_INDEX_MDEFORMVERT]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_dst_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+#if 0
+ prop = RNA_def_enum(srna, "layers_shapekey_select_dst", DT_layers_select_dst_items, DT_LAYERS_NAME_DST,
+ "Destination Layers Matching", "How to match source and destination layers");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_dst[DT_MULTILAYER_INDEX_SHAPEKEY]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_dst_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+#endif
+
+ prop = RNA_def_enum(srna, "layers_vcol_select_dst", DT_layers_select_dst_items, DT_LAYERS_NAME_DST,
+ "Destination Layers Matching", "How to match source and destination layers");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_dst[DT_MULTILAYER_INDEX_VCOL]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_dst_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_enum(srna, "layers_uv_select_dst", DT_layers_select_dst_items, DT_LAYERS_NAME_DST,
+ "Destination Layers Matching", "How to match source and destination layers");
+ RNA_def_property_enum_sdna(prop, NULL, "layers_select_dst[DT_MULTILAYER_INDEX_UV]");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_layers_select_dst_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /* Mix stuff */
+ prop = RNA_def_enum(srna, "mix_mode", DT_mix_mode_items, CDT_MIX_TRANSFER, "Mix Mode",
+ "How to affect destination elements with source values");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DataTransferModifier_mix_mode_itemf");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_float(srna, "mix_factor", 1.0f, 0.0f, 1.0f, "Mix Factor",
+ "Factor to use when applying data to destination (exact behavior depends on mix mode)",
+ 0.0f, 1.0f);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_string(srna, "vertex_group", NULL, MAX_VGROUP_NAME, "Vertex Group",
+ "Vertex group name for selecting the affected areas");
+ RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_DataTransferModifier_defgrp_name_set");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_boolean(srna, "invert_vertex_group", false, "Invert", "Invert vertex group influence");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_INVERT_VGROUP);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+}
+
static void rna_def_modifier_pointcache(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3797,6 +4450,7 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_meshcache(brna);
rna_def_modifier_laplaciandeform(brna);
rna_def_modifier_wireframe(brna);
+ rna_def_modifier_datatransfer(brna);
rna_def_modifier_pointcache(brna);
}
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index 170856a3061..e891ab520f9 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -317,8 +317,8 @@ static void rna_def_movieclip(BlenderRNA *brna)
/* grease pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this movie clip");
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 91dcb9f4d81..fa8d2669161 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -2199,6 +2199,10 @@ static void rna_NodeSocketStandard_float_range(PointerRNA *ptr, float *min, floa
bNodeSocketValueFloat *dval = sock->default_value;
int subtype = sock->typeinfo->subtype;
+ if (dval->max < dval->min) {
+ dval->max = dval->min;
+ }
+
*min = (subtype == PROP_UNSIGNED ? 0.0f : -FLT_MAX);
*max = FLT_MAX;
*softmin = dval->min;
@@ -2211,6 +2215,10 @@ static void rna_NodeSocketStandard_int_range(PointerRNA *ptr, int *min, int *max
bNodeSocketValueInt *dval = sock->default_value;
int subtype = sock->typeinfo->subtype;
+ if (dval->max < dval->min) {
+ dval->max = dval->min;
+ }
+
*min = (subtype == PROP_UNSIGNED ? 0 : INT_MIN);
*max = INT_MAX;
*softmin = dval->min;
@@ -2222,6 +2230,10 @@ static void rna_NodeSocketStandard_vector_range(PointerRNA *ptr, float *min, flo
bNodeSocket *sock = ptr->data;
bNodeSocketValueVector *dval = sock->default_value;
+ if (dval->max < dval->min) {
+ dval->max = dval->min;
+ }
+
*min = -FLT_MAX;
*max = FLT_MAX;
*softmin = dval->min;
@@ -7572,8 +7584,8 @@ static void rna_def_nodetree(BlenderRNA *brna)
/* Grease Pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil datablock");
RNA_def_property_update(prop, NC_NODE, NULL);
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 8ebeeafbc58..f9a76005df8 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -42,10 +42,13 @@
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "BKE_camera.h"
#include "BKE_paint.h"
#include "BKE_editmesh.h"
#include "BKE_group.h" /* needed for BKE_group_object_exists() */
#include "BKE_object.h" /* Needed for BKE_object_matrix_local_get() */
+#include "BKE_object_deform.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -231,21 +234,21 @@ static void rna_Object_matrix_local_get(PointerRNA *ptr, float values[16])
static void rna_Object_matrix_local_set(PointerRNA *ptr, const float values[16])
{
Object *ob = ptr->id.data;
+ float local_mat[4][4];
- /* localspace matrix is truly relative to the parent, but parameters
- * stored in object are relative to parentinv matrix. Undo the parent
- * inverse part before updating obmat and calling apply_obmat() */
+ /* localspace matrix is truly relative to the parent, but parameters stored in object are
+ * relative to parentinv matrix. Undo the parent inverse part before applying it as local matrix. */
if (ob->parent) {
float invmat[4][4];
invert_m4_m4(invmat, ob->parentinv);
- mul_m4_m4m4(ob->obmat, invmat, (float(*)[4])values);
+ mul_m4_m4m4(local_mat, invmat, (float(*)[4])values);
}
else {
- copy_m4_m4(ob->obmat, (float(*)[4])values);
+ copy_m4_m4(local_mat, (float(*)[4])values);
}
- /* don't use compat so we get predictable rotation */
- BKE_object_apply_mat4(ob, ob->obmat, false, false);
+ /* don't use compat so we get predictable rotation, and do not use parenting either, because it's a local matrix! */
+ BKE_object_apply_mat4(ob, local_mat, false, false);
}
static void rna_Object_matrix_basis_get(PointerRNA *ptr, float values[16])
@@ -775,7 +778,7 @@ static void rna_Object_rotation_axis_angle_set(PointerRNA *ptr, const float *val
/* for now, assume that rotation mode is axis-angle */
ob->rotAngle = value[0];
- copy_v3_v3(ob->rotAxis, (float *)&value[1]);
+ copy_v3_v3(ob->rotAxis, &value[1]);
/* TODO: validate axis? */
}
@@ -1389,7 +1392,7 @@ static void rna_Object_boundbox_get(PointerRNA *ptr, float *values)
static bDeformGroup *rna_Object_vgroup_new(Object *ob, const char *name)
{
- bDeformGroup *defgroup = ED_vgroup_add_name(ob, name);
+ bDeformGroup *defgroup = BKE_object_defgroup_add_name(ob, name);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
@@ -1404,7 +1407,7 @@ static void rna_Object_vgroup_remove(Object *ob, ReportList *reports, PointerRNA
return;
}
- ED_vgroup_delete(ob, defgroup);
+ BKE_object_defgroup_remove(ob, defgroup);
RNA_POINTER_INVALIDATE(defgroup_ptr);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
@@ -1412,7 +1415,7 @@ static void rna_Object_vgroup_remove(Object *ob, ReportList *reports, PointerRNA
static void rna_Object_vgroup_clear(Object *ob)
{
- ED_vgroup_clear(ob);
+ BKE_object_defgroup_remove_all(ob);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
@@ -1422,7 +1425,7 @@ static void rna_VertexGroup_vertex_add(ID *id, bDeformGroup *def, ReportList *re
{
Object *ob = (Object *)id;
- if (ED_vgroup_object_is_edit_mode(ob)) {
+ if (BKE_object_is_in_editmode_vgroup(ob)) {
BKE_report(reports, RPT_ERROR, "VertexGroup.add(): cannot be called while object is in edit mode");
return;
}
@@ -1437,7 +1440,7 @@ static void rna_VertexGroup_vertex_remove(ID *id, bDeformGroup *dg, ReportList *
{
Object *ob = (Object *)id;
- if (ED_vgroup_object_is_edit_mode(ob)) {
+ if (BKE_object_is_in_editmode_vgroup(ob)) {
BKE_report(reports, RPT_ERROR, "VertexGroup.remove(): cannot be called while object is in edit mode");
return;
}
@@ -2427,7 +2430,9 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "matrix_local", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Local Matrix", "Parent relative transformation matrix");
+ RNA_def_property_ui_text(prop, "Local Matrix", "Parent relative transformation matrix - "
+ "WARNING: Only takes into account 'Object' parenting, so e.g. in case of bone parenting "
+ "you get a matrix relative to the Armature object, not to the actual parent bone");
RNA_def_property_float_funcs(prop, "rna_Object_matrix_local_get", "rna_Object_matrix_local_set", NULL);
RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -2727,16 +2732,16 @@ static void rna_def_object(BlenderRNA *brna)
/* Grease Pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil datablock");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
/* pose */
prop = RNA_def_property(srna, "pose_library", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "poselib");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "Action");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Pose Library", "Action used as a pose library for armatures");
prop = RNA_def_property(srna, "pose", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 831e5486236..1b4bc10551b 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -109,7 +109,29 @@ static void rna_Scene_mat_convert_space(Object *ob, ReportList *reports, bPoseCh
}
}
- BKE_constraint_mat_convertspace(ob, pchan, (float (*)[4])mat_ret, from, to);
+ BKE_constraint_mat_convertspace(ob, pchan, (float (*)[4])mat_ret, from, to, false);
+}
+
+static void rna_Object_calc_matrix_camera(
+ Object *ob, float mat_ret[16], int width, int height, float scalex, float scaley)
+{
+ CameraParams params;
+
+ /* setup parameters */
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, ob);
+
+ /* compute matrix, viewplane, .. */
+ BKE_camera_params_compute_viewplane(&params, width, height, scalex, scaley);
+ BKE_camera_params_compute_matrix(&params);
+
+ copy_m4_m4((float (*)[4])mat_ret, params.winmat);
+}
+
+static void rna_Object_camera_fit_coords(
+ Object *ob, Scene *scene, int num_cos, float *cos, float co_ret[3], float *scale_ret)
+{
+ BKE_camera_view_frame_fit_to_coords(scene, (float (*)[3])cos, num_cos / 3, ob, co_ret, scale_ret);
}
/* copied from Mesh_getFromObject and adapted to RNA interface */
@@ -203,10 +225,9 @@ static void rna_Object_free_duplilist(Object *ob)
static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList *reports,
const char *name, int from_mix)
{
- Scene *scene = CTX_data_scene(C);
KeyBlock *kb = NULL;
- if ((kb = BKE_object_insert_shape_key(scene, ob, name, from_mix))) {
+ if ((kb = BKE_object_insert_shape_key(ob, name, from_mix))) {
PointerRNA keyptr;
RNA_pointer_create((ID *)ob->data, &RNA_ShapeKey, kb, &keyptr);
@@ -468,6 +489,35 @@ void RNA_api_object(StructRNA *srna)
parm = RNA_def_enum(func, "to_space", space_items, CONSTRAINT_SPACE_WORLD, "",
"The space to which you want to transform 'matrix'");
+ /* Camera-related operations */
+ func = RNA_def_function(srna, "calc_matrix_camera", "rna_Object_calc_matrix_camera");
+ RNA_def_function_ui_description(func, "Generate the camera projection matrix of this object "
+ "(mostly useful for Camera and Lamp types)");
+ parm = RNA_def_property(func, "result", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(parm, "", "The camera projection matrix");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_int(func, "x", 1, 0, INT_MAX, "", "Width of the render area", 0, 10000);
+ parm = RNA_def_int(func, "y", 1, 0, INT_MAX, "", "Height of the render area", 0, 10000);
+ parm = RNA_def_float(func, "scale_x", 1.0f, 1.0e-6f, FLT_MAX, "", "Width scaling factor", 1.0e-2f, 100.0f);
+ parm = RNA_def_float(func, "scale_y", 1.0f, 1.0e-6f, FLT_MAX, "", "height scaling factor", 1.0e-2f, 100.0f);
+
+ func = RNA_def_function(srna, "camera_fit_coords", "rna_Object_camera_fit_coords");
+ RNA_def_function_ui_description(func, "Compute the coordinate (and scale for ortho cameras) "
+ "given object should be to 'see' all given coordinates");
+ parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene to get render size information from, if available");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_float_array(func, "coordinates", 1, NULL, -FLT_MAX, FLT_MAX, "", "Coordinates to fit in",
+ -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_DYNAMIC);
+ parm = RNA_def_property(func, "co_return", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_array(parm, 3);
+ RNA_def_property_ui_text(parm, "", "The location to aim to be able to see all given points");
+ RNA_def_property_flag(parm, PROP_OUTPUT);
+ parm = RNA_def_property(func, "scale_return", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(parm, "", "The ortho scale to aim to be able to see all given points (if relevant)");
+ RNA_def_property_flag(parm, PROP_OUTPUT);
+
/* mesh */
func = RNA_def_function(srna, "to_mesh", "rna_Object_to_mesh");
RNA_def_function_ui_description(func, "Create a Mesh datablock with modifiers applied");
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index f72f97b1681..07dac63f3fe 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -258,7 +258,7 @@ static void rna_PoseChannel_rotation_axis_angle_set(PointerRNA *ptr, const float
/* for now, assume that rotation mode is axis-angle */
pchan->rotAngle = value[0];
- copy_v3_v3(pchan->rotAxis, (float *)&value[1]);
+ copy_v3_v3(pchan->rotAxis, &value[1]);
/* TODO: validate axis? */
}
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 0ee654d4ecc..6db9c8e9cd9 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -38,7 +38,6 @@
#include "RE_engine.h"
#include "RE_pipeline.h"
-#include "RE_engine.h"
EnumPropertyItem render_pass_type_items[] = {
@@ -520,6 +519,11 @@ static void rna_def_render_engine(BlenderRNA *brna)
prop = RNA_def_string(func, "message", NULL, 0, "Report Message", "");
RNA_def_property_flag(prop, PROP_REQUIRED);
+ func = RNA_def_function(srna, "error_set", "RE_engine_set_error_message");
+ RNA_def_function_ui_description(func, "Set error message displaying after the render is finished");
+ prop = RNA_def_string(func, "message", NULL, 0, "Report Message", "");
+ RNA_def_property_flag(prop, PROP_REQUIRED);
+
func = RNA_def_function(srna, "bind_display_space_shader", "engine_bind_display_space_shader");
RNA_def_function_ui_description(func, "Bind GLSL fragment shader that converts linear colors to display space colors using scene color management settings");
prop = RNA_def_pointer(func, "scene", "Scene", "", "");
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
index 86a8b162614..58a12f62644 100644
--- a/source/blender/makesrna/intern/rna_rigidbody.c
+++ b/source/blender/makesrna/intern/rna_rigidbody.c
@@ -644,8 +644,7 @@ static void rna_RigidBodyWorld_convex_sweep_test(
BKE_report(reports, RPT_ERROR, "Rigidbody world was not properly initialized, need to step the simulation first");
}
#else
- (void)rbw, (void)reports, (void)object, (void)ray_start, (void)ray_end;
- (void)r_location, (void)r_hitpoint, (void)r_normal, (void)r_hit;
+ UNUSED_VARS(rbw, reports, object, ray_start, ray_end, r_location, r_hitpoint, r_normal, r_hit);
#endif
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 519a52b04e2..d9587b8d983 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -737,7 +737,7 @@ static int rna_RenderSettings_threads_mode_get(PointerRNA *ptr)
return (rd->mode & R_FIXED_THREADS);
}
-static int rna_RenderSettings_is_movie_fomat_get(PointerRNA *ptr)
+static int rna_RenderSettings_is_movie_format_get(PointerRNA *ptr)
{
RenderData *rd = (RenderData *)ptr->data;
return BKE_imtype_is_movie(rd->im_format.imtype);
@@ -1773,6 +1773,14 @@ static void rna_def_tool_settings(BlenderRNA *brna)
{WT_VGROUP_BONE_DEFORM_OFF, "OTHER_DEFORM", 0, "Other", "Vertex Groups assigned to non Deform Bones"},
{0, NULL, 0, NULL, NULL}
};
+
+ static EnumPropertyItem gpencil_source_3d_items[] = {
+ {GP_TOOL_SOURCE_SCENE, "SCENE", 0, "Scene",
+ "Grease Pencil data attached to the current scene is used, unless the active object already has Grease Pencil data (i.e. for old files)"},
+ {GP_TOOL_SOURCE_OBJECT, "OBJECT", 0, "Object",
+ "Grease Pencil datablocks attached to the active object are used (required using pre 2.73 add-ons, e.g. BSurfaces)"},
+ {0, NULL, 0, NULL, NULL}
+ };
srna = RNA_def_struct(brna, "ToolSettings", NULL);
@@ -1965,6 +1973,13 @@ static void rna_def_tool_settings(BlenderRNA *brna)
"Allow drawing multiple strokes at a time with Grease Pencil");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* xxx: need toolbar to be redrawn... */
+ prop = RNA_def_property(srna, "grease_pencil_source", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "gpencil_src");
+ RNA_def_property_enum_items(prop, gpencil_source_3d_items);
+ RNA_def_property_ui_text(prop, "Grease Pencil Source",
+ "Datablock where active Grease Pencil data is found from");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
/* Auto Keying */
prop = RNA_def_property(srna, "use_keyframe_insert_auto", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "autokey_mode", AUTOKEY_ON);
@@ -4801,7 +4816,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "is_movie_format", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_is_movie_fomat_get", NULL);
+ RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_is_movie_format_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Movie Format", "When true the format is a movie");
@@ -5459,7 +5474,7 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "lay", 1);
RNA_def_property_array(prop, 20);
RNA_def_property_boolean_funcs(prop, NULL, "rna_Scene_layer_set");
- RNA_def_property_ui_text(prop, "Layers", "Visible layers - Shift-Click to select multiple layers");
+ RNA_def_property_ui_text(prop, "Layers", "Visible layers - Shift-Click/Drag to select multiple layers");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_Scene_layer_update");
/* active layer */
@@ -5738,10 +5753,10 @@ void RNA_def_scene(BlenderRNA *brna)
/* Grease Pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil datablock");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
/* Transform Orientations */
prop = RNA_def_property(srna, "orientations", PROP_COLLECTION, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 84134e7cd3a..be618c5d1a3 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -47,12 +47,14 @@
#include "BKE_animsys.h"
#include "BKE_depsgraph.h"
+#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_scene.h"
#include "BKE_writeavi.h"
#include "ED_transform.h"
+#include "ED_uvedit.h"
#ifdef WITH_PYTHON
# include "BPY_extern.h"
@@ -90,6 +92,20 @@ static void rna_Scene_frame_set(Scene *scene, int frame, float subframe)
}
}
+static void rna_Scene_uvedit_aspect(Scene *scene, Object *ob, float *aspect)
+{
+ if ((ob->type == OB_MESH) && (ob->mode == OB_MODE_EDIT)) {
+ BMEditMesh *em;
+ em = BKE_editmesh_from_object(ob);
+ if (EDBM_mtexpoly_check(em)) {
+ ED_uvedit_get_aspect(scene, ob, em->bm, aspect, aspect + 1);
+ return;
+ }
+ }
+
+ aspect[0] = aspect[1] = 1.0f;
+}
+
static void rna_Scene_update_tagged(Scene *scene)
{
#ifdef WITH_PYTHON
@@ -191,6 +207,15 @@ void RNA_api_scene(StructRNA *srna)
RNA_def_function_ui_description(func,
"Update data tagged to be updated from previous access to data or operators");
+ func = RNA_def_function(srna, "uvedit_aspect", "rna_Scene_uvedit_aspect");
+ RNA_def_function_ui_description(func, "Get uv aspect for current object");
+ parm = RNA_def_pointer(func, "object", "Object", "", "Object");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ parm = RNA_def_float_vector(func, "result", 2, NULL, 0.0f, FLT_MAX, "", "aspect", 0.0f, FLT_MAX);
+ RNA_def_property_flag(parm, PROP_THICK_WRAP);
+ RNA_def_function_output(func, parm);
+
/* Ray Cast */
func = RNA_def_function(srna, "ray_cast", "rna_Scene_ray_cast");
RNA_def_function_ui_description(func, "Cast a ray onto in object space");
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index 86a28fb80bf..7b01acff6a5 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -110,7 +110,9 @@ static void rna_Screen_redraw_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
static int rna_Screen_is_animation_playing_get(PointerRNA *UNUSED(ptr))
{
- return (ED_screen_animation_playing(G.main->wm.first) != NULL);
+ /* can be NULL on file load, T42619 */
+ wmWindowManager *wm = G.main->wm.first;
+ return wm ? (ED_screen_animation_playing(wm) != NULL) : 0;
}
static int rna_Screen_fullscreen_get(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 09e42e48e93..8e83543812d 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -289,7 +289,8 @@ static char *rna_ParticleBrush_path(PointerRNA *UNUSED(ptr))
static void rna_Paint_brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Brush *br = (Brush *)ptr->data;
+ Paint *paint = ptr->data;
+ Brush *br = paint->brush;
BKE_paint_invalidate_overlay_all();
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
}
@@ -303,22 +304,27 @@ static void rna_ImaPaint_viewport_update(Main *UNUSED(bmain), Scene *UNUSED(scen
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);
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ if (ob && ob->type == OB_MESH) {
+ /* 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);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ }
}
static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
{
- Object *ob = OBACT;
- GPU_drawobject_free(ob->derivedFinal);
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ Object *ob = OBACT;
+
+ if (ob && ob->type == OB_MESH) {
+ GPU_drawobject_free(ob->derivedFinal);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ }
}
static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
@@ -342,9 +348,11 @@ static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UN
}
}
- GPU_drawobject_free(ob->derivedFinal);
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ if (ob && ob->type == OB_MESH) {
+ GPU_drawobject_free(ob->derivedFinal);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ }
}
static int rna_ImaPaint_detect_data(ImagePaintSettings *imapaint)
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 00f0a6ff487..dda0e8493d9 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -1846,6 +1846,11 @@ static void rna_def_scene(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Camera_object_poll");
RNA_def_property_ui_text(prop, "Camera Override", "Override the scenes active camera");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "use_grease_pencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_SCENE_NO_GPENCIL);
+ RNA_def_property_ui_text(prop, "Use Grease Pencil", "Show Grease Pencil strokes in OpenGL previews");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
rna_def_filter_video(srna);
rna_def_proxy(srna);
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 70370f1ae36..3d358b412c8 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -313,6 +313,7 @@ static Sequence *rna_Sequences_new_effect(ID *id, Editing *ed, ReportList *repor
seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
+ BKE_sequence_calc(scene, seq);
BKE_sequence_calc_disp(scene, seq);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
diff --git a/source/blender/makesrna/intern/rna_sound.c b/source/blender/makesrna/intern/rna_sound.c
index 206a72a01b0..aa39e81d390 100644
--- a/source/blender/makesrna/intern/rna_sound.c
+++ b/source/blender/makesrna/intern/rna_sound.c
@@ -38,6 +38,7 @@
#include "BKE_sound.h"
#include "BKE_context.h"
+#include "BKE_sequencer.h"
static void rna_Sound_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
@@ -59,9 +60,9 @@ static void rna_Sound_caching_set(PointerRNA *ptr, const int value)
sound_delete_cache(sound);
}
-static void rna_Sound_caching_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Sound_caching_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
{
- sound_update_sequencer(bmain, (bSound *)(ptr->data));
+ BKE_sequencer_update_sound(scene, (bSound *)(ptr->data));
}
#else
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 68173ebefb4..af0e69cdc3e 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -266,13 +266,7 @@ static ScrArea *rna_area_from_space(PointerRNA *ptr)
{
bScreen *sc = (bScreen *)ptr->id.data;
SpaceLink *link = (SpaceLink *)ptr->data;
- ScrArea *sa;
-
- for (sa = sc->areabase.first; sa; sa = sa->next)
- if (BLI_findindex(&sa->spacedata, link) != -1)
- return sa;
-
- return NULL;
+ return BKE_screen_find_area_from_space(sc, link);
}
static void area_region_from_regiondata(bScreen *sc, void *regiondata, ScrArea **r_sa, ARegion **r_ar)
@@ -485,7 +479,7 @@ static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(sce
BKE_previewimg_free(&ma->preview);
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma);
}
@@ -856,7 +850,6 @@ static void rna_SpaceTextEditor_updateEdited(Main *UNUSED(bmain), Scene *UNUSED(
WM_main_add_notifier(NC_TEXT | NA_EDITED, st->text);
}
-
/* Space Properties */
/* note: this function exists only to avoid id refcounting */
@@ -1588,6 +1581,7 @@ static void rna_def_space_outliner(BlenderRNA *brna)
prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "search_string");
RNA_def_property_ui_text(prop, "Display Filter", "Live search filtering string");
+ RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
prop = RNA_def_property(srna, "use_filter_case_sensitive", PROP_BOOLEAN, PROP_NONE);
@@ -2041,6 +2035,11 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Only Render", "Display only objects which will be rendered");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ prop = RNA_def_property(srna, "show_world", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag3", V3D_SHOW_WORLD);
+ RNA_def_property_ui_text(prop, "World Background", "Display world colors in the background");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
prop = RNA_def_property(srna, "use_occlude_geometry", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_ZBUF_SELECT);
RNA_def_property_ui_text(prop, "Occlude Geometry", "Limit selection to visible (clipped with depth buffer)");
@@ -2201,13 +2200,20 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "persmat");
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* XXX: for now, it's too risky for users to do this */
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
- RNA_def_property_ui_text(prop, "Perspective Matrix", "Current perspective matrix of the 3D region");
+ RNA_def_property_ui_text(prop, "Perspective Matrix",
+ "Current perspective matrix (``window_matrix * view_matrix``)");
+
+ prop = RNA_def_property(srna, "window_matrix", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_float_sdna(prop, NULL, "winmat");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(prop, "Window Matrix", "Current window matrix");
prop = RNA_def_property(srna, "view_matrix", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "viewmat");
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_float_funcs(prop, NULL, "rna_RegionView3D_view_matrix_set", NULL);
- RNA_def_property_ui_text(prop, "View Matrix", "Current view matrix of the 3D region");
+ RNA_def_property_ui_text(prop, "View Matrix", "Current view matrix");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "view_perspective", PROP_ENUM, PROP_NONE);
@@ -2425,8 +2431,8 @@ static void rna_def_space_image(BlenderRNA *brna)
/* grease pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this space");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
@@ -2509,6 +2515,16 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem waveform_type_draw_items[] = {
+ {SEQ_NO_WAVEFORMS, "NO_WAVEFORMS", 0, "Waveforms Off",
+ "No waveforms drawn for any sound strips"},
+ {SEQ_ALL_WAVEFORMS, "ALL_WAVEFORMS", 0, "Waveforms On",
+ "Waveforms drawn for all sound strips"},
+ {0, "DEFAULT_WAVEFORMS", 0, "Use Strip Option",
+ "Waveforms drawn according to strip setting"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "SpaceSequenceEditor", "Space");
RNA_def_struct_sdna(srna, "SpaceSeq");
RNA_def_struct_ui_text(srna, "Space Sequence Editor", "Sequence editor space data");
@@ -2578,6 +2594,12 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Channels", "Channels of the preview to draw");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+ prop = RNA_def_property(srna, "waveform_draw_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
+ RNA_def_property_enum_items(prop, waveform_type_draw_items);
+ RNA_def_property_ui_text(prop, "Waveform Drawing", "How Waveforms are drawn");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
prop = RNA_def_property(srna, "draw_overexposed", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "zebra");
RNA_def_property_ui_text(prop, "Show Overexposed", "Show overexposed areas with zebra stripes");
@@ -2594,8 +2616,8 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
/* grease pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this space");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
@@ -2604,6 +2626,16 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_enum_items(prop, overlay_type_items);
RNA_def_property_ui_text(prop, "Overlay Type", "Overlay draw type");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
+ prop = RNA_def_property(srna, "show_backdrop", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "draw_flag", SEQ_DRAW_BACKDROP);
+ RNA_def_property_ui_text(prop, "Use Backdrop", "Display result under strips");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
+ prop = RNA_def_property(srna, "show_strip_offset", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "draw_flag", SEQ_DRAW_OFFSET_EXT);
+ RNA_def_property_ui_text(prop, "Show Offsets", "Display strip in/out offsets");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
}
static void rna_def_space_text(BlenderRNA *brna)
@@ -2716,6 +2748,8 @@ static void rna_def_space_text(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "replacestr");
RNA_def_property_ui_text(prop, "Replace Text", "Text to replace selected text with using the replace tool");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL);
+
+ RNA_api_space_text(srna);
}
static void rna_def_space_dopesheet(BlenderRNA *brna)
@@ -2935,14 +2969,12 @@ static void rna_def_space_graph(BlenderRNA *brna)
RNA_def_property_enum_items(prop, autosnap_items);
RNA_def_property_ui_text(prop, "Auto Snap", "Automatic time snapping settings for transformations");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
/* readonly state info */
prop = RNA_def_property(srna, "has_ghost_curves", PROP_BOOLEAN, PROP_NONE);
- /* XXX: hack to make this compile, since this property doesn't actually exist*/
- RNA_def_property_boolean_sdna(prop, NULL, "flag", 0);
RNA_def_property_boolean_funcs(prop, "rna_SpaceGraphEditor_has_ghost_curves_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Has Ghost Curves", "Graph Editor instance has some ghost curves stored");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
/* nromalize curves */
prop = RNA_def_property(srna, "use_normalization", PROP_BOOLEAN, PROP_NONE);
@@ -3078,7 +3110,6 @@ static void rna_def_console_line(BlenderRNA *brna)
srna = RNA_def_struct(brna, "ConsoleLine", NULL);
RNA_def_struct_ui_text(srna, "Console Input", "Input line for the interactive console");
- /* XXX using non-inited "prop", uh? RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CONSOLE, NULL); */
prop = RNA_def_property(srna, "body", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_ConsoleLine_body_get", "rna_ConsoleLine_body_length",
@@ -3203,55 +3234,55 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_image", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", IMAGEFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_IMAGE);
RNA_def_property_ui_text(prop, "Filter Images", "Show image files");
RNA_def_property_ui_icon(prop, ICON_FILE_IMAGE, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_blender", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", BLENDERFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_BLENDER);
RNA_def_property_ui_text(prop, "Filter Blender", "Show .blend files");
RNA_def_property_ui_icon(prop, ICON_FILE_BLEND, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_backup", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", BLENDERFILE_BACKUP);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_BLENDER_BACKUP);
RNA_def_property_ui_text(prop, "Filter BlenderBackup files", "Show .blend1, .blend2, etc. files");
RNA_def_property_ui_icon(prop, ICON_FILE_BACKUP, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_movie", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", MOVIEFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_MOVIE);
RNA_def_property_ui_text(prop, "Filter Movies", "Show movie files");
RNA_def_property_ui_icon(prop, ICON_FILE_MOVIE, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_script", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", PYSCRIPTFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_PYSCRIPT);
RNA_def_property_ui_text(prop, "Filter Script", "Show script files");
RNA_def_property_ui_icon(prop, ICON_FILE_SCRIPT, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_font", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", FTFONTFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_FTFONT);
RNA_def_property_ui_text(prop, "Filter Fonts", "Show font files");
RNA_def_property_ui_icon(prop, ICON_FILE_FONT, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_sound", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", SOUNDFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_SOUND);
RNA_def_property_ui_text(prop, "Filter Sound", "Show sound files");
RNA_def_property_ui_icon(prop, ICON_FILE_SOUND, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_text", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", TEXTFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_TEXT);
RNA_def_property_ui_text(prop, "Filter Text", "Show text files");
RNA_def_property_ui_icon(prop, ICON_FILE_TEXT, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_folder", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter", FOLDERFILE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_FOLDER);
RNA_def_property_ui_text(prop, "Filter Folder", "Show folders");
RNA_def_property_ui_icon(prop, ICON_FILE_FOLDER, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
@@ -3261,6 +3292,11 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Extension Filter", "");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ prop = RNA_def_property(srna, "filter_search", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "filter_search");
+ RNA_def_property_ui_text(prop, "Name Filter", "Filter by name, supports '*' wildcard");
+ RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
static void rna_def_space_filebrowser(BlenderRNA *brna)
@@ -3345,6 +3381,7 @@ static void rna_def_space_userpref(BlenderRNA *brna)
prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "filter");
+ RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
RNA_def_property_ui_text(prop, "Filter", "Search term for filtering in the UI");
}
diff --git a/source/blender/makesrna/intern/rna_space_api.c b/source/blender/makesrna/intern/rna_space_api.c
index aed77378241..4114ee8a289 100644
--- a/source/blender/makesrna/intern/rna_space_api.c
+++ b/source/blender/makesrna/intern/rna_space_api.c
@@ -31,6 +31,8 @@
#ifdef RNA_RUNTIME
+#include "ED_text.h"
+
static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d)
{
bScreen *sc = (bScreen *)id;
@@ -49,6 +51,19 @@ static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d)
}
}
+static void rna_SpaceTextEditor_region_location_from_cursor(
+ ID *id, SpaceText *st,
+ int line, int column, int r_pixel_pos[2])
+{
+ bScreen *sc = (bScreen *)id;
+ ScrArea *sa = BKE_screen_find_area_from_space(sc, (SpaceLink *)st);
+ if (sa) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ const int cursor_co[2] = {line, column};
+ ED_text_region_location_from_cursor(st, ar, cursor_co, r_pixel_pos);
+ }
+}
+
#else
void RNA_api_region_view3d(StructRNA *srna)
@@ -74,4 +89,20 @@ void RNA_api_space_node(StructRNA *srna)
RNA_def_property_flag(parm, PROP_REQUIRED);
}
+void RNA_api_space_text(StructRNA *srna)
+{
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ func = RNA_def_function(srna, "region_location_from_cursor", "rna_SpaceTextEditor_region_location_from_cursor");
+ RNA_def_function_ui_description(func, "Retrieve the region position from the given line and character position");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ parm = RNA_def_int(func, "line", 0, INT_MIN, INT_MAX, "Line", "Line index", 0, INT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_int(func, "column", 0, INT_MIN, INT_MAX, "Column", "Column index", 0, INT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_int_array(func, "result", 2, 0, -1, INT_MAX, "", "Region coordinates", -1, INT_MAX);
+ RNA_def_function_output(func, parm);
+}
+
#endif
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index f098a659671..188a30d23ce 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -119,6 +119,7 @@ static EnumPropertyItem blend_type_items[] = {
#include "BKE_main.h"
#include "ED_node.h"
+#include "ED_render.h"
static StructRNA *rna_Texture_refine(struct PointerRNA *ptr)
{
@@ -443,8 +444,10 @@ static void rna_Envmap_source_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Tex *tex = ptr->id.data;
- if (tex->env)
+ if (tex->env) {
+ ED_preview_kill_jobs(bmain->wm.first, bmain);
BKE_free_envmapdata(tex->env);
+ }
rna_Texture_update(bmain, scene, ptr);
}
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index 899da62d9d3..5a70d47a19a 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -1435,8 +1435,8 @@ static void rna_def_trackingTrack(BlenderRNA *brna)
/* grease pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this track");
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 92c5530202b..a61846fa028 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -1062,6 +1062,7 @@ static void rna_def_uilist(BlenderRNA *brna)
prop = RNA_def_property(srna, "filter_name", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "filter_byname");
+ RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
RNA_def_property_ui_text(prop, "Filter by Name", "Only show items matching this name (use '*' as wildcard)");
prop = RNA_def_property(srna, "use_filter_invert", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 33c35313b38..4f889c91665 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -137,9 +137,7 @@ static void rna_uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const
/* Get translated name (label). */
name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate);
-
- /* XXX This will search property again :( */
- uiItemMenuEnumR(layout, ptr, propname, name, icon);
+ uiItemMenuEnumR_prop(layout, ptr, prop, name, icon);
}
static void rna_uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *value,
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index ab5039df627..fa0e1db10e2 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -35,6 +35,8 @@
#include "BLI_utildefines.h"
+#include "BKE_appdir.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_sound.h"
#include "BKE_addon.h"
@@ -48,6 +50,7 @@
#include "WM_types.h"
#include "BLF_translation.h"
+#include "GPU_buffers.h"
#ifdef WITH_CYCLES
static EnumPropertyItem compute_device_type_items[] = {
@@ -141,6 +144,15 @@ static void rna_userdef_language_update(Main *UNUSED(bmain), Scene *UNUSED(scene
UI_reinit_font();
}
+static void rna_userdef_vbo_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+{
+ Object *ob;
+
+ for (ob = bmain->object.first; ob; ob = ob->id.next) {
+ GPU_drawobject_free(ob->derivedFinal);
+ }
+}
+
static void rna_userdef_show_manipulator_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
UserDef *userdef = (UserDef *)ptr->data;
@@ -414,7 +426,7 @@ static void rna_userdef_pathcompare_remove(ReportList *reports, PointerRNA *path
static void rna_userdef_temp_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
- BLI_temp_dir_init(U.tempdir);
+ BKE_tempdir_init(U.tempdir);
}
static void rna_userdef_text_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
@@ -1031,10 +1043,10 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Icon Alpha", "Transparency of icons in the interface, to reduce contrast");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "emboss", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "emboss");
+ prop = RNA_def_property(srna, "widget_emboss", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "widget_emboss");
RNA_def_property_array(prop, 4);
- RNA_def_property_ui_text(prop, "Emboss", "");
+ RNA_def_property_ui_text(prop, "Widget Emboss", "Color of the 1px shadow line underlying widgets");
RNA_def_property_update(prop, 0, "rna_userdef_update");
/* axis */
@@ -1476,6 +1488,26 @@ static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs
}
}
+static void rna_def_userdef_theme_spaces_gpencil(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "gp_vertex", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Grease Pencil Vertex", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "gp_vertex_select", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Grease Pencil Vertex Select", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "gp_vertex_size", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, 10);
+ RNA_def_property_ui_text(prop, "Grease Pencil Vertex Size", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+}
+
static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1504,6 +1536,8 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Wire Edit", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ rna_def_userdef_theme_spaces_gpencil(srna);
prop = RNA_def_property(srna, "lamp", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 4);
@@ -2034,6 +2068,8 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
rna_def_userdef_theme_spaces_main(srna);
rna_def_userdef_theme_spaces_list_main(srna);
+
+ rna_def_userdef_theme_spaces_gpencil(srna);
prop = RNA_def_property(srna, "node_selected", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "select");
@@ -2238,6 +2274,18 @@ static void rna_def_userdef_theme_space_time(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "time_keyframe", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "time_keyframe");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Keyframe", "Base color for keyframe indicator lines");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "time_grease_pencil", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "time_gp_keyframe");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Grease Pencil", "Color of Grease Pencil keyframes");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
@@ -2253,8 +2301,10 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Theme Image Editor", "Theme settings for the Image Editor");
rna_def_userdef_theme_spaces_main(srna);
+ rna_def_userdef_theme_spaces_gpencil(srna);
rna_def_userdef_theme_spaces_vertex(srna);
rna_def_userdef_theme_spaces_face(srna);
+
prop = RNA_def_property(srna, "editmesh_active", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 4);
@@ -2349,6 +2399,7 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Theme Sequence Editor", "Theme settings for the Sequence Editor");
rna_def_userdef_theme_spaces_main(srna);
+ rna_def_userdef_theme_spaces_gpencil(srna);
prop = RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
@@ -2760,6 +2811,8 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
rna_def_userdef_theme_spaces_main(srna);
rna_def_userdef_theme_spaces_list_main(srna);
+
+ rna_def_userdef_theme_spaces_gpencil(srna);
prop = RNA_def_property(srna, "marker_outline", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "marker_outline");
@@ -3951,7 +4004,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "VBOs",
"Use Vertex Buffer Objects (or Vertex Arrays, if unsupported) for viewport rendering");
/* this isn't essential but nice to check if VBO draws any differently */
- RNA_def_property_update(prop, NC_WINDOW, NULL);
+ RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_vbo_update");
prop = RNA_def_property(srna, "anisotropic_filter", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "anisotropic_filter");
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index f63350ea0ae..721cbaf21c7 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -89,7 +89,7 @@ static void rna_World_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
World *wo = ptr->id.data;
DAG_id_tag_update(&wo->id, 0);
- WM_main_add_notifier(NC_WORLD, wo);
+ WM_main_add_notifier(NC_WORLD | ND_WORLD, wo);
}
static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index 58bd515efdb..876a95d8d8c 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -53,6 +53,7 @@ set(SRC
intern/MOD_cloth.c
intern/MOD_collision.c
intern/MOD_curve.c
+ intern/MOD_datatransfer.c
intern/MOD_decimate.c
intern/MOD_displace.c
intern/MOD_dynamicpaint.c
diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h
index 2e50c5a045e..8edcb7e0380 100644
--- a/source/blender/modifiers/MOD_modifiertypes.h
+++ b/source/blender/modifiers/MOD_modifiertypes.h
@@ -81,6 +81,7 @@ extern ModifierTypeInfo modifierType_UVWarp;
extern ModifierTypeInfo modifierType_MeshCache;
extern ModifierTypeInfo modifierType_LaplacianDeform;
extern ModifierTypeInfo modifierType_Wireframe;
+extern ModifierTypeInfo modifierType_DataTransfer;
extern ModifierTypeInfo modifierType_PointCache;
/* MOD_util.c */
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 6046de2cf61..b6d75afaf23 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -167,8 +167,8 @@ typedef struct SortVertsElem {
static int svert_sum_cmp(const void *e1, const void *e2)
{
- const SortVertsElem *sv1 = (SortVertsElem *)e1;
- const SortVertsElem *sv2 = (SortVertsElem *)e2;
+ const SortVertsElem *sv1 = e1;
+ const SortVertsElem *sv2 = e2;
if (sv1->sum_co > sv2->sum_co) return 1;
else if (sv1->sum_co < sv2->sum_co) return -1;
@@ -404,7 +404,7 @@ static DerivedMesh *arrayModifier_doArray(
int *full_doubles_map = NULL;
int tot_doubles;
- const bool use_merge = amd->flags & MOD_ARR_MERGE;
+ const bool use_merge = (amd->flags & MOD_ARR_MERGE) != 0;
const bool use_recalc_normals = (dm->dirty & DM_DIRTY_NORMALS) || use_merge;
const bool use_offset_ob = ((amd->offset_type & MOD_ARR_OFF_OBJ) && amd->offset_ob);
/* allow pole vertices to be used by many faces */
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 49c0c091dee..22636e7c4d0 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -39,8 +39,6 @@
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
-
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
@@ -49,8 +47,6 @@
#include "MOD_boolean_util.h"
#include "MOD_util.h"
-#include "PIL_time.h"
-
static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.c b/source/blender/modifiers/intern/MOD_boolean_util.c
index 6e62a21ec4c..061b1198f7e 100644
--- a/source/blender/modifiers/intern/MOD_boolean_util.c
+++ b/source/blender/modifiers/intern/MOD_boolean_util.c
@@ -365,14 +365,6 @@ BLI_INLINE MPoly *which_mpoly(ExportMeshData *export_data, int which_mesh)
return mpoly;
}
-static void allocate_custom_layers(CustomData *data, int type, int num_elements, int num_layers)
-{
- int i;
- for (i = 0; i < num_layers; i++) {
- CustomData_add_layer(data, type, CD_DEFAULT, NULL, num_elements);
- }
-}
-
/* Create new external mesh */
static void exporter_InitGeomArrays(ExportMeshData *export_data,
int num_verts, int num_edges,
@@ -392,24 +384,15 @@ static void exporter_InitGeomArrays(ExportMeshData *export_data,
export_data->mloop = dm->getLoopArray(dm);
export_data->mpoly = dm->getPolyArray(dm);
- /* Allocate layers for UV layers and vertex colors.
- * Without this interpolation of those data will not happen.
- */
- allocate_custom_layers(&dm->loopData, CD_MLOOPCOL, num_loops,
- CustomData_number_of_layers(&dm_left->loopData, CD_MLOOPCOL));
- allocate_custom_layers(&dm->loopData, CD_MLOOPUV, num_loops,
- CustomData_number_of_layers(&dm_left->loopData, CD_MLOOPUV));
-
- allocate_custom_layers(&dm->loopData, CD_MLOOPCOL, num_loops,
- CustomData_number_of_layers(&dm_right->loopData, CD_MLOOPCOL));
- allocate_custom_layers(&dm->loopData, CD_MLOOPUV, num_loops,
- CustomData_number_of_layers(&dm_right->loopData, CD_MLOOPUV));
-
/* Merge custom data layers from operands.
*
* Will only create custom data layers for all the layers which appears in
* the operand. Data for those layers will not be allocated or initialized.
*/
+
+ CustomData_merge(&dm_left->loopData, &dm->loopData, merge_mask, CD_DEFAULT, num_loops);
+ CustomData_merge(&dm_right->loopData, &dm->loopData, merge_mask, CD_DEFAULT, num_loops);
+
CustomData_merge(&dm_left->polyData, &dm->polyData, merge_mask, CD_DEFAULT, num_polys);
CustomData_merge(&dm_right->polyData, &dm->polyData, merge_mask, CD_DEFAULT, num_polys);
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index f6ade2bf303..f30529bc40f 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -40,16 +40,16 @@
#include "BLI_math_vector.h"
#include "BLI_ghash.h"
-#include "DNA_scene_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_scene.h"
-#include "MOD_util.h"
+#ifdef _OPENMP
+# include "BKE_mesh.h" /* BKE_MESH_OMP_LIMIT */
+#endif
static void initData(ModifierData *md)
{
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index d2ac04d6f81..491b3deef01 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -32,7 +32,6 @@
* \ingroup modifiers
*/
-
#include "DNA_object_force.h"
#include "DNA_object_types.h"
#include "DNA_pointcache_types.h"
@@ -51,8 +50,6 @@
#include "BKE_pointcache.h"
#include "BKE_scene.h"
-#include "MOD_util.h"
-
static void initData(ModifierData *md)
{
CollisionModifierData *collmd = (CollisionModifierData *) md;
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index fbc72cef0e8..9c3ccf033a5 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -32,7 +32,6 @@
* \ingroup modifiers
*/
-
#include <string.h>
#include "DNA_scene_types.h"
@@ -47,7 +46,6 @@
#include "depsgraph_private.h"
-#include "MOD_util.h"
static void initData(ModifierData *md)
{
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
new file mode 100644
index 00000000000..2dca3218e41
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -0,0 +1,221 @@
+/*
+ * ***** 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.
+ *
+ * Contributor(s): None yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/modifiers/intern/MOD_datatransfer.c
+ * \ingroup modifiers
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_data_transfer.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_library.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h"
+#include "BKE_modifier.h"
+#include "BKE_report.h"
+
+#include "MEM_guardedalloc.h"
+#include "MOD_util.h"
+
+#include "depsgraph_private.h"
+
+/**************************************
+ * Modifiers functions. *
+ **************************************/
+static void initData(ModifierData *md)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ int i;
+
+ dtmd->ob_source = NULL;
+ dtmd->data_types = 0;
+
+ dtmd->vmap_mode = MREMAP_MODE_VERT_NEAREST;
+ dtmd->emap_mode = MREMAP_MODE_EDGE_NEAREST;
+ dtmd->lmap_mode = MREMAP_MODE_LOOP_NEAREST_POLYNOR;
+ dtmd->pmap_mode = MREMAP_MODE_POLY_NEAREST;
+
+ dtmd->map_max_distance = 1.0f;
+ dtmd->map_ray_radius = 0.0f;
+
+ for (i = 0; i < DT_MULTILAYER_INDEX_MAX; i++) {
+ dtmd->layers_select_src[i] = DT_LAYERS_ALL_SRC;
+ dtmd->layers_select_dst[i] = DT_LAYERS_NAME_DST;
+ }
+
+ dtmd->mix_mode = CDT_MIX_TRANSFER;
+ dtmd->mix_factor = 1.0f;
+ dtmd->defgrp_name[0] = '\0';
+
+ dtmd->flags = MOD_DATATRANSFER_OBSRC_TRANSFORM;
+}
+
+static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ CustomDataMask dataMask = 0;
+
+ if (dtmd->defgrp_name[0]) {
+ /* We need vertex groups! */
+ dataMask |= CD_MASK_MDEFORMVERT;
+ }
+
+ dataMask |= BKE_object_data_transfer_dttypes_to_cdmask(dtmd->data_types);
+
+ return dataMask;
+}
+
+static bool dependsOnNormals(ModifierData *md)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ int item_types = BKE_object_data_transfer_get_dttypes_item_types(dtmd->data_types);
+
+ if ((item_types & ME_VERT) && (dtmd->vmap_mode & (MREMAP_USE_NORPROJ | MREMAP_USE_NORMAL))) {
+ return true;
+ }
+ if ((item_types & ME_EDGE) && (dtmd->emap_mode & (MREMAP_USE_NORPROJ | MREMAP_USE_NORMAL))) {
+ return true;
+ }
+ if ((item_types & ME_LOOP) && (dtmd->lmap_mode & (MREMAP_USE_NORPROJ | MREMAP_USE_NORMAL))) {
+ return true;
+ }
+ if ((item_types & ME_POLY) && (dtmd->pmap_mode & (MREMAP_USE_NORPROJ | MREMAP_USE_NORMAL))) {
+ return true;
+ }
+
+ return false;
+}
+
+static void foreachObjectLink(ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ walk(userData, ob, &dtmd->ob_source);
+}
+
+static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
+{
+ foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
+ Object *UNUSED(ob), DagNode *obNode)
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ DagNode *curNode;
+
+ if (dtmd->ob_source) {
+ curNode = dag_get_node(forest, dtmd->ob_source);
+
+ dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
+ "DataTransfer Modifier");
+ }
+}
+
+static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ /* If no source object, bypass. */
+ return (dtmd->ob_source == NULL);
+}
+
+#define HIGH_POLY_WARNING 10000
+
+static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ ModifierApplyFlag UNUSED(flag))
+{
+ DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
+ DerivedMesh *dm = derivedData;
+ ReportList reports;
+
+ const bool invert_vgroup = (dtmd->flags & MOD_DATATRANSFER_INVERT_VGROUP) != 0;
+
+ const float max_dist = (dtmd->flags & MOD_DATATRANSFER_MAP_MAXDIST) ? dtmd->map_max_distance : FLT_MAX;
+
+ SpaceTransform space_transform_data;
+ SpaceTransform *space_transform = (dtmd->flags & MOD_DATATRANSFER_OBSRC_TRANSFORM) ? &space_transform_data : NULL;
+
+ if (space_transform) {
+ BLI_SPACE_TRANSFORM_SETUP(space_transform, ob, dtmd->ob_source);
+ }
+
+ BKE_reports_init(&reports, RPT_STORE);
+
+ /* Note: no islands precision for now here. */
+ BKE_object_data_transfer_dm(md->scene, dtmd->ob_source, ob, dm, dtmd->data_types, false,
+ dtmd->vmap_mode, dtmd->emap_mode, dtmd->lmap_mode, dtmd->pmap_mode,
+ space_transform, max_dist, dtmd->map_ray_radius, 0.0f,
+ dtmd->layers_select_src, dtmd->layers_select_dst,
+ dtmd->mix_mode, dtmd->mix_factor, dtmd->defgrp_name, invert_vgroup, &reports);
+
+ if (BKE_reports_contain(&reports, RPT_ERROR)) {
+ modifier_setError(md, "%s", BKE_reports_string(&reports, RPT_ERROR));
+ }
+ else if (dm->getNumVerts(dm) > HIGH_POLY_WARNING || ((Mesh *)(dtmd->ob_source->data))->totvert > HIGH_POLY_WARNING) {
+ modifier_setError(md, "You are using a rather high poly as source or destination, computation might be slow");
+ }
+
+ return dm;
+}
+
+
+ModifierTypeInfo modifierType_DataTransfer = {
+ /* name */ "DataTransfer",
+ /* structName */ "DataTransferModifierData",
+ /* structSize */ sizeof(DataTransferModifierData),
+ /* type */ eModifierTypeType_NonGeometrical,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_SupportsMapping |
+ eModifierTypeFlag_SupportsEditmode |
+ eModifierTypeFlag_UsesPreview,
+
+ /* copyData */ NULL,
+ /* deformVerts */ NULL,
+ /* deformMatrices */ NULL,
+ /* deformVertsEM */ NULL,
+ /* deformMatricesEM */ NULL,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ NULL,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ NULL,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ NULL,
+ /* dependsOnNormals */ dependsOnNormals,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ foreachIDLink,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
index b844b9e3bde..8a92deec8eb 100644
--- a/source/blender/modifiers/intern/MOD_decimate.c
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -35,17 +35,12 @@
#include "DNA_object_types.h"
#include "BLI_math.h"
-#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
-
#include "MEM_guardedalloc.h"
-#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
-#include "BKE_particle.h"
#include "BKE_cdderivedmesh.h"
#include "bmesh.h"
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index 838ceb5cfe0..5236365da70 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -28,7 +28,6 @@
#include <stddef.h>
#include "DNA_dynamicpaint_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -40,8 +39,6 @@
#include "depsgraph_private.h"
-#include "MOD_util.h"
-
static void initData(ModifierData *md)
{
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index d3c7e7d4779..32a6303d19d 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -54,7 +54,6 @@
#include "MEM_guardedalloc.h"
-#include "MOD_util.h"
static void initData(ModifierData *md)
{
@@ -892,7 +891,7 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
/* get particle */
pa = pars + ed_v2;
- psys_get_birth_coordinates(&sim, pa, &birth, 0, 0);
+ psys_get_birth_coords(&sim, pa, &birth, 0, 0);
state.time = cfra;
psys_get_particle_state(&sim, ed_v2, &state, 1);
diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c
index d3c56b8d7f7..9c973cd0d50 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim.c
@@ -45,7 +45,6 @@
#include "depsgraph_private.h"
-#include "MOD_util.h"
#include "MOD_fluidsim_util.h"
#include "MEM_guardedalloc.h"
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index ffadcda3e8c..a4f6d005d94 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -767,7 +767,7 @@ static void LaplacianDeformModifier_do(
LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
- (void)lmd, (void)ob, (void)dm, (void)vertexCos, (void)numVerts;
+ UNUSED_VARS(lmd, ob, dm, vertexCos, numVerts);
}
#endif /* WITH_OPENNL */
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index 9ba0bfc7ce9..6f33bfa73fc 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -41,7 +41,6 @@
#include "BKE_deform.h"
#include "BKE_modifier.h"
-#include "MOD_modifiertypes.h"
#include "MOD_util.h"
#ifdef WITH_OPENNL
@@ -613,7 +612,7 @@ static void laplaciansmoothModifier_do(
LaplacianSmoothModifierData *smd, Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
- (void)smd, (void)ob, (void)dm, (void)vertexCos, (void)numVerts;
+ UNUSED_VARS(smd, ob, dm, vertexCos, numVerts);
}
#endif /* WITH_OPENNL */
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index e4a359a93e2..86687865d02 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -38,7 +38,6 @@
#include "DNA_object_types.h"
#include "BLI_utildefines.h"
-#include "BLI_string.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_lattice.h"
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index 5cb9feb4fac..254ca0bda08 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -51,8 +51,6 @@
#include "depsgraph_private.h"
-#include "MOD_util.h"
-
static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c
index 925d9691892..db50d49f790 100644
--- a/source/blender/modifiers/intern/MOD_meshcache.c
+++ b/source/blender/modifiers/intern/MOD_meshcache.c
@@ -48,8 +48,6 @@
#include "MOD_modifiertypes.h"
-#include "MOD_util.h"
-
static void initData(ModifierData *md)
{
MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md;
diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
index 3ef0ee54886..679bdcd1d47 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_pc2.c
+++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
@@ -31,7 +31,6 @@
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
#include "BLI_fileops.h"
-#include "BLI_math.h"
#ifdef __BIG_ENDIAN__
# include "BLI_endian_switch.h"
#endif
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index c253c0314ad..584b5b5fc76 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -40,8 +40,6 @@
#include "BLI_task.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
-
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
#include "BKE_modifier.h"
@@ -84,9 +82,16 @@ static void copyData(ModifierData *md, ModifierData *target)
MeshDeformModifierData *mmd = (MeshDeformModifierData *) md;
MeshDeformModifierData *tmmd = (MeshDeformModifierData *) target;
- tmmd->gridsize = mmd->gridsize;
- tmmd->flag = mmd->flag;
- tmmd->object = mmd->object;
+ *tmmd = *mmd;
+
+ if (mmd->bindinfluences) tmmd->bindinfluences = MEM_dupallocN(mmd->bindinfluences);
+ if (mmd->bindoffsets) tmmd->bindoffsets = MEM_dupallocN(mmd->bindoffsets);
+ if (mmd->bindcagecos) tmmd->bindcagecos = MEM_dupallocN(mmd->bindcagecos);
+ if (mmd->dyngrid) tmmd->dyngrid = MEM_dupallocN(mmd->dyngrid);
+ if (mmd->dyninfluences) tmmd->dyninfluences = MEM_dupallocN(mmd->dyninfluences);
+ if (mmd->dynverts) tmmd->dynverts = MEM_dupallocN(mmd->dynverts);
+ if (mmd->bindweights) tmmd->dynverts = MEM_dupallocN(mmd->bindweights); /* deprecated */
+ if (mmd->bindcos) tmmd->dynverts = MEM_dupallocN(mmd->bindcos); /* deprecated */
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 5de4a76dcbe..7a7308639f5 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -42,8 +42,6 @@
#include "BKE_modifier.h"
#include "BKE_deform.h"
-#include "bmesh.h"
-
#include "MEM_guardedalloc.h"
#include "depsgraph_private.h"
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index deae10b5bcb..4754813a744 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -44,11 +44,8 @@
#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "BKE_modifier.h"
-#include "BKE_paint.h"
#include "BKE_subsurf.h"
-#include "MOD_util.h"
-
static void initData(ModifierData *md)
{
MultiresModifierData *mmd = (MultiresModifierData *)md;
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index a324702a6ae..1c8dcdff46d 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -43,8 +43,6 @@
#include "BKE_modifier.h"
#include "BKE_ocean.h"
-#include "MOD_util.h"
-
#ifdef WITH_OCEANSIM
static void init_cache_data(Object *ob, struct OceanModifierData *omd)
{
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 3ca791b7664..56197bfcca8 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -48,8 +48,6 @@
#include "BKE_particle.h"
#include "BKE_pointcache.h"
-#include "MOD_util.h"
-
#include "depsgraph_private.h"
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index 45725d1c453..f3327a03f2c 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -44,7 +44,7 @@
#include "MOD_modifiertypes.h"
-static void deformVerts(ModifierData *md, Object *ob,
+static void deformVerts(ModifierData *UNUSED(md), Object *ob,
DerivedMesh *UNUSED(derivedData),
float (*vertexCos)[3],
int numVerts,
@@ -54,8 +54,9 @@ static void deformVerts(ModifierData *md, Object *ob,
if (key && key->block.first) {
int deformedVerts_tot;
- BKE_key_evaluate_object_ex(md->scene, ob, &deformedVerts_tot,
- (float *)vertexCos, sizeof(*vertexCos) * numVerts);
+ BKE_key_evaluate_object_ex(
+ ob, &deformedVerts_tot,
+ (float *)vertexCos, sizeof(*vertexCos) * numVerts);
}
}
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index 229f4911ab4..302013b9b07 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -38,7 +38,6 @@
#include "DNA_object_types.h"
#include "BLI_math.h"
-#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 3314196b776..19761c43cf0 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -244,8 +244,6 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
}
-
-
/* SimpleDeform */
static void initData(ModifierData *md)
{
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index d43fa11cfb9..2bde963029a 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -79,8 +79,6 @@
#include "bmesh.h"
-#include "MOD_util.h"
-
typedef struct {
float mat[3][3];
/* Vert that edge is pointing away from, no relation to
@@ -328,8 +326,7 @@ static bool build_hull(SkinOutput *so, Frame **frames, int totframe)
return true;
#else
- (void)so, (void)frames, (void)totframe;
- (void)skin_frame_find_contained_faces;
+ UNUSED_VARS(so, frames, totframe, skin_frame_find_contained_faces);
return false;
#endif
}
@@ -1117,7 +1114,7 @@ static BMFace *collapse_face_corners(BMesh *bm, BMFace *f, int n,
orig_verts[i] = NULL;
}
else if (orig_verts[i] &&
- !BM_vert_in_face(vf, orig_verts[i]))
+ !BM_vert_in_face(orig_verts[i], vf))
{
wrong_face = true;
break;
diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c
index fcd4cc96410..f260c0491ee 100644
--- a/source/blender/modifiers/intern/MOD_smoke.c
+++ b/source/blender/modifiers/intern/MOD_smoke.c
@@ -52,9 +52,6 @@
#include "depsgraph_private.h"
-#include "MOD_util.h"
-
-
static void initData(ModifierData *md)
{
SmokeModifierData *smd = (SmokeModifierData *) md;
diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c
index 4cae3d662db..592ab4194ec 100644
--- a/source/blender/modifiers/intern/MOD_triangulate.c
+++ b/source/blender/modifiers/intern/MOD_triangulate.c
@@ -31,7 +31,6 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
-#include "BKE_editmesh.h"
#include "bmesh.h"
#include "bmesh_tools.h"
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index bbc5e28ddf3..228c42e526c 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -32,7 +32,6 @@
#include <string.h>
-#include "DNA_curve_types.h"
#include "DNA_image_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@@ -48,8 +47,6 @@
#include "BKE_image.h"
#include "BKE_lattice.h"
#include "BKE_mesh.h"
-#include "BKE_displist.h"
-#include "BKE_scene.h"
#include "BKE_modifier.h"
@@ -58,8 +55,6 @@
#include "MEM_guardedalloc.h"
-#include "RE_shader_ext.h"
-
#ifdef OPENNL_THREADING_HACK
#include "BLI_threads.h"
#endif
@@ -309,6 +304,7 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(MeshCache);
INIT_TYPE(LaplacianDeform);
INIT_TYPE(Wireframe);
+ INIT_TYPE(DataTransfer);
INIT_TYPE(PointCache);
#undef INIT_TYPE
}
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 2ff93efdb86..75a074a245a 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -49,7 +49,6 @@
#include "BKE_DerivedMesh.h"
#include "MOD_modifiertypes.h"
-#include "MOD_util.h"
#include "MEM_guardedalloc.h"
#include "depsgraph_private.h"
diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c
index 744b6b62c2a..c9de1dc083d 100644
--- a/source/blender/modifiers/intern/MOD_weightvg_util.c
+++ b/source/blender/modifiers/intern/MOD_weightvg_util.c
@@ -34,7 +34,6 @@
#include "BLI_utildefines.h"
#include "DNA_color_types.h" /* CurveMapping. */
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
@@ -43,11 +42,9 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_colortools.h" /* CurveMapping. */
#include "BKE_deform.h"
-#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_texture.h" /* Texture masking. */
-#include "depsgraph_private.h"
#include "MEM_guardedalloc.h"
#include "MOD_util.h"
#include "MOD_weightvg_util.h"
@@ -235,8 +232,6 @@ void weightvg_do_mask(int num, const int *indices, float *org_w, const float *ne
}
-
-
/* Applies weights to given vgroup (defgroup), and optionally add/remove vertices from the group.
* If dws is not NULL, it must be an array of MDeformWeight pointers of same length as weights (and
* defgrp_idx can then have any value).
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index f36abcceae0..5a6e958457e 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -34,7 +34,6 @@
#include "BLI_rand.h"
#include "DNA_color_types.h" /* CurveMapping. */
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
@@ -48,7 +47,6 @@
#include "depsgraph_private.h"
#include "MEM_guardedalloc.h"
-#include "MOD_util.h"
#include "MOD_weightvg_util.h"
/**************************************
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index bdc1099d682..099d4c7116e 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -44,7 +44,6 @@
#include "depsgraph_private.h"
#include "MEM_guardedalloc.h"
-#include "MOD_util.h"
#include "MOD_weightvg_util.h"
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 71d4742980e..766ffe529ab 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -47,7 +47,6 @@
#include "depsgraph_private.h"
#include "MEM_guardedalloc.h"
-#include "MOD_util.h"
#include "MOD_weightvg_util.h"
// #define USE_TIMEIT
diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c
index 7349ca9f9ef..8b611f9e6da 100644
--- a/source/blender/modifiers/intern/MOD_wireframe.c
+++ b/source/blender/modifiers/intern/MOD_wireframe.c
@@ -23,20 +23,14 @@
* \ingroup modifiers
*/
-#include "MEM_guardedalloc.h"
-
#include "DNA_object_types.h"
-#include "DNA_meshdata_types.h"
-#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_string.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_deform.h"
#include "MOD_modifiertypes.h"
-#include "MOD_util.h"
#include "bmesh.h"
#include "tools/bmesh_wireframe.h"
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index 6d5b85da569..e616680647e 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -36,11 +36,8 @@
#include "DNA_scene_types.h"
#include "DNA_node_types.h"
-#include "BLI_listbase.h"
-
#include "BLF_translation.h"
-#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -50,8 +47,6 @@
#include "node_common.h"
#include "node_util.h"
-#include "PIL_time.h"
-
#include "RNA_access.h"
#include "NOD_composite.h"
@@ -236,11 +231,10 @@ void ntreeCompositExecTree(Scene *scene, bNodeTree *ntree, RenderData *rd, int r
#ifdef WITH_COMPOSITOR
COM_execute(rd, scene, ntree, rendering, view_settings, display_settings);
#else
- (void)scene, (void)ntree, (void)rd, (void)rendering, (void)do_preview;
- (void)view_settings, (void)display_settings;
+ UNUSED_VARS(scene, ntree, rd, rendering, view_settings, display_settings);
#endif
- (void)do_preview;
+ UNUSED_VARS(do_preview);
}
/* *********************************************** */
diff --git a/source/blender/nodes/composite/nodes/node_composite_boxmask.c b/source/blender/nodes/composite/nodes/node_composite_boxmask.c
index 9cb0f1c75c7..0390eb43da0 100644
--- a/source/blender/nodes/composite/nodes/node_composite_boxmask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_boxmask.c
@@ -66,7 +66,3 @@ void register_node_type_cmp_boxmask(void)
nodeRegisterType(&ntype);
}
-
-
-
-
diff --git a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c
index 65f2391983e..70e52d432cd 100644
--- a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c
+++ b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c
@@ -29,11 +29,8 @@
* \ingroup cmpnodes
*/
-
-
#include "node_composite_util.h"
-
/* ******************* Color Balance ********************************* */
static bNodeSocketTemplate cmp_node_colorbalance_in[] = {
{SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR},
diff --git a/source/blender/nodes/composite/nodes/node_composite_common.c b/source/blender/nodes/composite/nodes/node_composite_common.c
index 36c12693bdf..75e7fa8fbac 100644
--- a/source/blender/nodes/composite/nodes/node_composite_common.c
+++ b/source/blender/nodes/composite/nodes/node_composite_common.c
@@ -35,7 +35,6 @@
#include "node_composite_util.h"
#include "NOD_common.h"
#include "node_common.h"
-#include "node_exec.h"
#include "BKE_node.h"
diff --git a/source/blender/nodes/composite/nodes/node_composite_composite.c b/source/blender/nodes/composite/nodes/node_composite_composite.c
index 41d417c2cb4..be9ed457150 100644
--- a/source/blender/nodes/composite/nodes/node_composite_composite.c
+++ b/source/blender/nodes/composite/nodes/node_composite_composite.c
@@ -31,10 +31,6 @@
#include "node_composite_util.h"
-#include "BKE_context.h"
-
-#include "RNA_access.h"
-
/* **************** COMPOSITE ******************** */
static bNodeSocketTemplate cmp_node_composite_in[] = {
{ SOCK_RGBA, 1, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f},
diff --git a/source/blender/nodes/composite/nodes/node_composite_defocus.c b/source/blender/nodes/composite/nodes/node_composite_defocus.c
index ef670b760c2..a3311755717 100644
--- a/source/blender/nodes/composite/nodes/node_composite_defocus.c
+++ b/source/blender/nodes/composite/nodes/node_composite_defocus.c
@@ -33,10 +33,6 @@
#include <limits.h>
-#include "BKE_context.h"
-
-#include "RNA_access.h"
-
/* ************ qdn: Defocus node ****************** */
static bNodeSocketTemplate cmp_node_defocus_in[] = {
{ SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f},
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index 659e582dc1d..ecc02e732ce 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -39,8 +39,6 @@
#include "BKE_global.h"
#include "BKE_main.h"
-#include "RNA_access.h"
-
/* **************** IMAGE (and RenderResult, multilayer image) ******************** */
static bNodeSocketTemplate cmp_node_rlayers_out[] = {
diff --git a/source/blender/nodes/composite/nodes/node_composite_keying.c b/source/blender/nodes/composite/nodes/node_composite_keying.c
index 6b5def1ea93..ba179bcbcd3 100644
--- a/source/blender/nodes/composite/nodes/node_composite_keying.c
+++ b/source/blender/nodes/composite/nodes/node_composite_keying.c
@@ -34,12 +34,8 @@
#include "DNA_movieclip_types.h"
-#include "BKE_movieclip.h"
-
-#include "BLI_listbase.h"
#include "BLI_math_base.h"
#include "BLI_math_color.h"
-#include "BLI_voronoi.h"
#include "node_composite_util.h"
diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
index 9965b55e088..0cdf15c0412 100644
--- a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
+++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
@@ -30,16 +30,10 @@
* \ingroup cmpnodes
*/
-#include "BLF_translation.h"
-
#include "DNA_movieclip_types.h"
-#include "BKE_movieclip.h"
-
-#include "BLI_listbase.h"
#include "BLI_math_base.h"
#include "BLI_math_color.h"
-#include "BLI_voronoi.h"
#include "node_composite_util.h"
diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c
index 83cea47db1b..dd05d5d83ad 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mask.c
@@ -30,12 +30,8 @@
* \ingroup cmpnodes
*/
-#include "BLF_translation.h"
-
#include "DNA_mask_types.h"
-#include "BKE_mask.h"
-
#include "node_composite_util.h"
/* **************** Translate ******************** */
diff --git a/source/blender/nodes/composite/nodes/node_composite_movieclip.c b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
index fc0d8060644..0fece9dd4f6 100644
--- a/source/blender/nodes/composite/nodes/node_composite_movieclip.c
+++ b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
@@ -30,13 +30,10 @@
* \ingroup cmpnodes
*/
-
#include "node_composite_util.h"
#include "BKE_context.h"
-#include "RNA_access.h"
-
static bNodeSocketTemplate cmp_node_movieclip_out[] = {
{ SOCK_RGBA, 0, N_("Image")},
{ SOCK_FLOAT, 0, N_("Alpha")},
diff --git a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
index 1d411aafe68..9c54009d2f1 100644
--- a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
+++ b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
@@ -34,8 +34,6 @@
#include "BKE_context.h"
-#include "RNA_access.h"
-
/* **************** Translate ******************** */
static bNodeSocketTemplate cmp_node_moviedistortion_in[] = {
diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
index 57c39b082b4..8e602c6179c 100644
--- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c
+++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
@@ -40,9 +40,6 @@
#include "node_composite_util.h"
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-
#include "intern/openexr/openexr_multi.h"
diff --git a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
index 28e2a2a205b..00791c278ae 100644
--- a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
+++ b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
@@ -30,13 +30,10 @@
* \ingroup cmpnodes
*/
-
#include "node_composite_util.h"
#include "BKE_context.h"
-#include "RNA_access.h"
-
/* **************** Translate ******************** */
static bNodeSocketTemplate cmp_node_stabilize2d_in[] = {
diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c
index c58c9c902ec..0e250dc3aa4 100644
--- a/source/blender/nodes/intern/node_common.c
+++ b/source/blender/nodes/intern/node_common.c
@@ -29,7 +29,6 @@
* \ingroup nodes
*/
-
#include <string.h>
#include <stddef.h>
@@ -43,15 +42,12 @@
#include "BKE_node.h"
-#include "RNA_access.h"
#include "RNA_types.h"
#include "MEM_guardedalloc.h"
#include "node_common.h"
#include "node_util.h"
-#include "node_exec.h"
-#include "NOD_socket.h"
#include "NOD_common.h"
diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c
index 2ac1a2c85f3..282567b797f 100644
--- a/source/blender/nodes/intern/node_socket.c
+++ b/source/blender/nodes/intern/node_socket.c
@@ -41,7 +41,6 @@
#include "BKE_node.h"
#include "RNA_access.h"
-#include "RNA_define.h"
#include "RNA_types.h"
#include "MEM_guardedalloc.h"
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index bea1d0532e8..f18ee1d649f 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -41,16 +41,13 @@
#include "DNA_linestyle_types.h"
#include "BLI_listbase.h"
-#include "BLI_math.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BLF_translation.h"
#include "BKE_context.h"
-#include "BKE_global.h"
#include "BKE_linestyle.h"
-#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_scene.h"
diff --git a/source/blender/nodes/shader/nodes/node_shader_background.c b/source/blender/nodes/shader/nodes/node_shader_background.c
index 2478fb4d38c..b387529e456 100644
--- a/source/blender/nodes/shader/nodes/node_shader_background.c
+++ b/source/blender/nodes/shader/nodes/node_shader_background.c
@@ -40,6 +40,11 @@ static bNodeSocketTemplate sh_node_background_out[] = {
{ -1, 0, "" }
};
+static int node_shader_gpu_background(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "node_background", in, out, GPU_builtin(GPU_VIEW_NORMAL));
+}
+
/* node type definition */
void register_node_type_sh_background(void)
{
@@ -50,6 +55,7 @@ void register_node_type_sh_background(void)
node_type_socket_templates(&ntype, sh_node_background_in, sh_node_background_out);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_background);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c
index 3ce01ce03bf..de152ee45d1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bump.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bump.c
@@ -29,11 +29,8 @@
* \ingroup shdnodes
*/
-
-
#include "node_shader_util.h"
-
/* **************** BUMP ******************** */
static bNodeSocketTemplate sh_node_bump_in[] = {
{ SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c
index 9956fd712c8..503fe034754 100644
--- a/source/blender/nodes/shader/nodes/node_shader_gamma.c
+++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c
@@ -41,6 +41,18 @@ static bNodeSocketTemplate sh_node_gamma_out[] = {
{ -1, 0, "" }
};
+static void node_shader_exec_gamma(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
+{
+ float col[3];
+ float gamma;
+ nodestack_get_vec(col, SOCK_VECTOR, in[0]);
+ nodestack_get_vec(&gamma, SOCK_FLOAT, in[1]);
+
+ out[0]->vec[0] = col[0] > 0.0 ? pow(col[0], gamma) : col[0];
+ out[0]->vec[1] = col[1] > 0.0 ? pow(col[1], gamma) : col[1];
+ out[0]->vec[2] = col[2] > 0.0 ? pow(col[2], gamma) : col[2];
+}
+
static int node_shader_gpu_gamma(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_gamma", in, out);
@@ -51,10 +63,11 @@ void register_node_type_sh_gamma(void)
static bNodeType ntype;
sh_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, 0);
- node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_compatibility(&ntype, NODE_OLD_SHADING | NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_gamma_in, sh_node_gamma_out);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_gamma);
node_type_gpu(&ntype, node_shader_gpu_gamma);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c
index eb018e6c7eb..be2e3dcd311 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.c
+++ b/source/blender/nodes/shader/nodes/node_shader_math.c
@@ -233,7 +233,7 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(
static const char *names[] = {"math_add", "math_subtract", "math_multiply",
"math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin",
"math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max",
- "math_round", "math_less_than", "math_greater_than", "math_modulo", "math_absolute"};
+ "math_round", "math_less_than", "math_greater_than", "math_modulo", "math_abs"};
switch (node->custom1) {
case NODE_MATH_ADD:
@@ -256,6 +256,7 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(
case NODE_MATH_ACOS:
case NODE_MATH_ATAN:
case NODE_MATH_ROUND:
+ case NODE_MATH_ABS:
if (in[0].hasinput || !in[1].hasinput) {
/* use only first item and terminator */
GPUNodeStack tmp_in[2];
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.c
index fcd738f0b15..092fc201aa7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal.c
@@ -61,12 +61,12 @@ static void node_shader_exec_normal(void *UNUSED(data), int UNUSED(thread), bNod
static int gpu_shader_normal(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *vec = GPU_uniform(out[0].vec);
- int ret = GPU_stack_link(mat, "normal", in, out, vec);
- if (ret && GPU_material_use_new_shading_nodes(mat)) {
- float fac[3] = {1.0f, 0.0f, 0.0f};
- GPU_link(mat, "invert", GPU_uniform(fac), out[1].link, &out[1].link);
+ if (GPU_material_use_new_shading_nodes(mat)) {
+ return GPU_stack_link(mat, "normal_new_shading", in, out, vec);
+ }
+ else {
+ return GPU_stack_link(mat, "normal", in, out, vec);
}
- return ret;
}
void register_node_type_sh_normal(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_world.c b/source/blender/nodes/shader/nodes/node_shader_output_world.c
index c8e47c47c5f..ad7389fd56e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_world.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_world.c
@@ -35,6 +35,16 @@ static bNodeSocketTemplate sh_node_output_world_in[] = {
{ -1, 0, "" }
};
+static int node_shader_gpu_output_world(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ GPUNodeLink *outlink;
+
+ GPU_stack_link(mat, "node_output_world", in, out, &outlink);
+ GPU_material_output_link(mat, outlink);
+
+ return 1;
+}
+
/* node type definition */
void register_node_type_sh_output_world(void)
{
@@ -45,7 +55,8 @@ void register_node_type_sh_output_world(void)
node_type_socket_templates(&ntype, sh_node_output_world_in, NULL);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
-
+ node_type_gpu(&ntype, node_shader_gpu_output_world);
+
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);
diff --git a/source/blender/nodes/shader/nodes/node_shader_script.c b/source/blender/nodes/shader/nodes/node_shader_script.c
index d5ed38297da..f640dd5ea13 100644
--- a/source/blender/nodes/shader/nodes/node_shader_script.c
+++ b/source/blender/nodes/shader/nodes/node_shader_script.c
@@ -31,8 +31,6 @@
#include "node_shader_util.h"
-#include "BKE_idprop.h"
-
/* **************** Script ******************** */
static void init(bNodeTree *UNUSED(ntree), bNode *node)
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c
index 605a3b9faa3..6375dcc8782 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c
@@ -65,9 +65,9 @@ void register_node_type_sh_sepxyz(void)
/* **************** COMBINE XYZ ******************** */
static bNodeSocketTemplate sh_node_combxyz_in[] = {
- { SOCK_FLOAT, 1, N_("X"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_UNSIGNED},
- { SOCK_FLOAT, 1, N_("Y"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_UNSIGNED},
- { SOCK_FLOAT, 1, N_("Z"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_UNSIGNED},
+ { SOCK_FLOAT, 1, N_("X"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f},
+ { SOCK_FLOAT, 1, N_("Y"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f},
+ { SOCK_FLOAT, 1, N_("Z"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f},
{ -1, 0, "" }
};
static bNodeSocketTemplate sh_node_combxyz_out[] = {
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
index 781b1bb5a93..85eca6ae990 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
@@ -46,10 +46,18 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), bNod
{
GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, "");
-
- return GPU_stack_link(mat, "node_tex_coord", in, out,
- GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
- GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), orco, mtface);
+ GPUMatType type = GPU_Material_get_type(mat);
+
+ if (type == GPU_MATERIAL_TYPE_MESH) {
+ return GPU_stack_link(mat, "node_tex_coord", in, out,
+ GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
+ GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), orco, mtface);
+ }
+ else {
+ return GPU_stack_link(mat, "node_tex_coord_background", in, out,
+ GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
+ GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), orco, mtface);
+ }
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index dcb3ef3c8a0..8d6a77455bb 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -27,8 +27,6 @@
#include "../node_shader_util.h"
-#include "IMB_colormanagement.h"
-
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_tex_environment_in[] = {
@@ -67,13 +65,22 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeE
if (!ima)
return GPU_stack_link(mat, "node_tex_environment_empty", in, out);
- if (!in[0].link)
- in[0].link = GPU_builtin(GPU_VIEW_POSITION);
-
+ if (!in[0].link) {
+ GPUMatType type = GPU_Material_get_type(mat);
+
+ if (type == GPU_MATERIAL_TYPE_MESH)
+ in[0].link = GPU_builtin(GPU_VIEW_POSITION);
+ else
+ GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &in[0].link);
+ }
+
node_shader_gpu_tex_mapping(mat, node, in, out);
- ret = GPU_stack_link(mat, "node_tex_environment", in, out, GPU_image(ima, iuser, isdata));
-
+ if (tex->projection == SHD_PROJ_EQUIRECTANGULAR)
+ ret = GPU_stack_link(mat, "node_tex_environment_equirectangular", in, out, GPU_image(ima, iuser, isdata));
+ else
+ ret = GPU_stack_link(mat, "node_tex_environment_mirror_ball", in, out, GPU_image(ima, iuser, isdata));
+
if (ret) {
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index 0a11ee4a9b6..62db5b70891 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -27,8 +27,6 @@
#include "../node_shader_util.h"
-#include "IMB_colormanagement.h"
-
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_tex_image_in[] = {
diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c
index d02d72563ba..5cdbaf444f8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_texture.c
+++ b/source/blender/nodes/shader/nodes/node_shader_texture.c
@@ -29,11 +29,8 @@
* \ingroup shdnodes
*/
-
#include "DNA_texture_types.h"
-#include "IMB_colormanagement.h"
-
#include "node_shader_util.h"
/* **************** TEXTURE ******************** */
diff --git a/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c b/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c
index 48eb4cadba4..67342e1e836 100644
--- a/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c
+++ b/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c
@@ -27,8 +27,6 @@
#include "../node_shader_util.h"
-#include "DNA_customdata_types.h"
-
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_uvalongstroke_out[] = {
diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
index f2ea2faa5a7..9e75d915d44 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
@@ -29,11 +29,8 @@
* \ingroup shdnodes
*/
-
-
#include "node_shader_util.h"
-
/* **************** VECTOR MATH ******************** */
static bNodeSocketTemplate sh_node_vect_math_in[] = {
{ SOCK_VECTOR, 1, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index 1b790f87faf..79923c5f7d5 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -43,9 +43,7 @@
#include "BLF_translation.h"
#include "BKE_context.h"
-#include "BKE_global.h"
#include "BKE_linestyle.h"
-#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_paint.h"
@@ -57,7 +55,6 @@
#include "RNA_access.h"
-#include "RE_pipeline.h"
#include "RE_shader_ext.h"
diff --git a/source/blender/pointcache/util/util_path.cpp b/source/blender/pointcache/util/util_path.cpp
index 4605d25d24e..4d543fb87e6 100644
--- a/source/blender/pointcache/util/util_path.cpp
+++ b/source/blender/pointcache/util/util_path.cpp
@@ -27,6 +27,7 @@ extern "C" {
#include "DNA_ID.h"
#include "DNA_pointcache_types.h"
+#include "BKE_appdir.h"
#include "BKE_global.h"
#include "BKE_main.h"
}
@@ -58,7 +59,7 @@ static int ptc_path(char *filename, const char *path, ID *id, bool is_external,
else {
/* use the temp path. this is weak but better then not using point cache at all */
/* temporary directory is assumed to exist and ALWAYS has a trailing slash */
- BLI_snprintf(filename, FILE_MAX, "%s" PTC_DIRECTORY, BLI_temp_dir_session());
+ BLI_snprintf(filename, FILE_MAX, "%s" PTC_DIRECTORY, BKE_tempdir_session());
}
return BLI_add_slash(filename); /* new strlen() */
diff --git a/source/blender/python/bmesh/bmesh_py_ops.c b/source/blender/python/bmesh/bmesh_py_ops.c
index 4fc0160bbd6..ee96c859858 100644
--- a/source/blender/python/bmesh/bmesh_py_ops.c
+++ b/source/blender/python/bmesh/bmesh_py_ops.c
@@ -37,17 +37,12 @@
#include "MEM_guardedalloc.h"
-#include "../generic/py_capi_utils.h"
#include "bmesh.h"
#include "bmesh_py_ops_call.h"
#include "bmesh_py_ops.h" /* own include */
-#include "bmesh_py_types.h"
-
-#include "bmesh_py_utils.h"
-
/* bmesh operator 'bmesh.ops.*' callable types
* ******************************************* */
static PyTypeObject bmesh_op_Type;
diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c
index 2c07df98973..84c1031a24a 100644
--- a/source/blender/python/bmesh/bmesh_py_ops_call.c
+++ b/source/blender/python/bmesh/bmesh_py_ops_call.c
@@ -39,11 +39,11 @@
#include "bmesh.h"
-#include "bmesh_py_ops.h"
#include "bmesh_py_ops_call.h" /* own include */
#include "bmesh_py_types.h"
-#include "bmesh_py_utils.h"
+
+#include "../generic/python_utildefines.h"
static int bpy_bm_op_as_py_error(BMesh *bm)
{
@@ -542,20 +542,20 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
item = PyFloat_FromDouble((double)BMO_SLOT_AS_FLOAT(slot));
break;
case BMO_OP_SLOT_MAT:
- item = Matrix_CreatePyObject((float *)BMO_SLOT_AS_MATRIX(slot), 4, 4, Py_NEW, NULL);
+ item = Matrix_CreatePyObject((float *)BMO_SLOT_AS_MATRIX(slot), 4, 4, NULL);
break;
case BMO_OP_SLOT_VEC:
- item = Vector_CreatePyObject(BMO_SLOT_AS_VECTOR(slot), slot->len, Py_NEW, NULL);
+ item = Vector_CreatePyObject(BMO_SLOT_AS_VECTOR(slot), slot->len, NULL);
break;
case BMO_OP_SLOT_PTR:
BLI_assert(0); /* currently we don't have any pointer return values in use */
- item = (Py_INCREF(Py_None), Py_None);
+ item = Py_INCREF_RET(Py_None);
break;
case BMO_OP_SLOT_ELEMENT_BUF:
{
if (slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) {
BMHeader *ele = BMO_slot_buffer_get_single(slot);
- item = ele ? BPy_BMElem_CreatePyObject(bm, ele) : (Py_INCREF(Py_None), Py_None);
+ item = ele ? BPy_BMElem_CreatePyObject(bm, ele) : Py_INCREF_RET(Py_None);
}
else {
const int size = slot->len;
@@ -666,7 +666,7 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
}
case BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL:
/* can't convert from these */
- item = (Py_INCREF(Py_None), Py_None);
+ item = Py_INCREF_RET(Py_None);
break;
}
break;
@@ -745,7 +745,7 @@ PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw)
ret = NULL; /* exception raised above */
}
else if (bmop.slots_out[0].slot_name == NULL) {
- ret = (Py_INCREF(Py_None), Py_None);
+ ret = Py_INCREF_RET(Py_None);
}
else {
/* build return value */
@@ -761,7 +761,7 @@ PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw)
/* this function doesn't throw exceptions */
item = bpy_slot_to_py(bm, slot);
if (item == NULL) {
- item = (Py_INCREF(Py_None), Py_None);
+ item = Py_INCREF_RET(Py_None);
}
#if 1
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index 8c13a66bea0..1da5599ea29 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -44,6 +44,7 @@
#include "../mathutils/mathutils.h"
#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
#include "bmesh_py_types.h" /* own include */
#include "bmesh_py_types_select.h"
@@ -342,7 +343,7 @@ PyDoc_STRVAR(bpy_bmvert_co_doc,
static PyObject *bpy_bmvert_co_get(BPy_BMVert *self)
{
BPY_BM_CHECK_OBJ(self);
- return Vector_CreatePyObject(self->v->co, 3, Py_WRAP, NULL);
+ return Vector_CreatePyObject_wrap(self->v->co, 3, NULL);
}
static int bpy_bmvert_co_set(BPy_BMVert *self, PyObject *value)
@@ -364,7 +365,7 @@ PyDoc_STRVAR(bpy_bmvert_normal_doc,
static PyObject *bpy_bmvert_normal_get(BPy_BMVert *self)
{
BPY_BM_CHECK_OBJ(self);
- return Vector_CreatePyObject(self->v->no, 3, Py_WRAP, NULL);
+ return Vector_CreatePyObject_wrap(self->v->no, 3, NULL);
}
static int bpy_bmvert_normal_set(BPy_BMVert *self, PyObject *value)
@@ -468,7 +469,7 @@ PyDoc_STRVAR(bpy_bmface_normal_doc,
static PyObject *bpy_bmface_normal_get(BPy_BMFace *self)
{
BPY_BM_CHECK_OBJ(self);
- return Vector_CreatePyObject(self->f->no, 3, Py_WRAP, NULL);
+ return Vector_CreatePyObject_wrap(self->f->no, 3, NULL);
}
static int bpy_bmface_normal_set(BPy_BMFace *self, PyObject *value)
@@ -1530,7 +1531,7 @@ static PyObject *bpy_bmedge_calc_tangent(BPy_BMEdge *self, PyObject *args)
BPY_BM_CHECK_OBJ(py_loop);
/* no need to check if they are from the same mesh or even connected */
BM_edge_calc_face_tangent(self->e, py_loop->l, vec);
- return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec, 3, NULL);
}
}
@@ -1711,7 +1712,7 @@ static PyObject *bpy_bmface_calc_center_mean(BPy_BMFace *self)
BPY_BM_CHECK_OBJ(self);
BM_face_calc_center_mean(self->f, cent);
- return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(cent, 3, NULL);
}
PyDoc_STRVAR(bpy_bmface_calc_center_mean_weighted_doc,
@@ -1728,7 +1729,7 @@ static PyObject *bpy_bmface_calc_center_mean_weighted(BPy_BMFace *self)
BPY_BM_CHECK_OBJ(self);
BM_face_calc_center_mean_weighted(self->f, cent);
- return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(cent, 3, NULL);
}
PyDoc_STRVAR(bpy_bmface_calc_center_bounds_doc,
@@ -1745,7 +1746,7 @@ static PyObject *bpy_bmface_calc_center_bounds(BPy_BMFace *self)
BPY_BM_CHECK_OBJ(self);
BM_face_calc_center_bounds(self->f, cent);
- return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(cent, 3, NULL);
}
@@ -1849,7 +1850,7 @@ static PyObject *bpy_bmloop_calc_normal(BPy_BMLoop *self)
float vec[3];
BPY_BM_CHECK_OBJ(self);
BM_loop_calc_face_normal(self->l, vec);
- return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec, 3, NULL);
}
PyDoc_STRVAR(bpy_bmloop_calc_tangent_doc,
@@ -1866,7 +1867,7 @@ static PyObject *bpy_bmloop_calc_tangent(BPy_BMLoop *self)
float vec[3];
BPY_BM_CHECK_OBJ(self);
BM_loop_calc_face_tangent(self->l, vec);
- return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec, 3, NULL);
}
/* Vert Seq
@@ -2796,7 +2797,6 @@ static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t s
bool ok;
PyObject *list;
- PyObject *item;
BMHeader *ele;
BPY_BM_CHECK_OBJ(self);
@@ -2821,9 +2821,7 @@ static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t s
/* add items until stop */
while ((ele = BM_iter_step(&iter))) {
- item = BPy_BMElem_CreatePyObject(self->bm, ele);
- PyList_Append(list, item);
- Py_DECREF(item);
+ PyList_APPEND(list, BPy_BMElem_CreatePyObject(self->bm, ele));
count++;
if (count == stop) {
diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h
index a2c2c312e71..66059a642d1 100644
--- a/source/blender/python/bmesh/bmesh_py_types.h
+++ b/source/blender/python/bmesh/bmesh_py_types.h
@@ -198,16 +198,17 @@ int bpy_bm_generic_valid_check_source(BMesh *bm_source, const char *error_prefi
#define BPY_BM_IS_VALID(obj) (LIKELY((obj)->bm != NULL))
-#define BM_ITER_BPY_BM_SEQ(ele, iter, bpy_bmelemseq) \
- for (ele = BM_iter_new(iter, \
- (bpy_bmelemseq)->bm, \
- (bpy_bmelemseq)->itype, \
- (bpy_bmelemseq)->py_ele ? \
- ((BPy_BMElem *)(bpy_bmelemseq)->py_ele)->ele : \
- NULL \
- ); \
- ele; \
- ele = BM_iter_step(iter))
+#define BM_ITER_BPY_BM_SEQ(ele, iter, bpy_bmelemseq) \
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new( \
+ iter, \
+ (bpy_bmelemseq)->bm, \
+ (bpy_bmelemseq)->itype, \
+ (bpy_bmelemseq)->py_ele ? \
+ ((BPy_BMElem *)(bpy_bmelemseq)->py_ele)->ele : \
+ NULL \
+ ); \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
#ifdef __PY_CAPI_UTILS_H__
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c
index 6ecb01a8528..bfcd91ac72d 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c
@@ -42,6 +42,7 @@
#include "bmesh_py_types_meshdata.h"
#include "../mathutils/mathutils.h"
+#include "../generic/python_utildefines.h"
#include "BKE_customdata.h"
@@ -483,8 +484,9 @@ static PyObject *bpy_bmlayercollection_items(BPy_BMLayerCollection *self)
for (i = 0; tot-- > 0; index++) {
item = PyTuple_New(2);
- PyTuple_SET_ITEM(item, 0, PyUnicode_FromString(data->layers[index].name));
- PyTuple_SET_ITEM(item, 1, BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index));
+ PyTuple_SET_ITEMS(item,
+ PyUnicode_FromString(data->layers[index].name),
+ BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index));
PyList_SET_ITEM(ret, i++, item);
}
@@ -559,7 +561,7 @@ static PyObject *bpy_bmlayercollection_get(BPy_BMLayerCollection *self, PyObject
}
}
- return Py_INCREF(def), def;
+ return Py_INCREF_RET(def);
}
static struct PyMethodDef bpy_bmlayeritem_methods[] = {
@@ -1014,7 +1016,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
}
case CD_SHAPEKEY:
{
- ret = Vector_CreatePyObject((float *)value, 3, Py_WRAP, NULL);
+ ret = Vector_CreatePyObject_wrap((float *)value, 3, NULL);
break;
}
case CD_BWEIGHT:
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
index 3512dc76cef..94f38ffdec7 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
@@ -45,6 +45,8 @@
#include "bmesh_py_types_meshdata.h"
+#include "../generic/python_utildefines.h"
+
/* Mesh BMTexPoly
* ************** */
@@ -150,7 +152,7 @@ PyDoc_STRVAR(bpy_bmloopuv_uv_doc,
);
static PyObject *bpy_bmloopuv_uv_get(BPy_BMLoopUV *self, void *UNUSED(closure))
{
- return Vector_CreatePyObject(self->data->uv, 2, Py_WRAP, NULL);
+ return Vector_CreatePyObject_wrap(self->data->uv, 2, NULL);
}
static int bpy_bmloopuv_uv_set(BPy_BMLoopUV *self, PyObject *value, void *UNUSED(closure))
@@ -263,7 +265,7 @@ PyDoc_STRVAR(bpy_bmvertskin_radius_doc,
);
static PyObject *bpy_bmvertskin_radius_get(BPy_BMVertSkin *self, void *UNUSED(closure))
{
- return Vector_CreatePyObject(self->data->radius, 2, Py_WRAP, NULL);
+ return Vector_CreatePyObject_wrap(self->data->radius, 2, NULL);
}
static int bpy_bmvertskin_radius_set(BPy_BMVertSkin *self, PyObject *value, void *UNUSED(closure))
@@ -369,7 +371,7 @@ PyObject *BPy_BMVertSkin_CreatePyObject(struct MVertSkin *mvertskin)
static void mloopcol_to_float(const MLoopCol *mloopcol, float r_col[3])
{
- rgb_uchar_to_float(r_col, (unsigned char *)&mloopcol->r);
+ rgb_uchar_to_float(r_col, (const unsigned char *)&mloopcol->r);
}
static void mloopcol_from_float(MLoopCol *mloopcol, const float col[3])
@@ -684,10 +686,9 @@ static PyObject *bpy_bmdeformvert_items(BPy_BMDeformVert *self)
ret = PyList_New(self->data->totweight);
for (i = 0; i < self->data->totweight; i++, dw++) {
item = PyTuple_New(2);
-
- PyTuple_SET_ITEM(item, 0, PyLong_FromLong(dw->def_nr));
- PyTuple_SET_ITEM(item, 1, PyFloat_FromDouble(dw->weight));
-
+ PyTuple_SET_ITEMS(item,
+ PyLong_FromLong(dw->def_nr),
+ PyFloat_FromDouble(dw->weight));
PyList_SET_ITEM(ret, i, item);
}
@@ -721,7 +722,7 @@ static PyObject *bpy_bmdeformvert_get(BPy_BMDeformVert *self, PyObject *args)
return PyFloat_FromDouble(dw->weight);
}
else {
- return Py_INCREF(def), def;
+ return Py_INCREF_RET(def);
}
}
}
diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c
index 71ca8440962..7b792e9f08e 100644
--- a/source/blender/python/bmesh/bmesh_py_types_select.c
+++ b/source/blender/python/bmesh/bmesh_py_types_select.c
@@ -43,11 +43,8 @@
#include "bmesh_py_types.h"
#include "bmesh_py_types_select.h"
-
-
#include "../generic/py_capi_utils.h"
-
-#include "bmesh_py_api.h" /* own include */
+#include "../generic/python_utildefines.h"
PyDoc_STRVAR(bpy_bmeditselseq_active_doc,
"The last selected element or None (read-only).\n\n:type: :class:`BMVert`, :class:`BMEdge` or :class:`BMFace`"
@@ -197,7 +194,6 @@ static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, Py_ssi
bool ok;
PyObject *list;
- PyObject *item;
BMEditSelection *ese;
BPY_BM_CHECK_OBJ(self);
@@ -222,9 +218,7 @@ static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, Py_ssi
/* add items until stop */
while ((ese = ese->next)) {
- item = BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head);
- PyList_Append(list, item);
- Py_DECREF(item);
+ PyList_APPEND(list, BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head));
count++;
if (count == stop) {
diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c
index 7088036245a..0b667ab9029 100644
--- a/source/blender/python/bmesh/bmesh_py_utils.c
+++ b/source/blender/python/bmesh/bmesh_py_utils.c
@@ -42,6 +42,8 @@
#include "bmesh_py_types.h"
#include "bmesh_py_utils.h" /* own include */
+#include "../generic/python_utildefines.h"
+
PyDoc_STRVAR(bpy_bm_utils_vert_collapse_edge_doc,
".. method:: vert_collapse_edge(vert, edge)\n"
@@ -365,8 +367,9 @@ static PyObject *bpy_bm_utils_edge_split(PyObject *UNUSED(self), PyObject *args)
if (v_new && e_new) {
PyObject *ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, BPy_BMEdge_CreatePyObject(bm, e_new));
- PyTuple_SET_ITEM(ret, 1, BPy_BMVert_CreatePyObject(bm, v_new));
+ PyTuple_SET_ITEMS(ret,
+ BPy_BMEdge_CreatePyObject(bm, e_new),
+ BPy_BMVert_CreatePyObject(bm, v_new));
return ret;
}
else {
@@ -524,8 +527,9 @@ static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args,
if (f_new && l_new) {
PyObject *ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, BPy_BMFace_CreatePyObject(bm, f_new));
- PyTuple_SET_ITEM(ret, 1, BPy_BMLoop_CreatePyObject(bm, l_new));
+ PyTuple_SET_ITEMS(ret,
+ BPy_BMFace_CreatePyObject(bm, f_new),
+ BPy_BMLoop_CreatePyObject(bm, l_new));
return ret;
}
else {
diff --git a/source/blender/python/generic/blf_py_api.c b/source/blender/python/generic/blf_py_api.c
index 655542e320a..ed1ac7ceed9 100644
--- a/source/blender/python/generic/blf_py_api.c
+++ b/source/blender/python/generic/blf_py_api.c
@@ -33,6 +33,9 @@
#include "BLI_utildefines.h"
+#include "../generic/python_utildefines.h"
+
+
PyDoc_STRVAR(py_blf_position_doc,
".. function:: position(fontid, x, y, z)\n"
"\n"
@@ -183,8 +186,9 @@ static PyObject *py_blf_dimensions(PyObject *UNUSED(self), PyObject *args)
BLF_width_and_height(fontid, text, INT_MAX, &r_width, &r_height);
ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(r_width));
- PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(r_height));
+ PyTuple_SET_ITEMS(ret,
+ PyFloat_FromDouble(r_width),
+ PyFloat_FromDouble(r_height));
return ret;
}
diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c
index 2d19fdb87b3..b0539607bdc 100644
--- a/source/blender/python/generic/bpy_internal_import.c
+++ b/source/blender/python/generic/bpy_internal_import.c
@@ -265,7 +265,7 @@ PyObject *bpy_text_reimport(PyObject *module, int *found)
}
/* make into a module */
- return PyImport_ExecCodeModule((char *)name, text->compiled);
+ return PyImport_ExecCodeModule(name, text->compiled);
}
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index b6790de8ddf..1f35572a483 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -33,16 +33,17 @@
#include "idprop_py_api.h"
-
#include "BKE_idprop.h"
-
#define USE_STRING_COERCE
#ifdef USE_STRING_COERCE
#include "py_capi_utils.h"
#endif
+#include "../generic/python_utildefines.h"
+
+
/*********************** ID Property Main Wrapper Stuff ***************/
/* ----------------------------------------------------------------------------
@@ -296,10 +297,10 @@ static PyObject *BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item)
}
/* returns NULL on success, error string on failure */
-static int idp_sequence_type(PyObject *seq_fast)
+static char idp_sequence_type(PyObject *seq_fast)
{
PyObject *item;
- int type = IDP_INT;
+ char type = IDP_INT;
Py_ssize_t i, len = PySequence_Fast_GET_SIZE(seq_fast);
for (i = 0; i < len; i++) {
@@ -376,7 +377,7 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group,
else if (PyUnicode_Check(ob)) {
#ifdef USE_STRING_COERCE
PyObject *value_coerce = NULL;
- val.string.str = (char *)PyC_UnicodeAsByte(ob, &value_coerce);
+ val.string.str = PyC_UnicodeAsByte(ob, &value_coerce);
val.string.subtype = IDP_STRING_SUB_UTF8;
prop = IDP_New(IDP_STRING, &val, name);
Py_XDECREF(value_coerce);
@@ -403,7 +404,7 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group,
return false;
}
- if ((val.array.type = idp_sequence_type(ob_seq_fast)) == -1) {
+ if ((val.array.type = idp_sequence_type(ob_seq_fast)) == (char)-1) {
Py_DECREF(ob_seq_fast);
PyErr_SetString(PyExc_TypeError, "only floats, ints and dicts are allowed in ID property arrays");
return false;
@@ -512,7 +513,7 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group,
else {
IDProperty *prop_exist;
- /* avoid freeing when types match incase they are referenced by the UI, see: T37073
+ /* avoid freeing when types match in case they are referenced by the UI, see: T37073
* obviously this isn't a complete solution, but helps for common cases. */
prop_exist = IDP_GetPropertyFromGroup(group, prop->name);
if ((prop_exist != NULL) &&
@@ -746,10 +747,9 @@ static void BPy_IDGroup_CorrectListLen(IDProperty *prop, PyObject *seq, int len,
printf("%s: ID Property Error found and corrected!\n", func);
- /*fill rest of list with valid references to None*/
+ /* fill rest of list with valid references to None */
for (j = len; j < prop->len; j++) {
- Py_INCREF(Py_None);
- PyList_SET_ITEM(seq, j, Py_None);
+ PyList_SET_ITEM(seq, j, Py_INCREF_RET(Py_None));
}
/*set correct group length*/
@@ -808,8 +808,9 @@ PyObject *BPy_Wrap_GetItems(ID *id, IDProperty *prop)
for (i = 0, loop = prop->data.group.first; loop; loop = loop->next, i++) {
PyObject *item = PyTuple_New(2);
- PyTuple_SET_ITEM(item, 0, PyUnicode_FromString(loop->name));
- PyTuple_SET_ITEM(item, 1, BPy_IDGroup_WrapData(id, loop, prop));
+ PyTuple_SET_ITEMS(item,
+ PyUnicode_FromString(loop->name),
+ BPy_IDGroup_WrapData(id, loop, prop));
PyList_SET_ITEM(seq, i, item);
}
@@ -1406,8 +1407,9 @@ static PyObject *BPy_Group_Iter_Next(BPy_IDGroup_Iter *self)
if (self->mode == IDPROP_ITER_ITEMS) {
ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, PyUnicode_FromString(cur->name));
- PyTuple_SET_ITEM(ret, 1, BPy_IDGroup_WrapData(self->group->id, cur, self->group->prop));
+ PyTuple_SET_ITEMS(ret,
+ PyUnicode_FromString(cur->name),
+ BPy_IDGroup_WrapData(self->group->id, cur, self->group->prop));
return ret;
}
else {
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 36ae30ada22..92ac82508e5 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -37,6 +37,8 @@
#include "py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+
/* only for BLI_strncpy_wchar_from_utf8, should replace with py funcs but too late in release now */
#include "BLI_string_utf8.h"
@@ -178,6 +180,17 @@ void PyC_Tuple_Fill(PyObject *tuple, PyObject *value)
}
}
+void PyC_List_Fill(PyObject *list, PyObject *value)
+{
+ unsigned int tot = PyList_GET_SIZE(list);
+ unsigned int i;
+
+ for (i = 0; i < tot; i++) {
+ PyList_SET_ITEM(list, i, value);
+ Py_INCREF(value);
+ }
+}
+
/* for debugging */
void PyC_ObSpit(const char *name, PyObject *var)
{
@@ -568,7 +581,7 @@ void PyC_MainModule_Restore(PyObject *main_mod)
Py_XDECREF(main_mod);
}
-/* must be called before Py_Initialize, expects output of BLI_get_folder(BLENDER_PYTHON, NULL) */
+/* must be called before Py_Initialize, expects output of BKE_appdir_folder_id(BLENDER_PYTHON, NULL) */
void PyC_SetHomePath(const char *py_path_bundle)
{
if (py_path_bundle == NULL) {
@@ -664,8 +677,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...)
PyErr_Print();
PyErr_Clear();
- PyList_SET_ITEM(values, i, Py_None); /* hold user */
- Py_INCREF(Py_None);
+ PyList_SET_ITEM(values, i, Py_INCREF_RET(Py_None)); /* hold user */
sizes[i] = 0;
}
diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h
index 559a8e15678..398d7da9179 100644
--- a/source/blender/python/generic/py_capi_utils.h
+++ b/source/blender/python/generic/py_capi_utils.h
@@ -42,6 +42,7 @@ int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length,
PyObject * PyC_FromArray(const void *array, int length, const PyTypeObject *type,
const bool is_double, const char *error_prefix);
void PyC_Tuple_Fill(PyObject *tuple, PyObject *value);
+void PyC_List_Fill(PyObject *list, PyObject *value);
/* follow http://www.python.org/dev/peps/pep-0383/ */
PyObject * PyC_UnicodeFromByte(const char *str);
diff --git a/source/blender/python/generic/python_utildefines.h b/source/blender/python/generic/python_utildefines.h
new file mode 100644
index 00000000000..f7d3e7a8b4a
--- /dev/null
+++ b/source/blender/python/generic/python_utildefines.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/generic/python_utildefines.h
+ * \ingroup pygen
+ * \brief header-only utilities
+ * \note light addition to Python.h, use py_capi_utils.h for larger features.
+ */
+
+#ifndef __PYTHON_UTILDEFINES_H__
+#define __PYTHON_UTILDEFINES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PyTuple_SET_ITEMS(op_arg, ...) \
+{ \
+ PyTupleObject *op = (PyTupleObject *)op_arg; \
+ PyObject **ob_items = op->ob_item; \
+ CHECK_TYPE_ANY(op_arg, PyObject *, PyTupleObject *); \
+ BLI_assert(_VA_NARGS_COUNT(__VA_ARGS__) == PyTuple_GET_SIZE(op)); \
+ ARRAY_SET_ITEMS(ob_items, __VA_ARGS__); \
+} (void)0
+
+/* wrap Py_INCREF & return the result,
+ * use sparingly to avoid comma operator or temp var assignment */
+BLI_INLINE PyObject *Py_INCREF_RET(PyObject *op) { Py_INCREF(op); return op; }
+
+/* append & transfer ownership to the list, avoids inline Py_DECREF all over (which is quite a large macro) */
+BLI_INLINE int PyList_APPEND(PyObject *op, PyObject *v)
+{
+ int ret = PyList_Append(op, v);
+ Py_DecRef(v);
+ return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PYTHON_UTILDEFINES_H__ */
+
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 134e718bce5..ec3c017a7ed 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -31,10 +31,9 @@
#include <Python.h>
#include "BLI_utildefines.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
-#include "BKE_main.h"
+#include "BKE_appdir.h"
#include "BKE_global.h" /* XXX, G.main only */
#include "BKE_blender.h"
#include "BKE_bpath.h"
@@ -52,15 +51,10 @@
#include "bpy_utils_units.h"
#include "../generic/py_capi_utils.h"
-
-#include "MEM_guardedalloc.h"
+#include "../generic/python_utildefines.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
# include "BPy_Freestyle.h"
@@ -82,11 +76,11 @@ static PyObject *bpy_script_paths(PyObject *UNUSED(self))
PyObject *item;
const char *path;
- path = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, NULL);
+ path = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, NULL);
item = PyC_UnicodeFromByte(path ? path : "");
BLI_assert(item != NULL);
PyTuple_SET_ITEM(ret, 0, item);
- path = BLI_get_folder(BLENDER_USER_SCRIPTS, NULL);
+ path = BKE_appdir_folder_id(BLENDER_USER_SCRIPTS, NULL);
item = PyC_UnicodeFromByte(path ? path : "");
BLI_assert(item != NULL);
PyTuple_SET_ITEM(ret, 1, item);
@@ -96,10 +90,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 = PyC_UnicodeFromByte(path_src);
- PyList_Append(list, item);
- Py_DECREF(item);
+ PyList_APPEND((PyObject *)userdata, PyC_UnicodeFromByte(path_src));
return false; /* never edits the path */
}
@@ -168,11 +159,11 @@ static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObj
return NULL;
}
- /* same logic as BLI_get_folder_create(), but best leave it up to the script author to create */
- path = BLI_get_folder(folder_id, subdir);
+ /* same logic as BKE_appdir_folder_id_create(), but best leave it up to the script author to create */
+ path = BKE_appdir_folder_id(folder_id, subdir);
if (!path)
- path = BLI_get_user_folder_notest(folder_id, subdir);
+ path = BKE_appdir_folder_id_user_notest(folder_id, subdir);
return PyC_UnicodeFromByte(path ? path : "");
}
@@ -211,7 +202,7 @@ static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObj
return NULL;
}
- path = BLI_get_folder_version(folder_id, (major * 100) + minor, false);
+ path = BKE_appdir_folder_id_version(folder_id, (major * 100) + minor, false);
return PyC_UnicodeFromByte(path ? path : "");
}
@@ -296,7 +287,7 @@ void BPy_init_modules(void)
PyObject *mod;
/* Needs to be first since this dir is needed for future modules */
- const char * const modpath = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, "modules");
+ const char * const modpath = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, "modules");
if (modpath) {
// printf("bpy: found module path '%s'.\n", modpath);
PyObject *sys_path = PySys_GetObject("path"); /* borrow */
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index 16cdd44ce38..678fd62ae89 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -44,13 +44,13 @@
#include "bpy_driver.h"
#include "BLI_utildefines.h"
-#include "BLI_path_util.h"
+#include "BKE_appdir.h"
#include "BKE_blender.h"
#include "BKE_global.h"
-#include "structseq.h"
#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
#ifdef BUILD_DATE
extern char build_date[];
@@ -135,7 +135,7 @@ static PyObject *make_app_info(void)
SetStrItem(STRINGIFY(BLENDER_VERSION_CHAR));
SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE));
- SetStrItem(BLI_program_path());
+ SetStrItem(BKE_appdir_program_path());
SetObjItem(PyBool_FromLong(G.background));
/* build info, use bytes since we can't assume _any_ encoding:
@@ -250,7 +250,7 @@ PyDoc_STRVAR(bpy_app_tempdir_doc,
);
static PyObject *bpy_app_tempdir_get(PyObject *UNUSED(self), void *UNUSED(closure))
{
- return PyC_UnicodeFromByte(BLI_temp_dir_session());
+ return PyC_UnicodeFromByte(BKE_tempdir_session());
}
PyDoc_STRVAR(bpy_app_driver_dict_doc,
@@ -265,8 +265,7 @@ static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(cl
}
}
- Py_INCREF(bpy_pydriver_Dict);
- return bpy_pydriver_Dict;
+ return Py_INCREF_RET(bpy_pydriver_Dict);
}
static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void *UNUSED(closure))
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index 44da322efc0..6a8b0b065c2 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -37,6 +37,8 @@
#include "bpy_rna.h"
#include "bpy_app_handlers.h"
+#include "../generic/python_utildefines.h"
+
#include "BPY_extern.h"
void bpy_app_generic_callback(struct Main *main, struct ID *id, void *arg);
@@ -44,23 +46,24 @@ void bpy_app_generic_callback(struct Main *main, struct ID *id, void *arg);
static PyTypeObject BlenderAppCbType;
static PyStructSequence_Field app_cb_info_fields[] = {
- {(char *)"frame_change_pre", (char *)"Callback list - on frame change for playback and rendering (before)"},
- {(char *)"frame_change_post", (char *)"Callback list - on frame change for playback and rendering (after)"},
- {(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)"},
- {(char *)"load_post", (char *)"Callback list - on loading a new blend file (after)"},
- {(char *)"save_pre", (char *)"Callback list - on saving a blend file (before)"},
- {(char *)"save_post", (char *)"Callback list - on saving a blend file (after)"},
- {(char *)"scene_update_pre", (char *)"Callback list - on updating the scenes data (before)"},
- {(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"},
+ {(char *)"frame_change_pre", (char *)"on frame change for playback and rendering (before)"},
+ {(char *)"frame_change_post", (char *)"on frame change for playback and rendering (after)"},
+ {(char *)"render_pre", (char *)"on render (before)"},
+ {(char *)"render_post", (char *)"on render (after)"},
+ {(char *)"render_write", (char *)"on writing a render frame (directly after the frame is written)"},
+ {(char *)"render_stats", (char *)"on printing render statistics"},
+ {(char *)"render_init", (char *)"on initialization of a render job"},
+ {(char *)"render_complete", (char *)"on completion of render job"},
+ {(char *)"render_cancel", (char *)"on canceling a render job"},
+ {(char *)"load_pre", (char *)"on loading a new blend file (before)"},
+ {(char *)"load_post", (char *)"on loading a new blend file (after)"},
+ {(char *)"save_pre", (char *)"on saving a blend file (before)"},
+ {(char *)"save_post", (char *)"on saving a blend file (after)"},
+ {(char *)"scene_update_pre", (char *)"on updating the scenes data (before)"},
+ {(char *)"scene_update_post", (char *)"on updating the scenes data (after)"},
+ {(char *)"game_pre", (char *)"on starting the game engine"},
+ {(char *)"game_post", (char *)"on ending the game engine"},
+ {(char *)"version_update", (char *)"on ending the versioning code"},
/* sets the permanent tag */
# define APP_CB_OTHER_FIELDS 1
@@ -71,7 +74,7 @@ static PyStructSequence_Field app_cb_info_fields[] = {
static PyStructSequence_Desc app_cb_info_desc = {
(char *)"bpy.app.handlers", /* name */
- (char *)"This module contains callbacks", /* doc */
+ (char *)"This module contains callback lists", /* doc */
app_cb_info_fields, /* fields */
ARRAY_SIZE(app_cb_info_fields) - 1
};
@@ -305,8 +308,7 @@ void bpy_app_generic_callback(struct Main *UNUSED(main), struct ID *id, void *ar
PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(&id_ptr));
}
else {
- PyTuple_SET_ITEM(args, 0, Py_None);
- Py_INCREF(Py_None);
+ PyTuple_SET_ITEM(args, 0, Py_INCREF_RET(Py_None));
}
/* Iterate the list and run the callbacks
diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c
index 0114e8e65e4..1a56c0f7c59 100644
--- a/source/blender/python/intern/bpy_app_translations.c
+++ b/source/blender/python/intern/bpy_app_translations.c
@@ -44,8 +44,8 @@
#include "BLF_translation.h"
#include "RNA_types.h"
-#include "RNA_access.h"
+#include "../generic/python_utildefines.h"
typedef struct
{
@@ -242,12 +242,9 @@ static void _build_translations_cache(PyObject *py_messages, const char *locale)
}
/* Clean up! */
- if (language)
- MEM_freeN(language);
- if (language_country)
- MEM_freeN(language_country);
- if (language_variant)
- MEM_freeN(language_variant);
+ MEM_SAFE_FREE(language);
+ MEM_SAFE_FREE(language_country);
+ MEM_SAFE_FREE(language_variant);
}
const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid)
@@ -410,7 +407,7 @@ static PyObject *app_translations_contexts_make(void)
}
#define SetObjString(item) PyStructSequence_SET_ITEM(translations_contexts, pos++, PyUnicode_FromString((item)))
-#define SetObjNone() Py_INCREF(Py_None); PyStructSequence_SET_ITEM(translations_contexts, pos++, Py_None)
+#define SetObjNone() PyStructSequence_SET_ITEM(translations_contexts, pos++, Py_INCREF_RET(Py_None))
for (ctxt = _contexts; ctxt->c_id; ctxt++) {
if (ctxt->value) {
@@ -520,9 +517,7 @@ static PyObject *_py_pgettext(PyObject *args, PyObject *kw, const char *(*_pgett
return NULL;
}
- Py_INCREF(msgid);
-
- return msgid;
+ return Py_INCREF_RET(msgid);
#endif
}
@@ -632,6 +627,7 @@ PyDoc_STRVAR(app_translations_locale_explode_doc,
);
static PyObject *app_translations_locale_explode(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw)
{
+ PyObject *ret_tuple;
static const char *kwlist[] = {"locale", NULL};
const char *locale;
char *language, *country, *variant, *language_country, *language_variant;
@@ -642,7 +638,15 @@ static PyObject *app_translations_locale_explode(BlenderAppTranslations *UNUSED(
BLF_locale_explode(locale, &language, &country, &variant, &language_country, &language_variant);
- return Py_BuildValue("sssss", language, country, variant, language_country, language_variant);
+ ret_tuple = Py_BuildValue("sssss", language, country, variant, language_country, language_variant);
+
+ MEM_SAFE_FREE(language);
+ MEM_SAFE_FREE(country);
+ MEM_SAFE_FREE(variant);
+ MEM_SAFE_FREE(language_country);
+ MEM_SAFE_FREE(language_variant);
+
+ return ret_tuple;
}
static PyMethodDef app_translations_methods[] = {
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index d46c95a25b8..5b4db89a41a 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -63,6 +63,7 @@
#include "DNA_text_types.h"
+#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_text.h"
#include "BKE_main.h"
@@ -243,11 +244,11 @@ void BPY_python_start(int argc, const char **argv)
{
#ifndef WITH_PYTHON_MODULE
PyThreadState *py_tstate = NULL;
- const char *py_path_bundle = BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL);
+ const char *py_path_bundle = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, NULL);
/* not essential but nice to set our name */
static wchar_t program_path_wchar[FILE_MAX]; /* python holds a reference */
- BLI_strncpy_wchar_from_utf8(program_path_wchar, BLI_program_path(), ARRAY_SIZE(program_path_wchar));
+ BLI_strncpy_wchar_from_utf8(program_path_wchar, BKE_appdir_program_path(), ARRAY_SIZE(program_path_wchar));
Py_SetProgramName(program_path_wchar);
/* must run before python initializes */
diff --git a/source/blender/python/intern/bpy_library.c b/source/blender/python/intern/bpy_library.c
index 3d7d08024c7..3b95b99a0a1 100644
--- a/source/blender/python/intern/bpy_library.c
+++ b/source/blender/python/intern/bpy_library.c
@@ -53,6 +53,8 @@
#include "bpy_util.h"
#include "bpy_library.h"
+#include "../generic/python_utildefines.h"
+
/* nifty feature. swap out strings for RNA data */
#define USE_RNA_DATABLOCKS
@@ -274,10 +276,9 @@ static PyObject *bpy_lib_enter(BPy_Library *self, PyObject *UNUSED(args))
/* return pair */
ret = PyTuple_New(2);
-
- PyTuple_SET_ITEM(ret, 0, (PyObject *)self_from);
-
- PyTuple_SET_ITEM(ret, 1, (PyObject *)self);
+ PyTuple_SET_ITEMS(ret,
+ (PyObject *)self_from,
+ (PyObject *)self);
Py_INCREF(self);
BKE_reports_clear(&reports);
@@ -362,8 +363,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
/* just warn for now */
/* err = -1; */
#ifdef USE_RNA_DATABLOCKS
- item = Py_None;
- Py_INCREF(item);
+ item = Py_INCREF_RET(Py_None);
#endif
}
@@ -375,8 +375,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
PyErr_Clear();
#ifdef USE_RNA_DATABLOCKS
- item = Py_None;
- Py_INCREF(item);
+ item = Py_INCREF_RET(Py_None);
#endif
}
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index 86282f251c3..aad47d14b7c 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -44,6 +44,7 @@
#include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */
#include "bpy_util.h"
#include "../generic/bpy_internal_import.h"
+#include "../generic/python_utildefines.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
@@ -127,9 +128,8 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
/* restore with original context dict, probably NULL but need this for nested operator calls */
Py_XDECREF(context_dict);
CTX_py_dict_set(C, (void *)context_dict_back);
-
- Py_INCREF(ret);
- return ret;
+
+ return Py_INCREF_RET(ret);
}
static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index b0232a4211c..b536e91bca8 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -64,6 +64,7 @@ static EnumPropertyItem property_flag_items[] = {
{PROP_ANIMATABLE, "ANIMATABLE", 0, "Animatable", ""},
{PROP_LIB_EXCEPTION, "LIBRARY_EDITABLE", 0, "Library Editable", ""},
{PROP_PROPORTIONAL, "PROPORTIONAL", 0, "Adjust values proportionally to eachother", ""},
+ {PROP_TEXTEDIT_UPDATE, "TEXTEDIT_UPDATE", 0, "Update on every keystroke in textedit 'mode'", ""},
{0, NULL, 0, NULL, NULL}};
#define BPY_PROPDEF_OPTIONS_DOC \
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index f6e97d6a2d8..592150239be 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -76,10 +76,7 @@
#include "../generic/idprop_py_api.h" /* for IDprop lookups */
#include "../generic/py_capi_utils.h"
-
-#ifdef WITH_INTERNATIONAL
-# include "BLF_translation.h"
-#endif
+#include "../generic/python_utildefines.h"
#define USE_PEDANTIC_WRITE
#define USE_MATHUTILS
@@ -641,7 +638,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
case PROP_ALL_VECTOR_SUBTYPES:
if (len >= 2 && len <= 4) {
if (is_thick) {
- ret = Vector_CreatePyObject(NULL, len, Py_NEW, NULL);
+ ret = Vector_CreatePyObject(NULL, len, NULL);
RNA_property_float_get_array(ptr, prop, ((VectorObject *)ret)->vec);
}
else {
@@ -654,7 +651,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
case PROP_MATRIX:
if (len == 16) {
if (is_thick) {
- ret = Matrix_CreatePyObject(NULL, 4, 4, Py_NEW, NULL);
+ ret = Matrix_CreatePyObject(NULL, 4, 4, NULL);
RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix);
}
else {
@@ -665,7 +662,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
}
else if (len == 9) {
if (is_thick) {
- ret = Matrix_CreatePyObject(NULL, 3, 3, Py_NEW, NULL);
+ ret = Matrix_CreatePyObject(NULL, 3, 3, NULL);
RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix);
}
else {
@@ -683,7 +680,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
PropertyRNA *prop_eul_order = NULL;
short order = pyrna_rotation_euler_order_get(ptr, &prop_eul_order, EULER_ORDER_XYZ);
- ret = Euler_CreatePyObject(NULL, order, Py_NEW, NULL); /* TODO, get order from RNA */
+ ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO, get order from RNA */
RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul);
}
else {
@@ -695,7 +692,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
}
else if (len == 4) {
if (is_thick) {
- ret = Quaternion_CreatePyObject(NULL, Py_NEW, NULL);
+ ret = Quaternion_CreatePyObject(NULL, NULL);
RNA_property_float_get_array(ptr, prop, ((QuaternionObject *)ret)->quat);
}
else {
@@ -709,7 +706,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
case PROP_COLOR_GAMMA:
if (len == 3) { /* color */
if (is_thick) {
- ret = Color_CreatePyObject(NULL, Py_NEW, NULL);
+ ret = Color_CreatePyObject(NULL, NULL);
RNA_property_float_get_array(ptr, prop, ((ColorObject *)ret)->col);
}
else {
@@ -809,7 +806,7 @@ static PyObject *pyrna_struct_richcmp(PyObject *a, PyObject *b, int op)
return NULL;
}
- return Py_INCREF(res), res;
+ return Py_INCREF_RET(res);
}
static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op)
@@ -839,7 +836,7 @@ static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op)
return NULL;
}
- return Py_INCREF(res), res;
+ return Py_INCREF_RET(res);
}
/*----------------------repr--------------------------------------------*/
@@ -2305,8 +2302,7 @@ static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py
RNA_property_collection_next(&rna_macro_iter))
{
item = pyrna_struct_CreatePyObject(&rna_macro_iter.ptr);
- PyList_Append(list, item);
- Py_DECREF(item);
+ PyList_APPEND(list, item);
count++;
if (count == stop) {
@@ -3430,7 +3426,6 @@ static void pyrna_dir_members_py(PyObject *list, PyObject *self)
static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr)
{
- PyObject *pystring;
const char *idname;
/* for looping over attrs and funcs */
@@ -3446,10 +3441,7 @@ static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr)
FunctionRNA *func = itemptr.data;
if (RNA_function_defined(func)) {
idname = RNA_function_identifier(itemptr.data);
-
- pystring = PyUnicode_FromString(idname);
- PyList_Append(list, pystring);
- Py_DECREF(pystring);
+ PyList_APPEND(list, PyUnicode_FromString(idname));
}
}
RNA_PROP_END;
@@ -3469,9 +3461,7 @@ static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr)
nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen);
if (nameptr) {
- pystring = PyUnicode_FromStringAndSize(nameptr, namelen);
- PyList_Append(list, pystring);
- Py_DECREF(pystring);
+ PyList_APPEND(list, PyUnicode_FromStringAndSize(nameptr, namelen));
if (name != nameptr) {
MEM_freeN(nameptr);
@@ -3486,7 +3476,6 @@ static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr)
static PyObject *pyrna_struct_dir(BPy_StructRNA *self)
{
PyObject *ret;
- PyObject *pystring;
PYRNA_STRUCT_CHECK_OBJ(self);
@@ -3505,9 +3494,7 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA *self)
LinkData *link;
for (link = lb.first; link; link = link->next) {
- pystring = PyUnicode_FromString(link->data);
- PyList_Append(ret, pystring);
- Py_DECREF(pystring);
+ PyList_APPEND(ret, PyUnicode_FromString(link->data));
}
BLI_freelistN(&lb);
@@ -3587,14 +3574,11 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
case CTX_DATA_TYPE_COLLECTION:
{
CollectionPointerLink *link;
- PyObject *linkptr;
ret = PyList_New(0);
for (link = newlb.first; link; link = link->next) {
- linkptr = pyrna_struct_CreatePyObject(&link->ptr);
- PyList_Append(ret, linkptr);
- Py_DECREF(linkptr);
+ PyList_APPEND(ret, pyrna_struct_CreatePyObject(&link->ptr));
}
break;
}
@@ -4101,7 +4085,6 @@ PyDoc_STRVAR(pyrna_prop_collection_keys_doc,
static PyObject *pyrna_prop_collection_keys(BPy_PropertyRNA *self)
{
PyObject *ret = PyList_New(0);
- PyObject *item;
char name[256], *nameptr;
int namelen;
@@ -4110,11 +4093,7 @@ static PyObject *pyrna_prop_collection_keys(BPy_PropertyRNA *self)
nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen);
if (nameptr) {
- /* add to python list */
- item = PyUnicode_FromStringAndSize(nameptr, namelen);
- PyList_Append(ret, item);
- Py_DECREF(item);
- /* done */
+ PyList_APPEND(ret, PyUnicode_FromStringAndSize(nameptr, namelen));
if (name != nameptr) {
MEM_freeN(nameptr);
@@ -4160,8 +4139,7 @@ static PyObject *pyrna_prop_collection_items(BPy_PropertyRNA *self)
}
PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr));
- PyList_Append(ret, item);
- Py_DECREF(item);
+ PyList_APPEND(ret, item);
i++;
}
@@ -4227,7 +4205,7 @@ static PyObject *pyrna_struct_get(BPy_StructRNA *self, PyObject *args)
}
}
- return Py_INCREF(def), def;
+ return Py_INCREF_RET(def);
}
PyDoc_STRVAR(pyrna_struct_as_pointer_doc,
@@ -4289,7 +4267,7 @@ static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args
Py_TYPE(key_ob)->tp_name);
}
- return Py_INCREF(def), def;
+ return Py_INCREF_RET(def);
}
PyDoc_STRVAR(pyrna_prop_collection_find_doc,
@@ -4802,8 +4780,7 @@ static PyObject *pyrna_prop_new(PyTypeObject *type, PyObject *args, PyObject *UN
return NULL;
if (type == Py_TYPE(base)) {
- Py_INCREF(base);
- return (PyObject *)base;
+ return Py_INCREF_RET((PyObject *)base);
}
else if (PyType_IsSubtype(type, &pyrna_prop_Type)) {
BPy_PropertyRNA *ret = (BPy_PropertyRNA *) type->tp_alloc(type, 0);
@@ -4855,15 +4832,15 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
switch (RNA_property_subtype(prop)) {
#ifdef USE_MATHUTILS
case PROP_ALL_VECTOR_SUBTYPES:
- ret = Vector_CreatePyObject(data, len, Py_NEW, NULL);
+ ret = Vector_CreatePyObject(data, len, NULL);
break;
case PROP_MATRIX:
if (len == 16) {
- ret = Matrix_CreatePyObject(data, 4, 4, Py_NEW, NULL);
+ ret = Matrix_CreatePyObject(data, 4, 4, NULL);
break;
}
else if (len == 9) {
- ret = Matrix_CreatePyObject(data, 3, 3, Py_NEW, NULL);
+ ret = Matrix_CreatePyObject(data, 3, 3, NULL);
break;
}
/* fall-through */
@@ -4971,14 +4948,11 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
{
ListBase *lb = (ListBase *)data;
CollectionPointerLink *link;
- PyObject *linkptr;
ret = PyList_New(0);
for (link = lb->first; link; link = link->next) {
- linkptr = pyrna_struct_CreatePyObject(&link->ptr);
- PyList_Append(ret, linkptr);
- Py_DECREF(linkptr);
+ PyList_APPEND(ret, pyrna_struct_CreatePyObject(&link->ptr));
}
break;
@@ -5142,9 +5116,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
#ifdef DEBUG_STRING_FREE
if (item) {
if (PyUnicode_Check(item)) {
- item = PyUnicode_FromString(_PyUnicode_AsString(item));
- PyList_Append(string_free_ls, item);
- Py_DECREF(item);
+ PyList_APPEND(string_free_ls, PyUnicode_FromString(_PyUnicode_AsString(item)));
}
}
#endif
@@ -6287,7 +6259,7 @@ static PyObject *pyrna_srna_Subtype(StructRNA *srna)
/* arg[1] (bases=...) */
PyTuple_SET_ITEM(args, 1, item = PyTuple_New(1));
- PyTuple_SET_ITEM(item, 0, py_base); Py_INCREF(py_base);
+ PyTuple_SET_ITEM(item, 0, Py_INCREF_RET(py_base));
/* arg[2] (dict=...) */
@@ -6601,7 +6573,6 @@ static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
{
PyObject *list;
#if 0
- PyObject *name;
PyMethodDef *meth;
#endif
@@ -6609,9 +6580,7 @@ static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
#if 0 /* for now only contains __dir__ */
for (meth = pyrna_basetype_methods; meth->ml_name; meth++) {
- name = PyUnicode_FromString(meth->ml_name);
- PyList_Append(list, name);
- Py_DECREF(name);
+ PyList_APPEND(list, PyUnicode_FromString(meth->ml_name));
}
#endif
return list;
@@ -6622,7 +6591,6 @@ static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
{
PyObject *ret = PyList_New(0);
- PyObject *item;
RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop)
{
@@ -6634,9 +6602,7 @@ static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
}
else {
/* add to python list */
- item = PyUnicode_FromString(RNA_struct_identifier(srna));
- PyList_Append(ret, item);
- Py_DECREF(item);
+ PyList_APPEND(ret, PyUnicode_FromString(RNA_struct_identifier(srna)));
}
}
RNA_PROP_END;
diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index ed51ba5bd1f..ced7d6a5c1c 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -53,6 +53,8 @@
#include "bpy_util.h"
#include "bpy_rna_anim.h"
+#include "../generic/python_utildefines.h"
+
/* for keyframes and drivers */
static int pyrna_struct_anim_args_parse(
PointerRNA *ptr, const char *error_prefix, const char *path,
@@ -329,16 +331,13 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
FCurve *fcu;
PointerRNA tptr;
- PyObject *item;
if (index == -1) { /* all, use a list */
int i = 0;
ret = PyList_New(0);
while ((fcu = list_find_fcurve(&adt->drivers, path_full, i++))) {
RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr);
- item = pyrna_struct_CreatePyObject(&tptr);
- PyList_Append(ret, item);
- Py_DECREF(item);
+ PyList_APPEND(ret, pyrna_struct_CreatePyObject(&tptr));
}
}
else {
diff --git a/source/blender/python/intern/bpy_utils_units.c b/source/blender/python/intern/bpy_utils_units.c
index cdbd57bcebe..a6df8f54cc3 100644
--- a/source/blender/python/intern/bpy_utils_units.c
+++ b/source/blender/python/intern/bpy_utils_units.c
@@ -35,9 +35,7 @@
#include "BLI_utildefines.h"
#include "BLI_string.h"
-#include "BLI_ghash.h"
-#include "BPY_extern.h"
#include "bpy_utils_units.h"
#include "../generic/py_capi_utils.h"
diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c
index 1002293ee0a..e4580e8035b 100644
--- a/source/blender/python/intern/gpu.c
+++ b/source/blender/python/intern/gpu.c
@@ -40,7 +40,6 @@
#include <Python.h>
#include "DNA_scene_types.h"
-#include "DNA_image_types.h"
#include "DNA_material_types.h"
#include "DNA_ID.h"
#include "DNA_customdata_types.h"
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 349f8483fb0..6fe8dc3866b 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -31,6 +31,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/python_utildefines.h"
+
#ifndef MATH_STANDALONE
# include "BLI_dynstr.h"
#endif
@@ -69,8 +71,11 @@ static int mathutils_array_parse_fast(float *array,
/* helper functionm returns length of the 'value', -1 on error */
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
{
+ const int flag = array_max;
int size;
+ array_max &= ~MU_ARRAY_FLAGS;
+
#if 1 /* approx 6x speedup for mathutils types */
if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) ||
@@ -82,6 +87,10 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
return -1;
}
+ if (flag & MU_ARRAY_SPILL) {
+ CLAMP_MAX(size, array_max);
+ }
+
if (size > array_max || size < array_min) {
if (array_max == array_min) {
PyErr_Format(PyExc_ValueError,
@@ -97,7 +106,6 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
}
memcpy(array, ((BaseMathObject *)value)->data, size * sizeof(float));
- return size;
}
else
#endif
@@ -112,6 +120,10 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
size = PySequence_Fast_GET_SIZE(value_fast);
+ if (flag & MU_ARRAY_SPILL) {
+ CLAMP_MAX(size, array_max);
+ }
+
if (size > array_max || size < array_min) {
if (array_max == array_min) {
PyErr_Format(PyExc_ValueError,
@@ -127,8 +139,19 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
return -1;
}
- return mathutils_array_parse_fast(array, size, value_fast, error_prefix);
+ size = mathutils_array_parse_fast(array, size, value_fast, error_prefix);
}
+
+ if (size != -1) {
+ if (flag & MU_ARRAY_ZERO) {
+ int size_left = array_max - size;
+ if (size_left) {
+ memset(&array[size], 0, sizeof(float) * size_left);
+ }
+ }
+ }
+
+ return size;
}
/* on error, -1 is returned and no allocation is made */
@@ -196,6 +219,7 @@ int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, c
int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix)
{
PyObject *value_fast = NULL;
+ const int array_dim_flag = array_dim;
int i, size;
/* non list/tuple cases */
@@ -209,12 +233,14 @@ int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value,
if (size != 0) {
float *fp;
+ array_dim &= ~MU_ARRAY_FLAGS;
+
fp = *array = PyMem_Malloc(size * array_dim * sizeof(float));
for (i = 0; i < size; i++, fp += array_dim) {
PyObject *item = PySequence_Fast_GET_ITEM(value, i);
- if (mathutils_array_parse(fp, array_dim, array_dim, item, error_prefix) == -1) {
+ if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) {
PyMem_Free(*array);
*array = NULL;
size = -1;
@@ -420,14 +446,13 @@ char BaseMathObject_owner_doc[] = "The item this is wrapping or None (read-only
PyObject *BaseMathObject_owner_get(BaseMathObject *self, void *UNUSED(closure))
{
PyObject *ret = self->cb_user ? self->cb_user : Py_None;
- Py_INCREF(ret);
- return ret;
+ return Py_INCREF_RET(ret);
}
char BaseMathObject_is_wrapped_doc[] = "True when this object wraps external data (read-only).\n\n:type: boolean";
PyObject *BaseMathObject_is_wrapped_get(BaseMathObject *self, void *UNUSED(closure))
{
- return PyBool_FromLong((self->wrapped == Py_WRAP) ? 1 : 0);
+ return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_WRAP) != 0);
}
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
@@ -445,7 +470,7 @@ int BaseMathObject_clear(BaseMathObject *self)
void BaseMathObject_dealloc(BaseMathObject *self)
{
/* only free non wrapped */
- if (self->wrapped != Py_WRAP) {
+ if ((self->flag & BASE_MATH_FLAG_IS_WRAP) == 0) {
PyMem_Free(self->data);
}
diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h
index eb25d9bff07..296b8cf9559 100644
--- a/source/blender/python/mathutils/mathutils.h
+++ b/source/blender/python/mathutils/mathutils.h
@@ -29,11 +29,23 @@
/* Can cast different mathutils types to this, use for generic funcs */
+#include "BLI_compiler_attrs.h"
+
struct DynStr;
extern char BaseMathObject_is_wrapped_doc[];
extern char BaseMathObject_owner_doc[];
+#define BASE_MATH_NEW(struct_name, root_type, base_type) \
+ (struct_name *)((base_type ? (base_type)->tp_alloc(base_type, 0) : _PyObject_GC_New(&(root_type))));
+
+
+/* BaseMathObject.flag */
+enum {
+ BASE_MATH_FLAG_IS_WRAP = (1 << 0),
+};
+#define BASE_MATH_FLAG_DEFAULT 0
+
#define BASE_MATH_MEMBERS(_data) \
PyObject_VAR_HEAD \
float *_data; /* array of data (alias), wrapped status depends on wrapped status */ \
@@ -42,7 +54,7 @@ extern char BaseMathObject_owner_doc[];
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ \
unsigned char cb_subtype; /* subtype: location, rotation... \
* to avoid defining many new functions for every attribute of the same type */ \
- unsigned char wrapped /* wrapped data type? */ \
+ unsigned char flag /* wrapped data type? */ \
typedef struct {
BASE_MATH_MEMBERS(data);
@@ -67,9 +79,6 @@ PyMODINIT_FUNC PyInit_mathutils(void);
int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps);
-#define Py_NEW 1
-#define Py_WRAP 2
-
typedef struct Mathutils_Callback Mathutils_Callback;
typedef int (*BaseMathCheckFunc)(BaseMathObject *); /* checks the user is still valid */
@@ -109,6 +118,14 @@ int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, c
int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix);
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix);
+/* zero remaining unused elements of the array */
+#define MU_ARRAY_ZERO (1 << 30)
+/* ignore larger py sequences than requested (just use first elements),
+ * handy when using 3d vectors as 2d */
+#define MU_ARRAY_SPILL (1 << 31)
+
+#define MU_ARRAY_FLAGS (MU_ARRAY_ZERO | MU_ARRAY_SPILL)
+
int column_vector_multiplication(float rvec[4], VectorObject *vec, MatrixObject *mat);
#ifndef MATH_STANDALONE
diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c
index aee2b9e9711..8426038f2d4 100644
--- a/source/blender/python/mathutils/mathutils_Color.c
+++ b/source/blender/python/mathutils/mathutils_Color.c
@@ -32,6 +32,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/python_utildefines.h"
+
#ifndef MATH_STANDALONE
# include "BLI_dynstr.h"
#endif
@@ -64,7 +66,7 @@ static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
"more than a single arg given");
return NULL;
}
- return Color_CreatePyObject(col, Py_NEW, type);
+ return Color_CreatePyObject(col, type);
}
/* -----------------------------METHODS---------------------------- */
@@ -107,7 +109,7 @@ static PyObject *Color_copy(ColorObject *self)
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- return Color_CreatePyObject(self->col, Py_NEW, Py_TYPE(self));
+ return Color_CreatePyObject(self->col, Py_TYPE(self));
}
static PyObject *Color_deepcopy(ColorObject *self, PyObject *args)
{
@@ -187,7 +189,7 @@ static PyObject *Color_richcmpr(PyObject *a, PyObject *b, int op)
return NULL;
}
- return Py_INCREF(res), res;
+ return Py_INCREF_RET(res);
}
/* ---------------------SEQUENCE PROTOCOLS------------------------ */
@@ -411,7 +413,7 @@ static PyObject *Color_add(PyObject *v1, PyObject *v2)
add_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
- return Color_CreatePyObject(col, Py_NEW, Py_TYPE(v1));
+ return Color_CreatePyObject(col, Py_TYPE(v1));
}
/* addition in-place: obj += obj */
@@ -460,7 +462,7 @@ static PyObject *Color_sub(PyObject *v1, PyObject *v2)
sub_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
- return Color_CreatePyObject(col, Py_NEW, Py_TYPE(v1));
+ return Color_CreatePyObject(col, Py_TYPE(v1));
}
/* subtraction in-place: obj -= obj */
@@ -492,7 +494,7 @@ static PyObject *color_mul_float(ColorObject *color, const float scalar)
{
float tcol[COLOR_SIZE];
mul_vn_vn_fl(tcol, color->col, COLOR_SIZE, scalar);
- return Color_CreatePyObject(tcol, Py_NEW, Py_TYPE(color));
+ return Color_CreatePyObject(tcol, Py_TYPE(color));
}
@@ -639,7 +641,7 @@ static PyObject *Color_neg(ColorObject *self)
return NULL;
negate_vn_vn(tcol, self->col, COLOR_SIZE);
- return Color_CreatePyObject(tcol, Py_NEW, Py_TYPE(self));
+ return Color_CreatePyObject(tcol, Py_TYPE(self));
}
@@ -753,9 +755,10 @@ static PyObject *Color_hsv_get(ColorObject *self, void *UNUSED(closure))
rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
ret = PyTuple_New(3);
- PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(hsv[0]));
- PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(hsv[1]));
- PyTuple_SET_ITEM(ret, 2, PyFloat_FromDouble(hsv[2]));
+ PyTuple_SET_ITEMS(ret,
+ PyFloat_FromDouble(hsv[0]),
+ PyFloat_FromDouble(hsv[1]),
+ PyFloat_FromDouble(hsv[2]));
return ret;
}
@@ -862,40 +865,60 @@ PyTypeObject color_Type = {
NULL, /* tp_weaklist */
NULL /* tp_del */
};
-/* ------------------------Color_CreatePyObject (internal)------------- */
-/* creates a new color object */
-/* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- * (i.e. it was allocated elsewhere by MEM_mallocN())
- * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- * (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *Color_CreatePyObject(float col[3], int type, PyTypeObject *base_type)
+
+PyObject *Color_CreatePyObject(
+ const float col[3],
+ PyTypeObject *base_type)
{
ColorObject *self;
+ float *col_alloc;
- self = base_type ? (ColorObject *)base_type->tp_alloc(base_type, 0) :
- (ColorObject *)PyObject_GC_New(ColorObject, &color_Type);
+ col_alloc = PyMem_Malloc(COLOR_SIZE * sizeof(float));
+ if (UNLIKELY(col_alloc == NULL)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "Color(): "
+ "problem allocating data");
+ return NULL;
+ }
+ self = BASE_MATH_NEW(ColorObject, color_Type, base_type);
if (self) {
+ self->col = col_alloc;
+
/* init callbacks as NULL */
self->cb_user = NULL;
self->cb_type = self->cb_subtype = 0;
- if (type == Py_WRAP) {
- self->col = col;
- self->wrapped = Py_WRAP;
- }
- else if (type == Py_NEW) {
- self->col = PyMem_Malloc(COLOR_SIZE * sizeof(float));
- if (col)
- copy_v3_v3(self->col, col);
- else
- zero_v3(self->col);
-
- self->wrapped = Py_NEW;
- }
- else {
- Py_FatalError("Color(): invalid type!");
- }
+ /* NEW */
+ if (col)
+ copy_v3_v3(self->col, col);
+ else
+ zero_v3(self->col);
+
+ self->flag = BASE_MATH_FLAG_DEFAULT;
+ }
+ else {
+ PyMem_Free(col_alloc);
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject *Color_CreatePyObject_wrap(
+ float col[3],
+ PyTypeObject *base_type)
+{
+ ColorObject *self;
+
+ self = BASE_MATH_NEW(ColorObject, color_Type, base_type);
+ if (self) {
+ /* init callbacks as NULL */
+ self->cb_user = NULL;
+ self->cb_type = self->cb_subtype = 0;
+
+ /* WRAP */
+ self->col = col;
+ self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP;
}
return (PyObject *)self;
@@ -904,7 +927,7 @@ PyObject *Color_CreatePyObject(float col[3], int type, PyTypeObject *base_type)
PyObject *Color_CreatePyObject_cb(PyObject *cb_user,
unsigned char cb_type, unsigned char cb_subtype)
{
- ColorObject *self = (ColorObject *)Color_CreatePyObject(NULL, Py_NEW, NULL);
+ ColorObject *self = (ColorObject *)Color_CreatePyObject(NULL, NULL);
if (self) {
Py_INCREF(cb_user);
self->cb_user = cb_user;
diff --git a/source/blender/python/mathutils/mathutils_Color.h b/source/blender/python/mathutils/mathutils_Color.h
index 193d30a2b6f..1290f73da62 100644
--- a/source/blender/python/mathutils/mathutils_Color.h
+++ b/source/blender/python/mathutils/mathutils_Color.h
@@ -42,8 +42,17 @@ typedef struct {
* blender (stored in blend_data). This is an either/or struct not both*/
/* prototypes */
-PyObject *Color_CreatePyObject(float col[3], int type, PyTypeObject *base_type);
-PyObject *Color_CreatePyObject_cb(PyObject *cb_user,
- unsigned char cb_type, unsigned char cb_subtype);
+PyObject *Color_CreatePyObject(
+ const float col[3],
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT;
+PyObject *Color_CreatePyObject_wrap(
+ float col[3],
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+PyObject *Color_CreatePyObject_cb(
+ PyObject *cb_user,
+ unsigned char cb_type, unsigned char cb_subtype
+ ) ATTR_WARN_UNUSED_RESULT;
#endif /* __MATHUTILS_COLOR_H__ */
diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c
index f6d124938a4..9c0ced39403 100644
--- a/source/blender/python/mathutils/mathutils_Euler.c
+++ b/source/blender/python/mathutils/mathutils_Euler.c
@@ -31,6 +31,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/python_utildefines.h"
#ifndef MATH_STANDALONE
# include "BLI_dynstr.h"
@@ -70,7 +71,7 @@ static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
break;
}
- return Euler_CreatePyObject(eul, order, Py_NEW, type);
+ return Euler_CreatePyObject(eul, order, type);
}
/* internal use, assume read callback is done */
@@ -150,7 +151,7 @@ static PyObject *Euler_to_quaternion(EulerObject *self)
eulO_to_quat(quat, self->eul, self->order);
- return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
+ return Quaternion_CreatePyObject(quat, NULL);
}
/* return a matrix representation of the euler */
@@ -171,7 +172,7 @@ static PyObject *Euler_to_matrix(EulerObject *self)
eulO_to_mat3((float (*)[3])mat, self->eul, self->order);
- return Matrix_CreatePyObject(mat, 3, 3, Py_NEW, NULL);
+ return Matrix_CreatePyObject(mat, 3, 3, NULL);
}
PyDoc_STRVAR(Euler_zero_doc,
@@ -233,7 +234,7 @@ static PyObject *Euler_rotate_axis(EulerObject *self, PyObject *args)
PyDoc_STRVAR(Euler_rotate_doc,
".. method:: rotate(other)\n"
"\n"
-" Rotates the euler a by another mathutils value.\n"
+" Rotates the euler by another mathutils value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
@@ -304,7 +305,7 @@ static PyObject *Euler_copy(EulerObject *self)
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- return Euler_CreatePyObject(self->eul, self->order, Py_NEW, Py_TYPE(self));
+ return Euler_CreatePyObject(self->eul, self->order, Py_TYPE(self));
}
static PyObject *Euler_deepcopy(EulerObject *self, PyObject *args)
{
@@ -382,7 +383,7 @@ static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op)
return NULL;
}
- return Py_INCREF(res), res;
+ return Py_INCREF_RET(res);
}
/* ---------------------SEQUENCE PROTOCOLS------------------------ */
@@ -710,53 +711,74 @@ PyTypeObject euler_Type = {
NULL, /* tp_weaklist */
NULL /* tp_del */
};
-/* ------------------------Euler_CreatePyObject (internal)------------- */
-/* creates a new euler object */
-/* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- * (i.e. it was allocated elsewhere by MEM_mallocN())
- * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- * (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *Euler_CreatePyObject(float eul[3], const short order, int type, PyTypeObject *base_type)
+
+
+PyObject *Euler_CreatePyObject(
+ const float eul[3], const short order,
+ PyTypeObject *base_type)
{
EulerObject *self;
+ float *eul_alloc;
- self = base_type ? (EulerObject *)base_type->tp_alloc(base_type, 0) :
- (EulerObject *)PyObject_GC_New(EulerObject, &euler_Type);
+ eul_alloc = PyMem_Malloc(EULER_SIZE * sizeof(float));
+ if (UNLIKELY(eul_alloc == NULL)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "Euler(): "
+ "problem allocating data");
+ return NULL;
+ }
+ self = BASE_MATH_NEW(EulerObject, euler_Type, base_type);
if (self) {
+ self->eul = eul_alloc;
+
/* init callbacks as NULL */
self->cb_user = NULL;
self->cb_type = self->cb_subtype = 0;
- if (type == Py_WRAP) {
- self->eul = eul;
- self->wrapped = Py_WRAP;
- }
- else if (type == Py_NEW) {
- self->eul = PyMem_Malloc(EULER_SIZE * sizeof(float));
- if (eul) {
- copy_v3_v3(self->eul, eul);
- }
- else {
- zero_v3(self->eul);
- }
-
- self->wrapped = Py_NEW;
+ if (eul) {
+ copy_v3_v3(self->eul, eul);
}
else {
- Py_FatalError("Euler(): invalid type!");
+ zero_v3(self->eul);
}
+ self->flag = BASE_MATH_FLAG_DEFAULT;
+ self->order = order;
+ }
+ else {
+ PyMem_Free(eul_alloc);
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject *Euler_CreatePyObject_wrap(
+ float eul[3], const short order,
+ PyTypeObject *base_type)
+{
+ EulerObject *self;
+
+ self = BASE_MATH_NEW(EulerObject, euler_Type, base_type);
+ if (self) {
+ /* init callbacks as NULL */
+ self->cb_user = NULL;
+ self->cb_type = self->cb_subtype = 0;
+
+ self->eul = eul;
+ self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP;
+
self->order = order;
}
return (PyObject *)self;
}
-PyObject *Euler_CreatePyObject_cb(PyObject *cb_user, const short order,
- unsigned char cb_type, unsigned char cb_subtype)
+PyObject *Euler_CreatePyObject_cb(
+ PyObject *cb_user, const short order,
+ unsigned char cb_type, unsigned char cb_subtype)
{
- EulerObject *self = (EulerObject *)Euler_CreatePyObject(NULL, order, Py_NEW, NULL);
+ EulerObject *self = (EulerObject *)Euler_CreatePyObject(NULL, order, NULL);
if (self) {
Py_INCREF(cb_user);
self->cb_user = cb_user;
diff --git a/source/blender/python/mathutils/mathutils_Euler.h b/source/blender/python/mathutils/mathutils_Euler.h
index 62fb83ef234..744f39faed1 100644
--- a/source/blender/python/mathutils/mathutils_Euler.h
+++ b/source/blender/python/mathutils/mathutils_Euler.h
@@ -43,9 +43,18 @@ typedef struct {
* blender (stored in blend_data). This is an either/or struct not both */
/* prototypes */
-PyObject *Euler_CreatePyObject(float eul[3], const short order, int type, PyTypeObject *base_type);
-PyObject *Euler_CreatePyObject_cb(PyObject *cb_user, const short order,
- unsigned char cb_type, unsigned char cb_subtype);
+PyObject *Euler_CreatePyObject(
+ const float eul[3], const short order,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT;
+PyObject *Euler_CreatePyObject_wrap(
+ float eul[3], const short order,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+PyObject *Euler_CreatePyObject_cb(
+ PyObject *cb_user, const short order,
+ unsigned char cb_type, unsigned char cb_subtype
+ ) ATTR_WARN_UNUSED_RESULT;
short euler_order_from_string(const char *str, const char *error_prefix);
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 282f29b4934..4706c09176e 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -32,6 +32,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/python_utildefines.h"
+
#ifndef MATH_STANDALONE
# include "BLI_string.h"
# include "BLI_dynstr.h"
@@ -344,7 +346,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
switch (PyTuple_GET_SIZE(args)) {
case 0:
- return Matrix_CreatePyObject(NULL, 4, 4, Py_NEW, type);
+ return Matrix_CreatePyObject(NULL, 4, 4, type);
case 1:
{
PyObject *arg = PyTuple_GET_ITEM(args, 0);
@@ -363,7 +365,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (num_col >= 2 && num_col <= 4) {
/* sane row & col size, new matrix and assign as slice */
- PyObject *matrix = Matrix_CreatePyObject(NULL, num_col, num_row, Py_NEW, type);
+ PyObject *matrix = Matrix_CreatePyObject(NULL, num_col, num_row, type);
if (Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) {
return matrix;
}
@@ -444,7 +446,7 @@ static PyObject *C_Matrix_Identity(PyObject *cls, PyObject *args)
return NULL;
}
- return Matrix_CreatePyObject(NULL, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
+ return Matrix_CreatePyObject(NULL, matSize, matSize, (PyTypeObject *)cls);
}
PyDoc_STRVAR(C_Matrix_Rotation_doc,
@@ -535,7 +537,7 @@ static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args)
matrix_3x3_as_4x4(mat);
}
/* pass to matrix creation */
- return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
+ return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls);
}
@@ -558,7 +560,7 @@ static PyObject *C_Matrix_Translation(PyObject *cls, PyObject *value)
if (mathutils_array_parse(mat[3], 3, 4, value, "mathutils.Matrix.Translation(vector), invalid vector arg") == -1)
return NULL;
- return Matrix_CreatePyObject(&mat[0][0], 4, 4, Py_NEW, (PyTypeObject *)cls);
+ return Matrix_CreatePyObject(&mat[0][0], 4, 4, (PyTypeObject *)cls);
}
/* ----------------------------------mathutils.Matrix.Scale() ------------- */
/* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */
@@ -650,7 +652,7 @@ static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args)
matrix_3x3_as_4x4(mat);
}
/* pass to matrix creation */
- return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
+ return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls);
}
/* ----------------------------------mathutils.Matrix.OrthoProjection() --- */
/* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */
@@ -771,7 +773,7 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args)
matrix_3x3_as_4x4(mat);
}
/* pass to matrix creation */
- return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
+ return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls);
}
PyDoc_STRVAR(C_Matrix_Shear_doc,
@@ -874,7 +876,7 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args)
matrix_3x3_as_4x4(mat);
}
/* pass to matrix creation */
- return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
+ return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls);
}
void matrix_as_3x3(float mat[3][3], MatrixObject *self)
@@ -1078,7 +1080,7 @@ static PyObject *Matrix_to_quaternion(MatrixObject *self)
mat4_to_quat(quat, (float (*)[4])self->matrix);
}
- return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
+ return Quaternion_CreatePyObject(quat, NULL);
}
/*---------------------------matrix.toEuler() --------------------*/
@@ -1152,7 +1154,7 @@ static PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args)
else mat3_to_eulO(eul, order, mat);
}
- return Euler_CreatePyObject(eul, order, Py_NEW, NULL);
+ return Euler_CreatePyObject(eul, order, NULL);
}
PyDoc_STRVAR(Matrix_resize_4x4_doc,
@@ -1165,7 +1167,7 @@ static PyObject *Matrix_resize_4x4(MatrixObject *self)
float mat[4][4];
int col;
- if (self->wrapped == Py_WRAP) {
+ if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
PyErr_SetString(PyExc_ValueError,
"Matrix.resize_4x4(): "
"cannot resize wrapped data - make a copy and resize that");
@@ -1214,12 +1216,12 @@ static PyObject *Matrix_to_4x4(MatrixObject *self)
return NULL;
if (self->num_row == 4 && self->num_col == 4) {
- return Matrix_CreatePyObject(self->matrix, 4, 4, Py_NEW, Py_TYPE(self));
+ return Matrix_CreatePyObject(self->matrix, 4, 4, Py_TYPE(self));
}
else if (self->num_row == 3 && self->num_col == 3) {
float mat[4][4];
copy_m4_m3(mat, (float (*)[3])self->matrix);
- return Matrix_CreatePyObject((float *)mat, 4, 4, Py_NEW, Py_TYPE(self));
+ return Matrix_CreatePyObject((float *)mat, 4, 4, Py_TYPE(self));
}
/* TODO, 2x2 matrix */
@@ -1252,15 +1254,15 @@ static PyObject *Matrix_to_3x3(MatrixObject *self)
matrix_as_3x3(mat, self);
- return Matrix_CreatePyObject((float *)mat, 3, 3, Py_NEW, Py_TYPE(self));
+ return Matrix_CreatePyObject((float *)mat, 3, 3, Py_TYPE(self));
}
PyDoc_STRVAR(Matrix_to_translation_doc,
".. method:: to_translation()\n"
"\n"
-" Return a the translation part of a 4 row matrix.\n"
+" Return the translation part of a 4 row matrix.\n"
"\n"
-" :return: Return a the translation of a matrix.\n"
+" :return: Return the translation of a matrix.\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Matrix_to_translation(MatrixObject *self)
@@ -1275,15 +1277,15 @@ static PyObject *Matrix_to_translation(MatrixObject *self)
return NULL;
}
- return Vector_CreatePyObject(MATRIX_COL_PTR(self, 3), 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(MATRIX_COL_PTR(self, 3), 3, NULL);
}
PyDoc_STRVAR(Matrix_to_scale_doc,
".. method:: to_scale()\n"
"\n"
-" Return a the scale part of a 3x3 or 4x4 matrix.\n"
+" Return the scale part of a 3x3 or 4x4 matrix.\n"
"\n"
-" :return: Return a the scale of a matrix.\n"
+" :return: Return the scale of a matrix.\n"
" :rtype: :class:`Vector`\n"
"\n"
" .. note:: This method does not return negative a scale on any axis because it is not possible to obtain this data from the matrix alone.\n"
@@ -1310,7 +1312,7 @@ static PyObject *Matrix_to_scale(MatrixObject *self)
/* compatible mat4_to_loc_rot_size */
mat3_to_rot_size(rot, size, mat);
- return Vector_CreatePyObject(size, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(size, 3, NULL);
}
/*---------------------------matrix.invert() ---------------------*/
@@ -1589,7 +1591,7 @@ static PyObject *Matrix_adjugated(MatrixObject *self)
PyDoc_STRVAR(Matrix_rotate_doc,
".. method:: rotate(other)\n"
"\n"
-" Rotates the matrix a by another mathutils value.\n"
+" Rotates the matrix by another mathutils value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
@@ -1653,10 +1655,10 @@ static PyObject *Matrix_decompose(MatrixObject *self)
mat3_to_quat(quat, rot);
ret = PyTuple_New(3);
- PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(loc, 3, Py_NEW, NULL));
- PyTuple_SET_ITEM(ret, 1, Quaternion_CreatePyObject(quat, Py_NEW, NULL));
- PyTuple_SET_ITEM(ret, 2, Vector_CreatePyObject(size, 3, Py_NEW, NULL));
-
+ PyTuple_SET_ITEMS(ret,
+ Vector_CreatePyObject(loc, 3, NULL),
+ Quaternion_CreatePyObject(quat, NULL),
+ Vector_CreatePyObject(size, 3, NULL));
return ret;
}
@@ -1706,7 +1708,7 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
return NULL;
}
- return Matrix_CreatePyObject(mat, self->num_col, self->num_row, Py_NEW, Py_TYPE(self));
+ return Matrix_CreatePyObject(mat, self->num_col, self->num_row, Py_TYPE(self));
}
/*---------------------------matrix.determinant() ----------------*/
@@ -1715,7 +1717,7 @@ PyDoc_STRVAR(Matrix_determinant_doc,
"\n"
" Return the determinant of a matrix.\n"
"\n"
-" :return: Return a the determinant of a matrix.\n"
+" :return: Return the determinant of a matrix.\n"
" :rtype: float\n"
"\n"
" .. seealso:: <http://en.wikipedia.org/wiki/Determinant>\n"
@@ -1836,7 +1838,6 @@ PyDoc_STRVAR(Matrix_zero_doc,
"\n"
" Set all the matrix values to zero.\n"
"\n"
-" :return: an instance of itself\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *Matrix_zero(MatrixObject *self)
@@ -1847,8 +1848,24 @@ static PyObject *Matrix_zero(MatrixObject *self)
return NULL;
Py_RETURN_NONE;
+
}
/*---------------------------matrix.identity(() ------------------*/
+static void matrix_identity_internal(MatrixObject *self)
+{
+ BLI_assert((self->num_col == self->num_row) && (self->num_row <= 4));
+
+ if (self->num_col == 2) {
+ unit_m2((float (*)[2])self->matrix);
+ }
+ else if (self->num_col == 3) {
+ unit_m3((float (*)[3])self->matrix);
+ }
+ else {
+ unit_m4((float (*)[4])self->matrix);
+ }
+}
+
PyDoc_STRVAR(Matrix_identity_doc,
".. method:: identity()\n"
"\n"
@@ -1871,15 +1888,7 @@ static PyObject *Matrix_identity(MatrixObject *self)
return NULL;
}
- if (self->num_col == 2) {
- unit_m2((float (*)[2])self->matrix);
- }
- else if (self->num_col == 3) {
- unit_m3((float (*)[3])self->matrix);
- }
- else {
- unit_m4((float (*)[4])self->matrix);
- }
+ matrix_identity_internal(self);
if (BaseMath_WriteCallback(self) == -1)
return NULL;
@@ -1891,7 +1900,7 @@ static PyObject *Matrix_identity(MatrixObject *self)
static PyObject *Matrix_copy_notest(MatrixObject *self, const float *matrix)
{
- return Matrix_CreatePyObject((float *)matrix, self->num_col, self->num_row, Py_NEW, Py_TYPE(self));
+ return Matrix_CreatePyObject((float *)matrix, self->num_col, self->num_row, Py_TYPE(self));
}
PyDoc_STRVAR(Matrix_copy_doc,
@@ -2025,7 +2034,7 @@ static PyObject *Matrix_richcmpr(PyObject *a, PyObject *b, int op)
return NULL;
}
- return Py_INCREF(res), res;
+ return Py_INCREF_RET(res);
}
/*---------------------SEQUENCE PROTOCOLS------------------------
@@ -2233,7 +2242,7 @@ static PyObject *Matrix_add(PyObject *m1, PyObject *m2)
add_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
- return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1));
+ return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1));
}
/*------------------------obj - obj------------------------------
* subtraction */
@@ -2265,7 +2274,7 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
- return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1));
+ return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1));
}
/*------------------------obj * obj------------------------------
* multiplication */
@@ -2273,7 +2282,7 @@ static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
{
float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
mul_vn_vn_fl(tmat, mat->matrix, mat->num_col * mat->num_row, scalar);
- return Matrix_CreatePyObject(tmat, mat->num_col, mat->num_row, Py_NEW, Py_TYPE(mat));
+ return Matrix_CreatePyObject(tmat, mat->num_col, mat->num_row, Py_TYPE(mat));
}
static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
@@ -2317,7 +2326,7 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
}
}
- return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1));
+ return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1));
}
else if (mat2) {
/*FLOAT/INT * MATRIX */
@@ -2343,7 +2352,7 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
vec_size = mat1->num_row;
}
- return Vector_CreatePyObject(tvec, vec_size, Py_NEW, Py_TYPE(m2));
+ return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(m2));
}
/*FLOAT/INT * MATRIX */
else if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
@@ -2762,15 +2771,13 @@ PyTypeObject matrix_Type = {
NULL /*tp_del*/
};
-/* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- * (i.e. it was allocated elsewhere by MEM_mallocN())
- * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- * (i.e. it must be created here with PyMEM_malloc()) */
-PyObject *Matrix_CreatePyObject(float *mat,
- const unsigned short num_col, const unsigned short num_row,
- int type, PyTypeObject *base_type)
+PyObject *Matrix_CreatePyObject(
+ const float *mat,
+ const unsigned short num_col, const unsigned short num_row,
+ PyTypeObject *base_type)
{
MatrixObject *self;
+ float *mat_alloc;
/* matrix objects can be any 2-4row x 2-4col matrix */
if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) {
@@ -2780,10 +2787,17 @@ PyObject *Matrix_CreatePyObject(float *mat,
return NULL;
}
- self = base_type ? (MatrixObject *)base_type->tp_alloc(base_type, 0) :
- (MatrixObject *)PyObject_GC_New(MatrixObject, &matrix_Type);
+ mat_alloc = PyMem_Malloc(num_col * num_row * sizeof(float));
+ if (UNLIKELY(mat_alloc == NULL)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "Matrix(): "
+ "problem allocating data");
+ return NULL;
+ }
+ self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type);
if (self) {
+ self->matrix = mat_alloc;
self->num_col = num_col;
self->num_row = num_row;
@@ -2791,37 +2805,52 @@ PyObject *Matrix_CreatePyObject(float *mat,
self->cb_user = NULL;
self->cb_type = self->cb_subtype = 0;
- if (type == Py_WRAP) {
- self->matrix = mat;
- self->wrapped = Py_WRAP;
+ if (mat) { /*if a float array passed*/
+ memcpy(self->matrix, mat, num_col * num_row * sizeof(float));
}
- else if (type == Py_NEW) {
- self->matrix = PyMem_Malloc(num_col * num_row * sizeof(float));
- if (self->matrix == NULL) { /*allocation failure*/
- PyErr_SetString(PyExc_MemoryError,
- "Matrix(): "
- "problem allocating pointer space");
- return NULL;
- }
-
- if (mat) { /*if a float array passed*/
- memcpy(self->matrix, mat, num_col * num_row * sizeof(float));
- }
- else if (num_col == num_row) {
- /* or if no arguments are passed return identity matrix for square matrices */
- PyObject *ret_dummy = Matrix_identity(self);
- Py_DECREF(ret_dummy);
- }
- else {
- /* otherwise zero everything */
- memset(self->matrix, 0, num_col * num_row * sizeof(float));
- }
- self->wrapped = Py_NEW;
+ else if (num_col == num_row) {
+ /* or if no arguments are passed return identity matrix for square matrices */
+ matrix_identity_internal(self);
}
else {
- Py_FatalError("Matrix(): invalid type!");
- return NULL;
+ /* otherwise zero everything */
+ memset(self->matrix, 0, num_col * num_row * sizeof(float));
}
+ self->flag = BASE_MATH_FLAG_DEFAULT;
+ }
+ else {
+ PyMem_Free(mat_alloc);
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject *Matrix_CreatePyObject_wrap(
+ float *mat,
+ const unsigned short num_col, const unsigned short num_row,
+ PyTypeObject *base_type)
+{
+ MatrixObject *self;
+
+ /* matrix objects can be any 2-4row x 2-4col matrix */
+ if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Matrix(): "
+ "row and column sizes must be between 2 and 4");
+ return NULL;
+ }
+
+ self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type);
+ if (self) {
+ self->num_col = num_col;
+ self->num_row = num_row;
+
+ /* init callbacks as NULL */
+ self->cb_user = NULL;
+ self->cb_type = self->cb_subtype = 0;
+
+ self->matrix = mat;
+ self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP;
}
return (PyObject *) self;
}
@@ -2830,7 +2859,7 @@ PyObject *Matrix_CreatePyObject_cb(PyObject *cb_user,
const unsigned short num_col, const unsigned short num_row,
unsigned char cb_type, unsigned char cb_subtype)
{
- MatrixObject *self = (MatrixObject *)Matrix_CreatePyObject(NULL, num_col, num_row, Py_NEW, NULL);
+ MatrixObject *self = (MatrixObject *)Matrix_CreatePyObject(NULL, num_col, num_row, NULL);
if (self) {
Py_INCREF(cb_user);
self->cb_user = cb_user;
diff --git a/source/blender/python/mathutils/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h
index f94af9e540e..9ae5a4bd61d 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.h
+++ b/source/blender/python/mathutils/mathutils_Matrix.h
@@ -61,12 +61,21 @@ typedef struct {
* blender (stored in blend_data). This is an either/or struct not both */
/* prototypes */
-PyObject *Matrix_CreatePyObject(float *mat,
- const unsigned short num_col, const unsigned short num_row,
- int type, PyTypeObject *base_type);
-PyObject *Matrix_CreatePyObject_cb(PyObject *user,
- const unsigned short num_col, const unsigned short num_row,
- unsigned char cb_type, unsigned char cb_subtype);
+PyObject *Matrix_CreatePyObject(
+ const float *mat,
+ const unsigned short num_col, const unsigned short num_row,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT;
+PyObject *Matrix_CreatePyObject_wrap(
+ float *mat,
+ const unsigned short num_col, const unsigned short num_row,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+PyObject *Matrix_CreatePyObject_cb(
+ PyObject *user,
+ const unsigned short num_col, const unsigned short num_row,
+ unsigned char cb_type, unsigned char cb_subtype
+ ) ATTR_WARN_UNUSED_RESULT;
extern unsigned char mathutils_matrix_row_cb_index; /* default */
extern unsigned char mathutils_matrix_col_cb_index;
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index ae3476f5802..d422634a496 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -32,6 +32,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/python_utildefines.h"
+
#ifndef MATH_STANDALONE
# include "BLI_dynstr.h"
#endif
@@ -121,7 +123,7 @@ static PyObject *Quaternion_to_euler(QuaternionObject *self, PyObject *args)
else quat_to_eulO(eul, order, tquat);
}
- return Euler_CreatePyObject(eul, order, Py_NEW, NULL);
+ return Euler_CreatePyObject(eul, order, NULL);
}
PyDoc_STRVAR(Quaternion_to_matrix_doc,
@@ -140,7 +142,7 @@ static PyObject *Quaternion_to_matrix(QuaternionObject *self)
return NULL;
quat_to_mat3((float (*)[3])mat, self->quat);
- return Matrix_CreatePyObject(mat, 3, 3, Py_NEW, NULL);
+ return Matrix_CreatePyObject(mat, 3, 3, NULL);
}
PyDoc_STRVAR(Quaternion_to_axis_angle_doc,
@@ -169,8 +171,9 @@ static PyObject *Quaternion_to_axis_angle(QuaternionObject *self)
quat__axis_angle_sanitize(axis, &angle);
ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(axis, 3, Py_NEW, NULL));
- PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(angle));
+ PyTuple_SET_ITEMS(ret,
+ Vector_CreatePyObject(axis, 3, NULL),
+ PyFloat_FromDouble(angle));
return ret;
}
@@ -198,7 +201,7 @@ static PyObject *Quaternion_cross(QuaternionObject *self, PyObject *value)
}
mul_qt_qtqt(quat, self->quat, tquat);
- return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(self));
+ return Quaternion_CreatePyObject(quat, Py_TYPE(self));
}
PyDoc_STRVAR(Quaternion_dot_doc,
@@ -252,7 +255,7 @@ static PyObject *Quaternion_rotation_difference(QuaternionObject *self, PyObject
rotation_between_quats_to_quat(quat, self->quat, tquat);
- return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(self));
+ return Quaternion_CreatePyObject(quat, Py_TYPE(self));
}
PyDoc_STRVAR(Quaternion_slerp_doc,
@@ -297,13 +300,13 @@ static PyObject *Quaternion_slerp(QuaternionObject *self, PyObject *args)
interp_qt_qtqt(quat, self->quat, tquat, fac);
- return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(self));
+ return Quaternion_CreatePyObject(quat, Py_TYPE(self));
}
PyDoc_STRVAR(Quaternion_rotate_doc,
".. method:: rotate(other)\n"
"\n"
-" Rotates the quaternion a by another mathutils value.\n"
+" Rotates the quaternion by another mathutils value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
@@ -393,7 +396,6 @@ PyDoc_STRVAR(Quaternion_identity_doc,
"\n"
" Set the quaternion to an identity quaternion.\n"
"\n"
-" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_identity(QuaternionObject *self)
@@ -412,7 +414,6 @@ PyDoc_STRVAR(Quaternion_negate_doc,
"\n"
" Set the quaternion to its negative.\n"
"\n"
-" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_negate(QuaternionObject *self)
@@ -470,7 +471,7 @@ static PyObject *Quaternion_copy(QuaternionObject *self)
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- return Quaternion_CreatePyObject(self->quat, Py_NEW, Py_TYPE(self));
+ return Quaternion_CreatePyObject(self->quat, Py_TYPE(self));
}
static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args)
{
@@ -546,7 +547,7 @@ static PyObject *Quaternion_richcmpr(PyObject *a, PyObject *b, int op)
return NULL;
}
- return Py_INCREF(res), res;
+ return Py_INCREF_RET(res);
}
/* ---------------------SEQUENCE PROTOCOLS------------------------ */
@@ -750,7 +751,7 @@ static PyObject *Quaternion_add(PyObject *q1, PyObject *q2)
return NULL;
add_qt_qtqt(quat, quat1->quat, quat2->quat, 1.0f);
- return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(q1));
+ return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
}
/* ------------------------obj - obj------------------------------ */
/* subtraction */
@@ -778,7 +779,7 @@ static PyObject *Quaternion_sub(PyObject *q1, PyObject *q2)
quat[x] = quat1->quat[x] - quat2->quat[x];
}
- return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(q1));
+ return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
}
static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar)
@@ -786,7 +787,7 @@ static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar)
float tquat[4];
copy_qt_qt(tquat, quat->quat);
mul_qt_fl(tquat, scalar);
- return Quaternion_CreatePyObject(tquat, Py_NEW, Py_TYPE(quat));
+ return Quaternion_CreatePyObject(tquat, Py_TYPE(quat));
}
/*------------------------obj * obj------------------------------
@@ -809,7 +810,7 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
if (quat1 && quat2) { /* QUAT * QUAT (cross product) */
mul_qt_qtqt(quat, quat1->quat, quat2->quat);
- return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(q1));
+ return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
}
/* the only case this can happen (for a supported type is "FLOAT * QUAT") */
else if (quat2) { /* FLOAT * QUAT */
@@ -837,7 +838,7 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
copy_v3_v3(tvec, vec2->vec);
mul_qt_v3(quat1->quat, tvec);
- return Vector_CreatePyObject(tvec, 3, Py_NEW, Py_TYPE(vec2));
+ return Vector_CreatePyObject(tvec, 3, Py_TYPE(vec2));
}
/* QUAT * FLOAT */
else if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
@@ -865,7 +866,7 @@ static PyObject *Quaternion_neg(QuaternionObject *self)
return NULL;
negate_v4_v4(tquat, self->quat);
- return Quaternion_CreatePyObject(tquat, Py_NEW, Py_TYPE(self));
+ return Quaternion_CreatePyObject(tquat, Py_TYPE(self));
}
@@ -1023,7 +1024,7 @@ static PyObject *Quaternion_axis_vector_get(QuaternionObject *self, void *UNUSED
quat__axis_angle_sanitize(axis, NULL);
- return Vector_CreatePyObject(axis, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(axis, 3, NULL);
}
static int Quaternion_axis_vector_set(QuaternionObject *self, PyObject *value, void *UNUSED(closure))
@@ -1089,7 +1090,7 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
/* PyArg_ParseTuple assures no more than 2 */
}
}
- return Quaternion_CreatePyObject(quat, Py_NEW, type);
+ return Quaternion_CreatePyObject(quat, type);
}
static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObject *self)
@@ -1240,41 +1241,60 @@ PyTypeObject quaternion_Type = {
NULL, /* tp_weaklist */
NULL, /* tp_del */
};
-/* ------------------------Quaternion_CreatePyObject (internal)------------- */
-/* creates a new quaternion object */
-/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- * (i.e. it was allocated elsewhere by MEM_mallocN())
- * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- * (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *Quaternion_CreatePyObject(float quat[4], int type, PyTypeObject *base_type)
+
+PyObject *Quaternion_CreatePyObject(
+ const float quat[4],
+ PyTypeObject *base_type)
{
QuaternionObject *self;
+ float *quat_alloc;
- self = base_type ? (QuaternionObject *)base_type->tp_alloc(base_type, 0) :
- (QuaternionObject *)PyObject_GC_New(QuaternionObject, &quaternion_Type);
+ quat_alloc = PyMem_Malloc(QUAT_SIZE * sizeof(float));
+ if (UNLIKELY(quat_alloc == NULL)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "Quaternion(): "
+ "problem allocating data");
+ return NULL;
+ }
+ self = BASE_MATH_NEW(QuaternionObject, quaternion_Type, base_type);
if (self) {
+ self->quat = quat_alloc;
/* init callbacks as NULL */
self->cb_user = NULL;
self->cb_type = self->cb_subtype = 0;
- if (type == Py_WRAP) {
- self->quat = quat;
- self->wrapped = Py_WRAP;
- }
- else if (type == Py_NEW) {
- self->quat = PyMem_Malloc(QUAT_SIZE * sizeof(float));
- if (!quat) { /* new empty */
- unit_qt(self->quat);
- }
- else {
- copy_qt_qt(self->quat, quat);
- }
- self->wrapped = Py_NEW;
+ /* NEW */
+ if (!quat) { /* new empty */
+ unit_qt(self->quat);
}
else {
- Py_FatalError("Quaternion(): invalid type!");
+ copy_qt_qt(self->quat, quat);
}
+ self->flag = BASE_MATH_FLAG_DEFAULT;
+ }
+ else {
+ PyMem_Free(quat_alloc);
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject *Quaternion_CreatePyObject_wrap(
+ float quat[4],
+ PyTypeObject *base_type)
+{
+ QuaternionObject *self;
+
+ self = BASE_MATH_NEW(QuaternionObject, quaternion_Type, base_type);
+ if (self) {
+ /* init callbacks as NULL */
+ self->cb_user = NULL;
+ self->cb_type = self->cb_subtype = 0;
+
+ /* WRAP */
+ self->quat = quat;
+ self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP;
}
return (PyObject *) self;
}
@@ -1282,7 +1302,7 @@ PyObject *Quaternion_CreatePyObject(float quat[4], int type, PyTypeObject *base_
PyObject *Quaternion_CreatePyObject_cb(PyObject *cb_user,
unsigned char cb_type, unsigned char cb_subtype)
{
- QuaternionObject *self = (QuaternionObject *)Quaternion_CreatePyObject(NULL, Py_NEW, NULL);
+ QuaternionObject *self = (QuaternionObject *)Quaternion_CreatePyObject(NULL, NULL);
if (self) {
Py_INCREF(cb_user);
self->cb_user = cb_user;
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.h b/source/blender/python/mathutils/mathutils_Quaternion.h
index 36036c6d3fa..66ee3362906 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.h
+++ b/source/blender/python/mathutils/mathutils_Quaternion.h
@@ -40,8 +40,17 @@ typedef struct {
* blender (stored in blend_data). This is an either/or struct not both */
/* prototypes */
-PyObject *Quaternion_CreatePyObject(float quat[4], int type, PyTypeObject *base_type);
-PyObject *Quaternion_CreatePyObject_cb(PyObject *cb_user,
- unsigned char cb_type, unsigned char cb_subtype);
+PyObject *Quaternion_CreatePyObject(
+ const float quat[4],
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT;
+PyObject *Quaternion_CreatePyObject_wrap(
+ float quat[4],
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+PyObject *Quaternion_CreatePyObject_cb(
+ PyObject *cb_user,
+ unsigned char cb_type, unsigned char cb_subtype
+ ) ATTR_WARN_UNUSED_RESULT;
#endif /* __MATHUTILS_QUATERNION_H__ */
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index 15a9860be0a..167fb5bcf3d 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -387,7 +387,7 @@ static PyObject *Vector_resize(VectorObject *self, PyObject *value)
{
int size;
- if (self->wrapped == Py_WRAP) {
+ if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize(): "
"cannot resize wrapped data - only python vectors");
@@ -475,7 +475,7 @@ PyDoc_STRVAR(Vector_resize_2d_doc,
);
static PyObject *Vector_resize_2d(VectorObject *self)
{
- if (self->wrapped == Py_WRAP) {
+ if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize_2d(): "
"cannot resize wrapped data - only python vectors");
@@ -507,7 +507,7 @@ PyDoc_STRVAR(Vector_resize_3d_doc,
);
static PyObject *Vector_resize_3d(VectorObject *self)
{
- if (self->wrapped == Py_WRAP) {
+ if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize_3d(): "
"cannot resize wrapped data - only python vectors");
@@ -542,7 +542,7 @@ PyDoc_STRVAR(Vector_resize_4d_doc,
);
static PyObject *Vector_resize_4d(VectorObject *self)
{
- if (self->wrapped == Py_WRAP) {
+ if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize_4d(): "
"cannot resize wrapped data - only python vectors");
@@ -586,7 +586,7 @@ static PyObject *Vector_to_2d(VectorObject *self)
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- return Vector_CreatePyObject(self->vec, 2, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(self->vec, 2, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_to_3d_doc,
".. method:: to_3d()\n"
@@ -604,7 +604,7 @@ static PyObject *Vector_to_3d(VectorObject *self)
return NULL;
memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 3));
- return Vector_CreatePyObject(tvec, 3, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(tvec, 3, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_to_4d_doc,
".. method:: to_4d()\n"
@@ -622,7 +622,7 @@ static PyObject *Vector_to_4d(VectorObject *self)
return NULL;
memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 4));
- return Vector_CreatePyObject(tvec, 4, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(tvec, 4, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_to_tuple_doc,
@@ -797,7 +797,7 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args)
vec_to_quat(quat, vec, track, up);
- return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
+ return Quaternion_CreatePyObject(quat, NULL);
}
PyDoc_STRVAR(Vector_orthogonal_doc,
@@ -829,7 +829,7 @@ static PyObject *Vector_orthogonal(VectorObject *self)
else
ortho_v2_v2(vec, self->vec);
- return Vector_CreatePyObject(vec, self->size, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(vec, self->size, Py_TYPE(self));
}
@@ -877,7 +877,7 @@ static PyObject *Vector_reflect(VectorObject *self, PyObject *value)
normalize_v3(mirror);
reflect_v3_v3v3(reflect, vec, mirror);
- return Vector_CreatePyObject(reflect, self->size, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(reflect, self->size, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_cross_doc,
@@ -910,7 +910,7 @@ static PyObject *Vector_cross(VectorObject *self, PyObject *value)
return NULL;
if (self->size == 3) {
- ret = Vector_CreatePyObject(NULL, 3, Py_NEW, Py_TYPE(self));
+ ret = Vector_CreatePyObject(NULL, 3, Py_TYPE(self));
cross_v3_v3v3(((VectorObject *)ret)->vec, self->vec, tvec);
}
else {
@@ -1102,7 +1102,7 @@ static PyObject *Vector_rotation_difference(VectorObject *self, PyObject *value)
rotation_between_vecs_to_quat(quat, vec_a, vec_b);
- return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
+ return Quaternion_CreatePyObject(quat, NULL);
}
PyDoc_STRVAR(Vector_project_doc,
@@ -1148,7 +1148,7 @@ static PyObject *Vector_project(VectorObject *self, PyObject *value)
for (x = 0; x < size; x++) {
vec[x] = (float)dot * tvec[x];
}
- return Vector_CreatePyObject(vec, size, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(vec, size, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_lerp_doc,
@@ -1287,7 +1287,7 @@ static PyObject *Vector_slerp(VectorObject *self, PyObject *args)
ret_vec[x] = (w[0] * self_vec[x]) + (w[1] * other_vec[x]);
}
- return Vector_CreatePyObject(ret_vec, size, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(ret_vec, size, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_rotate_doc,
@@ -1336,7 +1336,7 @@ static PyObject *Vector_copy(VectorObject *self)
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- return Vector_CreatePyObject(self->vec, self->size, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(self->vec, self->size, Py_TYPE(self));
}
static PyObject *Vector_deepcopy(VectorObject *self, PyObject *args)
{
@@ -1540,8 +1540,7 @@ static PyObject *Vector_add(PyObject *v1, PyObject *v2)
}
vec = PyMem_Malloc(vec1->size * sizeof(float));
-
- if (vec == NULL) { /*allocation failure*/
+ if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector(): "
"problem allocating pointer space");
@@ -1612,8 +1611,7 @@ static PyObject *Vector_sub(PyObject *v1, PyObject *v2)
}
vec = PyMem_Malloc(vec1->size * sizeof(float));
-
- if (vec == NULL) { /*allocation failure*/
+ if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector(): "
"problem allocating pointer space");
@@ -1705,8 +1703,7 @@ int column_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec,
static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
{
float *tvec = PyMem_Malloc(vec->size * sizeof(float));
-
- if (tvec == NULL) { /*allocation failure*/
+ if (tvec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"vec * float: "
"problem allocating pointer space");
@@ -1765,7 +1762,7 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
vec_size = ((MatrixObject *)v2)->num_col;
}
- return Vector_CreatePyObject(tvec, vec_size, Py_NEW, Py_TYPE(vec1));
+ return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
}
else if (QuaternionObject_Check(v2)) {
/* VEC * QUAT */
@@ -1791,7 +1788,7 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
copy_v3_v3(tvec, vec1->vec);
mul_qt_v3(quat2->quat, tvec);
- return Vector_CreatePyObject(tvec, 3, Py_NEW, Py_TYPE(vec1));
+ return Vector_CreatePyObject(tvec, 3, Py_TYPE(vec1));
#endif
/* ------ to be removed ------*/
}
@@ -1923,7 +1920,7 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2)
vec = PyMem_Malloc(vec1->size * sizeof(float));
- if (vec == NULL) { /*allocation failure*/
+ if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"vec / value: "
"problem allocating pointer space");
@@ -2308,7 +2305,7 @@ static PyObject *Vector_swizzle_get(VectorObject *self, void *closure)
axis_to++;
}
- return Vector_CreatePyObject(vec, axis_to, Py_NEW, Py_TYPE(self));
+ return Vector_CreatePyObject(vec, axis_to, Py_TYPE(self));
}
/* Set the items of this vector using a swizzle.
@@ -2994,15 +2991,12 @@ PyTypeObject vector_Type = {
NULL
};
-/*------------------------Vector_CreatePyObject (internal)-------------
- * creates a new vector object
- * pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- * (i.e. it was allocated elsewhere by MEM_mallocN())
- * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- * (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTypeObject *base_type)
+PyObject *Vector_CreatePyObject(
+ const float *vec, const int size,
+ PyTypeObject *base_type)
{
VectorObject *self;
+ float *vec_alloc;
if (size < 2) {
PyErr_SetString(PyExc_RuntimeError,
@@ -3010,44 +3004,72 @@ PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTy
return NULL;
}
- self = base_type ? (VectorObject *)base_type->tp_alloc(base_type, 0) :
- (VectorObject *)PyObject_GC_New(VectorObject, &vector_Type);
+ vec_alloc = PyMem_Malloc(size * sizeof(float));
+ if (UNLIKELY(vec_alloc == NULL)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "Vector(): "
+ "problem allocating data");
+ return NULL;
+ }
+ self = BASE_MATH_NEW(VectorObject, vector_Type, base_type);
if (self) {
+ self->vec = vec_alloc;
self->size = size;
/* init callbacks as NULL */
self->cb_user = NULL;
self->cb_type = self->cb_subtype = 0;
- if (type == Py_WRAP) {
- self->vec = vec;
- self->wrapped = Py_WRAP;
+ if (vec) {
+ memcpy(self->vec, vec, size * sizeof(float));
}
- else if (type == Py_NEW) {
- self->vec = PyMem_Malloc(size * sizeof(float));
- if (vec) {
- memcpy(self->vec, vec, size * sizeof(float));
+ else { /* new empty */
+ fill_vn_fl(self->vec, size, 0.0f);
+ if (size == 4) { /* do the homogeneous thing */
+ self->vec[3] = 1.0f;
}
- else { /* new empty */
- fill_vn_fl(self->vec, size, 0.0f);
- if (size == 4) { /* do the homogeneous thing */
- self->vec[3] = 1.0f;
- }
- }
- self->wrapped = Py_NEW;
- }
- else {
- Py_FatalError("Vector(): invalid type!");
}
+ self->flag = BASE_MATH_FLAG_DEFAULT;
+ }
+ else {
+ PyMem_Free(vec_alloc);
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject *Vector_CreatePyObject_wrap(
+ float *vec, const int size,
+ PyTypeObject *base_type)
+{
+ VectorObject *self;
+
+ if (size < 2) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Vector(): invalid size");
+ return NULL;
+ }
+
+ self = BASE_MATH_NEW(VectorObject, vector_Type, base_type);
+ if (self) {
+ self->size = size;
+
+ /* init callbacks as NULL */
+ self->cb_user = NULL;
+ self->cb_type = self->cb_subtype = 0;
+
+ self->vec = vec;
+ self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP;
}
return (PyObject *) self;
}
-PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, unsigned char cb_type, unsigned char cb_subtype)
+PyObject *Vector_CreatePyObject_cb(
+ PyObject *cb_user, int size,
+ unsigned char cb_type, unsigned char cb_subtype)
{
- float dummy[4] = {0.0, 0.0, 0.0, 0.0}; /* dummy init vector, callbacks will be used on access */
- VectorObject *self = (VectorObject *)Vector_CreatePyObject(dummy, size, Py_NEW, NULL);
+ VectorObject *self = (VectorObject *)Vector_CreatePyObject(NULL, size, NULL);
if (self) {
Py_INCREF(cb_user);
self->cb_user = cb_user;
@@ -3059,11 +3081,15 @@ PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, unsigned char cb
return (PyObject *)self;
}
-PyObject *Vector_CreatePyObject_alloc(const float *vec, const int size, PyTypeObject *base_type)
+PyObject *Vector_CreatePyObject_alloc(
+ float *vec, const int size,
+ PyTypeObject *base_type)
{
- VectorObject *vect_ob;
- vect_ob = (VectorObject *)Vector_CreatePyObject((float *)vec, size, Py_WRAP, base_type);
- vect_ob->wrapped = Py_NEW;
+ VectorObject *self;
+ self = (VectorObject *)Vector_CreatePyObject_wrap(vec, size, base_type);
+ if (self) {
+ self->flag = BASE_MATH_FLAG_DEFAULT;
+ }
- return (PyObject *)vect_ob;
+ return (PyObject *)self;
}
diff --git a/source/blender/python/mathutils/mathutils_Vector.h b/source/blender/python/mathutils/mathutils_Vector.h
index 2074270670a..74ca3336f4b 100644
--- a/source/blender/python/mathutils/mathutils_Vector.h
+++ b/source/blender/python/mathutils/mathutils_Vector.h
@@ -34,13 +34,25 @@ extern PyTypeObject vector_Type;
typedef struct {
BASE_MATH_MEMBERS(vec);
- int size; /* vec size 2,3 or 4 */
+ int size; /* vec size 2 or more */
} VectorObject;
/*prototypes*/
-PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTypeObject *base_type);
-PyObject *Vector_CreatePyObject_cb(PyObject *user, int size,
- unsigned char cb_type, unsigned char subtype);
-PyObject *Vector_CreatePyObject_alloc(const float *vec, const int size, PyTypeObject *base_type);
+PyObject *Vector_CreatePyObject(
+ const float *vec, const int size,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT;
+PyObject *Vector_CreatePyObject_wrap(
+ float *vec, const int size,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+PyObject *Vector_CreatePyObject_cb(
+ PyObject *user, int size,
+ unsigned char cb_type, unsigned char subtype
+ ) ATTR_WARN_UNUSED_RESULT;
+PyObject *Vector_CreatePyObject_alloc(
+ float *vec, const int size,
+ PyTypeObject *base_type
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
#endif /* __MATHUTILS_VECTOR_H__ */
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 0f0ffe9fec5..b496ee1fbf6 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -42,6 +42,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "../generic/python_utildefines.h"
/*-------------------------DOC STRINGS ---------------------------*/
PyDoc_STRVAR(M_Geometry_doc,
@@ -72,48 +73,37 @@ PyDoc_STRVAR(M_Geometry_intersect_ray_tri_doc,
);
static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *ray, *ray_off, *vec1, *vec2, *vec3;
- float dir[3], orig[3], v1[3], v2[3], v3[3], e1[3], e2[3], pvec[3], tvec[3], qvec[3];
+ const char *error_prefix = "intersect_ray_tri";
+ PyObject *py_ray, *py_ray_off, *py_tri[3];
+ float dir[3], orig[3], tri[3][3], e1[3], e2[3], pvec[3], tvec[3], qvec[3];
float det, inv_det, u, v, t;
int clip = 1;
+ int i;
- if (!PyArg_ParseTuple(args,
- "O!O!O!O!O!|i:intersect_ray_tri",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3,
- &vector_Type, &ray,
- &vector_Type, &ray_off, &clip))
+ if (!PyArg_ParseTuple(
+ args, "OOOOO|i:intersect_ray_tri",
+ UNPACK3_EX(&, py_tri, ), &py_ray, &py_ray_off, &clip))
{
return NULL;
}
- if (vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || ray->size != 3 || ray_off->size != 3) {
- PyErr_SetString(PyExc_ValueError,
- "only 3D vectors for all parameters");
- return NULL;
- }
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1 ||
- BaseMath_ReadCallback(ray) == -1 ||
- BaseMath_ReadCallback(ray_off) == -1)
+ if (((mathutils_array_parse(dir, 3, 3, py_ray, error_prefix) != -1) &&
+ (mathutils_array_parse(orig, 3, 3, py_ray_off, error_prefix) != -1)) == 0)
{
return NULL;
}
- copy_v3_v3(v1, vec1->vec);
- copy_v3_v3(v2, vec2->vec);
- copy_v3_v3(v3, vec3->vec);
+ for (i = 0; i < ARRAY_SIZE(tri); i++) {
+ if (mathutils_array_parse(tri[i], 2, 2 | MU_ARRAY_SPILL, py_tri[i], error_prefix) == -1) {
+ return NULL;
+ }
+ }
- copy_v3_v3(dir, ray->vec);
normalize_v3(dir);
- copy_v3_v3(orig, ray_off->vec);
-
/* find vectors for two edges sharing v1 */
- sub_v3_v3v3(e1, v2, v1);
- sub_v3_v3v3(e2, v3, v1);
+ sub_v3_v3v3(e1, tri[1], tri[0]);
+ sub_v3_v3v3(e2, tri[2], tri[0]);
/* begin calculating determinant - also used to calculated U parameter */
cross_v3_v3v3(pvec, dir, e2);
@@ -128,7 +118,7 @@ static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject *
inv_det = 1.0f / det;
/* calculate distance from v1 to ray origin */
- sub_v3_v3v3(tvec, orig, v1);
+ sub_v3_v3v3(tvec, orig, tri[0]);
/* calculate U parameter and test bounds */
u = dot_v3v3(tvec, pvec) * inv_det;
@@ -157,7 +147,7 @@ static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject *
mul_v3_fl(dir, t);
add_v3_v3v3(pvec, orig, dir);
- return Vector_CreatePyObject(pvec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(pvec, 3, NULL);
}
/* Line-Line intersection using algorithm from mathworld.wolfram.com */
@@ -179,82 +169,49 @@ PyDoc_STRVAR(M_Geometry_intersect_line_line_doc,
);
static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject *args)
{
+ const char *error_prefix = "intersect_line_line";
PyObject *tuple;
- VectorObject *vec1, *vec2, *vec3, *vec4;
- float v1[3], v2[3], v3[3], v4[3], i1[3], i2[3];
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_line_line",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3,
- &vector_Type, &vec4))
+ PyObject *py_lines[4];
+ float lines[4][3], i1[3], i2[3];
+ int len;
+ int result;
+
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_line_line",
+ UNPACK4_EX(&, py_lines, )))
{
return NULL;
}
- if (vec1->size != vec2->size || vec1->size != vec3->size || vec3->size != vec2->size) {
- PyErr_SetString(PyExc_ValueError,
- "vectors must be of the same size");
- return NULL;
- }
-
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1 ||
- BaseMath_ReadCallback(vec4) == -1)
+ if ((((len = mathutils_array_parse(lines[0], 2, 3, py_lines[0], error_prefix)) != -1) &&
+ (mathutils_array_parse(lines[1], len, len, py_lines[1], error_prefix) != -1) &&
+ (mathutils_array_parse(lines[2], len, len, py_lines[2], error_prefix) != -1) &&
+ (mathutils_array_parse(lines[3], len, len, py_lines[3], error_prefix) != -1)) == 0)
{
return NULL;
}
- if (vec1->size == 3 || vec1->size == 2) {
- int result;
-
- if (vec1->size == 3) {
- copy_v3_v3(v1, vec1->vec);
- copy_v3_v3(v2, vec2->vec);
- copy_v3_v3(v3, vec3->vec);
- copy_v3_v3(v4, vec4->vec);
- }
- else {
- v1[0] = vec1->vec[0];
- v1[1] = vec1->vec[1];
- v1[2] = 0.0f;
-
- v2[0] = vec2->vec[0];
- v2[1] = vec2->vec[1];
- v2[2] = 0.0f;
-
- v3[0] = vec3->vec[0];
- v3[1] = vec3->vec[1];
- v3[2] = 0.0f;
-
- v4[0] = vec4->vec[0];
- v4[1] = vec4->vec[1];
- v4[2] = 0.0f;
- }
+ if (len == 2) {
+ lines[0][2] = lines[1][2] = lines[2][2] = lines[3][2] = 0.0f;
+ }
- 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);
- }
+ result = isect_line_line_v3(UNPACK4(lines), 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, lines[2], lines[3]);
+ }
- if (result == 0) {
- /* colinear */
- Py_RETURN_NONE;
- }
- else {
- tuple = PyTuple_New(2);
- PyTuple_SET_ITEM(tuple, 0, Vector_CreatePyObject(i1, vec1->size, Py_NEW, NULL));
- PyTuple_SET_ITEM(tuple, 1, Vector_CreatePyObject(i2, vec1->size, Py_NEW, NULL));
- return tuple;
- }
+ if (result == 0) {
+ /* colinear */
+ Py_RETURN_NONE;
}
else {
- PyErr_SetString(PyExc_ValueError,
- "2D/3D vectors only");
- return NULL;
+ tuple = PyTuple_New(2);
+ PyTuple_SET_ITEMS(tuple,
+ Vector_CreatePyObject(i1, len, NULL),
+ Vector_CreatePyObject(i2, len, NULL));
+ return tuple;
}
}
@@ -277,31 +234,30 @@ PyDoc_STRVAR(M_Geometry_intersect_sphere_sphere_2d_doc,
);
static PyObject *M_Geometry_intersect_sphere_sphere_2d(PyObject *UNUSED(self), PyObject *args)
{
+ const char *error_prefix = "intersect_sphere_sphere_2d";
PyObject *ret;
- VectorObject *vec_a, *vec_b;
- const float *v_a, *v_b;
+ PyObject *py_v_a, *py_v_b;
+ float v_a[2], v_b[2];
float rad_a, rad_b;
float v_ab[2];
float dist;
- if (!PyArg_ParseTuple(args, "O!fO!f:intersect_sphere_sphere_2d",
- &vector_Type, &vec_a, &rad_a,
- &vector_Type, &vec_b, &rad_b))
+ if (!PyArg_ParseTuple(
+ args, "OfOf:intersect_sphere_sphere_2d",
+ &py_v_a, &rad_a,
+ &py_v_b, &rad_b))
{
return NULL;
}
- if (BaseMath_ReadCallback(vec_a) == -1 ||
- BaseMath_ReadCallback(vec_b) == -1)
+ if (((mathutils_array_parse(v_a, 2, 2, py_v_a, error_prefix) != -1) &&
+ (mathutils_array_parse(v_b, 2, 2, py_v_b, error_prefix) != -1)) == 0)
{
return NULL;
}
ret = PyTuple_New(2);
- v_a = vec_a->vec;
- v_b = vec_b->vec;
-
sub_v2_v2v2(v_ab, v_b, v_a);
dist = len_v2(v_ab);
@@ -313,8 +269,9 @@ static PyObject *M_Geometry_intersect_sphere_sphere_2d(PyObject *UNUSED(self), P
(dist < FLT_EPSILON))
{
/* out of range */
- PyTuple_SET_ITEM(ret, 0, Py_None); Py_INCREF(Py_None);
- PyTuple_SET_ITEM(ret, 1, Py_None); Py_INCREF(Py_None);
+ PyTuple_SET_ITEMS(ret,
+ Py_INCREF_RET(Py_None),
+ Py_INCREF_RET(Py_None));
}
else {
const float dist_delta = ((rad_a * rad_a) - (rad_b * rad_b) + (dist * dist)) / (2.0f * dist);
@@ -331,94 +288,51 @@ static PyObject *M_Geometry_intersect_sphere_sphere_2d(PyObject *UNUSED(self), P
i2[0] = i_cent[0] - h * v_ab[1] / dist;
i2[1] = i_cent[1] + h * v_ab[0] / dist;
- PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(i1, 2, Py_NEW, NULL));
- PyTuple_SET_ITEM(ret, 1, Vector_CreatePyObject(i2, 2, Py_NEW, NULL));
+ PyTuple_SET_ITEMS(ret,
+ Vector_CreatePyObject(i1, 2, NULL),
+ Vector_CreatePyObject(i2, 2, NULL));
}
return ret;
}
PyDoc_STRVAR(M_Geometry_normal_doc,
-".. function:: normal(v1, v2, v3, v4=None)\n"
+".. function:: normal(vectors)\n"
"\n"
-" Returns the normal of the 3D tri or quad.\n"
+" Returns the normal of a 3D polygon.\n"
"\n"
-" :arg v1: Point1\n"
-" :type v1: :class:`mathutils.Vector`\n"
-" :arg v2: Point2\n"
-" :type v2: :class:`mathutils.Vector`\n"
-" :arg v3: Point3\n"
-" :type v3: :class:`mathutils.Vector`\n"
-" :arg v4: Point4 (optional)\n"
-" :type v4: :class:`mathutils.Vector`\n"
+" :arg vectors: Vectors to calculate normals with\n"
+" :type vectors: sequence of 3 or more 3d vector\n"
" :rtype: :class:`mathutils.Vector`\n"
);
static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec1, *vec2, *vec3, *vec4;
+ float (*coords)[3];
+ int coords_len;
float n[3];
+ PyObject *ret = NULL;
- if (PyTuple_GET_SIZE(args) == 3) {
- if (!PyArg_ParseTuple(args, "O!O!O!:normal",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3))
- {
- return NULL;
- }
-
- if (vec1->size != vec2->size || vec1->size != vec3->size) {
- PyErr_SetString(PyExc_ValueError,
- "vectors must be of the same size");
- return NULL;
- }
- if (vec1->size < 3) {
- PyErr_SetString(PyExc_ValueError,
- "2D vectors unsupported");
- return NULL;
- }
-
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1)
- {
- return NULL;
- }
-
- normal_tri_v3(n, vec1->vec, vec2->vec, vec3->vec);
+ /* use */
+ if (PyTuple_GET_SIZE(args) == 1) {
+ args = PyTuple_GET_ITEM(args, 0);
}
- else {
- if (!PyArg_ParseTuple(args, "O!O!O!O!:normal",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3,
- &vector_Type, &vec4))
- {
- return NULL;
- }
- if (vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) {
- PyErr_SetString(PyExc_ValueError,
- "vectors must be of the same size");
- return NULL;
- }
- if (vec1->size < 3) {
- PyErr_SetString(PyExc_ValueError,
- "2D vectors unsupported");
- return NULL;
- }
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1 ||
- BaseMath_ReadCallback(vec4) == -1)
- {
- return NULL;
- }
+ if ((coords_len = mathutils_array_parse_alloc_v((float **)&coords, 3 | MU_ARRAY_SPILL, args, "normal")) == -1) {
+ return NULL;
+ }
- normal_quad_v3(n, vec1->vec, vec2->vec, vec3->vec, vec4->vec);
+ if (coords_len < 3) {
+ PyErr_SetString(PyExc_ValueError,
+ "Expected 3 or more vectors");
+ goto finally;
}
- return Vector_CreatePyObject(n, 3, Py_NEW, NULL);
+ normal_poly_v3(n, (const float (*)[3])coords, coords_len);
+ ret = Vector_CreatePyObject(n, 3, NULL);
+
+finally:
+ PyMem_Free(coords);
+ return ret;
}
/* --------------------------------- AREA FUNCTIONS-------------------- */
@@ -438,40 +352,26 @@ PyDoc_STRVAR(M_Geometry_area_tri_doc,
);
static PyObject *M_Geometry_area_tri(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec1, *vec2, *vec3;
-
- if (!PyArg_ParseTuple(args, "O!O!O!:area_tri",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3))
+ const char *error_prefix = "area_tri";
+ PyObject *py_tri[3];
+ float tri[3][3];
+ int len;
+
+ if (!PyArg_ParseTuple(
+ args, "OOO:area_tri",
+ UNPACK3_EX(&, py_tri, )))
{
return NULL;
}
- if (vec1->size != vec2->size || vec1->size != vec3->size) {
- PyErr_SetString(PyExc_ValueError,
- "vectors must be of the same size");
- return NULL;
- }
-
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1)
+ if ((((len = mathutils_array_parse(tri[0], 2, 3, py_tri[0], error_prefix)) != -1) &&
+ (mathutils_array_parse(tri[1], len, len, py_tri[1], error_prefix) != -1) &&
+ (mathutils_array_parse(tri[2], len, len, py_tri[2], error_prefix) != -1)) == 0)
{
return NULL;
}
- if (vec1->size == 3) {
- return PyFloat_FromDouble(area_tri_v3(vec1->vec, vec2->vec, vec3->vec));
- }
- else if (vec1->size == 2) {
- return PyFloat_FromDouble(area_tri_v2(vec1->vec, vec2->vec, vec3->vec));
- }
- else {
- PyErr_SetString(PyExc_ValueError,
- "only 2D,3D vectors are supported");
- return NULL;
- }
+ return PyFloat_FromDouble((len == 3 ? area_tri_v3 : area_tri_v2)(UNPACK3(tri)));
}
PyDoc_STRVAR(M_Geometry_volume_tetrahedron_doc,
@@ -491,33 +391,25 @@ PyDoc_STRVAR(M_Geometry_volume_tetrahedron_doc,
);
static PyObject *M_Geometry_volume_tetrahedron(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec1, *vec2, *vec3, *vec4;
+ const char *error_prefix = "volume_tetrahedron";
+ PyObject *py_tet[4];
+ float tet[4][3];
+ int i;
- if (!PyArg_ParseTuple(args, "O!O!O!O!:volume_tetrahedron",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3,
- &vector_Type, &vec4))
+ if (!PyArg_ParseTuple(
+ args, "OOOO:volume_tetrahedron",
+ UNPACK4_EX(&, py_tet, )))
{
return NULL;
}
- if (vec1->size < 3 || vec2->size < 3 || vec3->size < 3 || vec4->size < 3) {
- PyErr_SetString(PyExc_ValueError,
- "geometry.volume_tetrahedron(...): "
- " can't use 2D Vectors");
- return NULL;
- }
-
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1 ||
- BaseMath_ReadCallback(vec4) == -1)
- {
- return NULL;
+ for (i = 0; i < ARRAY_SIZE(tet); i++) {
+ if (mathutils_array_parse(tet[i], 3, 3 | MU_ARRAY_SPILL, py_tet[i], error_prefix) == -1) {
+ return NULL;
+ }
}
- return PyFloat_FromDouble(volume_tetrahedron_v3(vec1->vec, vec2->vec, vec3->vec, vec4->vec));
+ return PyFloat_FromDouble(volume_tetrahedron_v3(UNPACK4(tet)));
}
PyDoc_STRVAR(M_Geometry_intersect_line_line_2d_doc,
@@ -538,27 +430,27 @@ PyDoc_STRVAR(M_Geometry_intersect_line_line_2d_doc,
);
static PyObject *M_Geometry_intersect_line_line_2d(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *line_a1, *line_a2, *line_b1, *line_b2;
+ const char *error_prefix = "intersect_line_line_2d";
+ PyObject *py_lines[4];
+ float lines[4][2];
float vi[2];
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_line_line_2d",
- &vector_Type, &line_a1,
- &vector_Type, &line_a2,
- &vector_Type, &line_b1,
- &vector_Type, &line_b2))
+ int i;
+
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_line_line_2d",
+ UNPACK4_EX(&, py_lines, )))
{
return NULL;
}
-
- if (BaseMath_ReadCallback(line_a1) == -1 ||
- BaseMath_ReadCallback(line_a2) == -1 ||
- BaseMath_ReadCallback(line_b1) == -1 ||
- BaseMath_ReadCallback(line_b2) == -1)
- {
- return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(lines); i++) {
+ if (mathutils_array_parse(lines[i], 2, 2 | MU_ARRAY_SPILL, py_lines[i], error_prefix) == -1) {
+ return NULL;
+ }
}
- if (isect_seg_seg_v2_point(line_a1->vec, line_a2->vec, line_b1->vec, line_b2->vec, vi) == 1) {
- return Vector_CreatePyObject(vi, 2, Py_NEW, NULL);
+ if (isect_seg_seg_v2_point(UNPACK4(lines), vi) == 1) {
+ return Vector_CreatePyObject(vi, 2, NULL);
}
else {
Py_RETURN_NONE;
@@ -585,38 +477,31 @@ PyDoc_STRVAR(M_Geometry_intersect_line_plane_doc,
);
static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *line_a, *line_b, *plane_co, *plane_no;
+ const char *error_prefix = "intersect_line_plane";
+ PyObject *py_line_a, *py_line_b, *py_plane_co, *py_plane_no;
+ float line_a[3], line_b[3], plane_co[3], plane_no[3];
float isect[3];
int no_flip = false;
- if (!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_line_plane",
- &vector_Type, &line_a,
- &vector_Type, &line_b,
- &vector_Type, &plane_co,
- &vector_Type, &plane_no,
- &no_flip))
+ if (!PyArg_ParseTuple(
+ args, "OOOO|i:intersect_line_plane",
+ &py_line_a, &py_line_b, &py_plane_co, &py_plane_no,
+ &no_flip))
{
return NULL;
}
- if (BaseMath_ReadCallback(line_a) == -1 ||
- BaseMath_ReadCallback(line_b) == -1 ||
- BaseMath_ReadCallback(plane_co) == -1 ||
- BaseMath_ReadCallback(plane_no) == -1)
+ if (((mathutils_array_parse(line_a, 3, 3 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) &&
+ (mathutils_array_parse(line_b, 3, 3 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_co, 3, 3 | MU_ARRAY_SPILL, py_plane_co, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_no, 3, 3 | MU_ARRAY_SPILL, py_plane_no, error_prefix) != -1)) == 0)
{
return NULL;
}
- 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");
- return NULL;
- }
-
/* TODO: implements no_flip */
- if (isect_line_plane_v3(isect, line_a->vec, line_b->vec, plane_co->vec, plane_no->vec) == 1) {
- return Vector_CreatePyObject(isect, 3, Py_NEW, NULL);
+ if (isect_line_plane_v3(isect, line_a, line_b, plane_co, plane_no) == 1) {
+ return Vector_CreatePyObject(isect, 3, NULL);
}
else {
Py_RETURN_NONE;
@@ -641,68 +526,59 @@ PyDoc_STRVAR(M_Geometry_intersect_plane_plane_doc,
);
static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObject *args)
{
+ const char *error_prefix = "intersect_plane_plane";
PyObject *ret, *ret_co, *ret_no;
- VectorObject *plane_a_co, *plane_a_no, *plane_b_co, *plane_b_no;
+ PyObject *py_plane_a_co, *py_plane_a_no, *py_plane_b_co, *py_plane_b_no;
+ float plane_a_co[3], plane_a_no[3], plane_b_co[3], plane_b_no[3];
float isect_co[3];
float isect_no[3];
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_plane_plane",
- &vector_Type, &plane_a_co,
- &vector_Type, &plane_a_no,
- &vector_Type, &plane_b_co,
- &vector_Type, &plane_b_no))
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_plane_plane",
+ &py_plane_a_co, &py_plane_a_no, &py_plane_b_co, &py_plane_b_no))
{
return NULL;
}
- if (BaseMath_ReadCallback(plane_a_co) == -1 ||
- BaseMath_ReadCallback(plane_a_no) == -1 ||
- BaseMath_ReadCallback(plane_b_co) == -1 ||
- BaseMath_ReadCallback(plane_b_no) == -1)
+ if (((mathutils_array_parse(plane_a_co, 3, 3 | MU_ARRAY_SPILL, py_plane_a_co, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_a_no, 3, 3 | MU_ARRAY_SPILL, py_plane_a_no, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_b_co, 3, 3 | MU_ARRAY_SPILL, py_plane_b_co, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_b_no, 3, 3 | MU_ARRAY_SPILL, py_plane_b_no, error_prefix) != -1)) == 0)
{
return NULL;
}
- 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");
- return NULL;
- }
-
if (isect_plane_plane_v3(isect_co, isect_no,
- plane_a_co->vec, plane_a_no->vec,
- plane_b_co->vec, plane_b_no->vec))
+ plane_a_co, plane_a_no,
+ plane_b_co, plane_b_no))
{
normalize_v3(isect_no);
- ret_co = Vector_CreatePyObject(isect_co, 3, Py_NEW, NULL);
- ret_no = Vector_CreatePyObject(isect_no, 3, Py_NEW, NULL);
+ ret_co = Vector_CreatePyObject(isect_co, 3, NULL);
+ ret_no = Vector_CreatePyObject(isect_no, 3, NULL);
}
else {
- ret_co = Py_None;
- ret_no = Py_None;
-
- Py_INCREF(ret_co);
- Py_INCREF(ret_no);
+ ret_co = Py_INCREF_RET(Py_None);
+ ret_no = Py_INCREF_RET(Py_None);
}
ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, ret_co);
- PyTuple_SET_ITEM(ret, 1, ret_no);
+ PyTuple_SET_ITEMS(ret,
+ ret_co,
+ ret_no);
return ret;
}
PyDoc_STRVAR(M_Geometry_intersect_line_sphere_doc,
".. function:: intersect_line_sphere(line_a, line_b, sphere_co, sphere_radius, clip=True)\n"
"\n"
-" Takes a lines (as 2 vectors), a sphere as a point and a radius and\n"
+" Takes a line (as 2 points) and a sphere (as a point and a radius) and\n"
" returns the intersection\n"
"\n"
-" :arg line_a: First point of the first line\n"
+" :arg line_a: First point of the line\n"
" :type line_a: :class:`mathutils.Vector`\n"
-" :arg line_b: Second point of the first line\n"
+" :arg line_b: Second point of the line\n"
" :type line_b: :class:`mathutils.Vector`\n"
" :arg sphere_co: The center of the sphere\n"
" :type sphere_co: :class:`mathutils.Vector`\n"
@@ -713,35 +589,28 @@ PyDoc_STRVAR(M_Geometry_intersect_line_sphere_doc,
);
static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *line_a, *line_b, *sphere_co;
+ const char *error_prefix = "intersect_line_sphere";
+ PyObject *py_line_a, *py_line_b, *py_sphere_co;
+ float line_a[3], line_b[3], sphere_co[3];
float sphere_radius;
int clip = true;
float isect_a[3];
float isect_b[3];
- if (!PyArg_ParseTuple(args, "O!O!O!f|i:intersect_line_sphere",
- &vector_Type, &line_a,
- &vector_Type, &line_b,
- &vector_Type, &sphere_co,
- &sphere_radius, &clip))
+ if (!PyArg_ParseTuple(
+ args, "OOOf|i:intersect_line_sphere",
+ &py_line_a, &py_line_b, &py_sphere_co, &sphere_radius, &clip))
{
return NULL;
}
- if (BaseMath_ReadCallback(line_a) == -1 ||
- BaseMath_ReadCallback(line_b) == -1 ||
- BaseMath_ReadCallback(sphere_co) == -1)
+ if (((mathutils_array_parse(line_a, 3, 3 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) &&
+ (mathutils_array_parse(line_b, 3, 3 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) &&
+ (mathutils_array_parse(sphere_co, 3, 3 | MU_ARRAY_SPILL, py_sphere_co, error_prefix) != -1)) == 0)
{
return NULL;
}
-
- 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");
- return NULL;
- }
else {
bool use_a = true;
bool use_b = true;
@@ -749,14 +618,14 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
PyObject *ret = PyTuple_New(2);
- switch (isect_line_sphere_v3(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
+ switch (isect_line_sphere_v3(line_a, line_b, sphere_co, sphere_radius, isect_a, isect_b)) {
case 1:
- if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
use_b = false;
break;
case 2:
- if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
- if (!(!clip || (((lambda = line_point_factor_v3(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
+ if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v3(isect_b, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
break;
default:
use_a = false;
@@ -764,11 +633,9 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
break;
}
- if (use_a) { PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(isect_a, 3, Py_NEW, NULL)); }
- else { PyTuple_SET_ITEM(ret, 0, Py_None); Py_INCREF(Py_None); }
-
- if (use_b) { PyTuple_SET_ITEM(ret, 1, Vector_CreatePyObject(isect_b, 3, Py_NEW, NULL)); }
- else { PyTuple_SET_ITEM(ret, 1, Py_None); Py_INCREF(Py_None); }
+ PyTuple_SET_ITEMS(ret,
+ use_a ? Vector_CreatePyObject(isect_a, 3, NULL) : Py_INCREF_RET(Py_None),
+ use_b ? Vector_CreatePyObject(isect_b, 3, NULL) : Py_INCREF_RET(Py_None));
return ret;
}
@@ -778,12 +645,12 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
PyDoc_STRVAR(M_Geometry_intersect_line_sphere_2d_doc,
".. function:: intersect_line_sphere_2d(line_a, line_b, sphere_co, sphere_radius, clip=True)\n"
"\n"
-" Takes a lines (as 2 vectors), a sphere as a point and a radius and\n"
+" Takes a line (as 2 points) and a sphere (as a point and a radius) and\n"
" returns the intersection\n"
"\n"
-" :arg line_a: First point of the first line\n"
+" :arg line_a: First point of the line\n"
" :type line_a: :class:`mathutils.Vector`\n"
-" :arg line_b: Second point of the first line\n"
+" :arg line_b: Second point of the line\n"
" :type line_b: :class:`mathutils.Vector`\n"
" :arg sphere_co: The center of the sphere\n"
" :type sphere_co: :class:`mathutils.Vector`\n"
@@ -794,25 +661,25 @@ PyDoc_STRVAR(M_Geometry_intersect_line_sphere_2d_doc,
);
static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *line_a, *line_b, *sphere_co;
+ const char *error_prefix = "intersect_line_sphere_2d";
+ PyObject *py_line_a, *py_line_b, *py_sphere_co;
+ float line_a[2], line_b[2], sphere_co[2];
float sphere_radius;
int clip = true;
float isect_a[2];
float isect_b[2];
- if (!PyArg_ParseTuple(args, "O!O!O!f|i:intersect_line_sphere_2d",
- &vector_Type, &line_a,
- &vector_Type, &line_b,
- &vector_Type, &sphere_co,
- &sphere_radius, &clip))
+ if (!PyArg_ParseTuple(
+ args, "OOOf|i:intersect_line_sphere_2d",
+ &py_line_a, &py_line_b, &py_sphere_co, &sphere_radius, &clip))
{
return NULL;
}
- if (BaseMath_ReadCallback(line_a) == -1 ||
- BaseMath_ReadCallback(line_b) == -1 ||
- BaseMath_ReadCallback(sphere_co) == -1)
+ if (((mathutils_array_parse(line_a, 2, 2 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) &&
+ (mathutils_array_parse(line_b, 2, 2 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) &&
+ (mathutils_array_parse(sphere_co, 2, 2 | MU_ARRAY_SPILL, py_sphere_co, error_prefix) != -1)) == 0)
{
return NULL;
}
@@ -823,14 +690,14 @@ static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyO
PyObject *ret = PyTuple_New(2);
- switch (isect_line_sphere_v2(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
+ switch (isect_line_sphere_v2(line_a, line_b, sphere_co, sphere_radius, isect_a, isect_b)) {
case 1:
- if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
use_b = false;
break;
case 2:
- if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
- if (!(!clip || (((lambda = line_point_factor_v2(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
+ if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v2(isect_b, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
break;
default:
use_a = false;
@@ -838,11 +705,9 @@ static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyO
break;
}
- if (use_a) { PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(isect_a, 2, Py_NEW, NULL)); }
- else { PyTuple_SET_ITEM(ret, 0, Py_None); Py_INCREF(Py_None); }
-
- if (use_b) { PyTuple_SET_ITEM(ret, 1, Vector_CreatePyObject(isect_b, 2, Py_NEW, NULL)); }
- else { PyTuple_SET_ITEM(ret, 1, Py_None); Py_INCREF(Py_None); }
+ PyTuple_SET_ITEMS(ret,
+ use_a ? Vector_CreatePyObject(isect_a, 2, NULL) : Py_INCREF_RET(Py_None),
+ use_b ? Vector_CreatePyObject(isect_b, 2, NULL) : Py_INCREF_RET(Py_None));
return ret;
}
@@ -863,43 +728,35 @@ PyDoc_STRVAR(M_Geometry_intersect_point_line_doc,
);
static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt, *line_1, *line_2;
- float pt_in[3], pt_out[3], l1[3], l2[3];
+ const char *error_prefix = "intersect_point_line";
+ PyObject *py_pt, *py_line_a, *py_line_b;
+ float pt[3], pt_out[3], line_a[3], line_b[3];
float lambda;
PyObject *ret;
int size = 2;
- if (!PyArg_ParseTuple(args, "O!O!O!:intersect_point_line",
- &vector_Type, &pt,
- &vector_Type, &line_1,
- &vector_Type, &line_2))
+ if (!PyArg_ParseTuple(
+ args, "OOO:intersect_point_line",
+ &py_pt, &py_line_a, &py_line_b))
{
return NULL;
}
- if (BaseMath_ReadCallback(pt) == -1 ||
- BaseMath_ReadCallback(line_1) == -1 ||
- BaseMath_ReadCallback(line_2) == -1)
+ /* accept 2d verts */
+ if ((((size = mathutils_array_parse(pt, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_pt, error_prefix)) != -1) &&
+ (mathutils_array_parse(line_a, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_line_a, error_prefix) != -1) &&
+ (mathutils_array_parse(line_b, 3, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_line_b, error_prefix) != -1)) == 0)
{
return NULL;
}
- /* accept 2d verts */
- if (pt->size >= 3) { copy_v3_v3(pt_in, pt->vec); size = 3; }
- else { copy_v2_v2(pt_in, pt->vec); pt_in[2] = 0.0f; }
-
- if (line_1->size >= 3) { copy_v3_v3(l1, line_1->vec); size = 3; }
- else { copy_v2_v2(l1, line_1->vec); l1[2] = 0.0f; }
-
- if (line_2->size >= 3) { copy_v3_v3(l2, line_2->vec); size = 3; }
- else { copy_v2_v2(l2, line_2->vec); l2[2] = 0.0f; }
-
/* do the calculation */
- lambda = closest_to_line_v3(pt_out, pt_in, l1, l2);
+ lambda = closest_to_line_v3(pt_out, pt, line_a, line_b);
ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(pt_out, size, Py_NEW, NULL));
- PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(lambda));
+ PyTuple_SET_ITEMS(ret,
+ Vector_CreatePyObject(pt_out, size, NULL),
+ PyFloat_FromDouble(lambda));
return ret;
}
@@ -921,38 +778,30 @@ PyDoc_STRVAR(M_Geometry_intersect_point_tri_doc,
);
static PyObject *M_Geometry_intersect_point_tri(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt_vec, *tri_p1, *tri_p2, *tri_p3;
+ const char *error_prefix = "intersect_point_tri";
+ PyObject *py_pt, *py_tri[3];
+ float pt[3], tri[3][3];
float vi[3];
+ int i;
- 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))
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_point_tri",
+ &py_pt, UNPACK3_EX(&, py_tri, )))
{
return NULL;
}
- if (BaseMath_ReadCallback(pt_vec) == -1 ||
- BaseMath_ReadCallback(tri_p1) == -1 ||
- BaseMath_ReadCallback(tri_p2) == -1 ||
- BaseMath_ReadCallback(tri_p3) == -1)
- {
+ if (mathutils_array_parse(pt, 3, 3 | MU_ARRAY_SPILL, py_pt, error_prefix) == -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;
+ for (i = 0; i < ARRAY_SIZE(tri); i++) {
+ if (mathutils_array_parse(tri[i], 3, 3 | MU_ARRAY_SPILL, py_tri[i], error_prefix) == -1) {
+ 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);
+ if (isect_point_tri_v3(pt, UNPACK3(tri), vi)) {
+ return Vector_CreatePyObject(vi, 3, NULL);
}
else {
Py_RETURN_NONE;
@@ -976,26 +825,28 @@ PyDoc_STRVAR(M_Geometry_intersect_point_tri_2d_doc,
);
static PyObject *M_Geometry_intersect_point_tri_2d(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt_vec, *tri_p1, *tri_p2, *tri_p3;
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_point_tri_2d",
- &vector_Type, &pt_vec,
- &vector_Type, &tri_p1,
- &vector_Type, &tri_p2,
- &vector_Type, &tri_p3))
+ const char *error_prefix = "intersect_point_tri_2d";
+ PyObject *py_pt, *py_tri[3];
+ float pt[2], tri[3][2];
+ int i;
+
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_point_tri_2d",
+ &py_pt, UNPACK3_EX(&, py_tri, )))
{
return NULL;
}
-
- if (BaseMath_ReadCallback(pt_vec) == -1 ||
- BaseMath_ReadCallback(tri_p1) == -1 ||
- BaseMath_ReadCallback(tri_p2) == -1 ||
- BaseMath_ReadCallback(tri_p3) == -1)
- {
+
+ if (mathutils_array_parse(pt, 2, 2 | MU_ARRAY_SPILL, py_pt, error_prefix) == -1) {
return NULL;
}
+ for (i = 0; i < ARRAY_SIZE(tri); i++) {
+ if (mathutils_array_parse(tri[i], 2, 2 | MU_ARRAY_SPILL, py_tri[i], error_prefix) == -1) {
+ return NULL;
+ }
+ }
- return PyLong_FromLong(isect_point_tri_v2(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec));
+ return PyLong_FromLong(isect_point_tri_v2(pt, UNPACK3(tri)));
}
PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc,
@@ -1019,28 +870,28 @@ PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc,
);
static PyObject *M_Geometry_intersect_point_quad_2d(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt_vec, *quad_p1, *quad_p2, *quad_p3, *quad_p4;
+ const char *error_prefix = "intersect_point_quad_2d";
+ PyObject *py_pt, *py_quad[4];
+ float pt[2], quad[4][2];
+ int i;
- if (!PyArg_ParseTuple(args, "O!O!O!O!O!:intersect_point_quad_2d",
- &vector_Type, &pt_vec,
- &vector_Type, &quad_p1,
- &vector_Type, &quad_p2,
- &vector_Type, &quad_p3,
- &vector_Type, &quad_p4))
+ if (!PyArg_ParseTuple(
+ args, "OOOOO:intersect_point_quad_2d",
+ &py_pt, UNPACK4_EX(&, py_quad, )))
{
return NULL;
}
- if (BaseMath_ReadCallback(pt_vec) == -1 ||
- BaseMath_ReadCallback(quad_p1) == -1 ||
- BaseMath_ReadCallback(quad_p2) == -1 ||
- BaseMath_ReadCallback(quad_p3) == -1 ||
- BaseMath_ReadCallback(quad_p4) == -1)
- {
+ if (mathutils_array_parse(pt, 2, 2 | MU_ARRAY_SPILL, py_pt, error_prefix) == -1) {
return NULL;
}
+ for (i = 0; i < ARRAY_SIZE(quad); i++) {
+ if (mathutils_array_parse(quad[i], 2, 2 | MU_ARRAY_SPILL, py_quad[i], error_prefix) == -1) {
+ return NULL;
+ }
+ }
- return PyLong_FromLong(isect_point_quad_v2(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec));
+ return PyLong_FromLong(isect_point_quad_v2(pt, UNPACK4(quad)));
}
PyDoc_STRVAR(M_Geometry_distance_point_to_plane_doc,
@@ -1059,35 +910,27 @@ PyDoc_STRVAR(M_Geometry_distance_point_to_plane_doc,
);
static PyObject *M_Geometry_distance_point_to_plane(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt, *plane_co, *plane_no;
+ const char *error_prefix = "distance_point_to_plane";
+ PyObject *py_pt, *py_plane_co, *py_plane_no;
+ float pt[3], plane_co[3], plane_no[3];
float plane[4];
- if (!PyArg_ParseTuple(args, "O!O!O!:distance_point_to_plane",
- &vector_Type, &pt,
- &vector_Type, &plane_co,
- &vector_Type, &plane_no))
- {
- return NULL;
- }
-
- if (pt->size != 3 ||
- plane_co->size != 3 ||
- plane_no->size != 3)
+ if (!PyArg_ParseTuple(
+ args, "OOO:distance_point_to_plane",
+ &py_pt, &py_plane_co, &py_plane_no))
{
- PyErr_SetString(PyExc_ValueError,
- "One of more of the vector arguments wasn't a 3D vector");
return NULL;
}
- if (BaseMath_ReadCallback(pt) == -1 ||
- BaseMath_ReadCallback(plane_co) == -1 ||
- BaseMath_ReadCallback(plane_no) == -1)
+ if (((mathutils_array_parse(pt, 3, 3 | MU_ARRAY_SPILL, py_pt, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_co, 3, 3 | MU_ARRAY_SPILL, py_plane_co, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_no, 3, 3 | MU_ARRAY_SPILL, py_plane_no, error_prefix) != -1)) == 0)
{
return NULL;
}
- plane_from_point_normal_v3(plane, plane_co->vec, plane_no->vec);
- return PyFloat_FromDouble(dist_signed_to_plane_v3(pt->vec, plane));
+ plane_from_point_normal_v3(plane, plane_co, plane_no);
+ return PyFloat_FromDouble(dist_signed_to_plane_v3(pt, plane));
}
PyDoc_STRVAR(M_Geometry_barycentric_transform_doc,
@@ -1114,53 +957,37 @@ PyDoc_STRVAR(M_Geometry_barycentric_transform_doc,
);
static PyObject *M_Geometry_barycentric_transform(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec_pt;
- VectorObject *vec_t1_tar, *vec_t2_tar, *vec_t3_tar;
- 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",
- &vector_Type, &vec_pt,
- &vector_Type, &vec_t1_src,
- &vector_Type, &vec_t2_src,
- &vector_Type, &vec_t3_src,
- &vector_Type, &vec_t1_tar,
- &vector_Type, &vec_t2_tar,
- &vector_Type, &vec_t3_tar))
- {
- return NULL;
- }
+ const char *error_prefix = "barycentric_transform";
+ PyObject *py_pt_src, *py_tri_src[3], *py_tri_dst[3];
+ float pt_src[3], pt_dst[3], tri_src[3][3], tri_dst[3][3];
+ int i;
- if (vec_pt->size != 3 ||
- vec_t1_src->size != 3 ||
- vec_t2_src->size != 3 ||
- vec_t3_src->size != 3 ||
- vec_t1_tar->size != 3 ||
- vec_t2_tar->size != 3 ||
- vec_t3_tar->size != 3)
+ if (!PyArg_ParseTuple(
+ args, "OOOOOOO:barycentric_transform",
+ &py_pt_src,
+ UNPACK3_EX(&, py_tri_src, ),
+ UNPACK3_EX(&, py_tri_dst, )))
{
- PyErr_SetString(PyExc_ValueError,
- "One of more of the vector arguments wasn't a 3D vector");
return NULL;
}
- if (BaseMath_ReadCallback(vec_pt) == -1 ||
- BaseMath_ReadCallback(vec_t1_src) == -1 ||
- BaseMath_ReadCallback(vec_t2_src) == -1 ||
- BaseMath_ReadCallback(vec_t3_src) == -1 ||
- BaseMath_ReadCallback(vec_t1_tar) == -1 ||
- BaseMath_ReadCallback(vec_t2_tar) == -1 ||
- BaseMath_ReadCallback(vec_t3_tar) == -1)
- {
+ if (mathutils_array_parse(pt_src, 2, 2 | MU_ARRAY_SPILL, py_pt_src, error_prefix) == -1) {
return NULL;
}
+ for (i = 0; i < ARRAY_SIZE(tri_src); i++) {
+ if (((mathutils_array_parse(tri_src[i], 3, 3 | MU_ARRAY_SPILL, py_tri_src[i], error_prefix) != -1) &&
+ (mathutils_array_parse(tri_dst[i], 3, 3 | MU_ARRAY_SPILL, py_tri_dst[i], error_prefix) != -1)) == 0)
+ {
+ return NULL;
+ }
+ }
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);
+ pt_dst, pt_src,
+ UNPACK3(tri_dst),
+ UNPACK3(tri_src));
- return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(pt_dst, 3, NULL);
}
PyDoc_STRVAR(M_Geometry_points_in_planes_doc,
@@ -1180,8 +1007,9 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a
float (*planes)[4];
unsigned int planes_len;
- if (!PyArg_ParseTuple(args, "O:points_in_planes",
- &py_planes))
+ if (!PyArg_ParseTuple(
+ args, "O:points_in_planes",
+ &py_planes))
{
return NULL;
}
@@ -1233,10 +1061,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a
if (l == len) { /* ok */
/* python */
- PyObject *item = Vector_CreatePyObject(potentialVertex, 3, Py_NEW, NULL);
- PyList_Append(py_verts, item);
- Py_DECREF(item);
-
+ PyList_APPEND(py_verts, Vector_CreatePyObject(potentialVertex, 3, NULL));
planes_used[i] = planes_used[j] = planes_used[k] = true;
}
}
@@ -1252,17 +1077,16 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a
/* now make a list of used planes */
for (i = 0; i < len; i++) {
if (planes_used[i]) {
- PyObject *item = PyLong_FromLong(i);
- PyList_Append(py_plane_index, item);
- Py_DECREF(item);
+ PyList_APPEND(py_plane_index, PyLong_FromLong(i));
}
}
PyMem_Free(planes_used);
{
PyObject *ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, py_verts);
- PyTuple_SET_ITEM(ret, 1, py_plane_index);
+ PyTuple_SET_ITEMS(ret,
+ py_verts,
+ py_plane_index);
return ret;
}
}
@@ -1290,58 +1114,45 @@ PyDoc_STRVAR(M_Geometry_interpolate_bezier_doc,
);
static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec_k1, *vec_h1, *vec_k2, *vec_h2;
+ const char *error_prefix = "interpolate_bezier";
+ PyObject *py_data[4];
+ float data[4][4] = {{0.0f}};
int resolu;
- int dims;
+ int dims = 0;
int i;
float *coord_array, *fp;
PyObject *list;
- float k1[4] = {0.0, 0.0, 0.0, 0.0};
- float h1[4] = {0.0, 0.0, 0.0, 0.0};
- float k2[4] = {0.0, 0.0, 0.0, 0.0};
- float h2[4] = {0.0, 0.0, 0.0, 0.0};
-
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!i:interpolate_bezier",
- &vector_Type, &vec_k1,
- &vector_Type, &vec_h1,
- &vector_Type, &vec_h2,
- &vector_Type, &vec_k2, &resolu))
+ if (!PyArg_ParseTuple(
+ args, "OOOOi:interpolate_bezier",
+ UNPACK4_EX(&, py_data, ), &resolu))
{
return NULL;
}
+ for (i = 0; i < 4; i++) {
+ int dims_tmp;
+ if ((((dims_tmp = mathutils_array_parse(data[i], 2, 2 | MU_ARRAY_SPILL, py_data[i], error_prefix)) == -1))) {
+ return NULL;
+ }
+ dims = max_ii(dims, dims_tmp);
+ }
+
if (resolu <= 1) {
PyErr_SetString(PyExc_ValueError,
"resolution must be 2 or over");
return NULL;
}
- if (BaseMath_ReadCallback(vec_k1) == -1 ||
- BaseMath_ReadCallback(vec_h1) == -1 ||
- BaseMath_ReadCallback(vec_k2) == -1 ||
- BaseMath_ReadCallback(vec_h2) == -1)
- {
- return NULL;
- }
-
- dims = max_iiii(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);
-
- for (i = 0; i < vec_k1->size; i++) k1[i] = vec_k1->vec[i];
- for (i = 0; i < vec_h1->size; i++) h1[i] = vec_h1->vec[i];
- for (i = 0; i < vec_k2->size; i++) k2[i] = vec_k2->vec[i];
- for (i = 0; i < vec_h2->size; i++) h2[i] = vec_h2->vec[i];
-
- coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "interpolate_bezier");
+ coord_array = MEM_callocN(dims * (resolu) * sizeof(float), error_prefix);
for (i = 0; i < dims; i++) {
- BKE_curve_forward_diff_bezier(k1[i], h1[i], h2[i], k2[i], coord_array + i, resolu - 1, sizeof(float) * dims);
+ BKE_curve_forward_diff_bezier(UNPACK4_EX(, data, [i]), coord_array + i, resolu - 1, sizeof(float) * dims);
}
list = PyList_New(resolu);
fp = coord_array;
for (i = 0; i < resolu; i++, fp = fp + dims) {
- PyList_SET_ITEM(list, i, Vector_CreatePyObject(fp, dims, Py_NEW, NULL));
+ PyList_SET_ITEM(list, i, Vector_CreatePyObject(fp, dims, NULL));
}
MEM_freeN(coord_array);
return list;
@@ -1581,8 +1392,9 @@ static PyObject *M_Geometry_box_pack_2d(PyObject *UNUSED(self), PyObject *boxlis
}
ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(tot_width));
- PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(tot_height));
+ PyTuple_SET_ITEMS(ret,
+ PyFloat_FromDouble(tot_width),
+ PyFloat_FromDouble(tot_height));
return ret;
}
diff --git a/source/blender/python/mathutils/mathutils_kdtree.c b/source/blender/python/mathutils/mathutils_kdtree.c
index 519778aea7d..199c2e02da4 100644
--- a/source/blender/python/mathutils/mathutils_kdtree.c
+++ b/source/blender/python/mathutils/mathutils_kdtree.c
@@ -35,6 +35,7 @@
#include "BLI_kdtree.h"
#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
#include "mathutils.h"
#include "mathutils_kdtree.h" /* own include */
@@ -58,9 +59,10 @@ static void kdtree_nearest_to_py_tuple(const KDTreeNearest *nearest, PyObject *p
BLI_assert(nearest->index >= 0);
BLI_assert(PyTuple_GET_SIZE(py_retval) == 3);
- PyTuple_SET_ITEM(py_retval, 0, Vector_CreatePyObject((float *)nearest->co, 3, Py_NEW, NULL));
- PyTuple_SET_ITEM(py_retval, 1, PyLong_FromLong(nearest->index));
- PyTuple_SET_ITEM(py_retval, 2, PyFloat_FromDouble(nearest->dist));
+ PyTuple_SET_ITEMS(py_retval,
+ Vector_CreatePyObject((float *)nearest->co, 3, NULL),
+ PyLong_FromLong(nearest->index),
+ PyFloat_FromDouble(nearest->dist));
}
static PyObject *kdtree_nearest_to_py(const KDTreeNearest *nearest)
@@ -126,7 +128,7 @@ static void PyKDTree__tp_dealloc(PyKDTree *self)
}
PyDoc_STRVAR(py_kdtree_insert_doc,
-".. method:: insert(index, co)\n"
+".. method:: insert(co, index)\n"
"\n"
" Insert a point into the KDTree.\n"
"\n"
@@ -171,6 +173,10 @@ PyDoc_STRVAR(py_kdtree_balance_doc,
".. method:: balance()\n"
"\n"
" Balance the tree.\n"
+"\n"
+".. note::\n"
+"\n"
+" This builds the entire tree, avoid calling after each insertion.\n"
);
static PyObject *py_kdtree_balance(PyKDTree *self)
{
diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c
index 8dfa7904300..f0449c23dcd 100644
--- a/source/blender/python/mathutils/mathutils_noise.c
+++ b/source/blender/python/mathutils/mathutils_noise.c
@@ -34,8 +34,6 @@
#include <Python.h>
-#include "structseq.h"
-
#include "BLI_math.h"
#include "BLI_noise.h"
#include "BLI_utildefines.h"
@@ -311,7 +309,7 @@ static PyObject *M_Noise_random_unit_vector(PyObject *UNUSED(self), PyObject *ar
norm = normalize_vn(vec, size);
}
- return Vector_CreatePyObject(vec, size, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec, size, NULL);
}
/* This is dumb, most people will want a unit vector anyway, since this doesn't have uniform distribution over a sphere*/
#if 0
@@ -340,7 +338,7 @@ static PyObject *M_Noise_random_vector(PyObject *UNUSED(self), PyObject *args)
rand_vn(vec, size);
- return Vector_CreatePyObject(vec, size, Py_NEW, NULL);
+ return Vector_CreatePyObject(vec, size, NULL);
}
#endif
@@ -414,7 +412,7 @@ static PyObject *M_Noise_noise_vector(PyObject *UNUSED(self), PyObject *args)
noise_vector(vec[0], vec[1], vec[2], nb, r_vec);
- return Vector_CreatePyObject(r_vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(r_vec, 3, NULL);
}
PyDoc_STRVAR(M_Noise_turbulence_doc,
@@ -486,7 +484,7 @@ static PyObject *M_Noise_turbulence_vector(PyObject *UNUSED(self), PyObject *arg
return NULL;
vTurb(vec[0], vec[1], vec[2], oct, hd, nb, as, fs, r_vec);
- return Vector_CreatePyObject(r_vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(r_vec, 3, NULL);
}
/* F. Kenton Musgrave's fractal functions */
@@ -738,7 +736,7 @@ static PyObject *M_Noise_voronoi(PyObject *UNUSED(self), PyObject *args)
voronoi(vec[0], vec[1], vec[2], da, pa, me, dtype);
for (i = 0; i < 4; i++) {
- PyList_SET_ITEM(list, i, Vector_CreatePyObject(pa + 3 * i, 3, Py_NEW, NULL));
+ PyList_SET_ITEM(list, i, Vector_CreatePyObject(pa + 3 * i, 3, NULL));
}
return Py_BuildValue("[[ffff]O]", da[0], da[1], da[2], da[3], list);
@@ -790,7 +788,7 @@ static PyObject *M_Noise_cell_vector(PyObject *UNUSED(self), PyObject *args)
return NULL;
cellNoiseV(vec[0], vec[1], vec[2], r_vec);
- return Vector_CreatePyObject(r_vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(r_vec, 3, NULL);
}
static PyMethodDef M_Noise_methods[] = {
diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript
index 7f459444a39..ebd131082e4 100644
--- a/source/blender/render/SConscript
+++ b/source/blender/render/SConscript
@@ -38,7 +38,6 @@ incs = [
'../blenkernel',
'../blenlib',
'../imbuf',
- '../include',
'../makesdna',
'../makesrna',
'../../../intern/mikktspace',
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index 4b0473f7483..5edf970c129 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -144,6 +144,7 @@ void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char
void RE_engine_update_progress(RenderEngine *engine, float progress);
void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak);
void RE_engine_report(RenderEngine *engine, int type, const char *msg);
+void RE_engine_set_error_message(RenderEngine *engine, const char *msg);
int RE_engine_render(struct Render *re, int do_all);
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 61795c2c173..d1b6673c792 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -144,7 +144,7 @@ typedef struct RenderResult {
/* render info text */
char *text;
-
+ char *error;
} RenderResult;
diff --git a/source/blender/render/intern/include/rayintersection.h b/source/blender/render/intern/include/rayintersection.h
index 9c0835af56f..3607e66a237 100644
--- a/source/blender/render/intern/include/rayintersection.h
+++ b/source/blender/render/intern/include/rayintersection.h
@@ -121,7 +121,7 @@ typedef struct Isect {
/* arbitrary, but can't use e.g. FLT_MAX because of precision issues */
#define RE_RAYTRACE_MAXDIST 1e15f
-#define RE_RAYTRACE_EPSILON -FLT_EPSILON
+#define RE_RAYTRACE_EPSILON 0.0f
#ifdef __cplusplus
}
diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c
index 9b22c7d8bad..4aa2f4e919e 100644
--- a/source/blender/render/intern/source/bake.c
+++ b/source/blender/render/intern/source/bake.c
@@ -54,8 +54,6 @@
#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
-#include "RE_bake.h"
-
/* local include */
#include "rayintersection.h"
#include "rayobject.h"
@@ -374,8 +372,8 @@ static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist,
bs->vcol->b = col[2];
}
else {
- const char *imcol = (char *)(bs->rect + bs->rectx * y + x);
- copy_v4_v4_char((char *)imcol, (char *)col);
+ char *imcol = (char *)(bs->rect + bs->rectx * y + x);
+ copy_v4_v4_char(imcol, (char *)col);
}
}
if (bs->rect_mask) {
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index c732aa4664b..35878f664ea 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -82,9 +82,7 @@
#include "BKE_particle.h"
#include "BKE_scene.h"
-
#include "PIL_time.h"
-#include "IMB_imbuf_types.h"
#include "envmap.h"
#include "occlusion.h"
@@ -103,8 +101,6 @@
#include "zbuf.h"
#include "sunsky.h"
-#include "RE_render_ext.h"
-
/* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp (for quad detection) */
/* or for checking vertex normal flips */
#define FLT_EPSILON10 1.19209290e-06F
@@ -2725,12 +2721,13 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
vlr->v4= NULL;
/* to prevent float accuracy issues, we calculate normal in local object space (not world) */
- if (area_tri_v3(co3, co2, co1)>FLT_EPSILON) {
- if (negative_scale)
- normal_tri_v3(tmp, co1, co2, co3);
- else
- normal_tri_v3(tmp, co3, co2, co1);
- add_v3_v3(n, tmp);
+ if (normal_tri_v3(tmp, co1, co2, co3) > FLT_EPSILON) {
+ if (negative_scale == false) {
+ add_v3_v3(n, tmp);
+ }
+ else {
+ sub_v3_v3(n, tmp);
+ }
}
vlr->mat= matar[ dl->col ];
@@ -5138,8 +5135,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
re->lights.first= re->lights.last= NULL;
re->lampren.first= re->lampren.last= NULL;
-
- slurph_opt= 0;
+
re->i.partsdone = false; /* signal now in use for previewrender */
/* in localview, lamps are using normal layers, objects only local bits */
@@ -5201,8 +5197,6 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
re->i.totlamp= re->totlamp;
re->stats_draw(re->sdh, &re->i);
}
-
- slurph_opt= 1;
}
void RE_Database_Preprocess(Render *re)
@@ -5242,7 +5236,7 @@ void RE_Database_Preprocess(Render *re)
}
if (!re->test_break(re->tbh))
- project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1);
+ project_renderdata(re, projectverto, (re->r.mode & R_PANORAMA) != 0, 0, 1);
/* Occlusion */
if ((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && !re->test_break(re->tbh))
@@ -5320,8 +5314,6 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
re->i.totface=re->i.totvert=re->i.totstrand=re->i.totlamp=re->i.tothalo= 0;
re->lights.first= re->lights.last= NULL;
-
- slurph_opt= 0;
/* in localview, lamps are using normal layers, objects only local bits */
if (re->lay & 0xFF000000)
@@ -5342,7 +5334,7 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
database_init_objects(re, lay, 0, 0, NULL, timeoffset);
if (!re->test_break(re->tbh))
- project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1);
+ project_renderdata(re, projectverto, (re->r.mode & R_PANORAMA) != 0, 0, 1);
/* do this in end, particles for example need cfra */
scene->r.cfra -= timeoffset;
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index 06be00a5a5e..c3c70067836 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -55,14 +55,10 @@
/* this module */
#include "render_types.h"
-#include "renderpipeline.h"
#include "envmap.h"
-#include "rendercore.h"
#include "renderdatabase.h"
#include "texture.h"
#include "zbuf.h"
-#include "initrender.h"
-
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 54f142184e1..23ca376535e 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -46,9 +46,6 @@
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-
#include "RNA_access.h"
#ifdef WITH_PYTHON
@@ -358,6 +355,19 @@ void RE_engine_report(RenderEngine *engine, int type, const char *msg)
BKE_report(engine->reports, type, msg);
}
+void RE_engine_set_error_message(RenderEngine *engine, const char *msg)
+{
+ Render *re = engine->re;
+ if (re != NULL) {
+ RenderResult *rr = RE_AcquireResultRead(re);
+ if (rr->error != NULL) {
+ MEM_freeN(rr->error);
+ }
+ rr->error = BLI_strdup(msg);
+ RE_ReleaseResult(re);
+ }
+}
+
void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r)
{
RenderPart *pa;
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index 2787ce99b13..833d1a75559 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -50,12 +50,10 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BKE_main.h"
#include "BKE_image.h"
#include "RE_render_ext.h"
-#include "renderpipeline.h"
#include "render_types.h"
#include "texture.h"
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
index 4bb5dc154a6..b5b75f47193 100644
--- a/source/blender/render/intern/source/initrender.c
+++ b/source/blender/render/intern/source/initrender.c
@@ -36,8 +36,6 @@
#include "MEM_guardedalloc.h"
-#include "PIL_time.h"
-
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_jitter.h"
@@ -48,12 +46,8 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-
#include "BKE_camera.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-
#ifdef WITH_QUICKTIME
#include "quicktime_export.h"
#endif
@@ -62,10 +56,6 @@
#include "renderpipeline.h"
#include "render_types.h"
-#include "rendercore.h"
-#include "pixelshading.h"
-#include "zbuf.h"
-
/* Own includes */
#include "initrender.h"
diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c
index 0c6341fe9e5..f55dde588cb 100644
--- a/source/blender/render/intern/source/occlusion.c
+++ b/source/blender/render/intern/source/occlusion.c
@@ -56,9 +56,7 @@
#include "render_types.h"
#include "rendercore.h"
#include "renderdatabase.h"
-#include "pixelshading.h"
#include "shading.h"
-#include "zbuf.h"
/* ------------------------- Declarations --------------------------- */
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index cb812013ac9..0c17d2dd15d 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -90,7 +90,6 @@
#include "renderdatabase.h"
#include "rendercore.h"
#include "initrender.h"
-#include "shadbuf.h"
#include "pixelblending.h"
#include "zbuf.h"
@@ -2380,6 +2379,7 @@ static void do_render_seq(Render *re)
RenderResult *rr; /* don't assign re->result here as it might change during give_ibuf_seq */
int cfra = re->r.cfra;
SeqRenderData context;
+ int re_x, re_y;
re->i.cfra = cfra;
@@ -2393,14 +2393,19 @@ static void do_render_seq(Render *re)
if ((re->r.mode & R_BORDER) && (re->r.mode & R_CROP) == 0) {
/* if border rendering is used and cropping is disabled, final buffer should
* be as large as the whole frame */
- context = BKE_sequencer_new_render_data(re->eval_ctx, re->main, re->scene,
- re->winx, re->winy, 100);
+ re_x = re->winx;
+ re_y = re->winy;
}
else {
- context = BKE_sequencer_new_render_data(re->eval_ctx, re->main, re->scene,
- re->result->rectx, re->result->recty, 100);
+ re_x = re->result->rectx;
+ re_y = re->result->recty;
}
+ BKE_sequencer_new_render_data(
+ re->eval_ctx, re->main, re->scene,
+ re_x, re_y, 100,
+ &context);
+
out = BKE_sequencer_give_ibuf(&context, cfra, 0);
if (out) {
@@ -2808,6 +2813,9 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
}
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
+ if (write_still) {
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE);
+ }
}
BLI_callback_exec(re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
@@ -3005,6 +3013,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
if (G.is_break == false) {
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE);
}
}
else {
@@ -3088,6 +3097,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
if (G.is_break == false) {
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE);
}
}
}
diff --git a/source/blender/render/intern/source/pixelblending.c b/source/blender/render/intern/source/pixelblending.c
index 460a6814f07..32fb196e1f3 100644
--- a/source/blender/render/intern/source/pixelblending.c
+++ b/source/blender/render/intern/source/pixelblending.c
@@ -38,7 +38,6 @@
/* own includes */
#include "render_types.h"
-#include "renderpipeline.h"
#include "pixelblending.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c
index 014df802a78..ac4a7dbdccd 100644
--- a/source/blender/render/intern/source/pixelshading.c
+++ b/source/blender/render/intern/source/pixelshading.c
@@ -36,8 +36,6 @@
#include "BLI_utildefines.h"
/* External modules: */
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "DNA_group_types.h"
#include "DNA_material_types.h"
@@ -51,14 +49,11 @@
/* own module */
#include "render_types.h"
-#include "renderpipeline.h"
#include "renderdatabase.h"
#include "texture.h"
-#include "pixelblending.h"
#include "rendercore.h"
#include "shadbuf.h"
#include "pixelshading.h"
-#include "shading.h"
#include "sunsky.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index ac2e85a33b3..ff23e3788ab 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -55,7 +55,6 @@
#include "DNA_particle_types.h"
#include "render_types.h"
-#include "renderdatabase.h"
#include "texture.h"
#include "pointdensity.h"
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 54fb3b8d8a3..3575b78f95f 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -27,7 +27,6 @@
* \ingroup render
*/
-
#include <stdio.h>
#include <math.h>
#include <string.h>
@@ -50,25 +49,18 @@
#include "BKE_node.h"
-
-#include "PIL_time.h"
-
#include "render_result.h"
#include "render_types.h"
-#include "renderpipeline.h"
#include "rendercore.h"
#include "renderdatabase.h"
-#include "pixelblending.h"
#include "pixelshading.h"
#include "shading.h"
-#include "texture.h"
#include "volumetric.h"
#include "rayintersection.h"
#include "rayobject.h"
#include "raycounter.h"
-
#define RAY_TRA 1
#define RAY_INSIDE 2
@@ -1562,7 +1554,7 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr)
}
if (shi->combinedflag & SCE_PASS_REFLECT) {
- /* values in shr->spec can be greater then 1.0.
+ /* values in shr->spec can be greater than 1.0.
* In this case the mircol uses a zero blending factor, so ignoring it is ok.
* Fixes bug #18837 - when the spec is higher then 1.0,
* diff can become a negative color - Campbell */
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 08a82d026a0..de87fb200ae 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -35,13 +35,13 @@
#include "MEM_guardedalloc.h"
+#include "BKE_appdir.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_hash_md5.h"
#include "BLI_path_util.h"
#include "BLI_rect.h"
#include "BLI_string.h"
-#include "BLI_system.h"
#include "BLI_threads.h"
#include "BKE_image.h"
@@ -94,6 +94,8 @@ void render_result_free(RenderResult *res)
MEM_freeN(res->rectf);
if (res->text)
MEM_freeN(res->text);
+ if (res->error)
+ MEM_freeN(res->error);
MEM_freeN(res);
}
@@ -1072,7 +1074,7 @@ void render_result_exr_file_path(Scene *scene, const char *layname, int sample,
BLI_snprintf(name, sizeof(name), "%s_%s_%s%d.exr", fi, scene->id.name + 2, layname, sample);
}
- BLI_make_file_string("/", filepath, BLI_temp_dir_session(), name);
+ BLI_make_file_string("/", filepath, BKE_tempdir_session(), name);
}
/* only for temp buffer, makes exact copy of render result */
@@ -1163,14 +1165,14 @@ static void render_result_exr_file_cache_path(Scene *sce, const char *root, char
BLI_hash_md5_buffer(G.main->name, strlen(G.main->name), path_digest);
}
else {
- BLI_strncpy(dirname, BLI_temp_dir_base(), sizeof(dirname));
+ BLI_strncpy(dirname, BKE_tempdir_base(), sizeof(dirname));
BLI_strncpy(filename, "UNSAVED", sizeof(filename));
}
BLI_hash_md5_to_hexdigest(path_digest, path_hexdigest);
/* Default to *non-volatile* tmp dir. */
if (*root == '\0') {
- root = BLI_temp_dir_base();
+ root = BKE_tempdir_base();
}
BLI_snprintf(filename_full, sizeof(filename_full), "cached_RR_%s_%s_%s.exr",
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 1a8ab60d4d0..b1e00c4a451 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -48,7 +48,6 @@
#include "DNA_node_types.h"
#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
#include "BKE_image.h"
@@ -68,9 +67,7 @@
#include "envmap.h"
#include "pointdensity.h"
#include "voxeldata.h"
-#include "renderpipeline.h"
#include "render_types.h"
-#include "rendercore.h"
#include "shading.h"
#include "texture.h"
#include "texture_ocean.h"
@@ -3053,7 +3050,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
switch (mtex->texco) {
case TEXCO_ANGMAP:
/* only works with texture being "real" */
- /* use saacos(), fixes bug [#22398], float precision caused lo[2] to be slightly less then -1.0 */
+ /* use saacos(), fixes bug [#22398], float precision caused lo[2] to be slightly less than -1.0 */
if (lo[0] || lo[1]) { /* check for zero case [#24807] */
fact= (1.0f/(float)M_PI)*saacos(lo[2])/(sqrtf(lo[0]*lo[0] + lo[1]*lo[1]));
tempvec[0]= lo[0]*fact;
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index a67140c6334..5b054005bac 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -50,15 +50,7 @@
#include "DNA_material_types.h"
#include "DNA_group_types.h"
-#include "BKE_main.h"
-
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-#include "IMB_colormanagement.h"
-
/* local include */
-#include "rayintersection.h"
-#include "rayobject.h"
#include "renderpipeline.h"
#include "render_result.h"
#include "render_types.h"
@@ -71,8 +63,6 @@
#include "sss.h"
#include "zbuf.h"
-#include "PIL_time.h"
-
/* own include */
#include "rendercore.h"
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index 803da070e15..cafdbe2b488 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -78,11 +78,8 @@
#include "rayintersection.h"
#include "rayobject.h"
-#include "renderpipeline.h"
#include "render_types.h"
#include "renderdatabase.h"
-#include "texture.h"
-#include "strand.h"
#include "zbuf.h"
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 9d83ff1d7e8..0bd4815fb73 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -50,7 +50,6 @@
#include "PIL_time.h"
-#include "renderpipeline.h"
#include "render_types.h"
#include "renderdatabase.h"
#include "rendercore.h"
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 7aca6b9ac87..01055d87a38 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -46,11 +46,9 @@
/* local include */
#include "raycounter.h"
-#include "renderpipeline.h"
#include "render_types.h"
#include "renderdatabase.h"
#include "rendercore.h"
-#include "shadbuf.h"
#include "shading.h"
#include "strand.h"
#include "texture.h"
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index f909c585561..93e8c6a275a 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -47,9 +47,7 @@
/* local include */
#include "occlusion.h"
-#include "renderpipeline.h"
#include "render_types.h"
-#include "pixelblending.h"
#include "rendercore.h"
#include "shadbuf.h"
#include "sss.h"
diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c
index 7e9003aaee7..8ea3a753283 100644
--- a/source/blender/render/intern/source/sss.c
+++ b/source/blender/render/intern/source/sss.c
@@ -57,7 +57,6 @@
#include "BLF_translation.h"
-#include "PIL_time.h"
#include "DNA_material_types.h"
@@ -68,11 +67,7 @@
/* this module */
#include "render_types.h"
-#include "rendercore.h"
-#include "renderdatabase.h"
-#include "shading.h"
#include "sss.h"
-#include "zbuf.h"
/* Generic Multiple Scattering API */
diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c
index 485680da76f..6b52d4aa419 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -47,11 +47,8 @@
#include "render_types.h"
-#include "initrender.h"
#include "rendercore.h"
#include "renderdatabase.h"
-#include "renderpipeline.h"
-#include "pixelblending.h"
#include "shading.h"
#include "strand.h"
#include "zbuf.h"
diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c
index 1836b3f48a7..6078989f9f6 100644
--- a/source/blender/render/intern/source/sunsky.c
+++ b/source/blender/render/intern/source/sunsky.c
@@ -299,8 +299,7 @@ void GetSkyXYZRadiancef(struct SunSky *sunsky, const float varg[3], float color_
float theta, phi;
float v[3];
- copy_v3_v3(v, (float *)varg);
- normalize_v3(v);
+ normalize_v3_v3(v, varg);
if (v[2] < 0.001f) {
v[2] = 0.001f;
diff --git a/source/blender/render/intern/source/texture_ocean.c b/source/blender/render/intern/source/texture_ocean.c
index 55f4bf3794d..5261374b34d 100644
--- a/source/blender/render/intern/source/texture_ocean.c
+++ b/source/blender/render/intern/source/texture_ocean.c
@@ -56,8 +56,6 @@ extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-
-
/* ***** actual texture sampling ***** */
int ocean_texture(Tex *tex, const float texvec[2], TexResult *texres)
{
diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c
index 072f4192ccc..69a1317cf7d 100644
--- a/source/blender/render/intern/source/voxeldata.c
+++ b/source/blender/render/intern/source/voxeldata.c
@@ -67,7 +67,6 @@
#include "render_types.h"
-#include "renderdatabase.h"
#include "texture.h"
#include "voxeldata.h"
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 87e546ef24e..7e8f0e3e9fc 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -63,12 +63,10 @@
#include "pixelblending.h"
#include "render_result.h"
#include "render_types.h"
-#include "renderpipeline.h"
#include "renderdatabase.h"
#include "rendercore.h"
#include "shadbuf.h"
#include "shading.h"
-#include "sss.h"
#include "strand.h"
/* own includes */
@@ -2065,8 +2063,6 @@ static void zmask_rect(int *rectz, int *rectp, int xs, int ys, int neg)
}
-
-
/* ***************** ZBUFFER MAIN ROUTINES **************** */
void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart *, ZSpan *, int, void *), void *data)
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index 088bddc8a76..78b5d499644 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -130,10 +130,10 @@ if(WITH_BUILDINFO)
add_definitions(-DWITH_BUILDINFO)
endif()
-if(WIN322)
- list(APPEND INC
- ../../../intern/utfconv
- )
+if(WIN32)
+ if(WITH_INPUT_IME)
+ add_definitions(-DWITH_INPUT_IME)
+ endif()
endif()
if(WITH_COMPOSITOR)
diff --git a/source/blender/windowmanager/SConscript b/source/blender/windowmanager/SConscript
index b93192d5067..a6f64f7cdae 100644
--- a/source/blender/windowmanager/SConscript
+++ b/source/blender/windowmanager/SConscript
@@ -65,11 +65,14 @@ if env['WITH_BF_COLLADA']:
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
- incs += ' ../../intern/utfconv'
if env['BF_BUILDINFO']:
defs.append('WITH_BUILDINFO')
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'win64-mingw'):
+ if env['WITH_BF_IME']:
+ defs.append('WITH_INPUT_IME')
+
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 19d7f37d144..b1692e44ad0 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -268,6 +268,7 @@ void WM_operator_properties_select_action_simple(struct wmOperatorType *ot, int
bool WM_operator_check_ui_enabled(const struct bContext *C, const char *idname);
wmOperator *WM_operator_last_redo(const struct bContext *C);
+ID *WM_operator_drop_load_path(struct bContext *C, struct wmOperator *op, const short idcode);
bool WM_operator_last_properties_init(struct wmOperator *op);
bool WM_operator_last_properties_store(struct wmOperator *op);
@@ -398,6 +399,7 @@ enum {
WM_JOB_TYPE_CLIP_SOLVE_CAMERA,
WM_JOB_TYPE_CLIP_PREFETCH,
WM_JOB_TYPE_SEQ_BUILD_PROXY,
+ WM_JOB_TYPE_SEQ_BUILD_PREVIEW,
/* add as needed, screencast, seq proxy build
* if having hard coded values is a problem */
};
@@ -461,6 +463,10 @@ 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 WITH_INPUT_IME
+bool WM_event_is_ime_switch(const struct wmEvent *event);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index ff252f0fc20..e64b1152252 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -169,7 +169,7 @@ enum {
#define KM_OSKEY2 128
/* KM_MOD_ flags for wmKeyMapItem and wmEvent.alt/shift/oskey/ctrl */
-/* note that KM_ANY and false are used with these defines too */
+/* note that KM_ANY and KM_NOTHING are used with these defines too */
#define KM_MOD_FIRST 1
#define KM_MOD_SECOND 2
@@ -324,6 +324,9 @@ typedef struct wmNotifier {
#define ND_NLA_ACTCHANGE (74<<16)
#define ND_FCURVES_ORDER (75<<16)
+ /* NC_GPENCIL */
+#define ND_GPENCIL_EDITMODE (85<<16)
+
/* NC_GEOM Geometry */
/* Mesh, Curve, MetaBall, Armature, .. */
#define ND_SELECT (90<<16)
@@ -554,9 +557,7 @@ typedef struct wmOperatorType {
/* pointer to modal keymap, do not free! */
struct wmKeyMap *modalkeymap;
- /* only used for operators defined with python
- * use to store pointers to python functions */
- void *pyop_data;
+ /* python needs the operator type as well */
int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot) ATTR_WARN_UNUSED_RESULT;
/* RNA integration */
@@ -567,6 +568,24 @@ typedef struct wmOperatorType {
} wmOperatorType;
+#ifdef WITH_INPUT_IME
+/* *********** Input Method Editor (IME) *********** */
+
+/* similar to GHOST_TEventImeData */
+typedef struct wmIMEData {
+ size_t result_len, composite_len;
+
+ char *str_result; /* utf8 encoding */
+ char *str_composite; /* utf8 encoding */
+
+ int cursor_pos; /* cursor position in the IME composition. */
+ int sel_start; /* beginning of the selection */
+ int sel_end; /* end of the selection */
+
+ bool is_ime_composing;
+} wmIMEData;
+#endif
+
/* **************** Paint Cursor ******************* */
typedef void (*wmPaintCursorDraw)(struct bContext *C, int, int, void *customdata);
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 7222447ac55..a6a3c6b0a28 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -39,8 +39,6 @@
#include "DNA_windowmanager_types.h"
-#include "GHOST_C-api.h"
-
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
@@ -59,7 +57,6 @@
#include "WM_types.h"
#include "wm_window.h"
#include "wm_event_system.h"
-#include "wm_event_types.h"
#include "wm_draw.h"
#include "wm.h"
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 145e9df7eb0..68592b44845 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -45,10 +45,8 @@
#include "BIF_glutil.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -58,8 +56,6 @@
#include "WM_api.h"
#include "WM_types.h"
#include "wm_event_system.h"
-#include "wm.h"
-
/* ****************************************************** */
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 42cb5f36701..d5c88ff156c 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -81,7 +81,6 @@
#include "wm_window.h"
#include "wm_event_system.h"
#include "wm_event_types.h"
-#include "wm_draw.h"
#ifndef NDEBUG
# include "RNA_enum_types.h"
@@ -542,7 +541,7 @@ void WM_event_print(const wmEvent *event)
event->shift, event->ctrl, event->alt, event->oskey, event->keymodifier,
event->x, event->y, event->ascii,
BLI_str_utf8_size(event->utf8_buf), event->utf8_buf,
- event->keymap_idname, (void *)event);
+ event->keymap_idname, (const void *)event);
if (ISNDOF(event->type)) {
const wmNDOFMotionData *ndof = event->customdata;
@@ -1708,16 +1707,12 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
/* remlink now, for load file case before removing*/
BLI_remlink(handlers, handler);
-
+
if (val != EVT_FILESELECT_EXTERNAL_CANCEL) {
- if (screen != handler->filescreen) {
- ED_screen_full_prevspace(C, CTX_wm_area(C));
- }
- else {
- ED_area_prevspace(C, CTX_wm_area(C));
- }
+ ScrArea *sa = CTX_wm_area(C);
+ ED_screen_retore_temp_type(C, sa, screen != handler->filescreen);
}
-
+
wm_handler_op_context(C, handler);
/* needed for UI_popup_menu_reports */
@@ -2323,6 +2318,14 @@ void wm_event_do_handlers(bContext *C)
}
for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ /* after restoring a screen from SCREENMAXIMIZED we have to wait
+ * with the screen handling till the region coordinates are updated */
+ if (win->screen->skip_handling == true) {
+ /* restore for the next iteration of wm_event_do_handlers */
+ win->screen->skip_handling = false;
+ break;
+ }
+
if (wm_event_inside_i(event, &sa->totrct)) {
CTX_wm_area_set(C, sa);
@@ -3050,6 +3053,13 @@ static void wm_event_add_mousemove(wmWindow *win, const wmEvent *event)
void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int UNUSED(time), void *customdata)
{
wmWindow *owin;
+
+ /* Having both, event and evt, can be highly confusing to work with, but is necessary for
+ * our current event system, so let's clear things up a bit:
+ * - data added to event only will be handled immediately, but will not be copied to the next event
+ * - data added to evt only stays, but is handled with the next event -> execution delay
+ * - data added to event and evt stays and is handled immediately
+ */
wmEvent event, *evt = win->eventstate;
/* initialize and copy state (only mouse x y and modifiers) */
@@ -3190,6 +3200,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
case GHOST_kEventKeyUp:
{
GHOST_TEventKeyData *kd = customdata;
+ short keymodifier = KM_NOTHING;
event.type = convert_key(kd->key);
event.ascii = kd->ascii;
memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/
@@ -3230,28 +3241,38 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
}
}
- /* modifiers assign to eventstate, so next event gets the modifer (makes modifier key events work) */
/* assigning both first and second is strange - campbell */
switch (event.type) {
- case LEFTSHIFTKEY: case RIGHTSHIFTKEY:
- evt->shift = (event.val == KM_PRESS) ?
- ((evt->ctrl || evt->alt || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) :
- false;
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ if (event.val == KM_PRESS) {
+ if (evt->ctrl || evt->alt || evt->oskey) keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
+ else keymodifier = KM_MOD_FIRST;
+ }
+ event.shift = evt->shift = keymodifier;
break;
- case LEFTCTRLKEY: case RIGHTCTRLKEY:
- evt->ctrl = (event.val == KM_PRESS) ?
- ((evt->shift || evt->alt || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) :
- false;
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ if (event.val == KM_PRESS) {
+ if (evt->shift || evt->alt || evt->oskey) keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
+ else keymodifier = KM_MOD_FIRST;
+ }
+ event.ctrl = evt->ctrl = keymodifier;
break;
- case LEFTALTKEY: case RIGHTALTKEY:
- evt->alt = (event.val == KM_PRESS) ?
- ((evt->ctrl || evt->shift || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) :
- false;
+ case LEFTALTKEY:
+ case RIGHTALTKEY:
+ if (event.val == KM_PRESS) {
+ if (evt->ctrl || evt->shift || evt->oskey) keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
+ else keymodifier = KM_MOD_FIRST;
+ }
+ event.alt = evt->alt = keymodifier;
break;
case OSKEY:
- evt->oskey = (event.val == KM_PRESS) ?
- ((evt->ctrl || evt->alt || evt->shift) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) :
- false;
+ if (event.val == KM_PRESS) {
+ if (evt->ctrl || evt->alt || evt->shift) keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
+ else keymodifier = KM_MOD_FIRST;
+ }
+ event.oskey = evt->oskey = keymodifier;
break;
default:
if (event.val == KM_PRESS && event.keymodifier == 0)
@@ -3374,6 +3395,33 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
break;
}
+#ifdef WITH_INPUT_IME
+ case GHOST_kEventImeCompositionStart:
+ {
+ event.val = KM_PRESS;
+ win->ime_data = customdata;
+ win->ime_data->is_ime_composing = true;
+ event.type = WM_IME_COMPOSITE_START;
+ wm_event_add(win, &event);
+ break;
+ }
+ case GHOST_kEventImeComposition:
+ {
+ event.val = KM_PRESS;
+ event.type = WM_IME_COMPOSITE_EVENT;
+ wm_event_add(win, &event);
+ break;
+ }
+ case GHOST_kEventImeCompositionEnd:
+ {
+ event.val = KM_PRESS;
+ win->ime_data->is_ime_composing = false;
+ event.type = WM_IME_COMPOSITE_END;
+ wm_event_add(win, &event);
+ break;
+ }
+#endif /* WITH_INPUT_IME */
+
}
#if 0
@@ -3480,5 +3528,13 @@ bool WM_event_is_tablet(const struct wmEvent *event)
return (event->tablet_data) ? true : false;
}
+#ifdef WITH_INPUT_IME
+/* most os using ctrl/oskey + space to switch ime, avoid added space */
+bool WM_event_is_ime_switch(const struct wmEvent *event)
+{
+ return event->val == KM_PRESS && event->type == SPACEKEY &&
+ (event->ctrl || event->oskey || event->shift || event->alt);
+}
+#endif
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 8a6b5046b73..c1c31f6795d 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -69,6 +69,7 @@
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
+#include "BKE_appdir.h"
#include "BKE_utildefines.h"
#include "BKE_autoexec.h"
#include "BKE_blender.h"
@@ -96,8 +97,6 @@
#include "ED_view3d.h"
#include "ED_util.h"
-#include "RE_pipeline.h" /* only to report missing engine */
-
#include "GHOST_C-api.h"
#include "GHOST_Path-api.h"
@@ -319,7 +318,7 @@ static void wm_init_userdef(bContext *C, const bool from_memory)
}
/* update tempdir from user preferences */
- BLI_temp_dir_init(U.tempdir);
+ BKE_tempdir_init(U.tempdir);
BKE_userdef_state();
}
@@ -568,7 +567,7 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
G.relbase_valid = 0;
if (!from_memory) {
- const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
+ const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
if (custom_file) {
BLI_strncpy(startstr, custom_file, FILE_MAX);
@@ -614,7 +613,7 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
if (BLI_listbase_is_empty(&wmbase)) {
wm_clear_default_size(C);
}
- BLI_temp_dir_init(U.tempdir);
+ BKE_tempdir_init(U.tempdir);
#ifdef WITH_PYTHON_SECURITY
/* use alternative setting for security nuts
@@ -727,7 +726,7 @@ void wm_read_history(void)
struct RecentFile *recent;
const char *line;
int num;
- const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
+ const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
if (!cfgdir) return;
@@ -764,7 +763,7 @@ static void write_history(void)
return;
/* will be NULL in background mode */
- user_config_dir = BLI_get_folder_create(BLENDER_USER_CONFIG, NULL);
+ user_config_dir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL);
if (!user_config_dir)
return;
@@ -841,7 +840,7 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
if (scene->camera) {
ibuf = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, OB_SOLID, false, false, R_ADDSKY, err_out);
+ IB_rect, OB_SOLID, false, false, false, R_ADDSKY, err_out);
}
else {
ibuf = ED_view3d_draw_offscreen_imbuf(scene, v3d, ar, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
@@ -1024,7 +1023,7 @@ int wm_homefile_write_exec(bContext *C, wmOperator *op)
/* update keymaps in user preferences */
WM_keyconfig_update(wm);
- BLI_make_file_string("/", filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE);
+ BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE);
printf("trying to save homefile at %s ", filepath);
ED_editors_flush_edits(C, false);
@@ -1055,7 +1054,7 @@ int wm_userpref_write_exec(bContext *C, wmOperator *op)
/* update keymaps in user preferences */
WM_keyconfig_update(wm);
- BLI_make_file_string("/", filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_USERPREF_FILE);
+ BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_USERPREF_FILE);
printf("trying to save userpref at %s ", filepath);
if (BKE_write_file_userdef(filepath, op->reports) == 0) {
@@ -1096,14 +1095,14 @@ void wm_autosave_location(char *filepath)
* BLI_make_file_string will create string that has it most likely on C:\
* through get_default_root().
* If there is no C:\tmp autosave fails. */
- if (!BLI_exists(BLI_temp_dir_base())) {
- savedir = BLI_get_folder_create(BLENDER_USER_AUTOSAVE, NULL);
+ if (!BLI_exists(BKE_tempdir_base())) {
+ savedir = BKE_appdir_folder_id_create(BLENDER_USER_AUTOSAVE, NULL);
BLI_make_file_string("/", filepath, savedir, path);
return;
}
#endif
- BLI_make_file_string("/", filepath, BLI_temp_dir_base(), path);
+ BLI_make_file_string("/", filepath, BKE_tempdir_base(), path);
}
void WM_autosave_init(wmWindowManager *wm)
@@ -1167,7 +1166,7 @@ void wm_autosave_delete(void)
if (BLI_exists(filename)) {
char str[FILE_MAX];
- BLI_make_file_string("/", str, BLI_temp_dir_base(), BLENDER_QUIT_FILE);
+ BLI_make_file_string("/", str, BKE_tempdir_base(), BLENDER_QUIT_FILE);
/* if global undo; remove tempsave, otherwise rename */
if (U.uiflag & USER_GLOBALUNDO) BLI_delete(filename, false, false);
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index 3e287a3907b..46c3909f7bf 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -49,7 +49,6 @@
#include "WM_types.h"
#include "wm.h"
-#include "wm_event_system.h"
#include "wm_subwindow.h"
#include "wm_draw.h"
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index f762e19c969..cb03d022afd 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -40,9 +40,6 @@
#include "MEM_guardedalloc.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"
@@ -68,6 +65,7 @@
#include "BKE_report.h"
#include "BKE_addon.h"
+#include "BKE_appdir.h"
#include "BKE_sequencer.h" /* free seq clipboard */
#include "BKE_material.h" /* clear_matcopybuf */
#include "BKE_tracking.h" /* free tracking clipboard */
@@ -98,6 +96,7 @@
#include "wm_window.h"
#include "ED_armature.h"
+#include "ED_gpencil.h"
#include "ED_keyframing.h"
#include "ED_node.h"
#include "ED_render.h"
@@ -110,7 +109,6 @@
#include "BLF_translation.h"
#include "GPU_buffers.h"
-#include "GPU_extensions.h"
#include "GPU_draw.h"
#include "GPU_init_exit.h"
@@ -172,6 +170,8 @@ void WM_init(bContext *C, int argc, const char **argv)
BLF_lang_set(NULL);
+ ED_spacemacros_init();
+
/* note: there is a bug where python needs initializing before loading the
* startup.blend because it may contain PyDrivers. It also needs to be after
* initializing space types and other internal data.
@@ -190,8 +190,6 @@ 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);
@@ -219,7 +217,7 @@ void WM_init(bContext *C, int argc, const char **argv)
/* allow a path of "", this is what happens when making a new file */
#if 0
if (G.main->name[0] == 0)
- BLI_make_file_string("/", G.main->name, BLI_getDefaultDocumentFolder(), "untitled.blend");
+ BLI_make_file_string("/", G.main->name, BKE_appdir_folder_default(), "untitled.blend");
#endif
BLI_strncpy(G.lib, G.main->name, FILE_MAX);
@@ -414,7 +412,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
bool has_edited;
int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN | G_FILE_HISTORY);
- BLI_make_file_string("/", filename, BLI_temp_dir_base(), BLENDER_QUIT_FILE);
+ BLI_make_file_string("/", filename, BKE_tempdir_base(), BLENDER_QUIT_FILE);
has_edited = ED_editors_flush_edits(C, false);
@@ -478,6 +476,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
free_anim_copybuf();
free_anim_drivers_copybuf();
free_fmodifiers_copybuf();
+ ED_gpencil_strokes_copybuf_free();
ED_clipboard_posebuf_free();
BKE_node_clipboard_clear();
@@ -543,7 +542,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
}
wm_autosave_delete();
- BLI_temp_dir_session_purge();
+ BKE_tempdir_session_purge();
}
void WM_exit(bContext *C)
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index 74c504050ae..6bc858e861a 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -45,8 +45,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "wm_window.h"
-#include "wm_event_system.h"
#include "wm_event_types.h"
#include "wm.h"
@@ -630,17 +628,22 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
}
}
- /* on file load 'winactive' can be NULL, possibly it should not happen but for now do a NULL check - campbell */
- if (wm->winactive) {
- /* if there are running jobs, set the global progress indicator */
- if (jobs_progress > 0) {
- float progress = total_progress / (float)jobs_progress;
- WM_progress_set(wm->winactive, progress);
- }
- else {
- WM_progress_clear(wm->winactive);
- }
+
+ /* if there are running jobs, set the global progress indicator */
+ if (jobs_progress > 0) {
+ wmWindow *win;
+ float progress = total_progress / (float)jobs_progress;
+
+ for (win = wm->windows.first; win; win = win->next)
+ WM_progress_set(win, progress);
}
+ else {
+ wmWindow *win;
+
+ for (win = wm->windows.first; win; win = win->next)
+ WM_progress_clear(win);
+ }
+
}
bool WM_jobs_has_running(wmWindowManager *wm)
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index ff90de4b3c6..b52f3819d3f 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -56,7 +56,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "wm_window.h"
#include "wm_event_system.h"
#include "wm_event_types.h"
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index fe943e11c83..d49a298c424 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -38,8 +38,11 @@
#include <stdio.h>
#include <stddef.h>
#include <assert.h>
+#include <errno.h>
-#include "GHOST_C-api.h"
+#ifdef WIN32
+# include "GHOST_C-api.h"
+#endif
#include "MEM_guardedalloc.h"
@@ -58,12 +61,14 @@
#include "BLI_blenlib.h"
#include "BLI_dial.h"
#include "BLI_dynstr.h" /*for WM_operator_pystring */
+#include "BLI_linklist_stack.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLO_readfile.h"
+#include "BKE_appdir.h"
#include "BKE_autoexec.h"
#include "BKE_blender.h"
#include "BKE_brush.h"
@@ -72,12 +77,14 @@
#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h" /* BKE_ST_MAXNAME */
+#include "BKE_unit.h"
#include "BKE_utildefines.h"
#include "BKE_idcode.h"
@@ -90,6 +97,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "ED_numinput.h"
#include "ED_screen.h"
#include "ED_util.h"
#include "ED_view3d.h"
@@ -99,6 +107,7 @@
#include "RNA_enum_types.h"
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "UI_resources.h"
#include "WM_api.h"
@@ -1221,27 +1230,27 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type,
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
- prop = RNA_def_boolean(ot->srna, "filter_blender", (filter & BLENDERFILE) != 0, "Filter .blend files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_blender", (filter & FILE_TYPE_BLENDER) != 0, "Filter .blend files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_backup", (filter & BLENDERFILE_BACKUP) != 0, "Filter .blend files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_backup", (filter & FILE_TYPE_BLENDER_BACKUP) != 0, "Filter .blend files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_image", (filter & IMAGEFILE) != 0, "Filter image files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_image", (filter & FILE_TYPE_IMAGE) != 0, "Filter image files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_movie", (filter & MOVIEFILE) != 0, "Filter movie files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_movie", (filter & FILE_TYPE_MOVIE) != 0, "Filter movie files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_python", (filter & PYSCRIPTFILE) != 0, "Filter python files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_python", (filter & FILE_TYPE_PYSCRIPT) != 0, "Filter python files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_font", (filter & FTFONTFILE) != 0, "Filter font files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_font", (filter & FILE_TYPE_FTFONT) != 0, "Filter font files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_sound", (filter & SOUNDFILE) != 0, "Filter sound files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_sound", (filter & FILE_TYPE_SOUND) != 0, "Filter sound files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_text", (filter & TEXTFILE) != 0, "Filter text files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_text", (filter & FILE_TYPE_TEXT) != 0, "Filter text files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_btx", (filter & BTXFILE) != 0, "Filter btx files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_btx", (filter & FILE_TYPE_BTX) != 0, "Filter btx files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_collada", (filter & COLLADAFILE) != 0, "Filter COLLADA files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_collada", (filter & FILE_TYPE_COLLADA) != 0, "Filter COLLADA files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_folder", (filter & FOLDERFILE) != 0, "Filter folders", "");
+ prop = RNA_def_boolean(ot->srna, "filter_folder", (filter & FILE_TYPE_FOLDER) != 0, "Filter folders", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_int(ot->srna, "filemode", type, FILE_LOADLIB, FILE_SPECIAL,
@@ -1397,6 +1406,64 @@ wmOperator *WM_operator_last_redo(const bContext *C)
return op;
}
+/**
+ * Use for drag & drop a path or name with operators invoke() function.
+ */
+ID *WM_operator_drop_load_path(struct bContext *C, wmOperator *op, const short idcode)
+{
+ ID *id = NULL;
+ /* check input variables */
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
+ char path[FILE_MAX];
+ bool exists = false;
+
+ RNA_string_get(op->ptr, "filepath", path);
+
+ errno = 0;
+
+ if (idcode == ID_IM) {
+ id = (ID *)BKE_image_load_exists_ex(path, &exists);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (!id) {
+ BKE_reportf(op->reports, RPT_ERROR, "Cannot read %s '%s': %s",
+ BKE_idcode_to_name(idcode), path,
+ errno ? strerror(errno) : TIP_("unsupported format"));
+ return NULL;
+ }
+
+ if (is_relative_path ) {
+ if (exists == false) {
+ Main *bmain = CTX_data_main(C);
+
+ if (idcode == ID_IM) {
+ BLI_path_rel(((Image *)id)->name, bmain->name);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ }
+ }
+ else if (RNA_struct_property_is_set(op->ptr, "name")) {
+ char name[MAX_ID_NAME - 2];
+ RNA_string_get(op->ptr, "name", name);
+ id = BKE_libblock_find_name(idcode, name);
+ if (!id) {
+ BKE_reportf(op->reports, RPT_ERROR, "%s '%s' not found",
+ BKE_idcode_to_name(idcode), name);
+ return NULL;
+ }
+ id_us_plus(id);
+ }
+
+ return id;
+}
+
static void wm_block_redo_cb(bContext *C, void *arg_op, int UNUSED(arg_event))
{
wmOperator *op = arg_op;
@@ -1774,14 +1841,14 @@ static void wm_block_splash_refreshmenu(bContext *UNUSED(C), void *UNUSED(arg_bl
static int wm_resource_check_prev(void)
{
- const char *res = BLI_get_folder_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION, true);
+ const char *res = BKE_appdir_folder_id_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION, true);
// if (res) printf("USER: %s\n", res);
#if 0 /* ignore the local folder */
if (res == NULL) {
/* with a local dir, copying old files isn't useful since local dir get priority for config */
- res = BLI_get_folder_version(BLENDER_RESOURCE_PATH_LOCAL, BLENDER_VERSION, true);
+ res = BKE_appdir_folder_id_version(BLENDER_RESOURCE_PATH_LOCAL, BLENDER_VERSION, true);
}
#endif
@@ -1790,7 +1857,7 @@ static int wm_resource_check_prev(void)
return false;
}
else {
- return (BLI_get_folder_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION - 1, true) != NULL);
+ return (BKE_appdir_folder_id_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION - 1, true) != NULL);
}
}
@@ -1926,7 +1993,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
BLENDER_VERSION / 100, BLENDER_VERSION % 100);
uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", url);
uiItemStringO(col, IFACE_("Manual"), ICON_URL, "WM_OT_url_open", "url",
- "http://wiki.blender.org/index.php/Doc:2.6/Manual");
+ "http://www.blender.org/manual");
uiItemStringO(col, IFACE_("Blender Website"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org");
if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) {
BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d"
@@ -2392,7 +2459,7 @@ static void WM_OT_open_mainfile(wmOperatorType *ot)
ot->ui = wm_open_mainfile_ui;
/* omit window poll so this can work in background mode */
- WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
RNA_def_boolean(ot->srna, "load_ui", true, "Load UI", "Load user interface setup in the .blend file");
@@ -2579,6 +2646,13 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
lib = mainl->curlib;
BLI_assert(lib);
+ if (mainl->versionfile < 250) {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Linking or appending from a very old .blend file format (%d.%d), no animation conversion will "
+ "be done! You may want to re-save your lib file with current Blender",
+ mainl->versionfile, mainl->subversionfile);
+ }
+
if (totfiles == 0) {
BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag);
}
@@ -2652,7 +2726,7 @@ static void WM_OT_link(wmOperatorType *ot)
ot->flag |= OPTYPE_UNDO;
WM_operator_properties_filesel(
- ot, FOLDERFILE | BLENDERFILE, FILE_LOADLIB, FILE_OPENFILE,
+ ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_LOADLIB, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_RELPATH | WM_FILESEL_FILES,
FILE_DEFAULTDISPLAY);
@@ -2672,7 +2746,7 @@ static void WM_OT_append(wmOperatorType *ot)
ot->flag |= OPTYPE_UNDO;
WM_operator_properties_filesel(
- ot, FOLDERFILE | BLENDERFILE, FILE_LOADLIB, FILE_OPENFILE,
+ ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_LOADLIB, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_FILES,
FILE_DEFAULTDISPLAY);
@@ -2685,7 +2759,7 @@ void WM_recover_last_session(bContext *C, ReportList *reports)
{
char filepath[FILE_MAX];
- BLI_make_file_string("/", filepath, BLI_temp_dir_base(), BLENDER_QUIT_FILE);
+ BLI_make_file_string("/", filepath, BKE_tempdir_base(), BLENDER_QUIT_FILE);
/* if reports==NULL, it's called directly without operator, we add a quick check here */
if (reports || BLI_exists(filepath)) {
G.fileflags |= G_FILE_RECOVER;
@@ -2764,7 +2838,7 @@ static void WM_OT_recover_auto_save(wmOperatorType *ot)
ot->exec = wm_recover_auto_save_exec;
ot->invoke = wm_recover_auto_save_invoke;
- WM_operator_properties_filesel(ot, BLENDERFILE, FILE_BLENDER, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_BLENDER, FILE_BLENDER, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_LONGDISPLAY);
}
@@ -2842,6 +2916,8 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
(RNA_struct_find_property(op->ptr, "use_mesh_compat") &&
RNA_boolean_get(op->ptr, "use_mesh_compat")),
G_FILE_MESH_COMPAT);
+#else
+# error "don't remove by accident"
#endif
if (wm_file_write(C, path, fileflags, op->reports) != 0)
@@ -2880,7 +2956,7 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot)
ot->check = blend_save_check;
/* omit window poll so this can work in background mode */
- WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_SAVE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file");
RNA_def_boolean(ot->srna, "relative_remap", true, "Remap Relative",
@@ -2956,7 +3032,7 @@ static void WM_OT_save_mainfile(wmOperatorType *ot)
ot->check = blend_save_check;
/* omit window poll so this can work in background mode */
- WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_SAVE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file");
RNA_def_boolean(ot->srna, "relative_remap", false, "Remap Relative",
@@ -3731,6 +3807,7 @@ void WM_OT_straightline_gesture(wmOperatorType *ot)
#define WM_RADIAL_CONTROL_DISPLAY_SIZE 200
#define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE 35
#define WM_RADIAL_CONTROL_DISPLAY_WIDTH (WM_RADIAL_CONTROL_DISPLAY_SIZE - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE)
+#define WM_RADIAL_CONTROL_HEADER_LENGTH 180
#define WM_RADIAL_MAX_STR 6
typedef struct {
@@ -3748,8 +3825,24 @@ typedef struct {
ListBase orig_paintcursors;
bool use_secondary_tex;
void *cursor;
+ NumInput num_input;
} RadialControl;
+static void radial_control_update_header(wmOperator *op, bContext *C)
+{
+ RadialControl *rc = op->customdata;
+ char msg[WM_RADIAL_CONTROL_HEADER_LENGTH];
+ ScrArea *sa = CTX_wm_area(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (sa && hasNumInput(&rc->num_input)) {
+ char num_str[NUM_STR_REP_LEN];
+ outputNumInput(&rc->num_input, num_str, &scene->unit);
+ BLI_snprintf(msg, WM_RADIAL_CONTROL_HEADER_LENGTH, "%s: %s", RNA_property_ui_name(rc->prop), num_str);
+ ED_area_headerprint(sa, msg);
+ }
+}
+
static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *event)
{
float d[2] = {0, 0};
@@ -4134,6 +4227,13 @@ static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *eve
return OPERATOR_CANCELLED;
}
+ /* initialize numerical input */
+ initNumInput(&rc->num_input);
+ rc->num_input.idx_max = 0;
+ rc->num_input.val_flag[0] |= NUM_NO_NEGATIVE;
+ rc->num_input.unit_sys = USER_UNIT_NONE;
+ rc->num_input.unit_type[0] = B_UNIT_LENGTH;
+
/* get subtype of property */
rc->subtype = RNA_property_subtype(rc->prop);
if (!ELEM(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_PERCENTAGE, PROP_ANGLE, PROP_PIXEL)) {
@@ -4141,7 +4241,7 @@ static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *eve
MEM_freeN(rc);
return OPERATOR_CANCELLED;
}
-
+
rc->current_value = rc->initial_value;
radial_control_set_initial_mouse(rc, event);
radial_control_set_tex(rc);
@@ -4178,11 +4278,16 @@ static void radial_control_cancel(bContext *C, wmOperator *op)
{
RadialControl *rc = op->customdata;
wmWindowManager *wm = CTX_wm_manager(C);
+ ScrArea *sa = CTX_wm_area(C);
if (rc->dial) {
MEM_freeN(rc->dial);
rc->dial = NULL;
}
+
+ if (sa) {
+ ED_area_headerprint(sa, NULL);
+ }
WM_paint_cursor_end(wm, rc->cursor);
@@ -4206,126 +4311,182 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even
float delta[2], ret = OPERATOR_RUNNING_MODAL;
bool snap;
float angle_precision = 0.0f;
+ const bool has_numInput = hasNumInput(&rc->num_input);
+ bool handled = false;
+ float numValue;
/* TODO: fix hardcoded events */
snap = event->ctrl != 0;
- switch (event->type) {
- case MOUSEMOVE:
- 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];
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &rc->num_input, event)) {
+ handled = true;
+ applyNumInput(&rc->num_input, &numValue);
+
+ if (rc->subtype == PROP_ANGLE) {
+ numValue = DEG2RADF(numValue);
+ numValue = fmod(numValue, 2.0f * (float)M_PI);
+ if (numValue < 0.0f)
+ numValue += 2.0f * (float)M_PI;
+ }
+
+ CLAMP(numValue, rc->min_value, rc->max_value);
+ new_value = numValue;
+
+ radial_control_set_value(rc, new_value);
+ rc->current_value = new_value;
+ radial_control_update_header(op, C);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ handled = false;
+ switch (event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ /* canceled; restore original value */
+ radial_control_set_value(rc, rc->initial_value);
+ ret = OPERATOR_CANCELLED;
+ break;
+
+ case LEFTMOUSE:
+ case PADENTER:
+ case RETKEY:
+ /* done; value already set */
+ RNA_property_update(C, &rc->ptr, rc->prop);
+ ret = OPERATOR_FINISHED;
+ break;
+
+ case MOUSEMOVE:
+ if (!has_numInput) {
+ 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;
+
+ 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);
}
-
- 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];
+
+ /* calculate new value and apply snapping */
+ switch (rc->subtype) {
+ case PROP_NONE:
+ case PROP_DISTANCE:
+ case PROP_PERCENTAGE:
+ case PROP_PIXEL:
+ new_value = dist;
+ if (snap) new_value = ((int)new_value + 5) / 10 * 10;
+ break;
+ case PROP_FACTOR:
+ new_value = (WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / WM_RADIAL_CONTROL_DISPLAY_WIDTH;
+ if (snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f;
+ break;
+ case PROP_ANGLE:
+ new_value = atan2f(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:
+ new_value = dist; /* dummy value, should this ever happen? - campbell */
+ break;
}
-
- dist = dist + 0.1f * (delta[0] + delta[1]);
+
+ /* clamp and update */
+ CLAMP(new_value, rc->min_value, rc->max_value);
+ radial_control_set_value(rc, new_value);
+ rc->current_value = new_value;
+ handled = true;
+ break;
}
- }
- else {
- delta[0] = rc->initial_mouse[0] - event->x;
- delta[1] = rc->initial_mouse[1] - event->y;
+ break;
- if (rc->zoom_prop) {
- RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
- delta[0] /= zoom[0];
- delta[1] /= zoom[1];
+ 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);
+ }
+ handled = true;
}
-
- dist = len_v2(delta);
+ if (event->val == KM_RELEASE) {
+ rc->slow_mode = false;
+ handled = true;
+ if (rc->dial) {
+ MEM_freeN(rc->dial);
+ rc->dial = NULL;
+ }
+ }
+ break;
}
+ }
- /* calculate new value and apply snapping */
- switch (rc->subtype) {
- case PROP_NONE:
- case PROP_DISTANCE:
- case PROP_PERCENTAGE:
- case PROP_PIXEL:
- new_value = dist;
- if (snap) new_value = ((int)new_value + 5) / 10 * 10;
- break;
- case PROP_FACTOR:
- new_value = (WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / WM_RADIAL_CONTROL_DISPLAY_WIDTH;
- if (snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f;
- break;
- case PROP_ANGLE:
- new_value = atan2f(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:
- new_value = dist; /* dummy value, should this ever happen? - campbell */
- break;
+ /* Modal numinput inactive, try to handle numeric inputs last... */
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &rc->num_input, event)) {
+ applyNumInput(&rc->num_input, &numValue);
+
+ if (rc->subtype == PROP_ANGLE) {
+ numValue = DEG2RADF(numValue);
+ numValue = fmod(numValue, 2.0f * (float)M_PI);
+ if (numValue < 0.0f)
+ numValue += 2.0f * (float)M_PI;
}
- /* clamp and update */
- CLAMP(new_value, rc->min_value, rc->max_value);
+ CLAMP(numValue, rc->min_value, rc->max_value);
+ new_value = numValue;
+
radial_control_set_value(rc, new_value);
- rc->current_value = new_value;
- break;
-
- case ESCKEY:
- case RIGHTMOUSE:
- /* canceled; restore original value */
- radial_control_set_value(rc, rc->initial_value);
- ret = OPERATOR_CANCELLED;
- break;
-
- case LEFTMOUSE:
- case PADENTER:
- /* done; value already set */
- 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;
+ rc->current_value = new_value;
+ radial_control_update_header(op, C);
+ return OPERATOR_RUNNING_MODAL;
+ }
}
ED_region_tag_redraw(CTX_wm_region(C));
@@ -4547,6 +4708,90 @@ static void WM_OT_dependency_relations(wmOperatorType *ot)
ot->exec = dependency_relations_exec;
}
+/* *************************** Mat/tex/etc. previews generation ************* */
+
+typedef struct PreviewsIDEnsureStack {
+ Scene *scene;
+
+ BLI_LINKSTACK_DECLARE(id_stack, ID *);
+} PreviewsIDEnsureStack;
+
+static void previews_id_ensure(bContext *C, Scene *scene, ID *id)
+{
+ BLI_assert(ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA));
+
+ /* Only preview non-library datablocks, lib ones do not pertain to this .blend file!
+ * Same goes for ID with no user. */
+ if (!id->lib && (id->us != 0)) {
+ UI_id_icon_render(C, scene, id, false, false);
+ UI_id_icon_render(C, scene, id, true, false);
+ }
+}
+
+static bool previews_id_ensure_callback(void *todo_v, ID **idptr, int UNUSED(cd_flag))
+{
+ PreviewsIDEnsureStack *todo = todo_v;
+ ID *id = *idptr;
+
+ if (id && (id->flag & LIB_DOIT)) {
+ if (ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA)) {
+ previews_id_ensure(NULL, todo->scene, id);
+ }
+ id->flag &= ~LIB_DOIT; /* Tag the ID as done in any case. */
+ BLI_LINKSTACK_PUSH(todo->id_stack, id);
+ }
+
+ return true;
+}
+
+static int previews_ensure_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ ListBase *lb[] = {&bmain->mat, &bmain->tex, &bmain->image, &bmain->world, &bmain->lamp, NULL};
+ PreviewsIDEnsureStack preview_id_stack;
+ Scene *scene;
+ ID *id;
+ int i;
+
+ /* We use LIB_DOIT to check whether we have already handled a given ID or not. */
+ BKE_main_id_flag_all(bmain, LIB_DOIT, true);
+
+ BLI_LINKSTACK_INIT(preview_id_stack.id_stack);
+
+ for (scene = bmain->scene.first; scene; scene = scene->id.next) {
+ preview_id_stack.scene = scene;
+ id = (ID *)scene;
+
+ do {
+ /* This will loop over all IDs linked by current one, render icons for them if needed,
+ * and add them to 'todo' preview_id_stack. */
+ BKE_library_foreach_ID_link(id, previews_id_ensure_callback, &preview_id_stack, IDWALK_READONLY);
+ } while ((id = BLI_LINKSTACK_POP(preview_id_stack.id_stack)));
+ }
+
+ BLI_LINKSTACK_FREE(preview_id_stack.id_stack);
+
+ /* Check a last time for ID not used (fake users only, in theory), and
+ * do our best for those, using current scene... */
+ for (i = 0; lb[i]; i++) {
+ for (id = lb[i]->first; id; id = id->next) {
+ previews_id_ensure(C, NULL, id);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void WM_OT_previews_ensure(wmOperatorType *ot)
+{
+ ot->name = "Refresh DataBlock Previews";
+ ot->idname = "WM_OT_previews_ensure";
+ ot->description = "Ensure datablock previews are available and up-to-date "
+ "(to be saved in .blend file, only for some types like materials, textures, etc.)";
+
+ ot->exec = previews_ensure_exec;
+}
+
/* ******************************************************* */
static void operatortype_ghash_free_cb(wmOperatorType *ot)
@@ -4610,6 +4855,7 @@ void wm_operatortype_init(void)
#if defined(WIN32)
WM_operatortype_append(WM_OT_console_toggle);
#endif
+ WM_operatortype_append(WM_OT_previews_ensure);
}
/* circleselect-like modal operators */
@@ -4667,6 +4913,8 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "CLIP_OT_select_circle");
WM_modalkeymap_assign(keymap, "MASK_OT_select_circle");
WM_modalkeymap_assign(keymap, "NODE_OT_select_circle");
+ WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_circle");
+ WM_modalkeymap_assign(keymap, "GRAPH_OT_select_circle");
}
@@ -4763,6 +5011,7 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_border");
WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border"); /* XXX TODO: zoom border should perhaps map rightmouse to zoom out instead of in+cancel */
WM_modalkeymap_assign(keymap, "IMAGE_OT_render_border");
+ WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_border");
}
/* zoom to border modal operators */
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 677be734d4b..232c9ad2e4d 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -69,8 +69,6 @@
#include "GHOST_C-api.h"
#include "BLF_api.h"
-#include "wm_event_types.h"
-
#include "WM_api.h" /* only for WM_main_playanim */
struct PlayState;
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index e26bcac9b1a..d2df020600a 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -53,7 +53,6 @@
#include "WM_api.h"
#include "wm_subwindow.h"
-#include "wm_window.h"
/* wmSubWindow stored in wmWindow... but not exposed outside this C file */
/* it seems a bit redundant (area regions can store it too, but we keep it
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 46a20d3bf88..52fcdd797cb 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -1524,3 +1524,21 @@ bool WM_window_is_fullscreen(wmWindow *win)
return win->windowstate == GHOST_kWindowStateFullScreen;
}
+
+#ifdef WITH_INPUT_IME
+/* note: keep in mind wm_window_IME_begin is also used to reposition the IME window */
+void wm_window_IME_begin(wmWindow *win, int x, int y, int w, int h, bool complete)
+{
+ BLI_assert(win);
+
+ GHOST_BeginIME(win->ghostwin, x, win->sizey - y, w, h, complete);
+}
+
+void wm_window_IME_end(wmWindow *win)
+{
+ BLI_assert(win && win->ime_data);
+
+ GHOST_EndIME(win->ghostwin);
+ win->ime_data = NULL;
+}
+#endif /* WITH_INPUT_IME */
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index fe6d3431183..2301405a8ea 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -86,6 +86,13 @@ enum {
* paint and drawing tools however will want to handle these. */
INBETWEEN_MOUSEMOVE = 0x0011,
+/* IME event, GHOST_kEventImeCompositionStart in ghost */
+ WM_IME_COMPOSITE_START = 0x0014,
+/* IME event, GHOST_kEventImeComposition in ghost */
+ WM_IME_COMPOSITE_EVENT = 0x0015,
+/* IME event, GHOST_kEventImeCompositionEnd in ghost */
+ WM_IME_COMPOSITE_END = 0x0016,
+
/* *** Start of keyboard codes. *** */
/* standard keyboard.
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index 9c9c79d2f54..833234b0f13 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -69,6 +69,11 @@ wmWindow *wm_window_copy (bContext *C, wmWindow *winorig);
void wm_window_testbreak (void);
+#ifdef WITH_INPUT_IME
+void wm_window_IME_begin (wmWindow *win, int x, int y, int w, int h, bool complete);
+void wm_window_IME_end (wmWindow *win);
+#endif
+
/* *************** window operators ************** */
int wm_window_duplicate_exec(bContext *C, struct wmOperator *op);
int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op);
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 56abdfd27b1..9eff3405a2f 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -163,7 +163,9 @@ struct wmWindowManager;
#include "../blender/editors/include/ED_render.h"
#include "../blender/editors/include/ED_screen.h"
#include "../blender/editors/include/ED_space_api.h"
+#include "../blender/editors/include/ED_text.h"
#include "../blender/editors/include/ED_transform.h"
+#include "../blender/editors/include/ED_uvedit.h"
#include "../blender/editors/include/ED_view3d.h"
#include "../blender/editors/include/UI_interface.h"
#include "../blender/editors/include/UI_interface_icons.h"
@@ -217,6 +219,7 @@ void EDBM_mesh_load(struct Object *ob) RET_NONE
void EDBM_mesh_make(struct ToolSettings *ts, struct Object *ob) RET_NONE
void EDBM_mesh_normals_update(struct BMEditMesh *em) RET_NONE
void *g_system;
+bool EDBM_mtexpoly_check(struct BMEditMesh *em) RET_ZERO
float *RE_RenderLayerGetPass(struct RenderLayer *rl, int passtype) RET_NULL
float RE_filter_value(int type, float x) RET_ZERO
@@ -339,6 +342,8 @@ void ED_space_image_paint_update(struct wmWindowManager *wm, struct ToolSettings
void ED_space_image_set(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit, struct Image *ima) RET_NONE
void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct ToolSettings *settings) RET_NONE
+void ED_uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMesh *em, float *aspx, float *aspy) RET_NONE
+
void ED_screen_set_scene(struct bContext *C, struct bScreen *screen, struct Scene *scene) RET_NONE
struct MovieClip *ED_space_clip_get_clip(struct SpaceClip *sc) RET_NULL
void ED_space_clip_set_clip(struct bContext *C, struct bScreen *screen, struct SpaceClip *sc, struct MovieClip *clip) RET_NONE
@@ -349,6 +354,7 @@ void ED_area_tag_redraw_regiontype(struct ScrArea *sa, int regiontype) RET_NONE
void ED_render_engine_changed(struct Main *bmain) RET_NONE
void ED_file_read_bookmarks(void) RET_NONE
+void ED_preview_kill_jobs(struct wmWindowManager *wm, struct Main *bmain) RET_NONE
struct PTCacheEdit *PE_get_current(struct Scene *scene, struct Object *ob) RET_NULL
void PE_current_changed(struct Scene *scene, struct Object *ob) RET_NONE
@@ -461,13 +467,9 @@ bool ED_mesh_color_remove_named(struct Mesh *me, const char *name) RET_ZERO
bool ED_mesh_uv_texture_remove_named(struct Mesh *me, const char *name) RET_ZERO
void ED_object_constraint_dependency_update(struct Main *bmain, struct Object *ob) RET_NONE
void ED_object_constraint_update(struct Object *ob) RET_NONE
-struct bDeformGroup *ED_vgroup_add_name(struct Object *ob, const char *name) RET_NULL
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode) RET_NONE
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum) RET_NONE
float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum) RET_ZERO
-void ED_vgroup_delete(struct Object *ob, struct bDeformGroup *defgroup) RET_NONE
-void ED_vgroup_clear(struct Object *ob) RET_NONE
-bool ED_vgroup_object_is_edit_mode(struct Object *ob) RET_ZERO
int ED_mesh_mirror_topo_table(struct Object *ob, char mode) RET_ZERO
int ED_mesh_mirror_spatial_table(struct Object *ob, struct BMEditMesh *em, const float co[3], char mode) RET_ZERO
@@ -481,6 +483,8 @@ 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
+bool ED_text_region_location_from_cursor(SpaceText *st, ARegion *ar, const int cursor_co[2], int r_pixel_co[2]) RET_ZERO
+
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,
@@ -505,6 +509,7 @@ struct uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align) RE
bool uiLayoutGetRedAlert(struct uiLayout *layout) RET_ZERO
void uiLayoutSetRedAlert(uiLayout *layout, bool redalert) RET_NONE
void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname) RET_NONE
+void uiItemMenuEnumR_prop(uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon) RET_NONE
void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon) RET_NONE
void uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *value, const char *name, int icon) RET_NONE
void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *searchptr, const char *searchpropname, const char *name, int icon) RET_NONE
@@ -576,6 +581,7 @@ struct RenderStats *RE_GetStats(struct Render *re) RET_NULL
struct RenderData *RE_engine_get_render_data(struct Render *re) RET_NULL
void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result) RET_NONE
void RE_engine_update_progress(struct RenderEngine *engine, float progress) RET_NONE
+void RE_engine_set_error_message(RenderEngine *engine, const char *msg) RET_NONE
void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results) RET_NONE
void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info) RET_NONE
void RE_layer_load_from_file(struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y) RET_NONE
@@ -617,6 +623,7 @@ int WM_operator_ui_popup(struct bContext *C, struct wmOperator *op, int width, i
void update_autoflags_fcurve(struct FCurve *fcu, struct bContext *C, struct ReportList *reports, struct PointerRNA *ptr) RET_NONE
short insert_keyframe(struct ReportList *reports, struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) RET_ZERO
short delete_keyframe(struct ReportList *reports, struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) RET_ZERO
+struct bAction *verify_adt_action(struct ID *id, short add) RET_NULL
char *WM_operator_pystring_ex(struct bContext *C, struct wmOperator *op, const bool all_args, const bool macro_args, struct wmOperatorType *ot, struct PointerRNA *opptr) RET_NULL
char *WM_operator_pystring(struct bContext *C, struct wmOperator *op, const bool all_args, const bool macro_args) RET_NULL
struct wmKeyMapItem *WM_modalkeymap_add_item(struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value) RET_NULL
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 0e596fb0c5f..21cb41ddfa2 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -628,37 +628,54 @@ elseif(WIN32)
install(DIRECTORY DESTINATION ${TARGETDIR_VER}/python)
install(DIRECTORY DESTINATION ${TARGETDIR_VER}/python/lib)
- execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib")
+ # WARNING: its important that 'CMAKE_INSTALL_CONFIG_NAME' is evaluated at build time
+ # and _NOT_ configuration time, when modifying the lines below,
+ # check it works in both Release & Debug mode.
+ #
+ # Edit with extreme care! - Campbell
- if(\"\${CMAKE_INSTALL_CONFIG_NAME}\" STREQUAL \"Debug\")
- add_custom_target(python_std_lib
- COMMAND ${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_d.tar.gz"
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib)
- else()
- add_custom_target(python_std_lib
- COMMAND ${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}.tar.gz"
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib)
- endif()
+ # extract python
+ install(
+ CODE
+ "
+ message(STATUS \"Extracting Python to: \${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}/python\")
+ if(\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Dd][Ee][Bb][Uu][Gg])$\")
+ set(PYTHON_ZIP ${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_d.tar.gz)
+ else()
+ set(PYTHON_ZIP ${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}.tar.gz)
+ endif()
- add_dependencies(blender python_std_lib)
+ execute_process(
+ COMMAND \${CMAKE_COMMAND} -E make_directory
+ \"\${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}/python/lib\"
+ COMMAND \${CMAKE_COMMAND} -E
+ chdir \"\${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}/python/lib\"
+ \${CMAKE_COMMAND} -E
+ tar xzfv \"\${PYTHON_ZIP}\"
+ )
+ unset(PYTHON_ZIP)
+ "
+ )
# release/site-packages
- add_custom_target(python_site-packages
- COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/release/site-packages ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/)
-
- add_dependencies(blender python_site-packages)
+ install(
+ DIRECTORY ${LIBDIR}/release/site-packages
+ DESTINATION ${BLENDER_VERSION}/python/lib
+ PATTERN ".svn" EXCLUDE
+ PATTERN "__pycache__" EXCLUDE # * any cache *
+ PATTERN "*.pyc" EXCLUDE # * any cache *
+ PATTERN "*.pyo" EXCLUDE # * any cache *)
+ )
if(WITH_PYTHON_INSTALL_NUMPY)
- add_custom_target(python_numpy
- COMMAND ${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_1.8.tar.gz"
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages/numpy
+ COMMAND ${CMAKE_COMMAND} -E tar xzvf "${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_1.9.tar.gz"
+ DEPENDS ${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_1.9.tar.gz
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages)
+ add_custom_target(python_numpy ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages/numpy)
+ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages/numpy
+ DESTINATION ${BLENDER_VERSION}/python/lib/site-packages)
endif()
-
- add_dependencies(blender python_numpy)
-
- install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib
- DESTINATION ${BLENDER_VERSION}/python )
-
endif()
unset(_PYTHON_VERSION_NO_DOTS)
diff --git a/source/creator/creator.c b/source/creator/creator.c
index be03ffe0bda..83741a64ace 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -48,13 +48,6 @@
# include "utfconv.h"
#endif
-/* for backtrace */
-#if defined(__linux__) || defined(__APPLE__)
-# include <execinfo.h>
-#elif defined(_MSV_VER)
-# include <DbgHelp.h>
-#endif
-
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
@@ -82,6 +75,7 @@
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
+#include "BKE_appdir.h"
#include "BKE_blender.h"
#include "BKE_brush.h"
#include "BKE_context.h"
@@ -515,73 +509,12 @@ static int set_fpe(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(dat
return 0;
}
-#if defined(__linux__) || defined(__APPLE__)
-
-/* Unix */
static void blender_crash_handler_backtrace(FILE *fp)
{
-#define SIZE 100
- void *buffer[SIZE];
- int nptrs;
- char **strings;
- int i;
-
fputs("\n# backtrace\n", fp);
-
- /* include a backtrace for good measure */
- nptrs = backtrace(buffer, SIZE);
- strings = backtrace_symbols(buffer, nptrs);
- for (i = 0; i < nptrs; i++) {
- fputs(strings[i], fp);
- fputc('\n', fp);
- }
-
- free(strings);
-#undef SIZE
+ BLI_system_backtrace(fp);
}
-#elif defined(_MSC_VER)
-
-static void blender_crash_handler_backtrace(FILE *fp)
-{
- (void)fp;
-
-#if 0
-#define MAXSYMBOL 256
- unsigned short i;
- void *stack[SIZE];
- unsigned short nframes;
- SYMBOL_INFO *symbolinfo;
- HANDLE process;
-
- process = GetCurrentProcess();
-
- SymInitialize(process, NULL, true);
-
- nframes = CaptureStackBackTrace(0, SIZE, stack, NULL);
- symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof(char), "crash Symbol table");
- symbolinfo->MaxNameLen = MAXSYMBOL - 1;
- symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO);
-
- for (i = 0; i < nframes; i++) {
- SymFromAddr(process, ( DWORD64 )( stack[ i ] ), 0, symbolinfo);
-
- fprintf(fp, "%u: %s - 0x%0X\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address);
- }
-
- MEM_freeN(symbolinfo);
-#endif
-}
-
-#else /* non msvc/osx/linux */
-
-static void blender_crash_handler_backtrace(FILE *fp)
-{
- (void)fp;
-}
-
-#endif
-
static void blender_crash_handler(int signum)
{
@@ -590,7 +523,7 @@ static void blender_crash_handler(int signum)
char fname[FILE_MAX];
if (!G.main->name[0]) {
- BLI_make_file_string("/", fname, BLI_temp_dir_base(), "crash.blend");
+ BLI_make_file_string("/", fname, BKE_tempdir_base(), "crash.blend");
}
else {
BLI_strncpy(fname, G.main->name, sizeof(fname));
@@ -611,10 +544,10 @@ static void blender_crash_handler(int signum)
char fname[FILE_MAX];
if (!G.main->name[0]) {
- BLI_join_dirfile(fname, sizeof(fname), BLI_temp_dir_base(), "blender.crash.txt");
+ BLI_join_dirfile(fname, sizeof(fname), BKE_tempdir_base(), "blender.crash.txt");
}
else {
- BLI_join_dirfile(fname, sizeof(fname), BLI_temp_dir_base(), BLI_path_basename(G.main->name));
+ BLI_join_dirfile(fname, sizeof(fname), BKE_tempdir_base(), BLI_path_basename(G.main->name));
BLI_replace_extension(fname, sizeof(fname), ".crash.txt");
}
@@ -646,7 +579,7 @@ static void blender_crash_handler(int signum)
}
/* Delete content of temp dir! */
- BLI_temp_dir_session_purge();
+ BKE_tempdir_session_purge();
/* really crash */
signal(signum, SIG_DFL);
@@ -1195,7 +1128,7 @@ static int run_python_file(int argc, const char **argv, void *data)
return 0;
}
#else
- (void)argc; (void)argv; (void)data; /* unused */
+ UNUSED_VARS(argc, argv, data);
printf("This blender was built without python support\n");
return 0;
#endif /* WITH_PYTHON */
@@ -1225,7 +1158,7 @@ static int run_python_text(int argc, const char **argv, void *data)
return 0;
}
#else
- (void)argc; (void)argv; (void)data; /* unused */
+ UNUSED_VARS(argc, argv, data);
printf("This blender was built without python support\n");
return 0;
#endif /* WITH_PYTHON */
@@ -1240,7 +1173,7 @@ static int run_python_console(int UNUSED(argc), const char **argv, void *data)
return 0;
#else
- (void)argv; (void)data; /* unused */
+ UNUSED_VARS(argv, data);
printf("This blender was built without python support\n");
return 0;
#endif /* WITH_PYTHON */
@@ -1258,7 +1191,7 @@ static int set_addons(int argc, const char **argv, void *data)
BPY_CTX_SETUP(BPY_string_exec(C, str));
free(str);
#else
- (void)argv; (void)data; /* unused */
+ UNUSED_VARS(argv, data);
#endif /* WITH_PYTHON */
return 1;
}
@@ -1618,13 +1551,28 @@ int main(
#endif
setCallbacks();
+
+#if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE)
+/* patch to ignore argument finder gives us (pid?) */
+ if (argc == 2 && strncmp(argv[1], "-psn_", 5) == 0) {
+ extern int GHOST_HACK_getFirstFile(char buf[]);
+ static char firstfilebuf[512];
+
+ argc = 1;
+ if (GHOST_HACK_getFirstFile(firstfilebuf)) {
+ argc = 2;
+ argv[1] = firstfilebuf;
+ }
+ }
+#endif
+
#ifdef __FreeBSD__
fpsetmask(0);
#endif
/* initialize path to executable */
- BLI_init_program_path(argv[0]);
+ BKE_appdir_program_path_init(argv[0]);
BLI_threadapi_init();
@@ -1703,7 +1651,7 @@ int main(
/* this is properly initialized with user defs, but this is default */
/* call after loading the startup.blend so we can read U.tempdir */
- BLI_temp_dir_init(U.tempdir);
+ BKE_tempdir_init(U.tempdir);
}
else {
#ifndef WITH_PYTHON_MODULE
@@ -1713,7 +1661,7 @@ int main(
WM_init(C, argc, (const char **)argv);
/* don't use user preferences temp dir */
- BLI_temp_dir_init(NULL);
+ BKE_tempdir_init(NULL);
}
#ifdef WITH_PYTHON
/**
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index 2a7e631637e..60b8832b44e 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -280,8 +280,8 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0);
#endif
// bool novertexarrays = (SYS_GetCommandLineInt(syshandle, "novertexarrays", 0) != 0);
- bool mouse_state = startscene->gm.flag & GAME_SHOW_MOUSE;
- bool restrictAnimFPS = startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES;
+ bool mouse_state = (startscene->gm.flag & GAME_SHOW_MOUSE) != 0;
+ bool restrictAnimFPS = (startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES) != 0;
short drawtype = v3d->drawtype;
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index 3dd013dfd63..c756d8695e6 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -256,12 +256,14 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
if ((m_flag & ACT_FLAG_PLAY_END) && (m_flag & ACT_FLAG_ACTIVE) && obj->IsActionDone(m_layer))
{
m_flag &= ~ACT_FLAG_ACTIVE;
- m_flag &= ~ACT_FLAG_ATTEMPT_PLAY;
- if (m_playtype == ACT_ACTION_PINGPONG)
+ if (m_playtype == ACT_ACTION_PINGPONG) {
m_flag ^= ACT_FLAG_REVERSE;
- else
+ }
+ else {
+ m_flag &= ~ACT_FLAG_ATTEMPT_PLAY;
return false;
+ }
}
// If a different action is playing, we've been overruled and are no longer active
@@ -320,8 +322,9 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
case ACT_ACTION_FLIPPER:
// Convert into a play action and play back to the beginning
+ float temp = end;
end = start;
- start = obj->GetActionFrame(m_layer);
+ start = curr_action ? obj->GetActionFrame(m_layer) : temp;
obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags, 1.f, blendmode);
m_flag |= ACT_FLAG_PLAY_END;
diff --git a/source/gameengine/Converter/BL_ArmatureChannel.cpp b/source/gameengine/Converter/BL_ArmatureChannel.cpp
index cb33ff0e1e3..2b8dfd8f8d1 100644
--- a/source/gameengine/Converter/BL_ArmatureChannel.cpp
+++ b/source/gameengine/Converter/BL_ArmatureChannel.cpp
@@ -295,7 +295,7 @@ PyObject *BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const str
mul_v3_fl(joints,norm);
break;
}
- return Vector_CreatePyObject(joints, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(joints, 3, NULL);
}
int BL_ArmatureChannel::py_attr_set_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp
index 71dc1bdec87..3bc07113ff6 100644
--- a/source/gameengine/Converter/BL_ModifierDeformer.cpp
+++ b/source/gameengine/Converter/BL_ModifierDeformer.cpp
@@ -186,6 +186,7 @@ bool BL_ModifierDeformer::Update(void)
m_dm->release(m_dm);
// HACK! use deformedOnly as a user counter
m_dm->deformedOnly = 1;
+ DM_update_materials(m_dm, blendobj);
/* update the graphic controller */
PHY_IGraphicController *ctrl = m_gameobj->GetGraphicController();
if (ctrl) {
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index a20ebb3a081..eb4b9a8124a 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -69,6 +69,7 @@
#include "DNA_scene_types.h"
#include "DNA_world_types.h"
#include "BKE_main.h"
+#include "BKE_fcurve.h"
#include "BLI_math.h"
@@ -87,6 +88,7 @@ extern "C"
#include "BKE_mesh.h" // BKE_mesh_copy
#include "DNA_space_types.h"
#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
#include "RNA_define.h"
#include "../../blender/editors/include/ED_keyframing.h"
}
@@ -843,13 +845,26 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
{
KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
if (gameObj->IsRecordAnimation()) {
-#if 0
Object* blenderObject = gameObj->GetBlenderObject();
- if (blenderObject && blenderObject->ipo)
+ if (blenderObject && blenderObject->adt)
{
+ bAction *act = verify_adt_action(&blenderObject->id, false);
+ FCurve *fcu;
+
+ if (!act) {
+ continue;
+ }
+
+ /* for now, not much choice but to run this on all curves... */
+ for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
+ /* Note: calling `sort_time_fcurve()` here is not needed, since
+ * all keys have been added in 'right' order. */
+ calchandles_fcurve(fcu);
+ }
+#if 0
// XXX animato
Ipo* ipo = blenderObject->ipo;
-
+
//create the curves, if not existing
//testhandles_ipocurve checks for NULL
testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"));
@@ -858,8 +873,8 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"));
testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"));
testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"));
- }
#endif
+ }
}
}
}
diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp
index 75e3b490505..5e0eb92eb58 100644
--- a/source/gameengine/Expressions/ListValue.cpp
+++ b/source/gameengine/Expressions/ListValue.cpp
@@ -432,7 +432,7 @@ static PyObject *listvalue_buffer_concat(PyObject *self, PyObject *other)
for (i=0;i<numitems;i++)
{
- listitemval = listval->ConvertPythonToValue(PyList_GetItem(other,i), true, "cList + pyList: CListValue, ");
+ listitemval = listval->ConvertPythonToValue(PyList_GET_ITEM(other, i), true, "cList + pyList: CListValue, ");
if (listitemval) {
listval_new->SetValue(i+numitems_orig, listitemval);
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
index c025d439fc0..a65d61bc98b 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -418,7 +418,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
return NULL;
}
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject(val, attrdef->m_imax, Py_NEW, NULL);
+ return Vector_CreatePyObject(val, attrdef->m_imax, NULL);
#else
PyObject *resultlist = PyList_New(attrdef->m_imax);
for (unsigned int i=0; i<attrdef->m_imax; i++)
@@ -435,7 +435,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
return NULL;
}
#ifdef USE_MATHUTILS
- return Matrix_CreatePyObject(val, attrdef->m_imin, attrdef->m_imax, Py_WRAP, NULL);
+ return Matrix_CreatePyObject_wrap(val, attrdef->m_imin, attrdef->m_imax, NULL);
#else
PyObject *collist = PyList_New(attrdef->m_imin);
for (unsigned int i=0; i<attrdef->m_imin; i++)
@@ -458,7 +458,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
#ifdef USE_MATHUTILS
float fval[3];
val->getValue(fval);
- return Vector_CreatePyObject(fval, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(fval, 3, NULL);
#else
PyObject *resultlist = PyList_New(3);
for (unsigned int i=0; i<3; i++)
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index bdef2dbd5b0..286db016476 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -568,7 +568,7 @@ CValue *CValue::ConvertPythonToValue(PyObject *pyobj, const bool do_type_excepti
Py_ssize_t numitems = PyList_GET_SIZE(pyobj);
for (i=0;i<numitems;i++)
{
- PyObject *listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
+ PyObject *listitem = PyList_GET_ITEM(pyobj,i); /* borrowed ref */
CValue* listitemval = ConvertPythonToValue(listitem, error_prefix);
if (listitemval)
{
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
index 228adbb942e..daf869e3e61 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
@@ -41,7 +41,9 @@
#include "BLI_path_util.h"
-#define SDL_CHECK(x) ((x) != (void*)0)
+#ifdef WITH_SDL
+# define SDL_CHECK(x) ((x) != (void *)0)
+#endif
SCA_Joystick::SCA_Joystick(short int index)
:
@@ -109,7 +111,11 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex )
char *videodriver = getenv("SDL_VIDEODRIVER");
BLI_setenv("SDL_VIDEODRIVER", "dummy");
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ int success = (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != -1 );
+#else
int success = (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO) != -1 );
+#endif
BLI_setenv("SDL_VIDEODRIVER", videodriver);
# endif
@@ -154,11 +160,11 @@ void SCA_Joystick::ReleaseInstance()
/* The video subsystem is required for joystick input to work. However,
* when GHOST is running under SDL, video is freed elsewhere.
* Do this once only. */
-# ifdef WITH_GHOST_SDL
+#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
-# else
+#else
SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO);
-# endif
+#endif
#endif /* WITH_SDL */
}
}
diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
index 08f4d97ed1b..0033c137eb6 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
@@ -124,6 +124,12 @@ void SCA_Joystick::HandleEvents(void)
SCA_Joystick::m_instance[sdl_event.jball.which]->OnBallMotion(&sdl_event);
break;
#endif
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ case SDL_JOYDEVICEADDED:
+ case SDL_JOYDEVICEREMOVED:
+ /* pass */
+ break;
+#endif
default:
printf("SCA_Joystick::HandleEvents, Unknown SDL event (%d), this should not happen\n", sdl_event.type);
break;
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
index cc203880f94..e5d717e0140 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
@@ -511,6 +511,7 @@ PyObject *SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBU
PyList_SET_ITEM(keypair,0,PyLong_FromLong(i));
PyList_SET_ITEM(keypair,1,PyLong_FromLong(inevent.m_status));
PyList_Append(resultlist,keypair);
+ Py_DECREF(keypair);
}
}
return resultlist;
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index d7a63c28da3..2791931fe43 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -567,7 +567,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", gm->flag & GAME_DISPLAY_LISTS) != 0) && GPU_display_list_support();
bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 1) != 0);
- bool restrictAnimFPS = gm->flag & GAME_RESTRICT_ANIM_UPDATES;
+ bool restrictAnimFPS = (gm->flag & GAME_RESTRICT_ANIM_UPDATES) != 0;
if (GLEW_ARB_multitexture && GLEW_VERSION_1_1)
m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0);
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index 1a6501fae6e..915fe614957 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -64,6 +64,7 @@ extern "C"
#include "BLO_readfile.h"
#include "BLO_runtime.h"
+#include "BKE_appdir.h"
#include "BKE_blender.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
@@ -79,6 +80,10 @@ extern "C"
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
+#ifdef __APPLE__
+ int GHOST_HACK_getFirstFile(char buf[]);
+#endif
+
// For BLF
#include "BLF_api.h"
#include "BLF_translation.h"
@@ -296,6 +301,12 @@ static void get_filename(int argc, char **argv, char *filename)
if (BLI_exists(argv[argc-1])) {
BLI_strncpy(filename, argv[argc-1], FILE_MAX);
}
+ if (::strncmp(argv[argc-1], "-psn_", 5)==0) {
+ static char firstfilebuf[512];
+ if (GHOST_HACK_getFirstFile(firstfilebuf)) {
+ BLI_strncpy(filename, firstfilebuf, FILE_MAX);
+ }
+ }
}
srclen -= ::strlen("MacOS/blenderplayer");
@@ -430,8 +441,8 @@ int main(int argc, char** argv)
sdlewInit();
#endif
- BLI_init_program_path(argv[0]);
- BLI_temp_dir_init(NULL);
+ BKE_appdir_program_path_init(argv[0]);
+ BKE_tempdir_init(NULL);
// We don't use threads directly in the BGE, but we need to call this so things like
// freeing up GPU_Textures works correctly.
@@ -870,7 +881,7 @@ int main(int argc, char** argv)
}
}
else {
- bfd = load_game_data(BLI_program_path(), filename[0]? filename: NULL);
+ bfd = load_game_data(BKE_appdir_program_path(), filename[0]? filename: NULL);
}
#if defined(DEBUG)
@@ -1142,7 +1153,7 @@ int main(int argc, char** argv)
MEM_printmemlist();
}
- BLI_temp_dir_session_purge();
+ BKE_tempdir_session_purge();
return error ? -1 : 0;
}
diff --git a/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt b/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt
index 0c661cf2c87..cfc6ded4e65 100644
--- a/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt
+++ b/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../../GameLogic
../../Network
../../SceneGraph
+ ../../../blender/blenlib
../../../../intern/container
../../../../intern/string
)
diff --git a/source/gameengine/Ketsji/KXNetwork/SConscript b/source/gameengine/Ketsji/KXNetwork/SConscript
index 355dcc4f78f..ab03e03e74d 100644
--- a/source/gameengine/Ketsji/KXNetwork/SConscript
+++ b/source/gameengine/Ketsji/KXNetwork/SConscript
@@ -39,6 +39,7 @@ incs = [
'#source/gameengine/Ketsji',
'#source/gameengine/Network',
'#source/gameengine/SceneGraph',
+ '../../../blender/blenlib',
]
incs = ' '.join(incs)
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp
index e0761154ed2..ce2fe5f5ad8 100644
--- a/source/gameengine/Ketsji/KX_Camera.cpp
+++ b/source/gameengine/Ketsji/KX_Camera.cpp
@@ -747,7 +747,7 @@ int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef,
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float param = PyFloat_AsDouble(value);
if (param == -1) {
- PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -772,7 +772,7 @@ int KX_Camera::pyattr_set_fov(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float fov = PyFloat_AsDouble(value);
if (fov <= 0.0) {
- PyErr_SetString(PyExc_AttributeError, "camera.fov = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.fov = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -796,7 +796,7 @@ int KX_Camera::pyattr_set_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *at
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float param = PyFloat_AsDouble(value);
if (param == -1) {
- PyErr_SetString(PyExc_AttributeError, "camera.ortho_scale = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.ortho_scale = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -816,7 +816,7 @@ int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef,
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float param = PyFloat_AsDouble(value);
if (param == -1) {
- PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -836,7 +836,7 @@ int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float param = PyFloat_AsDouble(value);
if (param == -1) {
- PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
index a77269c116d..f58fee88d48 100644
--- a/source/gameengine/Ketsji/KX_Dome.cpp
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -2044,7 +2044,6 @@ 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 dc246406a88..e8b68d20e84 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -575,6 +575,39 @@ CValue* KX_GameObject::GetReplica()
return replica;
}
+float KX_GameObject::getLinearDamping() const
+{
+ if (m_pPhysicsController)
+ return m_pPhysicsController->GetLinearDamping();
+ return 0;
+}
+
+float KX_GameObject::getAngularDamping() const
+{
+ if (m_pPhysicsController)
+ return m_pPhysicsController->GetAngularDamping();
+ return 0;
+}
+
+void KX_GameObject::setLinearDamping(float damping)
+{
+ if (m_pPhysicsController)
+ m_pPhysicsController->SetLinearDamping(damping);
+}
+
+
+void KX_GameObject::setAngularDamping(float damping)
+{
+ if (m_pPhysicsController)
+ m_pPhysicsController->SetAngularDamping(damping);
+}
+
+
+void KX_GameObject::setDamping(float linear, float angular)
+{
+ if (m_pPhysicsController)
+ m_pPhysicsController->SetDamping(linear, angular);
+}
void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
@@ -930,27 +963,6 @@ 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();
@@ -1824,7 +1836,7 @@ static Mathutils_Callback mathutils_kxgameob_matrix_cb = {
void KX_GameObject_Mathutils_Callback_Init(void)
{
- // register mathutils callbacks, ok to run more then once.
+ // register mathutils callbacks, ok to run more than once.
mathutils_kxgameob_vector_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_vector_cb);
mathutils_kxgameob_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_matrix_cb);
}
@@ -1843,6 +1855,7 @@ PyMethodDef KX_GameObject::Methods[] = {
{"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
{"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
{"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
+ {"setDamping", (PyCFunction) KX_GameObject::sPySetDamping, METH_VARARGS},
{"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
{"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
{"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
@@ -1918,6 +1931,8 @@ PyAttributeDef KX_GameObject::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("angularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_worldAngularVelocity),
KX_PYATTRIBUTE_RW_FUNCTION("localAngularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_localAngularVelocity),
KX_PYATTRIBUTE_RW_FUNCTION("worldAngularVelocity", KX_GameObject, pyattr_get_worldAngularVelocity, pyattr_set_worldAngularVelocity),
+ KX_PYATTRIBUTE_RW_FUNCTION("linearDamping", KX_GameObject, pyattr_get_linearDamping, pyattr_set_linearDamping),
+ KX_PYATTRIBUTE_RW_FUNCTION("angularDamping", KX_GameObject, pyattr_get_angularDamping, pyattr_set_angularDamping),
KX_PYATTRIBUTE_RO_FUNCTION("children", KX_GameObject, pyattr_get_children),
KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive),
KX_PYATTRIBUTE_RO_FUNCTION("attrDict", KX_GameObject, pyattr_get_attrDict),
@@ -2708,6 +2723,34 @@ int KX_GameObject::pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTR
return PY_SET_ATTR_SUCCESS;
}
+PyObject *KX_GameObject::pyattr_get_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ return PyFloat_FromDouble(self->getLinearDamping());
+}
+
+int KX_GameObject::pyattr_set_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ float val = PyFloat_AsDouble(value);
+ self->setLinearDamping(val);
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_GameObject::pyattr_get_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ return PyFloat_FromDouble(self->getAngularDamping());
+}
+
+int KX_GameObject::pyattr_set_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ float val = PyFloat_AsDouble(value);
+ self->setAngularDamping(val);
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyObject *KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
@@ -3004,6 +3047,18 @@ PyObject *KX_GameObject::PySetAngularVelocity(PyObject *args)
return NULL;
}
+PyObject *KX_GameObject::PySetDamping(PyObject *args)
+{
+ float linear;
+ float angular;
+
+ if (!PyArg_ParseTuple(args,"ff|i:setDamping", &linear, &angular))
+ return NULL;
+
+ setDamping(linear, angular);
+ Py_RETURN_NONE;
+}
+
PyObject *KX_GameObject::PySetVisible(PyObject *args)
{
int visible, recursive = 0;
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index d4fa4851696..4538679303f 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -684,6 +684,12 @@ public:
bool local
);
+ virtual float getLinearDamping() const;
+ virtual float getAngularDamping() const;
+ virtual void setLinearDamping(float damping);
+ virtual void setAngularDamping(float damping);
+ virtual void setDamping(float linear, float angular);
+
/**
* Update the physics object transform based upon the current SG_Node
* position.
@@ -852,10 +858,10 @@ public:
/**
* Was this object culled?
*/
- bool
+ inline bool
GetCulled(
void
- );
+ ) { return m_bCulled; }
/**
* Set culled flag of this object
@@ -965,6 +971,7 @@ public:
KX_PYMETHOD_VARARGS(KX_GameObject,GetAngularVelocity);
KX_PYMETHOD_VARARGS(KX_GameObject,SetAngularVelocity);
KX_PYMETHOD_VARARGS(KX_GameObject,GetVelocity);
+ KX_PYMETHOD_VARARGS(KX_GameObject,SetDamping);
KX_PYMETHOD_NOARGS(KX_GameObject,GetReactionForce);
@@ -1070,6 +1077,10 @@ public:
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);
+ static PyObject* pyattr_get_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
/* Experimental! */
static PyObject* pyattr_get_sensors(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 f76580cd44d..f1d0e4262e9 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -140,6 +140,7 @@ 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),
@@ -686,6 +687,16 @@ 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();
@@ -787,6 +798,27 @@ 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);
@@ -1155,15 +1187,8 @@ 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();
@@ -1295,11 +1320,6 @@ 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);
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
index 2b80e3bd69a..e18b203b675 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.h
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -111,6 +111,7 @@ 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 */
diff --git a/source/gameengine/Ketsji/KX_MouseActuator.cpp b/source/gameengine/Ketsji/KX_MouseActuator.cpp
index aae5d18189a..8774abe04b2 100644
--- a/source/gameengine/Ketsji/KX_MouseActuator.cpp
+++ b/source/gameengine/Ketsji/KX_MouseActuator.cpp
@@ -126,24 +126,33 @@ bool KX_MouseActuator::Update()
float movement[2];
MT_Vector3 rotation;
float setposition[2] = {0.0};
+ float center_x = 0.5, center_y = 0.5;
getMousePosition(position);
movement[0] = position[0];
movement[1] = position[1];
+ //preventing undesired drifting when resolution is odd
+ if ((m_canvas->GetWidth() % 2) != 0) {
+ center_x = ((m_canvas->GetWidth() - 1.0) / 2.0) / (m_canvas->GetWidth());
+ }
+ if ((m_canvas->GetHeight() % 2) != 0) {
+ center_y = ((m_canvas->GetHeight() - 1.0) / 2.0) / (m_canvas->GetHeight());
+ }
+
//preventing initial skipping.
if ((m_oldposition[0] <= -0.9) && (m_oldposition[1] <= -0.9)) {
if (m_reset_x) {
- m_oldposition[0] = 0.5;
+ m_oldposition[0] = center_x;
}
else {
m_oldposition[0] = position[0];
}
if (m_reset_y) {
- m_oldposition[1] = 0.5;
+ m_oldposition[1] = center_y;
}
else {
m_oldposition[1] = position[1];
@@ -156,8 +165,8 @@ bool KX_MouseActuator::Update()
if (m_use_axis_x) {
if (m_reset_x) {
- setposition[0] = 0.5;
- movement[0] -= 0.5;
+ setposition[0] = center_x;
+ movement[0] -= center_x;
}
else {
setposition[0] = position[0];
@@ -166,12 +175,10 @@ bool KX_MouseActuator::Update()
movement[0] *= -1.0;
- /* Don't apply the rotation when width resolution is odd (+ little movement) to
- avoid undesired drifting or when we are under a certain threshold for mouse
+ /* Don't apply the rotation when we are under a certain threshold for mouse
movement */
- if (!((m_canvas->GetWidth() % 2 != 0) && MT_abs(movement[0]) < 0.01) &&
- ((movement[0] > (m_threshold[0] / 10.0)) ||
+ if (((movement[0] > (m_threshold[0] / 10.0)) ||
((movement[0] * (-1.0)) > (m_threshold[0] / 10.0)))) {
movement[0] *= m_sensitivity[0];
@@ -209,15 +216,15 @@ bool KX_MouseActuator::Update()
}
}
else {
- setposition[0] = 0.5;
+ setposition[0] = center_x;
}
//Calculating Y axis.
if (m_use_axis_y) {
if (m_reset_y) {
- setposition[1] = 0.5;
- movement[1] -= 0.5;
+ setposition[1] = center_y;
+ movement[1] -= center_y;
}
else {
setposition[1] = position[1];
@@ -226,12 +233,10 @@ bool KX_MouseActuator::Update()
movement[1] *= -1.0;
- /* Don't apply the rotation when height resolution is odd (+ little movement) to
- avoid undesired drifting or when we are under a certain threshold for mouse
+ /* Don't apply the rotation when we are under a certain threshold for mouse
movement */
- if (!((m_canvas->GetHeight() % 2 != 0) && MT_abs(movement[1]) < 0.01) &&
- ((movement[1] > (m_threshold[1] / 10.0)) ||
+ if (((movement[1] > (m_threshold[1] / 10.0)) ||
((movement[1] * (-1.0)) > (m_threshold[1] / 10.0)))) {
movement[1] *= m_sensitivity[1];
@@ -270,7 +275,7 @@ bool KX_MouseActuator::Update()
}
}
else {
- setposition[1] = 0.5;
+ setposition[1] = center_y;
}
setMousePosition(setposition[0], setposition[1]);
@@ -399,8 +404,8 @@ int KX_MouseActuator::pyattr_set_limit_x(void *self_v, const KX_PYATTRIBUTE_DEF
if (PyList_Size(value) != 2)
return PY_SET_ATTR_FAIL;
- item1 = PyList_GetItem(value, 0);
- item2 = PyList_GetItem(value, 1);
+ item1 = PyList_GET_ITEM(value, 0);
+ item2 = PyList_GET_ITEM(value, 1);
if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) {
return PY_SET_ATTR_FAIL;
@@ -430,8 +435,8 @@ int KX_MouseActuator::pyattr_set_limit_y(void *self_v, const KX_PYATTRIBUTE_DEF
if (PyList_Size(value) != 2)
return PY_SET_ATTR_FAIL;
- item1 = PyList_GetItem(value, 0);
- item2 = PyList_GetItem(value, 1);
+ item1 = PyList_GET_ITEM(value, 0);
+ item2 = PyList_GET_ITEM(value, 1);
if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) {
return PY_SET_ATTR_FAIL;
@@ -461,8 +466,8 @@ int KX_MouseActuator::pyattr_set_angle(void *self_v, const KX_PYATTRIBUTE_DEF *a
if (PyList_Size(value) != 2)
return PY_SET_ATTR_FAIL;
- item1 = PyList_GetItem(value, 0);
- item2 = PyList_GetItem(value, 1);
+ item1 = PyList_GET_ITEM(value, 0);
+ item2 = PyList_GET_ITEM(value, 1);
if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) {
return PY_SET_ATTR_FAIL;
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
index a9f6bb0d2ff..c2c83266791 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
@@ -269,8 +269,8 @@ bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam)
m_kxengine->GetSceneViewport(m_kxscene, cam, area, viewport);
/* Check if the mouse is in the viewport */
- if (( m_x < viewport.m_x2 && // less then right
- m_x > viewport.m_x1 && // more then then left
+ if (( m_x < viewport.m_x2 && // less than right
+ m_x > viewport.m_x1 && // more than then left
m_y_inv < viewport.m_y2 && // below top
m_y_inv > viewport.m_y1) == 0) // above bottom
{
diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp
index 804e8de2ad1..76332e75204 100644
--- a/source/gameengine/Ketsji/KX_PyMath.cpp
+++ b/source/gameengine/Ketsji/KX_PyMath.cpp
@@ -100,7 +100,7 @@ PyObject *PyObjectFrom(const MT_Matrix4x4 &mat)
#ifdef USE_MATHUTILS
float fmat[16];
mat.getValue(fmat);
- return Matrix_CreatePyObject(fmat, 4, 4, Py_NEW, NULL);
+ return Matrix_CreatePyObject(fmat, 4, 4, NULL);
#else
PyObject *collist = PyList_New(4);
PyObject *col;
@@ -124,7 +124,7 @@ PyObject *PyObjectFrom(const MT_Matrix3x3 &mat)
#ifdef USE_MATHUTILS
float fmat[9];
mat.getValue3x3(fmat);
- return Matrix_CreatePyObject(fmat, 3, 3, Py_NEW, NULL);
+ return Matrix_CreatePyObject(fmat, 3, 3, NULL);
#else
PyObject *collist = PyList_New(3);
PyObject *col;
@@ -148,7 +148,7 @@ PyObject *PyObjectFrom(const MT_Quaternion &qrot)
/* NOTE, were re-ordering here for Mathutils compat */
float fvec[4];
qrot.getValue(fvec);
- return Quaternion_CreatePyObject(fvec, Py_NEW, NULL);
+ return Quaternion_CreatePyObject(fvec, NULL);
}
#endif
@@ -157,7 +157,7 @@ PyObject *PyObjectFrom(const MT_Tuple4 &vec)
#ifdef USE_MATHUTILS
float fvec[4];
vec.getValue(fvec);
- return Vector_CreatePyObject(fvec, 4, Py_NEW, NULL);
+ return Vector_CreatePyObject(fvec, 4, NULL);
#else
PyObject *list = PyList_New(4);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
@@ -173,7 +173,7 @@ PyObject *PyObjectFrom(const MT_Tuple3 &vec)
#ifdef USE_MATHUTILS
float fvec[3];
vec.getValue(fvec);
- return Vector_CreatePyObject(fvec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(fvec, 3, NULL);
#else
PyObject *list = PyList_New(3);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
@@ -188,7 +188,7 @@ PyObject *PyObjectFrom(const MT_Tuple2 &vec)
#ifdef USE_MATHUTILS
float fvec[2];
vec.getValue(fvec);
- return Vector_CreatePyObject(fvec, 2, Py_NEW, NULL);
+ return Vector_CreatePyObject(fvec, 2, NULL);
#else
PyObject *list = PyList_New(2);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index fefc64b4bad..3ddd53b971f 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -130,12 +130,16 @@ extern "C" {
#include "DNA_scene_types.h"
#include "PHY_IPhysicsEnvironment.h"
+
+extern "C" {
#include "BKE_main.h"
#include "BKE_global.h"
#include "BKE_library.h"
+#include "BKE_appdir.h"
#include "BLI_blenlib.h"
#include "GPU_material.h"
#include "MEM_guardedalloc.h"
+}
/* for converting new scenes */
#include "KX_BlenderSceneConverter.h"
@@ -2071,7 +2075,7 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur
* somehow it remembers the sys.path - Campbell
*/
static bool first_time = true;
- const char * const py_path_bundle = BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL);
+ const char * const py_path_bundle = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, NULL);
#if 0 // TODO - py3
STR_String pname = progname;
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index d0eab9de1c1..b6fd69fe1f4 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -218,7 +218,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_bucketmanager=new RAS_BucketManager();
- bool showObstacleSimulation = scene->gm.flag & GAME_SHOW_OBSTACLE_SIMULATION;
+ bool showObstacleSimulation = (scene->gm.flag & GAME_SHOW_OBSTACLE_SIMULATION) != 0;
switch (scene->gm.obstacleSimulation)
{
case OBSTSIMULATION_TOI_rays:
@@ -1502,6 +1502,15 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int
bool dbvt_culling = false;
if (m_dbvt_culling)
{
+ /* Reset KX_GameObject m_bCulled to true before doing culling
+ * since DBVT culling will only set it to false.
+ * This is similar to what RAS_BucketManager does for RAS_MeshSlot culling.
+ */
+ for (int i = 0; i < m_objectlist->GetCount(); i++) {
+ KX_GameObject *gameobj = static_cast<KX_GameObject*>(m_objectlist->GetValue(i));
+ gameobj->SetCulled(true);
+ }
+
// test culling through Bullet
MT_Vector4 planes[6];
// get the clip planes
@@ -1531,9 +1540,6 @@ 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
@@ -1642,20 +1648,6 @@ 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) {
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index c5840c28041..2e1ee9f101d 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -289,8 +289,6 @@ 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/Network/CMakeLists.txt b/source/gameengine/Network/CMakeLists.txt
index bae00c464f2..019fc3e6032 100644
--- a/source/gameengine/Network/CMakeLists.txt
+++ b/source/gameengine/Network/CMakeLists.txt
@@ -27,6 +27,7 @@ set(INC
.
../../../intern/container
../../../intern/string
+ ../../blender/blenlib
)
set(INC_SYS
diff --git a/source/gameengine/Network/SConscript b/source/gameengine/Network/SConscript
index 1d78cdba174..feb14e29552 100644
--- a/source/gameengine/Network/SConscript
+++ b/source/gameengine/Network/SConscript
@@ -31,6 +31,7 @@ sources = env.Glob('*.cpp') #'NG_NetworkMessage.cpp NG_NetworkObject.cpp NG_Netw
incs = [
'.',
+ '../../blender/blenlib',
'#intern/container',
'#intern/string',
'#intern/moto/include',
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index 72c3b13e301..ff68021f09e 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -207,6 +207,11 @@ btRigidBody* CcdPhysicsController::GetRigidBody()
{
return btRigidBody::upcast(m_object);
}
+const btRigidBody* CcdPhysicsController::GetRigidBody() const
+{
+ return btRigidBody::upcast(m_object);
+}
+
btCollisionObject* CcdPhysicsController::GetCollisionObject()
{
return m_object;
@@ -1354,6 +1359,42 @@ void CcdPhysicsController::Jump()
void CcdPhysicsController::SetActive(bool active)
{
}
+
+float CcdPhysicsController::GetLinearDamping() const
+{
+ const btRigidBody* body = GetRigidBody();
+ if (body)
+ return body->getLinearDamping();
+ return 0;
+}
+
+float CcdPhysicsController::GetAngularDamping() const
+{
+ const btRigidBody* body = GetRigidBody();
+ if (body)
+ return body->getAngularDamping();
+ return 0;
+}
+
+void CcdPhysicsController::SetLinearDamping(float damping)
+{
+ SetDamping(damping, GetAngularDamping());
+}
+
+void CcdPhysicsController::SetAngularDamping(float damping)
+{
+ SetDamping(GetLinearDamping(), damping);
+}
+
+void CcdPhysicsController::SetDamping(float linear, float angular)
+{
+ btRigidBody* body = GetRigidBody();
+ if (!body) return;
+
+ body->setDamping(linear, angular);
+}
+
+
// reading out information from physics
MT_Vector3 CcdPhysicsController::GetLinearVelocity()
{
@@ -2265,7 +2306,7 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
/* transverts are only used for deformed RAS_Meshes, the RAS_TexVert data
* is too hard to get at, see below for details */
float (*transverts)[3] = NULL;
- int transverts_tot= 0; /* with deformed meshes - should always be greater then the max orginal index, or we get crashes */
+ int transverts_tot= 0; /* with deformed meshes - should always be greater than the max orginal index, or we get crashes */
if (deformer) {
/* map locations from the deformed array
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 4d0d96e07c6..557a5fe603a 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -522,6 +522,7 @@ protected:
btRigidBody* GetRigidBody();
+ const btRigidBody* GetRigidBody() const;
btCollisionObject* GetCollisionObject();
btSoftBody* GetSoftBody();
btKinematicCharacterController* GetCharacterController();
@@ -573,6 +574,12 @@ protected:
virtual void Jump();
virtual void SetActive(bool active);
+ virtual float GetLinearDamping() const;
+ virtual float GetAngularDamping() const;
+ virtual void SetLinearDamping(float damping);
+ virtual void SetAngularDamping(float damping);
+ virtual void SetDamping(float linear, float angular);
+
// reading out information from physics
virtual MT_Vector3 GetLinearVelocity();
virtual MT_Vector3 GetAngularVelocity();
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index e17d4402556..38e7df6c573 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -504,9 +504,9 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr
btRigidBody* body = ctrl->GetRigidBody();
if (body)
{
- for (int i=body->getNumConstraintRefs()-1;i>=0;i--)
+ for (int i = m_dynamicsWorld->getNumConstraints()-1;i>=0;i--)
{
- btTypedConstraint* con = body->getConstraintRef(i);
+ btTypedConstraint *con = m_dynamicsWorld->getConstraint(i);
m_dynamicsWorld->removeConstraint(con);
body->removeConstraintRef(con);
//delete con; //might be kept by python KX_ConstraintWrapper
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h
index f9975484fa7..1717f8d90cb 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsController.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h
@@ -89,6 +89,12 @@ class PHY_IPhysicsController : public PHY_IController
virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local)=0;
virtual void ResolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) = 0;
+ virtual float GetLinearDamping() const=0;
+ virtual float GetAngularDamping() const=0;
+ virtual void SetLinearDamping(float damping)=0;
+ virtual void SetAngularDamping(float damping)=0;
+ virtual void SetDamping(float linear, float angular)=0;
+
virtual void SuspendDynamics(bool ghost=false)=0;
virtual void RestoreDynamics()=0;
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp
index 617e7fd1d8e..57b2e85845c 100644
--- a/source/gameengine/VideoTexture/ImageRender.cpp
+++ b/source/gameengine/VideoTexture/ImageRender.cpp
@@ -274,8 +274,6 @@ 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 edf3c58bcbe..db76ba5822a 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
@@ -86,6 +86,13 @@ VideoFFmpeg::~VideoFFmpeg ()
{
}
+void VideoFFmpeg::refresh(void)
+{
+ // a fixed image will not refresh because it is loaded only once at creation
+ if (m_isImage)
+ return;
+ m_avail = false;
+}
// release components
bool VideoFFmpeg::release()
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h
index 4a948fe61de..4834a7cef6d 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.h
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.h
@@ -85,7 +85,8 @@ public:
/// release video source
virtual bool release (void);
-
+ /// overwrite base refresh to handle fixed image
+ virtual void refresh(void);
/// play video
virtual bool play (void);
/// pause video
diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc
index ea761bcf32e..c4ef7c2c970 100644
--- a/tests/gtests/blenlib/BLI_path_util_test.cc
+++ b/tests/gtests/blenlib/BLI_path_util_test.cc
@@ -31,6 +31,7 @@ const char *GHOST_getSystemDir(int version, const char *versionstr)
struct ImBuf;
void IMB_freeImBuf(struct ImBuf *ibuf) {}
+struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf) {return NULL;}
#ifdef __linux__
char *zLhm65070058860608_br_find_exe(const char *default_exe)
diff --git a/tests/gtests/blenlib/BLI_polyfill2d_test.cc b/tests/gtests/blenlib/BLI_polyfill2d_test.cc
index 785274757aa..fac5c6f7674 100644
--- a/tests/gtests/blenlib/BLI_polyfill2d_test.cc
+++ b/tests/gtests/blenlib/BLI_polyfill2d_test.cc
@@ -7,6 +7,7 @@
/* test every possible offset and reverse */
#define USE_COMBINATIONS_ALL
+#define USE_BEAUTIFY
extern "C" {
#include "BLI_array.h"
@@ -18,6 +19,12 @@ extern "C" {
#ifdef USE_OBJ_PREVIEW
# include "BLI_string.h"
#endif
+
+#ifdef USE_BEAUTIFY
+#include "BLI_polyfill2d_beautify.h"
+#include "BLI_memarena.h"
+#include "BLI_heap.h"
+#endif
}
static void polyfill_to_obj(
@@ -179,6 +186,25 @@ static void test_polyfill_template(
/* check all went well */
test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+
+#ifdef USE_BEAUTIFY
+ /* check beautify gives good results too */
+ {
+ MemArena *pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
+ Heap *pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ EdgeHash *pf_ehash = BLI_edgehash_new_ex(__func__, BLI_POLYFILL_ALLOC_NGON_RESERVE);
+
+ BLI_polyfill_beautify(
+ poly, poly_tot, tris,
+ pf_arena, pf_heap, pf_ehash);
+
+ test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+
+ BLI_memarena_free(pf_arena);
+ BLI_heap_free(pf_heap, NULL);
+ BLI_edgehash_free(pf_ehash, NULL);
+ }
+#endif
}
#ifdef USE_COMBINATIONS_ALL
diff --git a/tests/gtests/testing/testing_main.cc b/tests/gtests/testing/testing_main.cc
index ef8e743b642..b2dcc445aca 100644
--- a/tests/gtests/testing/testing_main.cc
+++ b/tests/gtests/testing/testing_main.cc
@@ -28,7 +28,7 @@
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
- google::ParseCommandLineFlags(&argc, &argv, true);
+ gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
return RUN_ALL_TESTS();